1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
5 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
6 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
10 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
11 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
19 #if defined(_TARGET_ARM64_)
21 /*****************************************************************************/
22 /*****************************************************************************/
28 /* static */ bool emitter::strictArmAsm = true;
30 /*****************************************************************************/
32 const instruction emitJumpKindInstructions[] = {
35 #define JMP_SMALL(en, rev, ins) INS_##ins,
39 const emitJumpKind emitReverseJumpKinds[] = {
42 #define JMP_SMALL(en, rev, ins) EJ_##rev,
46 /*****************************************************************************
47 * Look up the instruction for a jump kind
50 /*static*/ instruction emitter::emitJumpKindToIns(emitJumpKind jumpKind)
52 assert((unsigned)jumpKind < ArrLen(emitJumpKindInstructions));
53 return emitJumpKindInstructions[jumpKind];
56 /*****************************************************************************
57 * Look up the jump kind for an instruction. It better be a conditional
58 * branch instruction with a jump kind!
61 /*static*/ emitJumpKind emitter::emitInsToJumpKind(instruction ins)
63 for (unsigned i = 0; i < ArrLen(emitJumpKindInstructions); i++)
65 if (ins == emitJumpKindInstructions[i])
67 emitJumpKind ret = (emitJumpKind)i;
68 assert(EJ_NONE < ret && ret < EJ_COUNT);
75 /*****************************************************************************
76 * Reverse the conditional jump
79 /*static*/ emitJumpKind emitter::emitReverseJumpKind(emitJumpKind jumpKind)
81 assert(jumpKind < EJ_COUNT);
82 return emitReverseJumpKinds[jumpKind];
85 /*****************************************************************************
87 * Return the allocated size (in bytes) of the given instruction descriptor.
90 size_t emitter::emitSizeOfInsDsc(instrDesc* id)
92 assert(!emitIsTinyInsDsc(id));
94 if (emitIsScnsInsDsc(id))
95 return SMALL_IDSC_SIZE;
97 assert((unsigned)id->idInsFmt() < emitFmtCount);
99 ID_OPS idOp = (ID_OPS)emitFmtToOps[id->idInsFmt()];
100 bool isCallIns = (id->idIns() == INS_bl) || (id->idIns() == INS_blr) || (id->idIns() == INS_b_tail) ||
101 (id->idIns() == INS_br_tail);
102 bool maybeCallIns = (id->idIns() == INS_b) || (id->idIns() == INS_br);
110 return sizeof(instrDescJmp);
113 assert(isCallIns || maybeCallIns);
114 if (id->idIsLargeCall())
116 /* Must be a "fat" call descriptor */
117 return sizeof(instrDescCGCA);
121 assert(!id->idIsLargeDsp());
122 assert(!id->idIsLargeCns());
123 return sizeof(instrDesc);
128 NO_WAY("unexpected instruction descriptor format");
132 if (id->idIsLargeCns())
134 if (id->idIsLargeDsp())
135 return sizeof(instrDescCnsDsp);
137 return sizeof(instrDescCns);
141 if (id->idIsLargeDsp())
142 return sizeof(instrDescDsp);
144 return sizeof(instrDesc);
149 /*****************************************************************************
151 * The following called for each recorded instruction -- use for debugging.
153 void emitter::emitInsSanityCheck(instrDesc* id)
155 /* What instruction format have we got? */
157 switch (id->idInsFmt())
169 case IF_BI_0A: // BI_0A ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
172 case IF_BI_0B: // BI_0B ......iiiiiiiiii iiiiiiiiiiii.... simm19:00
180 case IF_BI_0C: // BI_0C ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
183 case IF_BI_1A: // BI_1A ......iiiiiiiiii iiiiiiiiiiittttt Rt simm19:00
184 assert(isValidGeneralDatasize(id->idOpSize()));
185 assert(isGeneralRegister(id->idReg1()));
188 case IF_BI_1B: // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
189 assert(isValidGeneralDatasize(id->idOpSize()));
190 assert(isGeneralRegister(id->idReg1()));
191 assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
194 case IF_BR_1A: // BR_1A ................ ......nnnnn..... Rn
195 assert(isGeneralRegister(id->idReg1()));
198 case IF_BR_1B: // BR_1B ................ ......nnnnn..... Rn
199 assert(isGeneralRegister(id->idReg3()));
202 case IF_LS_1A: // LS_1A .X......iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB)
203 assert(isGeneralRegister(id->idReg1()) || isVectorRegister(id->idReg1()));
204 assert(insOptsNone(id->idInsOpt()));
207 case IF_LS_2A: // LS_2A .X.......X...... ......nnnnnttttt Rt Rn
208 assert(isIntegerRegister(id->idReg1()) || // ZR
209 isVectorRegister(id->idReg1()));
210 assert(isIntegerRegister(id->idReg2())); // SP
211 assert(emitGetInsSC(id) == 0);
212 assert(insOptsNone(id->idInsOpt()));
215 case IF_LS_2B: // LS_2B .X.......Xiiiiii iiiiiinnnnnttttt Rt Rn imm(0-4095)
216 assert(isIntegerRegister(id->idReg1()) || // ZR
217 isVectorRegister(id->idReg1()));
218 assert(isIntegerRegister(id->idReg2())); // SP
219 assert(isValidUimm12(emitGetInsSC(id)));
220 assert(insOptsNone(id->idInsOpt()));
223 case IF_LS_2C: // LS_2C .X.......X.iiiii iiiiPPnnnnnttttt Rt Rn imm(-256..+255) no/pre/post inc
224 assert(isIntegerRegister(id->idReg1()) || // ZR
225 isVectorRegister(id->idReg1()));
226 assert(isIntegerRegister(id->idReg2())); // SP
227 assert(emitGetInsSC(id) >= -0x100);
228 assert(emitGetInsSC(id) < 0x100);
229 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
232 case IF_LS_3A: // LS_3A .X.......X.mmmmm oooS..nnnnnttttt Rt Rn Rm ext(Rm) LSL {}
233 assert(isIntegerRegister(id->idReg1()) || // ZR
234 isVectorRegister(id->idReg1()));
235 assert(isIntegerRegister(id->idReg2())); // SP
236 if (id->idIsLclVar())
238 assert(isGeneralRegister(codeGen->rsGetRsvdReg()));
242 assert(isGeneralRegister(id->idReg3()));
244 assert(insOptsLSExtend(id->idInsOpt()));
247 case IF_LS_3B: // LS_3B X............... .aaaaannnnnttttt Rt Ra Rn
248 assert((isValidGeneralDatasize(id->idOpSize()) && isIntegerRegister(id->idReg1())) ||
249 (isValidVectorLSPDatasize(id->idOpSize()) && isVectorRegister(id->idReg1())));
250 assert(isIntegerRegister(id->idReg1()) || // ZR
251 isVectorRegister(id->idReg1()));
252 assert(isIntegerRegister(id->idReg2()) || // ZR
253 isVectorRegister(id->idReg2()));
254 assert(isIntegerRegister(id->idReg3())); // SP
255 assert(emitGetInsSC(id) == 0);
256 assert(insOptsNone(id->idInsOpt()));
259 case IF_LS_3C: // LS_3C X.........iiiiii iaaaaannnnnttttt Rt Ra Rn imm(im7,sh)
260 assert((isValidGeneralDatasize(id->idOpSize()) && isIntegerRegister(id->idReg1())) ||
261 (isValidVectorLSPDatasize(id->idOpSize()) && isVectorRegister(id->idReg1())));
262 assert(isIntegerRegister(id->idReg1()) || // ZR
263 isVectorRegister(id->idReg1()));
264 assert(isIntegerRegister(id->idReg2()) || // ZR
265 isVectorRegister(id->idReg2()));
266 assert(isIntegerRegister(id->idReg3())); // SP
267 assert(emitGetInsSC(id) >= -0x40);
268 assert(emitGetInsSC(id) < 0x40);
269 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
272 case IF_LS_3D: // LS_3D .X.......X.mmmmm ......nnnnnttttt Wm Rt Rn
273 assert(isIntegerRegister(id->idReg1()));
274 assert(isIntegerRegister(id->idReg2()));
275 assert(isIntegerRegister(id->idReg3()));
276 assert(emitGetInsSC(id) == 0);
277 assert(!id->idIsLclVar());
278 assert(insOptsNone(id->idInsOpt()));
281 case IF_DI_1A: // DI_1A X.......shiiiiii iiiiiinnnnn..... Rn imm(i12,sh)
282 assert(isValidGeneralDatasize(id->idOpSize()));
283 assert(isGeneralRegister(id->idReg1()));
284 assert(isValidUimm12(emitGetInsSC(id)));
285 assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
288 case IF_DI_1B: // DI_1B X........hwiiiii iiiiiiiiiiiddddd Rd imm(i16,hw)
289 assert(isValidGeneralDatasize(id->idOpSize()));
290 assert(isGeneralRegister(id->idReg1()));
291 assert(isValidImmHWVal(emitGetInsSC(id), id->idOpSize()));
294 case IF_DI_1C: // DI_1C X........Nrrrrrr ssssssnnnnn..... Rn imm(N,r,s)
295 assert(isValidGeneralDatasize(id->idOpSize()));
296 assert(isGeneralRegister(id->idReg1()));
297 assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
300 case IF_DI_1D: // DI_1D X........Nrrrrrr ssssss.....ddddd Rd imm(N,r,s)
301 assert(isValidGeneralDatasize(id->idOpSize()));
302 assert(isIntegerRegister(id->idReg1())); // SP
303 assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
306 case IF_DI_1E: // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
307 assert(isGeneralRegister(id->idReg1()));
310 case IF_DI_1F: // DI_1F X..........iiiii cccc..nnnnn.nzcv Rn imm5 nzcv cond
311 assert(isValidGeneralDatasize(id->idOpSize()));
312 assert(isGeneralRegister(id->idReg1()));
313 assert(isValidImmCondFlagsImm5(emitGetInsSC(id)));
316 case IF_DI_2A: // DI_2A X.......shiiiiii iiiiiinnnnnddddd Rd Rn imm(i12,sh)
317 assert(isValidGeneralDatasize(id->idOpSize()));
318 assert(isIntegerRegister(id->idReg1())); // SP
319 assert(isIntegerRegister(id->idReg2())); // SP
320 assert(isValidUimm12(emitGetInsSC(id)));
321 assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
324 case IF_DI_2B: // DI_2B X.........Xnnnnn ssssssnnnnnddddd Rd Rn imm(0-63)
325 assert(isValidGeneralDatasize(id->idOpSize()));
326 assert(isGeneralRegister(id->idReg1()));
327 assert(isGeneralRegister(id->idReg2()));
328 assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
331 case IF_DI_2C: // DI_2C X........Nrrrrrr ssssssnnnnnddddd Rd Rn imm(N,r,s)
332 assert(isValidGeneralDatasize(id->idOpSize()));
333 assert(isIntegerRegister(id->idReg1())); // SP
334 assert(isGeneralRegister(id->idReg2()));
335 assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
338 case IF_DI_2D: // DI_2D X........Nrrrrrr ssssssnnnnnddddd Rd Rn imr, imms (N,r,s)
339 assert(isValidGeneralDatasize(id->idOpSize()));
340 assert(isGeneralRegister(id->idReg1()));
341 assert(isGeneralRegister(id->idReg2()));
342 assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
345 case IF_DR_1D: // DR_1D X............... cccc.......ddddd Rd cond
346 assert(isValidGeneralDatasize(id->idOpSize()));
347 assert(isGeneralRegister(id->idReg1()));
348 assert(isValidImmCond(emitGetInsSC(id)));
351 case IF_DR_2A: // DR_2A X..........mmmmm ......nnnnn..... Rn Rm
352 assert(isValidGeneralDatasize(id->idOpSize()));
353 assert(isGeneralRegister(id->idReg1()));
354 assert(isGeneralRegister(id->idReg2()));
357 case IF_DR_2B: // DR_2B X.......sh.mmmmm ssssssnnnnn..... Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
358 assert(isValidGeneralDatasize(id->idOpSize()));
359 assert(isIntegerRegister(id->idReg1())); // ZR
360 assert(isGeneralRegister(id->idReg2()));
361 assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
362 if (!insOptsNone(id->idInsOpt()))
364 if (id->idIns() == INS_tst) // tst allows ROR, cmp/cmn don't
366 assert(insOptsAnyShift(id->idInsOpt()));
370 assert(insOptsAluShift(id->idInsOpt()));
373 assert(insOptsNone(id->idInsOpt()) || (emitGetInsSC(id) > 0));
376 case IF_DR_2C: // DR_2C X..........mmmmm ooosssnnnnn..... Rn Rm ext(Rm) LSL imm(0-4)
377 assert(isValidGeneralDatasize(id->idOpSize()));
378 assert(isIntegerRegister(id->idReg1())); // SP
379 assert(isGeneralRegister(id->idReg2()));
380 assert(insOptsNone(id->idInsOpt()) || insOptsLSL(id->idInsOpt()) || insOptsAnyExtend(id->idInsOpt()));
381 assert(emitGetInsSC(id) >= 0);
382 assert(emitGetInsSC(id) <= 4);
383 if (insOptsLSL(id->idInsOpt()))
385 assert(emitGetInsSC(id) > 0);
389 case IF_DR_2D: // DR_2D X..........nnnnn cccc..nnnnnmmmmm Rd Rn cond
390 assert(isValidGeneralDatasize(id->idOpSize()));
391 assert(isGeneralRegister(id->idReg1()));
392 assert(isGeneralRegister(id->idReg2()));
393 assert(isValidImmCond(emitGetInsSC(id)));
396 case IF_DR_2E: // DR_2E X..........mmmmm ...........ddddd Rd Rm
397 assert(isValidGeneralDatasize(id->idOpSize()));
398 assert(isGeneralRegister(id->idReg1()));
399 assert(isIntegerRegister(id->idReg2())); // ZR
402 case IF_DR_2F: // DR_2F X.......sh.mmmmm ssssss.....ddddd Rd Rm {LSL,LSR,ASR} imm(0-63)
403 assert(isValidGeneralDatasize(id->idOpSize()));
404 assert(isGeneralRegister(id->idReg1()));
405 assert(isGeneralRegister(id->idReg2()));
406 assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
407 assert(insOptsNone(id->idInsOpt()) || insOptsAluShift(id->idInsOpt()));
408 assert(insOptsNone(id->idInsOpt()) || (emitGetInsSC(id) > 0));
411 case IF_DR_2G: // DR_2G X............... ......nnnnnddddd Rd Rm
412 assert(isValidGeneralDatasize(id->idOpSize()));
413 assert(isIntegerRegister(id->idReg1())); // SP
414 assert(isIntegerRegister(id->idReg2())); // SP
417 case IF_DR_2H: // DR_2H X........X...... ......nnnnnddddd Rd Rn
418 assert(isValidGeneralDatasize(id->idOpSize()));
419 assert(isGeneralRegister(id->idReg1()));
420 assert(isGeneralRegister(id->idReg2()));
423 case IF_DR_2I: // DR_2I X..........mmmmm cccc..nnnnn.nzcv Rn Rm nzcv cond
424 assert(isValidGeneralDatasize(id->idOpSize()));
425 assert(isGeneralRegister(id->idReg1()));
426 assert(isGeneralRegister(id->idReg2()));
427 assert(isValidImmCondFlags(emitGetInsSC(id)));
430 case IF_DR_3A: // DR_3A X..........mmmmm ......nnnnnmmmmm Rd Rn Rm
431 assert(isValidGeneralDatasize(id->idOpSize()));
432 assert(isIntegerRegister(id->idReg1())); // SP
433 assert(isIntegerRegister(id->idReg2())); // SP
434 if (id->idIsLclVar())
436 assert(isGeneralRegister(codeGen->rsGetRsvdReg()));
440 assert(isGeneralRegister(id->idReg3()));
442 assert(insOptsNone(id->idInsOpt()));
445 case IF_DR_3B: // DR_3B X.......sh.mmmmm ssssssnnnnnddddd Rd Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
446 assert(isValidGeneralDatasize(id->idOpSize()));
447 assert(isGeneralRegister(id->idReg1()));
448 assert(isGeneralRegister(id->idReg2()));
449 assert(isGeneralRegister(id->idReg3()));
450 assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
451 assert(insOptsNone(id->idInsOpt()) || insOptsAnyShift(id->idInsOpt()));
452 assert(insOptsNone(id->idInsOpt()) || (emitGetInsSC(id) > 0));
455 case IF_DR_3C: // DR_3C X..........mmmmm ooosssnnnnnddddd Rd Rn Rm ext(Rm) LSL imm(0-4)
456 assert(isValidGeneralDatasize(id->idOpSize()));
457 assert(isIntegerRegister(id->idReg1())); // SP
458 assert(isIntegerRegister(id->idReg2())); // SP
459 assert(isGeneralRegister(id->idReg3()));
460 assert(insOptsNone(id->idInsOpt()) || insOptsLSL(id->idInsOpt()) || insOptsAnyExtend(id->idInsOpt()));
461 assert(emitGetInsSC(id) >= 0);
462 assert(emitGetInsSC(id) <= 4);
463 if (insOptsLSL(id->idInsOpt()))
465 assert((emitGetInsSC(id) > 0) ||
466 (id->idReg2() == REG_ZR)); // REG_ZR encodes SP and we allow a shift of zero
470 case IF_DR_3D: // DR_3D X..........mmmmm cccc..nnnnnmmmmm Rd Rn Rm cond
471 assert(isValidGeneralDatasize(id->idOpSize()));
472 assert(isGeneralRegister(id->idReg1()));
473 assert(isGeneralRegister(id->idReg2()));
474 assert(isGeneralRegister(id->idReg3()));
475 assert(isValidImmCond(emitGetInsSC(id)));
478 case IF_DR_3E: // DR_3E X........X.mmmmm ssssssnnnnnddddd Rd Rn Rm imm(0-63)
479 assert(isValidGeneralDatasize(id->idOpSize()));
480 assert(isGeneralRegister(id->idReg1()));
481 assert(isGeneralRegister(id->idReg2()));
482 assert(isGeneralRegister(id->idReg3()));
483 assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
484 assert(insOptsNone(id->idInsOpt()));
487 case IF_DR_4A: // DR_4A X..........mmmmm .aaaaannnnnddddd Rd Rn Rm Ra
488 assert(isValidGeneralDatasize(id->idOpSize()));
489 assert(isGeneralRegister(id->idReg1()));
490 assert(isGeneralRegister(id->idReg2()));
491 assert(isGeneralRegister(id->idReg3()));
492 assert(isGeneralRegister(id->idReg4()));
495 case IF_DV_1A: // DV_1A .........X.iiiii iii........ddddd Vd imm8 (fmov - immediate scalar)
496 assert(insOptsNone(id->idInsOpt()));
497 elemsize = id->idOpSize();
498 assert(isValidVectorElemsizeFloat(elemsize));
499 assert(isVectorRegister(id->idReg1()));
500 assert(isValidUimm8(emitGetInsSC(id)));
503 case IF_DV_1B: // DV_1B .QX..........iii cmod..iiiiiddddd Vd imm8 (immediate vector)
505 imm = emitGetInsSC(id) & 0x0ff;
506 immShift = (emitGetInsSC(id) & 0x700) >> 8;
507 assert(immShift >= 0);
508 datasize = id->idOpSize();
509 assert(isValidVectorDatasize(datasize));
510 assert(isValidArrangement(datasize, id->idInsOpt()));
511 elemsize = optGetElemsize(id->idInsOpt());
514 assert(isValidVectorElemsizeFloat(elemsize));
515 assert(id->idInsOpt() != INS_OPTS_1D); // Reserved encoding
516 assert(immShift == 0);
520 assert(isValidVectorElemsize(elemsize));
521 assert((immShift != 4) && (immShift != 7)); // always invalid values
522 if (ins != INS_movi) // INS_mvni, INS_orr, INS_bic
524 assert((elemsize != EA_1BYTE) && (elemsize != EA_8BYTE)); // only H or S
525 if (elemsize == EA_2BYTE)
527 assert(immShift < 2);
529 else // (elemsize == EA_4BYTE)
533 assert(immShift < 4);
538 assert(isVectorRegister(id->idReg1()));
539 assert(isValidUimm8(imm));
542 case IF_DV_1C: // DV_1C .........X...... ......nnnnn..... Vn #0.0 (fcmp - with zero)
543 assert(insOptsNone(id->idInsOpt()));
544 elemsize = id->idOpSize();
545 assert(isValidVectorElemsizeFloat(elemsize));
546 assert(isVectorRegister(id->idReg1()));
549 case IF_DV_2A: // DV_2A .Q.......X...... ......nnnnnddddd Vd Vn (fabs, fcvt - vector)
550 case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
551 assert(isValidVectorDatasize(id->idOpSize()));
552 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
553 assert(isVectorRegister(id->idReg1()));
554 assert(isVectorRegister(id->idReg2()));
557 case IF_DV_2N: // DV_2N .........iiiiiii ......nnnnnddddd Vd Vn imm (shift - scalar)
558 assert(id->idOpSize() == EA_8BYTE);
559 assert(insOptsNone(id->idInsOpt()));
560 assert(isVectorRegister(id->idReg1()));
561 assert(isVectorRegister(id->idReg2()));
562 assert(isValidImmShift(emitGetInsSC(id), EA_8BYTE));
565 case IF_DV_2O: // DV_2O .Q.......iiiiiii ......nnnnnddddd Vd Vn imm (shift - vector)
566 assert(isValidVectorDatasize(id->idOpSize()));
567 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
568 assert(isVectorRegister(id->idReg1()));
569 assert(isVectorRegister(id->idReg2()));
570 elemsize = optGetElemsize(id->idInsOpt());
571 assert(isValidImmShift(emitGetInsSC(id), elemsize));
574 case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov/smov - to general)
575 elemsize = id->idOpSize();
576 index = emitGetInsSC(id);
577 assert(insOptsNone(id->idInsOpt()));
578 assert(isValidVectorIndex(EA_16BYTE, elemsize, index));
579 assert(isValidVectorElemsize(elemsize));
580 assert(isGeneralRegister(id->idReg1()));
581 assert(isVectorRegister(id->idReg2()));
584 case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
585 if (id->idIns() == INS_dup)
587 datasize = id->idOpSize();
588 assert(isValidVectorDatasize(datasize));
589 assert(isValidArrangement(datasize, id->idInsOpt()));
590 elemsize = optGetElemsize(id->idInsOpt());
594 datasize = EA_16BYTE;
595 elemsize = id->idOpSize();
596 assert(isValidVectorElemsize(elemsize));
598 assert(isVectorRegister(id->idReg1()));
599 assert(isGeneralRegisterOrZR(id->idReg2()));
602 case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
603 datasize = id->idOpSize();
604 assert(isValidVectorDatasize(datasize));
605 assert(isValidArrangement(datasize, id->idInsOpt()));
606 elemsize = optGetElemsize(id->idInsOpt());
607 index = emitGetInsSC(id);
608 assert(isValidVectorIndex(datasize, elemsize, index));
609 assert(isVectorRegister(id->idReg1()));
610 assert(isVectorRegister(id->idReg2()));
613 case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
614 elemsize = id->idOpSize();
615 index = emitGetInsSC(id);
616 assert(isValidVectorIndex(EA_16BYTE, elemsize, index));
617 assert(isValidVectorElemsize(elemsize));
618 assert(isVectorRegister(id->idReg1()));
619 assert(isVectorRegister(id->idReg2()));
622 case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
623 imm = emitGetInsSC(id);
624 index = (imm >> 4) & 0xf;
626 elemsize = id->idOpSize();
627 assert(isValidVectorElemsize(elemsize));
628 assert(isValidVectorIndex(EA_16BYTE, elemsize, index));
629 assert(isValidVectorIndex(EA_16BYTE, elemsize, index2));
630 assert(isVectorRegister(id->idReg1()));
631 assert(isVectorRegister(id->idReg2()));
634 case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
635 assert(id->idOpSize() == EA_8BYTE); // only type D is supported
638 case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov, fcvtXX - register)
639 case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
640 assert(insOptsNone(id->idInsOpt()));
641 assert(isValidVectorElemsizeFloat(id->idOpSize()));
642 assert(isVectorRegister(id->idReg1()));
643 assert(isVectorRegister(id->idReg2()));
646 case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov/fcvtXX - to general)
647 assert(insOptsConvertFloatToInt(id->idInsOpt()));
648 dstsize = optGetDstsize(id->idInsOpt());
649 srcsize = optGetSrcsize(id->idInsOpt());
650 assert(isValidGeneralDatasize(dstsize));
651 assert(isValidVectorElemsizeFloat(srcsize));
652 assert(dstsize == id->idOpSize());
653 assert(isGeneralRegister(id->idReg1()));
654 assert(isVectorRegister(id->idReg2()));
657 case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov/Xcvtf - from general)
658 assert(insOptsConvertIntToFloat(id->idInsOpt()));
659 dstsize = optGetDstsize(id->idInsOpt());
660 srcsize = optGetSrcsize(id->idInsOpt());
661 assert(isValidGeneralDatasize(srcsize));
662 assert(isValidVectorElemsizeFloat(dstsize));
663 assert(dstsize == id->idOpSize());
664 assert(isVectorRegister(id->idReg1()));
665 assert(isGeneralRegister(id->idReg2()));
668 case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
669 assert(insOptsConvertFloatToFloat(id->idInsOpt()));
670 dstsize = optGetDstsize(id->idInsOpt());
671 srcsize = optGetSrcsize(id->idInsOpt());
672 assert(isValidVectorFcvtsize(srcsize));
673 assert(isValidVectorFcvtsize(dstsize));
674 assert(dstsize == id->idOpSize());
675 assert(isVectorRegister(id->idReg1()));
676 assert(isVectorRegister(id->idReg2()));
679 case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
680 assert(isValidVectorDatasize(id->idOpSize()));
681 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
682 assert(isVectorRegister(id->idReg1()));
683 assert(isVectorRegister(id->idReg2()));
684 assert(isVectorRegister(id->idReg3()));
685 elemsize = optGetElemsize(id->idInsOpt());
689 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
691 else if (ins == INS_pmul)
693 assert(elemsize == EA_1BYTE); // only supports 8B or 16B
697 case IF_DV_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
698 assert(isValidVectorDatasize(id->idOpSize()));
699 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
700 assert(isVectorRegister(id->idReg1()));
701 assert(isVectorRegister(id->idReg2()));
702 assert(isVectorRegister(id->idReg3()));
703 elemsize = optGetElemsize(id->idInsOpt());
704 assert(isValidVectorIndex(EA_16BYTE, elemsize, emitGetInsSC(id)));
705 // Only has encodings for H or S elemsize
706 assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE));
709 case IF_DV_3B: // DV_3B .Q.......X.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
710 assert(isValidVectorDatasize(id->idOpSize()));
711 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
712 assert(isVectorRegister(id->idReg1()));
713 assert(isVectorRegister(id->idReg2()));
714 assert(isVectorRegister(id->idReg3()));
717 case IF_DV_3BI: // DV_3BI .Q.......XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
718 assert(isValidVectorDatasize(id->idOpSize()));
719 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
720 assert(isVectorRegister(id->idReg1()));
721 assert(isVectorRegister(id->idReg2()));
722 assert(isVectorRegister(id->idReg3()));
723 elemsize = optGetElemsize(id->idInsOpt());
724 assert(isValidVectorIndex(id->idOpSize(), elemsize, emitGetInsSC(id)));
727 case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
728 assert(isValidVectorDatasize(id->idOpSize()));
729 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
730 assert(isVectorRegister(id->idReg1()));
731 assert(isVectorRegister(id->idReg2()));
732 assert(isVectorRegister(id->idReg3()));
735 case IF_DV_3D: // DV_3D .........X.mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
736 assert(isValidScalarDatasize(id->idOpSize()));
737 assert(insOptsNone(id->idInsOpt()));
738 assert(isVectorRegister(id->idReg1()));
739 assert(isVectorRegister(id->idReg2()));
740 assert(isVectorRegister(id->idReg3()));
743 case IF_DV_3DI: // DV_3DI .........XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (scalar by elem)
744 assert(isValidScalarDatasize(id->idOpSize()));
745 assert(insOptsNone(id->idInsOpt()));
746 assert(isVectorRegister(id->idReg1()));
747 assert(isVectorRegister(id->idReg2()));
748 assert(isVectorRegister(id->idReg3()));
749 elemsize = id->idOpSize();
750 assert(isValidVectorIndex(EA_16BYTE, elemsize, emitGetInsSC(id)));
753 case IF_DV_3E: // DV_3E ...........mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
754 assert(insOptsNone(id->idInsOpt()));
755 assert(id->idOpSize() == EA_8BYTE);
756 assert(isVectorRegister(id->idReg1()));
757 assert(isVectorRegister(id->idReg2()));
758 assert(isVectorRegister(id->idReg3()));
761 case IF_DV_4A: // DR_4A .........X.mmmmm .aaaaannnnnddddd Rd Rn Rm Ra (scalar)
762 assert(isValidGeneralDatasize(id->idOpSize()));
763 assert(isVectorRegister(id->idReg1()));
764 assert(isVectorRegister(id->idReg2()));
765 assert(isVectorRegister(id->idReg3()));
766 assert(isVectorRegister(id->idReg4()));
769 case IF_SN_0A: // SN_0A ................ ................
770 case IF_SI_0A: // SI_0A ...........iiiii iiiiiiiiiii..... imm16
771 case IF_SI_0B: // SI_0B ................ ....bbbb........ imm4 - barrier
775 printf("unexpected format %s\n", emitIfName(id->idInsFmt()));
776 assert(!"Unexpected format");
782 bool emitter::emitInsMayWriteToGCReg(instrDesc* id)
784 instruction ins = id->idIns();
785 insFormat fmt = id->idInsFmt();
790 // These are the formats with "destination" registers:
792 case IF_DI_1B: // DI_1B X........hwiiiii iiiiiiiiiiiddddd Rd imm(i16,hw)
793 case IF_DI_1D: // DI_1D X........Nrrrrrr ssssss.....ddddd Rd imm(N,r,s)
794 case IF_DI_1E: // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
796 case IF_DI_2A: // DI_2A X.......shiiiiii iiiiiinnnnnddddd Rd Rn imm(i12,sh)
797 case IF_DI_2B: // DI_2B X.........Xnnnnn ssssssnnnnnddddd Rd Rn imm(0-63)
798 case IF_DI_2C: // DI_2C X........Nrrrrrr ssssssnnnnnddddd Rd Rn imm(N,r,s)
799 case IF_DI_2D: // DI_2D X........Nrrrrrr ssssssnnnnnddddd Rd Rn imr, imms (N,r,s)
801 case IF_DR_1D: // DR_1D X............... cccc.......ddddd Rd cond
803 case IF_DR_2D: // DR_2D X..........nnnnn cccc..nnnnnddddd Rd Rn cond
804 case IF_DR_2E: // DR_2E X..........mmmmm ...........ddddd Rd Rm
805 case IF_DR_2F: // DR_2F X.......sh.mmmmm ssssss.....ddddd Rd Rm {LSL,LSR,ASR} imm(0-63)
806 case IF_DR_2G: // DR_2G X............... ......nnnnnddddd Rd Rn
807 case IF_DR_2H: // DR_2H X........X...... ......nnnnnddddd Rd Rn
809 case IF_DR_3A: // DR_3A X..........mmmmm ......nnnnnddddd Rd Rn Rm
810 case IF_DR_3B: // DR_3B X.......sh.mmmmm ssssssnnnnnddddd Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
811 case IF_DR_3C: // DR_3C X..........mmmmm xxxsssnnnnnddddd Rd Rn Rm ext(Rm) LSL imm(0-4)
812 case IF_DR_3D: // DR_3D X..........mmmmm cccc..nnnnnddddd Rd Rn Rm cond
813 case IF_DR_3E: // DR_3E X........X.mmmmm ssssssnnnnnddddd Rd Rn Rm imm(0-63)
815 case IF_DR_4A: // DR_4A X..........mmmmm .aaaaannnnnddddd Rd Rn Rm Ra
817 case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov - to general)
818 case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov - to general)
822 case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
823 case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
824 case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
825 case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
826 case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov, fcvtXX - register)
827 case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov - from general)
828 case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
829 case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
830 case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
831 case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
832 case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
833 case IF_DV_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector)
834 case IF_DV_3B: // DV_3B .Q.......X.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
835 case IF_DV_3BI: // DV_3BI .Q.......XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
836 case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
837 case IF_DV_3D: // DV_3D .........X.mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
838 case IF_DV_3DI: // DV_3DI .........XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (scalar by elem)
839 case IF_DV_3E: // DV_3E ...........mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
840 case IF_DV_4A: // DV_4A .........X.mmmmm .aaaaannnnnddddd Vd Va Vn Vm (scalar)
841 // Tracked GC pointers cannot be placed into the SIMD registers.
844 // These are the load/store formats with "target" registers:
846 case IF_LS_1A: // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB)
847 case IF_LS_2A: // LS_2A .X.......X...... ......nnnnnttttt Rt Rn
848 case IF_LS_2B: // LS_2B .X.......Xiiiiii iiiiiinnnnnttttt Rt Rn imm(0-4095)
849 case IF_LS_2C: // LS_2C .X.......X.iiiii iiiiP.nnnnnttttt Rt Rn imm(-256..+255) pre/post inc
850 case IF_LS_3A: // LS_3A .X.......X.mmmmm xxxS..nnnnnttttt Rt Rn Rm ext(Rm) LSL {}
851 case IF_LS_3B: // LS_3B X............... .aaaaannnnnttttt Rt Ra Rn
852 case IF_LS_3C: // LS_3C X.........iiiiii iaaaaannnnnttttt Rt Ra Rn imm(im7,sh)
853 case IF_LS_3D: // LS_3D .X.......X.mmmmm ......nnnnnttttt Wm Rt Rn
855 // For the Store instructions the "target" register is actually a "source" value
857 if (emitInsIsStore(ins))
863 assert(emitInsIsLoad(ins));
872 bool emitter::emitInsWritesToLclVarStackLoc(instrDesc* id)
874 if (!id->idIsLclVar())
877 instruction ins = id->idIns();
879 // This list is related to the list of instructions used to store local vars in emitIns_S_R().
880 // We don't accept writing to float local vars.
896 bool emitter::emitInsWritesToLclVarStackLocPair(instrDesc* id)
898 if (!id->idIsLclVar())
901 instruction ins = id->idIns();
903 // This list is related to the list of instructions used to store local vars in emitIns_S_S_R_R().
904 // We don't accept writing to float local vars.
916 bool emitter::emitInsMayWriteMultipleRegs(instrDesc* id)
918 instruction ins = id->idIns();
931 // For the small loads/store instruction we adjust the size 'attr'
932 // depending upon whether we have a load or a store
934 emitAttr emitter::emitInsAdjustLoadStoreAttr(instruction ins, emitAttr attr)
936 if (EA_SIZE(attr) <= EA_4BYTE)
938 if (emitInsIsLoad(ins))
940 // The value of 'ins' encodes the size to load
941 // we use EA_8BYTE here because it is the size we will write (into dataReg)
942 // it is also required when ins is INS_ldrsw
948 assert(emitInsIsStore(ins));
950 // The value of 'ins' encodes the size to store
951 // we use EA_4BYTE here because it is the size of the register
952 // that we want to display when storing small values
960 // Takes an instrDesc 'id' and uses the instruction 'ins' to determine the
961 // size of the target register that is written or read by the instruction.
962 // Note that even if EA_4BYTE is returned a load instruction will still
963 // always zero the upper 4 bytes of the target register.
964 // This method is required so that we can distinguish between loads that are
965 // sign-extending as they can have two different sizes for their target register.
966 // Additionally for instructions like 'ldr' and 'str' these can load/store
967 // either 4 byte or 8 bytes to/from the target register.
968 // By convention the small unsigned load instructions are considered to write
969 // a 4 byte sized target register, though since these also zero the upper 4 bytes
970 // they could equally be considered to write the unsigned value to full 8 byte register.
972 emitAttr emitter::emitInsTargetRegSize(instrDesc* id)
974 instruction ins = id->idIns();
975 emitAttr result = EA_UNKNOWN;
977 // This is used to determine the size of the target registers for a load/store instruction
1011 if (id->idOpSize() == EA_8BYTE)
1027 result = id->idOpSize();
1040 result = id->idOpSize();
1044 NO_WAY("unexpected instruction");
1050 // Takes an instrDesc and uses the instruction to determine the 'size' of the
1051 // data that is loaded from memory.
1053 emitAttr emitter::emitInsLoadStoreSize(instrDesc* id)
1055 instruction ins = id->idIns();
1056 emitAttr result = EA_UNKNOWN;
1058 // The 'result' returned is the 'size' of the data that is loaded from memory.
1094 result = id->idOpSize();
1103 result = id->idOpSize();
1107 NO_WAY("unexpected instruction");
1113 /*****************************************************************************/
1117 static const char * const xRegNames[] =
1119 #define REGDEF(name, rnum, mask, xname, wname) xname,
1120 #include "register.h"
1123 static const char * const wRegNames[] =
1125 #define REGDEF(name, rnum, mask, xname, wname) wname,
1126 #include "register.h"
1129 static const char * const vRegNames[] =
1131 "v0", "v1", "v2", "v3", "v4",
1132 "v5", "v6", "v7", "v8", "v9",
1133 "v10", "v11", "v12", "v13", "v14",
1134 "v15", "v16", "v17", "v18", "v19",
1135 "v20", "v21", "v22", "v23", "v24",
1136 "v25", "v26", "v27", "v28", "v29",
1140 static const char * const qRegNames[] =
1142 "q0", "q1", "q2", "q3", "q4",
1143 "q5", "q6", "q7", "q8", "q9",
1144 "q10", "q11", "q12", "q13", "q14",
1145 "q15", "q16", "q17", "q18", "q19",
1146 "q20", "q21", "q22", "q23", "q24",
1147 "q25", "q26", "q27", "q28", "q29",
1151 static const char * const hRegNames[] =
1153 "h0", "h1", "h2", "h3", "h4",
1154 "h5", "h6", "h7", "h8", "h9",
1155 "h10", "h11", "h12", "h13", "h14",
1156 "h15", "h16", "h17", "h18", "h19",
1157 "h20", "h21", "h22", "h23", "h24",
1158 "h25", "h26", "h27", "h28", "h29",
1161 static const char * const bRegNames[] =
1163 "b0", "b1", "b2", "b3", "b4",
1164 "b5", "b6", "b7", "b8", "b9",
1165 "b10", "b11", "b12", "b13", "b14",
1166 "b15", "b16", "b17", "b18", "b19",
1167 "b20", "b21", "b22", "b23", "b24",
1168 "b25", "b26", "b27", "b28", "b29",
1173 /*****************************************************************************
1175 * Return a string that represents the given register.
1178 const char* emitter::emitRegName(regNumber reg, emitAttr size, bool varName)
1180 assert(reg < REG_COUNT);
1182 const char* rn = nullptr;
1184 if (size == EA_8BYTE)
1186 rn = xRegNames[reg];
1188 else if (size == EA_4BYTE)
1190 rn = wRegNames[reg];
1192 else if (isVectorRegister(reg))
1194 if (size == EA_16BYTE)
1196 rn = qRegNames[reg - REG_V0];
1198 else if (size == EA_2BYTE)
1200 rn = hRegNames[reg - REG_V0];
1202 else if (size == EA_1BYTE)
1204 rn = bRegNames[reg - REG_V0];
1208 assert(rn != nullptr);
1213 /*****************************************************************************
1215 * Return a string that represents the given register.
1218 const char* emitter::emitVectorRegName(regNumber reg)
1220 assert((reg >= REG_V0) && (reg <= REG_V31));
1222 int index = (int)reg - (int)REG_V0;
1224 return vRegNames[index];
1228 /*****************************************************************************
1230 * Returns the base encoding of the given CPU instruction.
1233 emitter::insFormat emitter::emitInsFormat(instruction ins)
1236 const static insFormat insFormats[] =
1238 #define INST1(id, nm, fp, ldst, fmt, e1 ) fmt,
1239 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) fmt,
1240 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) fmt,
1241 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) fmt,
1242 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) fmt,
1243 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) fmt,
1244 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) fmt,
1249 assert(ins < ArrLen(insFormats));
1250 assert((insFormats[ins] != IF_NONE));
1252 return insFormats[ins];
1261 /*static*/ const BYTE CodeGenInterface::instInfo[] =
1263 #define INST1(id, nm, fp, ldst, fmt, e1 ) ldst | INST_FP*fp,
1264 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) ldst | INST_FP*fp,
1265 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) ldst | INST_FP*fp,
1266 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) ldst | INST_FP*fp,
1267 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) ldst | INST_FP*fp,
1268 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) ldst | INST_FP*fp,
1269 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) ldst | INST_FP*fp,
1274 /*****************************************************************************
1276 * Returns true if the instruction is some kind of compare or test instruction
1279 bool emitter::emitInsIsCompare(instruction ins)
1281 // We have pseudo ins like lea which are not included in emitInsLdStTab.
1282 if (ins < ArrLen(CodeGenInterface::instInfo))
1283 return (CodeGenInterface::instInfo[ins] & CMP) ? true : false;
1288 /*****************************************************************************
1290 * Returns true if the instruction is some kind of load instruction
1293 bool emitter::emitInsIsLoad(instruction ins)
1295 // We have pseudo ins like lea which are not included in emitInsLdStTab.
1296 if (ins < ArrLen(CodeGenInterface::instInfo))
1297 return (CodeGenInterface::instInfo[ins] & LD) ? true : false;
1301 /*****************************************************************************
1303 * Returns true if the instruction is some kind of store instruction
1306 bool emitter::emitInsIsStore(instruction ins)
1308 // We have pseudo ins like lea which are not included in emitInsLdStTab.
1309 if (ins < ArrLen(CodeGenInterface::instInfo))
1310 return (CodeGenInterface::instInfo[ins] & ST) ? true : false;
1315 /*****************************************************************************
1317 * Returns true if the instruction is some kind of load/store instruction
1320 bool emitter::emitInsIsLoadOrStore(instruction ins)
1322 // We have pseudo ins like lea which are not included in emitInsLdStTab.
1323 if (ins < ArrLen(CodeGenInterface::instInfo))
1324 return (CodeGenInterface::instInfo[ins] & (LD | ST)) ? true : false;
1333 /*****************************************************************************
1335 * Returns the specific encoding of the given CPU instruction and format
1338 emitter::code_t emitter::emitInsCode(instruction ins, insFormat fmt)
1341 const static code_t insCodes1[] =
1343 #define INST1(id, nm, fp, ldst, fmt, e1 ) e1,
1344 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) e1,
1345 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) e1,
1346 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e1,
1347 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e1,
1348 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e1,
1349 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e1,
1352 const static code_t insCodes2[] =
1354 #define INST1(id, nm, fp, ldst, fmt, e1 )
1355 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) e2,
1356 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) e2,
1357 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e2,
1358 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e2,
1359 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e2,
1360 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e2,
1363 const static code_t insCodes3[] =
1365 #define INST1(id, nm, fp, ldst, fmt, e1 )
1366 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1367 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) e3,
1368 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e3,
1369 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e3,
1370 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e3,
1371 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e3,
1374 const static code_t insCodes4[] =
1376 #define INST1(id, nm, fp, ldst, fmt, e1 )
1377 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1378 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
1379 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e4,
1380 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e4,
1381 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e4,
1382 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e4,
1385 const static code_t insCodes5[] =
1387 #define INST1(id, nm, fp, ldst, fmt, e1 )
1388 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1389 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
1390 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
1391 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e5,
1392 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e5,
1393 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e5,
1396 const static code_t insCodes6[] =
1398 #define INST1(id, nm, fp, ldst, fmt, e1 )
1399 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1400 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
1401 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
1402 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
1403 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e6,
1404 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e6,
1407 const static code_t insCodes7[] =
1409 #define INST1(id, nm, fp, ldst, fmt, e1 )
1410 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1411 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
1412 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
1413 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
1414 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 )
1415 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e7,
1418 const static code_t insCodes8[] =
1420 #define INST1(id, nm, fp, ldst, fmt, e1 )
1421 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1422 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
1423 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
1424 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
1425 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 )
1426 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e8,
1429 const static code_t insCodes9[] =
1431 #define INST1(id, nm, fp, ldst, fmt, e1 )
1432 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1433 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
1434 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
1435 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
1436 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 )
1437 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e9,
1442 const static insFormat formatEncode9[9] = {IF_DR_2E, IF_DR_2G, IF_DI_1B, IF_DI_1D, IF_DV_3C,
1443 IF_DV_2B, IF_DV_2C, IF_DV_2E, IF_DV_2F};
1444 const static insFormat formatEncode6A[6] = {IF_DR_3A, IF_DR_3B, IF_DR_3C, IF_DI_2A, IF_DV_3A, IF_DV_3E};
1445 const static insFormat formatEncode5A[5] = {IF_LS_2A, IF_LS_2B, IF_LS_2C, IF_LS_3A, IF_LS_1A};
1446 const static insFormat formatEncode5B[5] = {IF_DV_2G, IF_DV_2H, IF_DV_2I, IF_DV_1A, IF_DV_1B};
1447 const static insFormat formatEncode5C[5] = {IF_DR_3A, IF_DR_3B, IF_DI_2C, IF_DV_3C, IF_DV_1B};
1448 const static insFormat formatEncode4A[4] = {IF_LS_2A, IF_LS_2B, IF_LS_2C, IF_LS_3A};
1449 const static insFormat formatEncode4B[4] = {IF_DR_3A, IF_DR_3B, IF_DR_3C, IF_DI_2A};
1450 const static insFormat formatEncode4C[4] = {IF_DR_2A, IF_DR_2B, IF_DR_2C, IF_DI_1A};
1451 const static insFormat formatEncode4D[4] = {IF_DV_3B, IF_DV_3D, IF_DV_3BI, IF_DV_3DI};
1452 const static insFormat formatEncode4E[4] = {IF_DR_3A, IF_DR_3B, IF_DI_2C, IF_DV_3C};
1453 const static insFormat formatEncode4F[4] = {IF_DR_3A, IF_DR_3B, IF_DV_3C, IF_DV_1B};
1454 const static insFormat formatEncode4G[4] = {IF_DR_2E, IF_DR_2F, IF_DV_2M, IF_DV_2L};
1455 const static insFormat formatEncode4H[4] = {IF_DV_3E, IF_DV_3A, IF_DV_2L, IF_DV_2M};
1456 const static insFormat formatEncode4I[4] = {IF_DV_3D, IF_DV_3B, IF_DV_2G, IF_DV_2A};
1457 const static insFormat formatEncode3A[3] = {IF_DR_3A, IF_DR_3B, IF_DI_2C};
1458 const static insFormat formatEncode3B[3] = {IF_DR_2A, IF_DR_2B, IF_DI_1C};
1459 const static insFormat formatEncode3C[3] = {IF_DR_3A, IF_DR_3B, IF_DV_3C};
1460 const static insFormat formatEncode3D[3] = {IF_DV_2C, IF_DV_2D, IF_DV_2E};
1461 const static insFormat formatEncode3E[3] = {IF_DV_3B, IF_DV_3BI, IF_DV_3DI};
1462 const static insFormat formatEncode3F[3] = {IF_DV_2A, IF_DV_2G, IF_DV_2H};
1463 const static insFormat formatEncode3G[3] = {IF_DV_2A, IF_DV_2G, IF_DV_2I};
1464 const static insFormat formatEncode3H[3] = {IF_DR_3A, IF_DV_3A, IF_DV_3AI};
1465 const static insFormat formatEncode3I[3] = {IF_DR_2E, IF_DR_2F, IF_DV_2M};
1466 const static insFormat formatEncode2A[2] = {IF_DR_2E, IF_DR_2F};
1467 const static insFormat formatEncode2B[2] = {IF_DR_3A, IF_DR_3B};
1468 const static insFormat formatEncode2C[2] = {IF_DR_3A, IF_DI_2D};
1469 const static insFormat formatEncode2D[2] = {IF_DR_3A, IF_DI_2B};
1470 const static insFormat formatEncode2E[2] = {IF_LS_3B, IF_LS_3C};
1471 const static insFormat formatEncode2F[2] = {IF_DR_2I, IF_DI_1F};
1472 const static insFormat formatEncode2G[2] = {IF_DV_3B, IF_DV_3D};
1473 const static insFormat formatEncode2H[2] = {IF_DV_2C, IF_DV_2F};
1474 const static insFormat formatEncode2I[2] = {IF_DV_2K, IF_DV_1C};
1475 const static insFormat formatEncode2J[2] = {IF_DV_2A, IF_DV_2G};
1476 const static insFormat formatEncode2K[2] = {IF_DV_2M, IF_DV_2L};
1477 const static insFormat formatEncode2L[2] = {IF_DV_2G, IF_DV_2M};
1478 const static insFormat formatEncode2M[2] = {IF_DV_3A, IF_DV_3AI};
1479 const static insFormat formatEncode2N[2] = {IF_DV_2N, IF_DV_2O};
1480 const static insFormat formatEncode2O[2] = {IF_DV_3E, IF_DV_3A};
1481 const static insFormat formatEncode2P[2] = {IF_DV_2G, IF_DV_3B};
1483 code_t code = BAD_CODE;
1484 insFormat insFmt = emitInsFormat(ins);
1485 bool encoding_found = false;
1491 for (index = 0; index < 9; index++)
1493 if (fmt == formatEncode9[index])
1495 encoding_found = true;
1502 for (index = 0; index < 6; index++)
1504 if (fmt == formatEncode6A[index])
1506 encoding_found = true;
1513 for (index = 0; index < 5; index++)
1515 if (fmt == formatEncode5A[index])
1517 encoding_found = true;
1524 for (index = 0; index < 5; index++)
1526 if (fmt == formatEncode5B[index])
1528 encoding_found = true;
1535 for (index = 0; index < 5; index++)
1537 if (fmt == formatEncode5C[index])
1539 encoding_found = true;
1546 for (index = 0; index < 4; index++)
1548 if (fmt == formatEncode4A[index])
1550 encoding_found = true;
1557 for (index = 0; index < 4; index++)
1559 if (fmt == formatEncode4B[index])
1561 encoding_found = true;
1568 for (index = 0; index < 4; index++)
1570 if (fmt == formatEncode4C[index])
1572 encoding_found = true;
1579 for (index = 0; index < 4; index++)
1581 if (fmt == formatEncode4D[index])
1583 encoding_found = true;
1590 for (index = 0; index < 4; index++)
1592 if (fmt == formatEncode4E[index])
1594 encoding_found = true;
1601 for (index = 0; index < 4; index++)
1603 if (fmt == formatEncode4F[index])
1605 encoding_found = true;
1612 for (index = 0; index < 4; index++)
1614 if (fmt == formatEncode4G[index])
1616 encoding_found = true;
1623 for (index = 0; index < 4; index++)
1625 if (fmt == formatEncode4H[index])
1627 encoding_found = true;
1634 for (index = 0; index < 4; index++)
1636 if (fmt == formatEncode4I[index])
1638 encoding_found = true;
1645 for (index = 0; index < 3; index++)
1647 if (fmt == formatEncode3A[index])
1649 encoding_found = true;
1656 for (index = 0; index < 3; index++)
1658 if (fmt == formatEncode3B[index])
1660 encoding_found = true;
1667 for (index = 0; index < 3; index++)
1669 if (fmt == formatEncode3C[index])
1671 encoding_found = true;
1678 for (index = 0; index < 3; index++)
1680 if (fmt == formatEncode3D[index])
1682 encoding_found = true;
1689 for (index = 0; index < 3; index++)
1691 if (fmt == formatEncode3E[index])
1693 encoding_found = true;
1700 for (index = 0; index < 3; index++)
1702 if (fmt == formatEncode3F[index])
1704 encoding_found = true;
1711 for (index = 0; index < 3; index++)
1713 if (fmt == formatEncode3G[index])
1715 encoding_found = true;
1722 for (index = 0; index < 3; index++)
1724 if (fmt == formatEncode3H[index])
1726 encoding_found = true;
1733 for (index = 0; index < 3; index++)
1735 if (fmt == formatEncode3I[index])
1737 encoding_found = true;
1744 for (index = 0; index < 2; index++)
1746 if (fmt == formatEncode2A[index])
1748 encoding_found = true;
1755 for (index = 0; index < 2; index++)
1757 if (fmt == formatEncode2B[index])
1759 encoding_found = true;
1766 for (index = 0; index < 2; index++)
1768 if (fmt == formatEncode2C[index])
1770 encoding_found = true;
1777 for (index = 0; index < 2; index++)
1779 if (fmt == formatEncode2D[index])
1781 encoding_found = true;
1788 for (index = 0; index < 2; index++)
1790 if (fmt == formatEncode2E[index])
1792 encoding_found = true;
1799 for (index = 0; index < 2; index++)
1801 if (fmt == formatEncode2F[index])
1803 encoding_found = true;
1810 for (index = 0; index < 2; index++)
1812 if (fmt == formatEncode2G[index])
1814 encoding_found = true;
1821 for (index = 0; index < 2; index++)
1823 if (fmt == formatEncode2H[index])
1825 encoding_found = true;
1832 for (index = 0; index < 2; index++)
1834 if (fmt == formatEncode2I[index])
1836 encoding_found = true;
1843 for (index = 0; index < 2; index++)
1845 if (fmt == formatEncode2J[index])
1847 encoding_found = true;
1854 for (index = 0; index < 2; index++)
1856 if (fmt == formatEncode2K[index])
1858 encoding_found = true;
1865 for (index = 0; index < 2; index++)
1867 if (fmt == formatEncode2L[index])
1869 encoding_found = true;
1876 for (index = 0; index < 2; index++)
1878 if (fmt == formatEncode2M[index])
1880 encoding_found = true;
1887 for (index = 0; index < 2; index++)
1889 if (fmt == formatEncode2N[index])
1891 encoding_found = true;
1898 for (index = 0; index < 2; index++)
1900 if (fmt == formatEncode2O[index])
1902 encoding_found = true;
1909 for (index = 0; index < 2; index++)
1911 if (fmt == formatEncode2P[index])
1913 encoding_found = true;
1992 encoding_found = true;
1997 encoding_found = false;
2001 assert(encoding_found);
2006 assert(ins < ArrLen(insCodes1));
2007 code = insCodes1[ins];
2010 assert(ins < ArrLen(insCodes2));
2011 code = insCodes2[ins];
2014 assert(ins < ArrLen(insCodes3));
2015 code = insCodes3[ins];
2018 assert(ins < ArrLen(insCodes4));
2019 code = insCodes4[ins];
2022 assert(ins < ArrLen(insCodes5));
2023 code = insCodes5[ins];
2026 assert(ins < ArrLen(insCodes6));
2027 code = insCodes6[ins];
2030 assert(ins < ArrLen(insCodes7));
2031 code = insCodes7[ins];
2034 assert(ins < ArrLen(insCodes8));
2035 code = insCodes8[ins];
2038 assert(ins < ArrLen(insCodes9));
2039 code = insCodes9[ins];
2043 assert((code != BAD_CODE));
2048 // true if this 'imm' can be encoded as a input operand to a mov instruction
2049 /*static*/ bool emitter::emitIns_valid_imm_for_mov(INT64 imm, emitAttr size)
2051 // Check for "MOV (wide immediate)".
2052 if (canEncodeHalfwordImm(imm, size))
2055 // Next try the ones-complement form of 'halfword immediate' imm(i16,hw),
2056 // namely "MOV (inverted wide immediate)".
2057 ssize_t notOfImm = NOT_helper(imm, getBitWidth(size));
2058 if (canEncodeHalfwordImm(notOfImm, size))
2061 // Finally try "MOV (bitmask immediate)" imm(N,r,s)
2062 if (canEncodeBitMaskImm(imm, size))
2068 // true if this 'imm' can be encoded as a input operand to a vector movi instruction
2069 /*static*/ bool emitter::emitIns_valid_imm_for_movi(INT64 imm, emitAttr elemsize)
2071 if (elemsize == EA_8BYTE)
2076 INT64 loByte = uimm & 0xFF;
2077 if ((loByte == 0) || (loByte == 0xFF))
2091 // First try the standard 'byteShifted immediate' imm(i8,bySh)
2092 if (canEncodeByteShiftedImm(imm, elemsize, true))
2095 // Next try the ones-complement form of the 'immediate' imm(i8,bySh)
2096 ssize_t notOfImm = NOT_helper(imm, getBitWidth(elemsize));
2097 if (canEncodeByteShiftedImm(notOfImm, elemsize, true))
2103 // true if this 'imm' can be encoded as a input operand to a fmov instruction
2104 /*static*/ bool emitter::emitIns_valid_imm_for_fmov(double immDbl)
2106 if (canEncodeFloatImm8(immDbl))
2112 // true if this 'imm' can be encoded as a input operand to an add instruction
2113 /*static*/ bool emitter::emitIns_valid_imm_for_add(INT64 imm, emitAttr size)
2115 if (unsigned_abs(imm) <= 0x0fff)
2117 else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
2123 // true if this 'imm' can be encoded as a input operand to an non-add/sub alu instruction
2124 /*static*/ bool emitter::emitIns_valid_imm_for_cmp(INT64 imm, emitAttr size)
2126 return emitIns_valid_imm_for_add(imm, size);
2129 // true if this 'imm' can be encoded as a input operand to an non-add/sub alu instruction
2130 /*static*/ bool emitter::emitIns_valid_imm_for_alu(INT64 imm, emitAttr size)
2132 if (canEncodeBitMaskImm(imm, size))
2138 // true if this 'imm' can be encoded as the offset in a ldr/str instruction
2139 /*static*/ bool emitter::emitIns_valid_imm_for_ldst_offset(INT64 imm, emitAttr attr)
2142 return true; // Encodable using IF_LS_2A
2144 if ((imm >= -256) && (imm <= 255))
2145 return true; // Encodable using IF_LS_2C (or possibly IF_LS_2B)
2148 return false; // not encodable
2150 emitAttr size = EA_SIZE(attr);
2151 unsigned scale = NaturalScale_helper(size);
2152 ssize_t mask = size - 1; // the mask of low bits that must be zero to encode the immediate
2154 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
2155 return true; // Encodable using IF_LS_2B
2157 return false; // not encodable
2160 /************************************************************************
2162 * A helper method to return the natural scale for an EA 'size'
2165 /*static*/ unsigned emitter::NaturalScale_helper(emitAttr size)
2167 assert(size == EA_1BYTE || size == EA_2BYTE || size == EA_4BYTE || size == EA_8BYTE || size == EA_16BYTE);
2169 unsigned result = 0;
2170 unsigned utemp = (unsigned)size;
2172 // Compute log base 2 of utemp (aka 'size')
2182 /************************************************************************
2184 * A helper method to perform a Rotate-Right shift operation
2185 * the source is 'value' and it is rotated right by 'sh' bits
2186 * 'value' is considered to be a fixed size 'width' set of bits.
2189 * value is '00001111', sh is 2 and width is 8
2190 * result is '11000011'
2193 /*static*/ UINT64 emitter::ROR_helper(UINT64 value, unsigned sh, unsigned width)
2195 assert(width <= 64);
2196 // Check that 'value' fits in 'width' bits
2197 assert((width == 64) || (value < (1ULL << width)));
2198 // We don't support shifts >= width
2204 unsigned lsh = width - rsh;
2206 result = (value >> rsh);
2207 result |= (value << lsh);
2211 // mask off any extra bits that we got from the left shift
2212 result &= ((1ULL << width) - 1);
2216 /************************************************************************
2218 * A helper method to perform a 'NOT' bitwise complement operation.
2219 * 'value' is considered to be a fixed size 'width' set of bits.
2222 * value is '01001011', and width is 8
2223 * result is '10110100'
2226 /*static*/ UINT64 emitter::NOT_helper(UINT64 value, unsigned width)
2228 assert(width <= 64);
2230 UINT64 result = ~value;
2234 // Check that 'value' fits in 'width' bits. Don't consider "sign" bits above width.
2235 UINT64 maxVal = 1ULL << width;
2236 UINT64 lowBitsMask = maxVal - 1;
2237 UINT64 signBitsMask = ~lowBitsMask | (1ULL << (width - 1)); // The high bits must be set, and the top bit
2238 // (sign bit) must be set.
2239 assert((value < maxVal) || ((value & signBitsMask) == signBitsMask));
2241 // mask off any extra bits that we got from the complement operation
2242 result &= lowBitsMask;
2248 /************************************************************************
2250 * A helper method to perform a bit Replicate operation
2251 * the source is 'value' with a fixed size 'width' set of bits.
2252 * value is replicated to fill out 32 or 64 bits as determined by 'size'.
2255 * value is '11000011' (0xE3), width is 8 and size is EA_8BYTE
2256 * result is '11000011 11000011 11000011 11000011 11000011 11000011 11000011 11000011'
2257 * 0xE3E3E3E3E3E3E3E3
2260 /*static*/ UINT64 emitter::Replicate_helper(UINT64 value, unsigned width, emitAttr size)
2262 assert(emitter::isValidGeneralDatasize(size));
2264 unsigned immWidth = (size == EA_8BYTE) ? 64 : 32;
2265 assert(width <= immWidth);
2267 UINT64 result = value;
2268 unsigned filledBits = width;
2270 while (filledBits < immWidth)
2274 filledBits += width;
2279 /************************************************************************
2281 * Convert an imm(N,r,s) into a 64-bit immediate
2282 * inputs 'bmImm' a bitMaskImm struct
2283 * 'size' specifies the size of the result (64 or 32 bits)
2286 /*static*/ INT64 emitter::emitDecodeBitMaskImm(const emitter::bitMaskImm bmImm, emitAttr size)
2288 assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2290 unsigned N = bmImm.immN; // read the N,R and S values from the 'bitMaskImm' encoding
2291 unsigned R = bmImm.immR;
2292 unsigned S = bmImm.immS;
2294 unsigned elemWidth = 64; // used when immN == 1
2296 if (bmImm.immN == 0) // find the smaller elemWidth when immN == 0
2298 // Scan S for the highest bit not set
2300 for (unsigned bitNum = 5; bitNum > 0; bitNum--)
2302 unsigned oneBit = elemWidth;
2303 if ((S & oneBit) == 0)
2310 assert(size == EA_8BYTE);
2313 unsigned maskSR = elemWidth - 1;
2318 // encoding for S is one less than the number of consecutive one bits
2319 S++; // Number of consecutive ones to generate in 'welem'
2323 // 'elemWidth' is the number of bits that we will use for the ROR and Replicate operations
2324 // 'S' is the number of consecutive 1 bits for the immediate
2325 // 'R' is the number of bits that we will Rotate Right the immediate
2326 // 'size' selects the final size of the immedate that we return (64 or 32 bits)
2328 assert(S < elemWidth); // 'elemWidth' consecutive one's is a reserved encoding
2333 welem = (1ULL << S) - 1;
2335 wmask = ROR_helper(welem, R, elemWidth);
2336 wmask = Replicate_helper(wmask, elemWidth, size);
2341 /*****************************************************************************
2343 * Check if an immediate can use the left shifted by 12 bits encoding
2346 /*static*/ bool emitter::canEncodeWithShiftImmBy12(INT64 imm)
2350 imm = -imm; // convert to unsigned
2355 return false; // Must be MIN_INT64
2358 if ((imm & 0xfff) != 0) // Now the low 12 bits all have to be zero
2363 imm >>= 12; // shift right by 12 bits
2365 return (imm <= 0x0fff); // Does it fit in 12 bits
2368 /*****************************************************************************
2370 * Normalize the 'imm' so that the upper bits, as defined by 'size' are zero
2373 /*static*/ INT64 emitter::normalizeImm64(INT64 imm, emitAttr size)
2375 unsigned immWidth = getBitWidth(size);
2380 // Check that 'imm' fits in 'immWidth' bits. Don't consider "sign" bits above width.
2381 INT64 maxVal = 1LL << immWidth;
2382 INT64 lowBitsMask = maxVal - 1;
2383 INT64 hiBitsMask = ~lowBitsMask;
2384 INT64 signBitsMask =
2385 hiBitsMask | (1LL << (immWidth - 1)); // The high bits must be set, and the top bit (sign bit) must be set.
2386 assert((imm < maxVal) || ((imm & signBitsMask) == signBitsMask));
2388 // mask off the hiBits
2389 result &= lowBitsMask;
2394 /*****************************************************************************
2396 * Normalize the 'imm' so that the upper bits, as defined by 'size' are zero
2399 /*static*/ INT32 emitter::normalizeImm32(INT32 imm, emitAttr size)
2401 unsigned immWidth = getBitWidth(size);
2406 // Check that 'imm' fits in 'immWidth' bits. Don't consider "sign" bits above width.
2407 INT32 maxVal = 1 << immWidth;
2408 INT32 lowBitsMask = maxVal - 1;
2409 INT32 hiBitsMask = ~lowBitsMask;
2410 INT32 signBitsMask = hiBitsMask | (1 << (immWidth - 1)); // The high bits must be set, and the top bit
2411 // (sign bit) must be set.
2412 assert((imm < maxVal) || ((imm & signBitsMask) == signBitsMask));
2414 // mask off the hiBits
2415 result &= lowBitsMask;
2420 /************************************************************************
2422 * returns true if 'imm' of 'size bits (32/64) can be encoded
2423 * using the ARM64 'bitmask immediate' form.
2424 * When a non-null value is passed for 'wbBMI' then this method
2425 * writes back the 'N','S' and 'R' values use to encode this immediate
2429 /*static*/ bool emitter::canEncodeBitMaskImm(INT64 imm, emitAttr size, emitter::bitMaskImm* wbBMI)
2431 assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2433 unsigned immWidth = (size == EA_8BYTE) ? 64 : 32;
2434 unsigned maxLen = (size == EA_8BYTE) ? 6 : 5;
2436 imm = normalizeImm64(imm, size);
2438 // Starting with len=1, elemWidth is 2 bits
2439 // len=2, elemWidth is 4 bits
2440 // len=3, elemWidth is 8 bits
2441 // len=4, elemWidth is 16 bits
2442 // len=5, elemWidth is 32 bits
2443 // (optionally) len=6, elemWidth is 64 bits
2445 for (unsigned len = 1; (len <= maxLen); len++)
2447 unsigned elemWidth = 1 << len;
2448 UINT64 elemMask = ((UINT64)-1) >> (64 - elemWidth);
2449 UINT64 tempImm = (UINT64)imm; // A working copy of 'imm' that we can mutate
2450 UINT64 elemVal = tempImm & elemMask; // The low 'elemWidth' bits of 'imm'
2452 // Check for all 1's or 0's as these can't be encoded
2453 if ((elemVal == 0) || (elemVal == elemMask))
2456 // 'checkedBits' is the count of bits that are known to match 'elemVal' when replicated
2457 unsigned checkedBits = elemWidth; // by definition the first 'elemWidth' bits match
2459 // Now check to see if each of the next bits match...
2461 while (checkedBits < immWidth)
2463 tempImm >>= elemWidth;
2465 UINT64 nextElem = tempImm & elemMask;
2466 if (nextElem != elemVal)
2468 // Not matching, exit this loop and checkedBits will not be equal to immWidth
2472 // The 'nextElem' is matching, so increment 'checkedBits'
2473 checkedBits += elemWidth;
2476 // Did the full immediate contain bits that can be formed by repeating 'elemVal'?
2477 if (checkedBits == immWidth)
2479 // We are not quite done, since the only values that we can encode as a
2480 // 'bitmask immediate' are those that can be formed by starting with a
2481 // bit string of 0*1* that is rotated by some number of bits.
2483 // We check to see if 'elemVal' can be formed using these restrictions.
2486 // Rotating by one bit any value that passes these restrictions
2487 // can be xor-ed with the original value and will result it a string
2488 // of bits that have exactly two 1 bits: 'elemRorXor'
2489 // Further the distance between the two one bits tells us the value
2490 // of S and the location of the 1 bits tells us the value of R
2492 // Some examples: (immWidth is 8)
2494 // S=4,R=0 S=5,R=3 S=3,R=6
2495 // elemVal: 00001111 11100011 00011100
2496 // elemRor: 10000111 11110001 00001110
2497 // elemRorXor: 10001000 00010010 00010010
2498 // compute S 45678--- ---5678- ---3210-
2499 // compute R 01234567 ---34567 ------67
2501 UINT64 elemRor = ROR_helper(elemVal, 1, elemWidth); // Rotate 'elemVal' Right by one bit
2502 UINT64 elemRorXor = elemVal ^ elemRor; // Xor elemVal and elemRor
2504 // If we only have a two-bit change in elemROR then we can form a mask for this value
2505 unsigned bitCount = 0;
2506 UINT64 oneBit = 0x1;
2507 unsigned R = elemWidth; // R is shift count for ROR (rotate right shift)
2508 unsigned S = 0; // S is number of consecutive one bits
2511 // Loop over the 'elemWidth' bits in 'elemRorXor'
2513 for (unsigned bitNum = 0; bitNum < elemWidth; bitNum++)
2517 R--; // We decrement R by one whenever incr is -1
2521 S += incr; // We incr/decr S, after we find the first one bit in 'elemRorXor'
2524 // Is this bit position a 1 bit in 'elemRorXor'?
2526 if (oneBit & elemRorXor)
2529 // Is this the first 1 bit that we found in 'elemRorXor'?
2532 // Does this 1 bit represent a transition to zero bits?
2533 bool toZeros = ((oneBit & elemVal) != 0);
2536 // S :: Count down from elemWidth
2540 else // this 1 bit represent a transition to one bits.
2542 // S :: Count up from zero
2547 else // bitCount > 1
2549 // We found the second (or third...) 1 bit in 'elemRorXor'
2550 incr = 0; // stop decrementing 'R'
2554 // More than 2 transitions from 0/1 in 'elemVal'
2555 // This means that 'elemVal' can't be encoded
2556 // using a 'bitmask immediate'.
2558 // Furthermore, it will continue to fail
2559 // with any larger 'len' that we try.
2560 // so just return false.
2567 // shift oneBit left by one bit to test the next position
2571 // We expect that bitCount will always be two at this point
2572 // but just in case return false for any bad cases.
2574 assert(bitCount == 2);
2578 // Perform some sanity checks on the values of 'S' and 'R'
2580 assert(S < elemWidth);
2581 assert(R < elemWidth);
2583 // Does the caller want us to return the N,R,S encoding values?
2585 if (wbBMI != nullptr)
2588 // The encoding used for S is one less than the
2589 // number of consecutive one bits
2599 // The encoding used for 'S' here is a bit peculiar.
2601 // The upper bits need to be complemented, followed by a zero bit
2602 // then the value of 'S-1'
2604 unsigned upperBitsOfS = 64 - (1 << (len + 1));
2610 // Verify that what we are returning is correct.
2611 assert(imm == emitDecodeBitMaskImm(*wbBMI, size));
2613 // Tell the caller that we can successfully encode this immediate
2614 // using a 'bitmask immediate'.
2622 /************************************************************************
2624 * Convert a 64-bit immediate into its 'bitmask immediate' representation imm(N,r,s)
2627 /*static*/ emitter::bitMaskImm emitter::emitEncodeBitMaskImm(INT64 imm, emitAttr size)
2629 emitter::bitMaskImm result;
2632 bool canEncode = canEncodeBitMaskImm(imm, size, &result);
2638 /************************************************************************
2640 * Convert an imm(i16,hw) into a 32/64-bit immediate
2641 * inputs 'hwImm' a halfwordImm struct
2642 * 'size' specifies the size of the result (64 or 32 bits)
2645 /*static*/ INT64 emitter::emitDecodeHalfwordImm(const emitter::halfwordImm hwImm, emitAttr size)
2647 assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2649 unsigned hw = hwImm.immHW;
2650 INT64 val = (INT64)hwImm.immVal;
2652 assert((hw <= 1) || (size == EA_8BYTE));
2654 INT64 result = val << (16 * hw);
2658 /************************************************************************
2660 * returns true if 'imm' of 'size' bits (32/64) can be encoded
2661 * using the ARM64 'halfword immediate' form.
2662 * When a non-null value is passed for 'wbHWI' then this method
2663 * writes back the 'immHW' and 'immVal' values use to encode this immediate
2667 /*static*/ bool emitter::canEncodeHalfwordImm(INT64 imm, emitAttr size, emitter::halfwordImm* wbHWI)
2669 assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2671 unsigned immWidth = (size == EA_8BYTE) ? 64 : 32;
2672 unsigned maxHW = (size == EA_8BYTE) ? 4 : 2;
2674 // setup immMask to a (EA_4BYTE) 0x00000000_FFFFFFFF or (EA_8BYTE) 0xFFFFFFFF_FFFFFFFF
2675 const UINT64 immMask = ((UINT64)-1) >> (64 - immWidth);
2676 const INT64 mask16 = (INT64)0xFFFF;
2678 imm = normalizeImm64(imm, size);
2680 // Try each of the valid hw shift sizes
2681 for (unsigned hw = 0; (hw < maxHW); hw++)
2683 INT64 curMask = mask16 << (hw * 16); // Represents the mask of the bits in the current halfword
2684 INT64 checkBits = immMask & ~curMask;
2686 // Excluding the current halfword (using ~curMask)
2687 // does the immediate have zero bits in every other bit that we care about?
2688 // note we care about all 64-bits for EA_8BYTE
2689 // and we care about the lowest 32 bits for EA_4BYTE
2691 if ((imm & checkBits) == 0)
2693 // Does the caller want us to return the imm(i16,hw) encoding values?
2695 if (wbHWI != nullptr)
2697 INT64 val = ((imm & curMask) >> (hw * 16)) & mask16;
2699 wbHWI->immVal = val;
2701 // Verify that what we are returning is correct.
2702 assert(imm == emitDecodeHalfwordImm(*wbHWI, size));
2704 // Tell the caller that we can successfully encode this immediate
2705 // using a 'halfword immediate'.
2713 /************************************************************************
2715 * Convert a 64-bit immediate into its 'halfword immediate' representation imm(i16,hw)
2718 /*static*/ emitter::halfwordImm emitter::emitEncodeHalfwordImm(INT64 imm, emitAttr size)
2720 emitter::halfwordImm result;
2721 result.immHWVal = 0;
2723 bool canEncode = canEncodeHalfwordImm(imm, size, &result);
2729 /************************************************************************
2731 * Convert an imm(i8,sh) into a 16/32-bit immediate
2732 * inputs 'bsImm' a byteShiftedImm struct
2733 * 'size' specifies the size of the result (16 or 32 bits)
2736 /*static*/ INT32 emitter::emitDecodeByteShiftedImm(const emitter::byteShiftedImm bsImm, emitAttr size)
2738 bool onesShift = (bsImm.immOnes == 1);
2739 unsigned bySh = bsImm.immBY; // Num Bytes to shift 0,1,2,3
2740 INT32 val = (INT32)bsImm.immVal; // 8-bit immediate
2745 assert((size == EA_2BYTE) || (size == EA_4BYTE)); // Only EA_2BYTE or EA_4BYTE forms
2746 if (size == EA_2BYTE)
2755 result <<= (8 * bySh);
2759 result |= ((1 << (8 * bySh)) - 1);
2765 /************************************************************************
2767 * returns true if 'imm' of 'size' bits (16/32) can be encoded
2768 * using the ARM64 'byteShifted immediate' form.
2769 * When a non-null value is passed for 'wbBSI' then this method
2770 * writes back the 'immBY' and 'immVal' values use to encode this immediate
2774 /*static*/ bool emitter::canEncodeByteShiftedImm(INT64 imm,
2777 emitter::byteShiftedImm* wbBSI)
2779 bool canEncode = false;
2780 bool onesShift = false; // true if we use the shifting ones variant
2781 unsigned bySh = 0; // number of bytes to shift: 0, 1, 2, 3
2782 unsigned imm8 = 0; // immediate to use in the encoding
2784 imm = normalizeImm64(imm, size);
2786 if (size == EA_1BYTE)
2788 imm8 = (unsigned)imm;
2789 assert(imm8 < 0x100);
2792 else if (size == EA_8BYTE)
2794 imm8 = (unsigned)imm;
2795 assert(imm8 < 0x100);
2800 assert((size == EA_2BYTE) || (size == EA_4BYTE)); // Only EA_2BYTE or EA_4BYTE forms
2802 unsigned immWidth = (size == EA_4BYTE) ? 32 : 16;
2803 unsigned maxBY = (size == EA_4BYTE) ? 4 : 2;
2805 // setup immMask to a (EA_2BYTE) 0x0000FFFF or (EA_4BYTE) 0xFFFFFFFF
2806 const UINT32 immMask = ((UINT32)-1) >> (32 - immWidth);
2807 const INT32 mask8 = (INT32)0xFF;
2809 // Try each of the valid by shift sizes
2810 for (bySh = 0; (bySh < maxBY); bySh++)
2812 INT32 curMask = mask8 << (bySh * 8); // Represents the mask of the bits in the current byteShifted
2813 INT32 checkBits = immMask & ~curMask;
2814 INT32 immCheck = (imm & checkBits);
2816 // Excluding the current byte (using ~curMask)
2817 // does the immediate have zero bits in every other bit that we care about?
2818 // or can be use the shifted one variant?
2819 // note we care about all 32-bits for EA_4BYTE
2820 // and we care about the lowest 16 bits for EA_2BYTE
2828 if ((bySh == 1) && (immCheck == 0xFF))
2833 else if ((bySh == 2) && (immCheck == 0xFFFF))
2841 imm8 = (unsigned)(((imm & curMask) >> (bySh * 8)) & mask8);
2849 // Does the caller want us to return the imm(i8,bySh) encoding values?
2851 if (wbBSI != nullptr)
2853 wbBSI->immOnes = onesShift;
2854 wbBSI->immBY = bySh;
2855 wbBSI->immVal = imm8;
2857 // Verify that what we are returning is correct.
2858 assert(imm == emitDecodeByteShiftedImm(*wbBSI, size));
2860 // Tell the caller that we can successfully encode this immediate
2861 // using a 'byteShifted immediate'.
2868 /************************************************************************
2870 * Convert a 32-bit immediate into its 'byteShifted immediate' representation imm(i8,by)
2873 /*static*/ emitter::byteShiftedImm emitter::emitEncodeByteShiftedImm(INT64 imm, emitAttr size, bool allow_MSL)
2875 emitter::byteShiftedImm result;
2876 result.immBSVal = 0;
2878 bool canEncode = canEncodeByteShiftedImm(imm, size, allow_MSL, &result);
2884 /************************************************************************
2886 * Convert a 'float 8-bit immediate' into a double.
2887 * inputs 'fpImm' a floatImm8 struct
2890 /*static*/ double emitter::emitDecodeFloatImm8(const emitter::floatImm8 fpImm)
2892 unsigned sign = fpImm.immSign;
2893 unsigned exp = fpImm.immExp ^ 0x4;
2894 unsigned mant = fpImm.immMant + 16;
2895 unsigned scale = 16 * 8;
2903 double result = ((double)mant) / ((double)scale);
2912 /************************************************************************
2914 * returns true if the 'immDbl' can be encoded using the 'float 8-bit immediate' form.
2915 * also returns the encoding if wbFPI is non-null
2919 /*static*/ bool emitter::canEncodeFloatImm8(double immDbl, emitter::floatImm8* wbFPI)
2921 bool canEncode = false;
2922 double val = immDbl;
2932 while ((val < 1.0) && (exp >= -4))
2937 while ((val >= 2.0) && (exp <= 5))
2944 int ival = (int)val;
2946 if ((exp >= 0) && (exp <= 7))
2948 if (val == (double)ival)
2952 if (wbFPI != nullptr)
2955 assert((ival >= 0) && (ival <= 15));
2957 wbFPI->immSign = sign;
2958 wbFPI->immExp = exp ^ 0x4;
2959 wbFPI->immMant = ival;
2960 unsigned imm8 = wbFPI->immFPIVal;
2961 assert((imm8 >= 0) && (imm8 <= 0xff));
2969 /************************************************************************
2971 * Convert a double into its 'float 8-bit immediate' representation
2974 /*static*/ emitter::floatImm8 emitter::emitEncodeFloatImm8(double immDbl)
2976 emitter::floatImm8 result;
2977 result.immFPIVal = 0;
2979 bool canEncode = canEncodeFloatImm8(immDbl, &result);
2985 /*****************************************************************************
2987 * For the given 'ins' returns the reverse instruction
2988 * if one exists, otherwise returns INS_INVALID
2991 /*static*/ instruction emitter::insReverse(instruction ins)
3020 /*****************************************************************************
3022 * For the given 'datasize' and 'elemsize', make the proper arrangement option
3023 * returns the insOpts that specifies the vector register arrangement
3024 * if one does not exist returns INS_OPTS_NONE
3027 /*static*/ insOpts emitter::optMakeArrangement(emitAttr datasize, emitAttr elemsize)
3029 insOpts result = INS_OPTS_NONE;
3031 if (datasize == EA_8BYTE)
3036 result = INS_OPTS_8B;
3039 result = INS_OPTS_4H;
3042 result = INS_OPTS_2S;
3045 result = INS_OPTS_1D;
3052 else if (datasize == EA_16BYTE)
3057 result = INS_OPTS_16B;
3060 result = INS_OPTS_8H;
3063 result = INS_OPTS_4S;
3066 result = INS_OPTS_2D;
3076 /*****************************************************************************
3078 * For the given 'datasize' and arrangement 'opts'
3079 * returns true is the pair spcifies a valid arrangement
3081 /*static*/ bool emitter::isValidArrangement(emitAttr datasize, insOpts opt)
3083 if (datasize == EA_8BYTE)
3085 if ((opt == INS_OPTS_8B) || (opt == INS_OPTS_4H) || (opt == INS_OPTS_2S) || (opt == INS_OPTS_1D))
3090 else if (datasize == EA_16BYTE)
3092 if ((opt == INS_OPTS_16B) || (opt == INS_OPTS_8H) || (opt == INS_OPTS_4S) || (opt == INS_OPTS_2D))
3100 // For the given 'arrangement' returns the 'datasize' specified by the vector register arrangement
3101 // asserts and returns EA_UNKNOWN if an invalid 'arrangement' value is passed
3103 /*static*/ emitAttr emitter::optGetDatasize(insOpts arrangement)
3105 if ((arrangement == INS_OPTS_8B) || (arrangement == INS_OPTS_4H) || (arrangement == INS_OPTS_2S) ||
3106 (arrangement == INS_OPTS_1D))
3110 else if ((arrangement == INS_OPTS_16B) || (arrangement == INS_OPTS_8H) || (arrangement == INS_OPTS_4S) ||
3111 (arrangement == INS_OPTS_2D))
3117 assert(!" invalid 'arrangement' value");
3122 // For the given 'arrangement' returns the 'elemsize' specified by the vector register arrangement
3123 // asserts and returns EA_UNKNOWN if an invalid 'arrangement' value is passed
3125 /*static*/ emitAttr emitter::optGetElemsize(insOpts arrangement)
3127 if ((arrangement == INS_OPTS_8B) || (arrangement == INS_OPTS_16B))
3131 else if ((arrangement == INS_OPTS_4H) || (arrangement == INS_OPTS_8H))
3135 else if ((arrangement == INS_OPTS_2S) || (arrangement == INS_OPTS_4S))
3139 else if ((arrangement == INS_OPTS_1D) || (arrangement == INS_OPTS_2D))
3145 assert(!" invalid 'arrangement' value");
3150 // For the given 'arrangement' returns the 'widen-arrangement' specified by the vector register arrangement
3151 // asserts and returns INS_OPTS_NONE if an invalid 'arrangement' value is passed
3153 /*static*/ insOpts emitter::optWidenElemsize(insOpts arrangement)
3155 if ((arrangement == INS_OPTS_8B) || (arrangement == INS_OPTS_16B))
3159 else if ((arrangement == INS_OPTS_4H) || (arrangement == INS_OPTS_8H))
3163 else if ((arrangement == INS_OPTS_2S) || (arrangement == INS_OPTS_4S))
3169 assert(!" invalid 'arrangement' value");
3170 return INS_OPTS_NONE;
3174 // For the given 'conversion' returns the 'dstsize' specified by the conversion option
3175 /*static*/ emitAttr emitter::optGetDstsize(insOpts conversion)
3179 case INS_OPTS_S_TO_8BYTE:
3180 case INS_OPTS_D_TO_8BYTE:
3181 case INS_OPTS_4BYTE_TO_D:
3182 case INS_OPTS_8BYTE_TO_D:
3183 case INS_OPTS_S_TO_D:
3184 case INS_OPTS_H_TO_D:
3188 case INS_OPTS_S_TO_4BYTE:
3189 case INS_OPTS_D_TO_4BYTE:
3190 case INS_OPTS_4BYTE_TO_S:
3191 case INS_OPTS_8BYTE_TO_S:
3192 case INS_OPTS_D_TO_S:
3193 case INS_OPTS_H_TO_S:
3197 case INS_OPTS_S_TO_H:
3198 case INS_OPTS_D_TO_H:
3203 assert(!" invalid 'conversion' value");
3208 // For the given 'conversion' returns the 'srcsize' specified by the conversion option
3209 /*static*/ emitAttr emitter::optGetSrcsize(insOpts conversion)
3213 case INS_OPTS_D_TO_8BYTE:
3214 case INS_OPTS_D_TO_4BYTE:
3215 case INS_OPTS_8BYTE_TO_D:
3216 case INS_OPTS_8BYTE_TO_S:
3217 case INS_OPTS_D_TO_S:
3218 case INS_OPTS_D_TO_H:
3222 case INS_OPTS_S_TO_8BYTE:
3223 case INS_OPTS_S_TO_4BYTE:
3224 case INS_OPTS_4BYTE_TO_S:
3225 case INS_OPTS_4BYTE_TO_D:
3226 case INS_OPTS_S_TO_D:
3227 case INS_OPTS_S_TO_H:
3231 case INS_OPTS_H_TO_S:
3232 case INS_OPTS_H_TO_D:
3237 assert(!" invalid 'conversion' value");
3242 // For the given 'size' and 'index' returns true if it specifies a valid index for a vector register of 'size'
3243 /*static*/ bool emitter::isValidVectorIndex(emitAttr datasize, emitAttr elemsize, ssize_t index)
3245 assert(isValidVectorDatasize(datasize));
3246 assert(isValidVectorElemsize(elemsize));
3248 bool result = false;
3251 if (datasize == EA_8BYTE)
3256 result = (index < 8);
3259 result = (index < 4);
3262 result = (index < 2);
3265 result = (index < 1);
3272 else if (datasize == EA_16BYTE)
3277 result = (index < 16);
3280 result = (index < 8);
3283 result = (index < 4);
3286 result = (index < 2);
3297 /*****************************************************************************
3299 * Add an instruction with no operands.
3302 void emitter::emitIns(instruction ins)
3304 instrDesc* id = emitNewInstrSmall(EA_8BYTE);
3305 insFormat fmt = emitInsFormat(ins);
3307 assert(fmt == IF_SN_0A);
3316 /*****************************************************************************
3318 * Add an instruction with a single immediate value.
3321 void emitter::emitIns_I(instruction ins, emitAttr attr, ssize_t imm)
3323 insFormat fmt = IF_NONE;
3325 /* Figure out the encoding format of the instruction */
3329 if ((imm & 0x0000ffff) == imm)
3335 assert(!"Instruction cannot be encoded: IF_SI_0A");
3342 assert(fmt != IF_NONE);
3344 instrDesc* id = emitNewInstrSC(attr, imm);
3353 /*****************************************************************************
3355 * Add an instruction referencing a single register.
3358 void emitter::emitIns_R(instruction ins, emitAttr attr, regNumber reg)
3360 emitAttr size = EA_SIZE(attr);
3361 insFormat fmt = IF_NONE;
3362 instrDesc* id = nullptr;
3364 /* Figure out the encoding format of the instruction */
3369 assert(isGeneralRegister(reg));
3370 id = emitNewInstrSmall(attr);
3379 assert(fmt != IF_NONE);
3388 /*****************************************************************************
3390 * Add an instruction referencing a register and a constant.
3393 void emitter::emitIns_R_I(instruction ins, emitAttr attr, regNumber reg, ssize_t imm, insOpts opt /* = INS_OPTS_NONE */)
3395 emitAttr size = EA_SIZE(attr);
3396 emitAttr elemsize = EA_UNKNOWN;
3397 insFormat fmt = IF_NONE;
3398 bool canEncode = false;
3400 /* Figure out the encoding format of the instruction */
3409 assert(insOptsNone(opt));
3410 assert(isGeneralRegister(reg));
3412 canEncode = canEncodeBitMaskImm(imm, size, &bmi);
3416 assert(isValidImmNRS(imm, size));
3424 assert(isValidGeneralDatasize(size));
3425 assert(insOptsNone(opt)); // No LSL here (you must use emitIns_R_I_I if a shift is needed)
3426 assert(isGeneralRegister(reg));
3427 assert(isValidUimm16(imm));
3431 assert(imm == emitDecodeHalfwordImm(hwi, size));
3439 assert(isValidGeneralDatasize(size));
3440 assert(insOptsNone(opt)); // No explicit LSL here
3441 // We will automatically determine the shift based upon the imm
3443 // First try the standard 'halfword immediate' imm(i16,hw)
3445 canEncode = canEncodeHalfwordImm(imm, size, &hwi);
3448 // uses a movz encoding
3449 assert(isGeneralRegister(reg));
3451 assert(isValidImmHWVal(imm, size));
3456 // Next try the ones-complement form of 'halfword immediate' imm(i16,hw)
3457 notOfImm = NOT_helper(imm, getBitWidth(size));
3458 canEncode = canEncodeHalfwordImm(notOfImm, size, &hwi);
3461 assert(isGeneralRegister(reg));
3463 ins = INS_movn; // uses a movn encoding
3464 assert(isValidImmHWVal(imm, size));
3469 // Finally try the 'bitmask immediate' imm(N,r,s)
3471 canEncode = canEncodeBitMaskImm(imm, size, &bmi);
3474 assert(isGeneralRegisterOrSP(reg));
3475 reg = encodingSPtoZR(reg);
3477 assert(isValidImmNRS(imm, size));
3483 assert(!"Instruction cannot be encoded: mov imm");
3489 assert(isValidVectorDatasize(size));
3490 assert(isVectorRegister(reg));
3491 if (insOptsNone(opt) && (size == EA_8BYTE))
3495 assert(isValidArrangement(size, opt));
3496 elemsize = optGetElemsize(opt);
3498 if (elemsize == EA_8BYTE)
3504 bool failed = false;
3507 INT64 loByte = uimm & 0xFF;
3508 if (((loByte == 0) || (loByte == 0xFF)) && (pos < 8))
3524 assert(isValidUimm8(imm));
3532 // No explicit LSL/MSL is used for the immediate
3533 // We will automatically determine the shift based upon the value of imm
3535 // First try the standard 'byteShifted immediate' imm(i8,bySh)
3537 canEncode = canEncodeByteShiftedImm(imm, elemsize, true, &bsi);
3541 assert(isValidImmBSVal(imm, size));
3546 // Next try the ones-complement form of the 'immediate' imm(i8,bySh)
3547 if ((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE)) // Only EA_2BYTE or EA_4BYTE forms
3549 notOfImm = NOT_helper(imm, getBitWidth(elemsize));
3550 canEncode = canEncodeByteShiftedImm(notOfImm, elemsize, true, &bsi);
3554 ins = INS_mvni; // uses a mvni encoding
3555 assert(isValidImmBSVal(imm, size));
3566 assert(isValidVectorDatasize(size));
3567 assert(isVectorRegister(reg));
3568 assert(isValidArrangement(size, opt));
3569 elemsize = optGetElemsize(opt);
3570 assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE)); // Only EA_2BYTE or EA_4BYTE forms
3574 // No explicit LSL/MSL is used for the immediate
3575 // We will automatically determine the shift based upon the value of imm
3577 // First try the standard 'byteShifted immediate' imm(i8,bySh)
3579 canEncode = canEncodeByteShiftedImm(imm, elemsize,
3580 (ins == INS_mvni), // mvni supports the ones shifting variant (aka MSL)
3585 assert(isValidImmBSVal(imm, size));
3593 assert(insOptsNone(opt));
3594 assert(isGeneralRegister(reg));
3596 if (unsigned_abs(imm) <= 0x0fff)
3600 ins = insReverse(ins);
3603 assert(isValidUimm12(imm));
3607 else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
3609 // Encoding will use a 12-bit left shift of the immediate
3610 opt = INS_OPTS_LSL12;
3613 ins = insReverse(ins);
3616 assert((imm & 0xfff) == 0);
3618 assert(isValidUimm12(imm));
3624 assert(!"Instruction cannot be encoded: IF_DI_1A");
3632 } // end switch (ins)
3635 assert(fmt != IF_NONE);
3637 instrDesc* id = emitNewInstrSC(attr, imm);
3649 /*****************************************************************************
3651 * Add an instruction referencing a register and a floating point constant.
3654 void emitter::emitIns_R_F(
3655 instruction ins, emitAttr attr, regNumber reg, double immDbl, insOpts opt /* = INS_OPTS_NONE */)
3658 emitAttr size = EA_SIZE(attr);
3659 emitAttr elemsize = EA_UNKNOWN;
3660 insFormat fmt = IF_NONE;
3662 bool canEncode = false;
3664 /* Figure out the encoding format of the instruction */
3671 assert(insOptsNone(opt));
3672 assert(isValidVectorElemsizeFloat(size));
3673 assert(isVectorRegister(reg));
3682 assert(isVectorRegister(reg));
3684 canEncode = canEncodeFloatImm8(immDbl, &fpi);
3686 if (insOptsAnyArrangement(opt))
3689 assert(isValidVectorDatasize(size));
3690 assert(isValidArrangement(size, opt));
3691 elemsize = optGetElemsize(opt);
3692 assert(isValidVectorElemsizeFloat(elemsize));
3693 assert(opt != INS_OPTS_1D); // Reserved encoding
3697 imm = fpi.immFPIVal;
3698 assert((imm >= 0) && (imm <= 0xff));
3705 assert(insOptsNone(opt));
3706 assert(isValidVectorElemsizeFloat(size));
3710 imm = fpi.immFPIVal;
3711 assert((imm >= 0) && (imm <= 0xff));
3721 } // end switch (ins)
3724 assert(fmt != IF_NONE);
3726 instrDesc* id = emitNewInstrSC(attr, imm);
3738 /*****************************************************************************
3740 * Add an instruction referencing two registers
3743 void emitter::emitIns_R_R(
3744 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insOpts opt /* = INS_OPTS_NONE */)
3746 emitAttr size = EA_SIZE(attr);
3747 emitAttr elemsize = EA_UNKNOWN;
3748 insFormat fmt = IF_NONE;
3750 /* Figure out the encoding format of the instruction */
3754 assert(insOptsNone(opt));
3755 // Is the mov even necessary?
3758 // A mov with a EA_4BYTE has the side-effect of clearing the upper bits
3759 // So only eliminate mov instructions that are not clearing the upper bits
3761 if (isGeneralRegisterOrSP(reg1) && (size == EA_8BYTE))
3765 else if (isVectorRegister(reg1) && (size == EA_16BYTE))
3771 // Check for the 'mov' aliases for the vector registers
3772 if (isVectorRegister(reg1))
3774 if (isVectorRegister(reg2) && isValidVectorDatasize(size))
3776 return emitIns_R_R_R(INS_mov, size, reg1, reg2, reg2);
3780 return emitIns_R_R_I(INS_mov, size, reg1, reg2, 0);
3785 if (isVectorRegister(reg2))
3787 assert(isGeneralRegister(reg1));
3788 return emitIns_R_R_I(INS_mov, size, reg1, reg2, 0);
3792 // Is this a MOV to/from SP instruction?
3793 if ((reg1 == REG_SP) || (reg2 == REG_SP))
3795 assert(isGeneralRegisterOrSP(reg1));
3796 assert(isGeneralRegisterOrSP(reg2));
3797 reg1 = encodingSPtoZR(reg1);
3798 reg2 = encodingSPtoZR(reg2);
3803 assert(insOptsNone(opt));
3804 assert(isGeneralRegister(reg1));
3805 assert(isGeneralRegisterOrZR(reg2));
3812 assert(insOptsAnyArrangement(opt));
3813 assert(isVectorRegister(reg1));
3814 assert(isGeneralRegisterOrZR(reg2));
3815 assert(isValidVectorDatasize(size));
3816 assert(isValidArrangement(size, opt));
3822 assert(isVectorRegister(reg1));
3823 assert(isVectorRegister(reg2));
3824 // for 'NOT' we can construct the arrangement: 8B or 16B
3825 if ((ins == INS_not) && insOptsNone(opt))
3827 assert(isValidVectorDatasize(size));
3828 elemsize = EA_1BYTE;
3829 opt = optMakeArrangement(size, elemsize);
3831 if (insOptsNone(opt))
3834 assert(size == EA_8BYTE); // Only type D is supported
3840 assert(insOptsAnyArrangement(opt));
3841 assert(isValidVectorDatasize(size));
3842 assert(isValidArrangement(size, opt));
3843 elemsize = optGetElemsize(opt);
3846 assert(elemsize == EA_1BYTE);
3854 if (isVectorRegister(reg1))
3856 assert(isVectorRegister(reg2));
3857 // for 'mvn' we can construct the arrangement: 8B or 16b
3858 if ((ins == INS_mvn) && insOptsNone(opt))
3860 assert(isValidVectorDatasize(size));
3861 elemsize = EA_1BYTE;
3862 opt = optMakeArrangement(size, elemsize);
3864 if (insOptsNone(opt))
3867 assert(size == EA_8BYTE); // Only type D is supported
3873 assert(isValidVectorDatasize(size));
3874 assert(isValidArrangement(size, opt));
3875 elemsize = optGetElemsize(opt);
3878 assert(elemsize == EA_1BYTE); // Only supports 8B or 16B
3887 assert(insOptsNone(opt));
3888 assert(isGeneralRegister(reg1));
3889 assert(isGeneralRegisterOrZR(reg2));
3894 assert(size == EA_8BYTE);
3901 assert(insOptsNone(opt));
3902 assert(isValidGeneralDatasize(size));
3903 assert(isGeneralRegister(reg1));
3904 assert(isGeneralRegister(reg2));
3912 return emitIns_R_R_I(ins, size, reg1, reg2, 0, opt);
3920 if (isVectorRegister(reg1))
3922 assert(isVectorRegister(reg2));
3923 assert(isValidVectorDatasize(size));
3924 assert(isValidArrangement(size, opt));
3925 elemsize = optGetElemsize(opt);
3926 if ((ins == INS_cls) || (ins == INS_clz))
3928 assert(elemsize != EA_8BYTE); // No encoding for type D
3930 else if (ins == INS_rev32)
3932 assert((elemsize == EA_2BYTE) || (elemsize == EA_1BYTE));
3936 assert(elemsize == EA_1BYTE); // Only supports 8B or 16B
3943 // Doesn't have general register version(s)
3950 assert(insOptsNone(opt));
3951 assert(isGeneralRegister(reg1));
3952 assert(isGeneralRegister(reg2));
3953 if (ins == INS_rev32)
3955 assert(size == EA_8BYTE);
3959 assert(isValidGeneralDatasize(size));
3972 assert(isVectorRegister(reg1));
3973 assert(isVectorRegister(reg2));
3974 assert(isValidVectorDatasize(size));
3975 assert(isValidArrangement(size, opt));
3976 elemsize = optGetElemsize(opt);
3977 assert(elemsize != EA_8BYTE); // No encoding for type D
3983 assert(isVectorRegister(reg1));
3984 assert(isVectorRegister(reg2));
3985 assert(isValidVectorDatasize(size));
3986 assert(isValidArrangement(size, opt));
3987 elemsize = optGetElemsize(opt);
3988 assert(size != EA_16BYTE); // Narrowing must start with wide format
3989 assert(elemsize != EA_1BYTE); // Narrowing must start with more than one byte src
3997 assert(isValidGeneralDatasize(size));
4009 assert(isValidGeneralLSDatasize(size));
4010 assert(isGeneralRegisterOrZR(reg1));
4011 assert(isGeneralRegisterOrSP(reg2));
4012 assert(insOptsNone(opt));
4014 reg2 = encodingSPtoZR(reg2);
4032 assert(insOptsNone(opt));
4033 emitIns_R_R_I(ins, attr, reg1, reg2, 0, INS_OPTS_NONE);
4037 assert(isValidVectorElemsizeFloat(size));
4039 // Is the mov even necessary?
4045 if (isVectorRegister(reg1))
4047 if (isVectorRegister(reg2))
4049 assert(insOptsNone(opt));
4054 assert(isGeneralRegister(reg2));
4056 // if the optional conversion specifier is not present we calculate it
4057 if (opt == INS_OPTS_NONE)
4059 opt = (size == EA_4BYTE) ? INS_OPTS_4BYTE_TO_S : INS_OPTS_8BYTE_TO_D;
4061 assert(insOptsConvertIntToFloat(opt));
4068 assert(isGeneralRegister(reg1));
4069 assert(isVectorRegister(reg2));
4071 // if the optional conversion specifier is not present we calculate it
4072 if (opt == INS_OPTS_NONE)
4074 opt = (size == EA_4BYTE) ? INS_OPTS_S_TO_4BYTE : INS_OPTS_D_TO_8BYTE;
4076 assert(insOptsConvertFloatToInt(opt));
4084 assert(insOptsNone(opt));
4085 assert(isValidVectorElemsizeFloat(size));
4086 assert(isVectorRegister(reg1));
4087 assert(isVectorRegister(reg2));
4101 if (insOptsAnyArrangement(opt))
4104 assert(isVectorRegister(reg1));
4105 assert(isVectorRegister(reg2));
4106 assert(isValidVectorDatasize(size));
4107 assert(isValidArrangement(size, opt));
4108 elemsize = optGetElemsize(opt);
4109 assert(isValidVectorElemsizeFloat(elemsize));
4110 assert(opt != INS_OPTS_1D); // Reserved encoding
4116 assert(isVectorRegister(reg2));
4117 if (isVectorRegister(reg1))
4119 assert(insOptsNone(opt));
4120 assert(isValidVectorElemsizeFloat(size));
4125 assert(isGeneralRegister(reg1));
4126 assert(insOptsConvertFloatToInt(opt));
4127 assert(isValidVectorElemsizeFloat(size));
4135 assert(isVectorRegister(reg1));
4136 assert(isVectorRegister(reg2));
4137 assert(isValidVectorDatasize(size));
4138 assert(isValidArrangement(size, opt));
4139 elemsize = optGetElemsize(opt);
4140 assert(elemsize == EA_4BYTE); // Widening from Float to Double, opt should correspond to src layout
4146 assert(isVectorRegister(reg1));
4147 assert(isVectorRegister(reg2));
4148 assert(isValidVectorDatasize(size));
4149 assert(isValidArrangement(size, opt));
4150 elemsize = optGetElemsize(opt);
4151 assert(elemsize == EA_8BYTE); // Narrowing from Double to Float, opt should correspond to src layout
4157 if (insOptsAnyArrangement(opt))
4160 assert(isVectorRegister(reg1));
4161 assert(isVectorRegister(reg2));
4162 assert(isValidVectorDatasize(size));
4163 assert(isValidArrangement(size, opt));
4164 elemsize = optGetElemsize(opt);
4165 assert(isValidVectorElemsizeFloat(elemsize));
4166 assert(opt != INS_OPTS_1D); // Reserved encoding
4172 assert(isVectorRegister(reg1));
4173 if (isVectorRegister(reg2))
4175 assert(insOptsNone(opt));
4176 assert(isValidVectorElemsizeFloat(size));
4181 assert(isGeneralRegister(reg2));
4182 assert(insOptsConvertIntToFloat(opt));
4183 assert(isValidVectorElemsizeFloat(size));
4199 if (insOptsAnyArrangement(opt))
4202 assert(isVectorRegister(reg1));
4203 assert(isVectorRegister(reg2));
4204 assert(isValidVectorDatasize(size));
4205 assert(isValidArrangement(size, opt));
4206 elemsize = optGetElemsize(opt);
4207 assert(isValidVectorElemsizeFloat(elemsize));
4208 assert(opt != INS_OPTS_1D); // Reserved encoding
4214 assert(insOptsNone(opt));
4215 assert(isValidVectorElemsizeFloat(size));
4216 assert(isVectorRegister(reg1));
4217 assert(isVectorRegister(reg2));
4224 assert(insOptsNone(opt));
4225 assert(isValidVectorElemsizeFloat(size));
4226 assert(isVectorRegister(reg1));
4227 assert(isVectorRegister(reg2));
4232 assert(insOptsConvertFloatToFloat(opt));
4233 assert(isValidVectorFcvtsize(size));
4234 assert(isVectorRegister(reg1));
4235 assert(isVectorRegister(reg2));
4243 } // end switch (ins)
4245 assert(fmt != IF_NONE);
4247 instrDesc* id = emitNewInstrSmall(attr);
4260 /*****************************************************************************
4262 * Add an instruction referencing a register and two constants.
4265 void emitter::emitIns_R_I_I(
4266 instruction ins, emitAttr attr, regNumber reg, ssize_t imm1, ssize_t imm2, insOpts opt /* = INS_OPTS_NONE */)
4268 emitAttr size = EA_SIZE(attr);
4269 insFormat fmt = IF_NONE;
4270 size_t immOut = 0; // composed from imm1 and imm2 and stored in the instrDesc
4272 /* Figure out the encoding format of the instruction */
4279 ins = INS_movz; // INS_mov with LSL is an alias for INS_movz LSL
4285 assert(isValidGeneralDatasize(size));
4286 assert(isGeneralRegister(reg));
4287 assert(isValidUimm16(imm1));
4288 assert(insOptsLSL(opt)); // Must be INS_OPTS_LSL
4290 if (size == EA_8BYTE)
4292 assert((imm2 == 0) || (imm2 == 16) || // shift amount: 0, 16, 32 or 48
4293 (imm2 == 32) || (imm2 == 48));
4297 assert((imm2 == 0) || (imm2 == 16)); // shift amount: 0 or 16
4332 immOut = hwi.immHWVal;
4333 assert(isValidImmHWVal(immOut, size));
4342 } // end switch (ins)
4344 assert(fmt != IF_NONE);
4346 instrDesc* id = emitNewInstrSC(attr, immOut);
4357 /*****************************************************************************
4359 * Add an instruction referencing two registers and a constant.
4362 void emitter::emitIns_R_R_I(
4363 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm, insOpts opt /* = INS_OPTS_NONE */)
4365 emitAttr size = EA_SIZE(attr);
4366 emitAttr elemsize = EA_UNKNOWN;
4367 insFormat fmt = IF_NONE;
4368 bool isLdSt = false;
4369 bool isSIMD = false;
4370 bool isAddSub = false;
4371 bool setFlags = false;
4373 bool unscaledOp = false;
4375 /* Figure out the encoding format of the instruction */
4382 // Check for the 'mov' aliases for the vector registers
4383 assert(insOptsNone(opt));
4384 assert(isValidVectorElemsize(size));
4386 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4388 if (isVectorRegister(reg1))
4390 if (isGeneralRegisterOrZR(reg2))
4392 fmt = IF_DV_2C; // Alias for 'ins'
4395 else if (isVectorRegister(reg2))
4397 fmt = IF_DV_2E; // Alias for 'dup'
4401 else // isGeneralRegister(reg1)
4403 assert(isGeneralRegister(reg1));
4404 if (isVectorRegister(reg2))
4406 fmt = IF_DV_2B; // Alias for 'umov'
4410 assert(!" invalid INS_mov operands");
4416 assert(insOptsNone(opt));
4417 assert(isValidGeneralDatasize(size));
4418 assert(isGeneralRegister(reg1));
4419 assert(isGeneralRegister(reg2));
4420 assert(isValidImmShift(imm, size));
4425 assert(insOptsNone(opt));
4426 assert(isValidGeneralDatasize(size));
4427 assert(isGeneralRegister(reg1));
4428 assert(isGeneralRegister(reg2));
4429 assert(isValidImmShift(imm, size));
4444 assert(isVectorRegister(reg1));
4445 assert(isVectorRegister(reg2));
4446 if (insOptsAnyArrangement(opt))
4449 assert(isValidVectorDatasize(size));
4450 assert(isValidArrangement(size, opt));
4451 elemsize = optGetElemsize(opt);
4452 assert(isValidVectorElemsize(elemsize));
4453 assert(isValidImmShift(imm, elemsize));
4454 assert(opt != INS_OPTS_1D); // Reserved encoding
4461 assert(insOptsNone(opt));
4462 assert(size == EA_8BYTE); // only supported size
4463 assert(isValidImmShift(imm, size));
4477 assert(isVectorRegister(reg1));
4478 assert(isVectorRegister(reg2));
4480 assert(size == EA_8BYTE);
4481 assert(isValidArrangement(size, opt));
4482 elemsize = optGetElemsize(opt);
4483 assert(elemsize != EA_8BYTE); // Reserved encodings
4484 assert(isValidVectorElemsize(elemsize));
4485 assert(isValidImmShift(imm, elemsize));
4498 assert(isVectorRegister(reg1));
4499 assert(isVectorRegister(reg2));
4501 assert(size == EA_16BYTE);
4502 assert(isValidArrangement(size, opt));
4503 elemsize = optGetElemsize(opt);
4504 assert(elemsize != EA_8BYTE); // Reserved encodings
4505 assert(isValidVectorElemsize(elemsize));
4506 assert(isValidImmShift(imm, elemsize));
4513 assert(isValidGeneralDatasize(size));
4514 assert(isGeneralRegister(reg1));
4515 assert(isGeneralRegisterOrZR(reg2));
4519 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4527 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
4531 assert(insOptsAluShift(opt)); // a non-zero imm, must select shift kind, can't use ROR
4533 assert(isValidImmShift(imm, size));
4539 assert(isValidGeneralDatasize(size));
4540 assert(isGeneralRegisterOrZR(reg1));
4541 assert(isGeneralRegister(reg2));
4543 if (insOptsAnyShift(opt))
4545 assert(isValidImmShift(imm, size) && (imm != 0));
4550 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4558 assert(isValidGeneralDatasize(size));
4559 assert(isGeneralRegisterOrSP(reg1));
4560 assert(isGeneralRegister(reg2));
4562 reg1 = encodingSPtoZR(reg1);
4563 if (insOptsAnyExtend(opt))
4565 assert((imm >= 0) && (imm <= 4));
4571 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4577 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
4578 assert(isValidImmShift(imm, size));
4587 assert(insOptsNone(opt));
4588 assert(isGeneralRegister(reg2));
4589 if (ins == INS_ands)
4591 assert(isGeneralRegister(reg1));
4595 assert(isGeneralRegisterOrSP(reg1));
4596 reg1 = encodingSPtoZR(reg1);
4600 canEncode = canEncodeBitMaskImm(imm, size, &bmi);
4604 assert(isValidImmNRS(imm, size));
4609 case INS_dup: // by element, imm selects the element of reg2
4610 assert(isVectorRegister(reg1));
4611 if (isVectorRegister(reg2))
4613 if (insOptsAnyArrangement(opt))
4616 assert(isValidVectorDatasize(size));
4617 assert(isValidArrangement(size, opt));
4618 elemsize = optGetElemsize(opt);
4619 assert(isValidVectorElemsize(elemsize));
4620 assert(isValidVectorIndex(size, elemsize, imm));
4621 assert(opt != INS_OPTS_1D); // Reserved encoding
4628 assert(insOptsNone(opt));
4630 assert(isValidVectorElemsize(elemsize));
4631 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4638 case INS_ins: // (MOV from general)
4639 assert(insOptsNone(opt));
4640 assert(isValidVectorElemsize(size));
4641 assert(isVectorRegister(reg1));
4642 assert(isGeneralRegisterOrZR(reg2));
4644 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4648 case INS_umov: // (MOV to general)
4649 assert(insOptsNone(opt));
4650 assert(isValidVectorElemsize(size));
4651 assert(isGeneralRegister(reg1));
4652 assert(isVectorRegister(reg2));
4654 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4659 assert(insOptsNone(opt));
4660 assert(isValidVectorElemsize(size));
4661 assert(size != EA_8BYTE); // no encoding, use INS_umov
4662 assert(isGeneralRegister(reg1));
4663 assert(isVectorRegister(reg2));
4665 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4683 // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4684 assert(isValidGeneralDatasize(size));
4685 unscaledOp = (ins == INS_ldursb);
4692 // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4693 assert(isValidGeneralDatasize(size));
4694 unscaledOp = (ins == INS_ldursh);
4701 // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4702 assert(size == EA_8BYTE);
4703 unscaledOp = (ins == INS_ldursw);
4742 // Is the target a vector register?
4743 if (isVectorRegister(reg1))
4745 assert(isValidVectorLSDatasize(size));
4746 assert(isGeneralRegisterOrSP(reg2));
4751 assert(isValidGeneralDatasize(size));
4754 scale = NaturalScale_helper(size);
4760 // Is the target a vector register?
4761 if (isVectorRegister(reg1))
4763 assert(isValidVectorLSDatasize(size));
4764 assert(isGeneralRegisterOrSP(reg2));
4769 assert(isValidGeneralDatasize(size));
4780 } // end switch (ins)
4788 assert(isValidVectorLSDatasize(size));
4789 assert(isVectorRegister(reg1));
4790 assert((scale >= 0) && (scale <= 4));
4794 assert(isValidGeneralLSDatasize(size));
4795 assert(isGeneralRegisterOrZR(reg1));
4796 assert((scale >= 0) && (scale <= 3));
4799 assert(isGeneralRegisterOrSP(reg2));
4801 // Load/Store reserved encodings:
4802 if (insOptsIndexed(opt))
4804 assert(reg1 != reg2);
4807 reg2 = encodingSPtoZR(reg2);
4809 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
4812 assert(insOptsNone(opt)); // PRE/POST Index doesn't make sense with an immediate of zero
4816 else if (insOptsIndexed(opt) || unscaledOp || (imm < 0) || ((imm & mask) != 0))
4818 if ((imm >= -256) && (imm <= 255))
4824 assert(!"Instruction cannot be encoded: IF_LS_2C");
4829 assert(insOptsNone(opt));
4830 assert(!unscaledOp);
4832 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
4834 imm >>= scale; // The immediate is scaled by the size of the ld/st
4840 assert(!"Instruction cannot be encoded: IF_LS_2B");
4847 assert(insOptsNone(opt));
4849 if (setFlags) // Can't encode SP with setFlags
4851 assert(isGeneralRegister(reg1));
4852 assert(isGeneralRegister(reg2));
4856 assert(isGeneralRegisterOrSP(reg1));
4857 assert(isGeneralRegisterOrSP(reg2));
4859 // Is it just a mov?
4862 // Is the mov even necessary?
4865 emitIns_R_R(INS_mov, attr, reg1, reg2);
4870 reg1 = encodingSPtoZR(reg1);
4871 reg2 = encodingSPtoZR(reg2);
4874 if (unsigned_abs(imm) <= 0x0fff)
4878 ins = insReverse(ins);
4881 assert(isValidUimm12(imm));
4884 else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
4886 // Encoding will use a 12-bit left shift of the immediate
4887 opt = INS_OPTS_LSL12;
4890 ins = insReverse(ins);
4893 assert((imm & 0xfff) == 0);
4895 assert(isValidUimm12(imm));
4900 assert(!"Instruction cannot be encoded: IF_DI_2A");
4904 assert(fmt != IF_NONE);
4906 instrDesc* id = emitNewInstrSC(attr, imm);
4919 /*****************************************************************************
4921 * Add an instruction referencing two registers and a constant.
4922 * Also checks for a large immediate that needs a second instruction
4923 * and will load it in reg1
4925 * - Supports instructions: add, adds, sub, subs, and, ands, eor and orr
4926 * - Requires that reg1 is a general register and not SP or ZR
4927 * - Requires that reg1 != reg2
4929 void emitter::emitIns_R_R_Imm(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm)
4931 assert(isGeneralRegister(reg1));
4932 assert(reg1 != reg2);
4934 bool immFits = true;
4942 immFits = emitter::emitIns_valid_imm_for_add(imm, attr);
4949 immFits = emitter::emitIns_valid_imm_for_alu(imm, attr);
4953 assert(!"Unsupported instruction in emitIns_R_R_Imm");
4958 emitIns_R_R_I(ins, attr, reg1, reg2, imm);
4962 // Load 'imm' into the reg1 register
4963 // then issue: 'ins' reg1, reg2, reg1
4965 codeGen->instGen_Set_Reg_To_Imm(attr, reg1, imm);
4966 emitIns_R_R_R(ins, attr, reg1, reg2, reg1);
4970 /*****************************************************************************
4972 * Add an instruction referencing three registers.
4975 void emitter::emitIns_R_R_R(
4976 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insOpts opt) /* = INS_OPTS_NONE */
4978 emitAttr size = EA_SIZE(attr);
4979 emitAttr elemsize = EA_UNKNOWN;
4980 insFormat fmt = IF_NONE;
4982 /* Figure out the encoding format of the instruction */
5006 assert(insOptsNone(opt));
5007 assert(isValidGeneralDatasize(size));
5008 assert(isGeneralRegister(reg1));
5009 assert(isGeneralRegister(reg2));
5010 assert(isGeneralRegister(reg3));
5015 if (insOptsNone(opt))
5018 assert(isValidGeneralDatasize(size));
5019 assert(isGeneralRegister(reg1));
5020 assert(isGeneralRegister(reg2));
5021 assert(isGeneralRegister(reg3));
5030 assert(insOptsAnyArrangement(opt));
5031 assert(isVectorRegister(reg1));
5032 assert(isVectorRegister(reg2));
5033 assert(isVectorRegister(reg3));
5034 assert(isValidVectorDatasize(size));
5035 assert(isValidArrangement(size, opt));
5036 elemsize = optGetElemsize(opt);
5037 if (ins == INS_pmul)
5039 assert(elemsize == EA_1BYTE); // only supports 8B or 16B
5041 else // INS_mul, INS_mla, INS_mls
5043 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
5050 if (isVectorRegister(reg1))
5052 assert(isVectorRegister(reg2));
5053 assert(isVectorRegister(reg3));
5055 if (insOptsAnyArrangement(opt))
5058 assert(opt != INS_OPTS_1D); // Reserved encoding
5059 assert(isValidVectorDatasize(size));
5060 assert(isValidArrangement(size, opt));
5066 assert(insOptsNone(opt));
5067 assert(size == EA_8BYTE);
5076 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, INS_OPTS_NONE);
5085 assert(isVectorRegister(reg1));
5086 assert(isVectorRegister(reg2));
5087 assert(isVectorRegister(reg3));
5089 if (isValidVectorDatasize(size))
5092 assert(insOptsAnyArrangement(opt));
5093 assert(isValidArrangement(size, opt));
5094 elemsize = optGetElemsize(opt);
5101 assert(size == EA_8BYTE); // Only Double supported
5109 assert(isVectorRegister(reg1));
5110 assert(isVectorRegister(reg2));
5111 assert(isVectorRegister(reg3));
5113 if (isValidVectorDatasize(size))
5116 assert(insOptsAnyArrangement(opt));
5117 assert(isValidArrangement(size, opt));
5118 elemsize = optGetElemsize(opt);
5119 assert((elemsize == EA_8BYTE) || (elemsize == EA_4BYTE)); // Only Double/Float supported
5120 assert(opt != INS_OPTS_1D); // Reserved encoding
5127 assert((size == EA_8BYTE) || (size == EA_4BYTE)); // Only Double/Float supported
5140 assert(isVectorRegister(reg1));
5141 assert(isVectorRegister(reg2));
5142 assert(isVectorRegister(reg3));
5143 assert(insOptsAnyArrangement(opt));
5146 assert(isValidVectorDatasize(size));
5147 assert(isValidArrangement(size, opt));
5148 elemsize = optGetElemsize(opt);
5149 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
5155 assert(isVectorRegister(reg1));
5156 assert(isVectorRegister(reg2));
5157 assert(reg2 == reg3);
5158 assert(isValidVectorDatasize(size));
5159 // INS_mov is an alias for INS_orr (vector register)
5160 if (opt == INS_OPTS_NONE)
5162 elemsize = EA_1BYTE;
5163 opt = optMakeArrangement(size, elemsize);
5165 assert(isValidArrangement(size, opt));
5174 if (isVectorRegister(reg1))
5176 assert(isValidVectorDatasize(size));
5177 assert(isVectorRegister(reg2));
5178 assert(isVectorRegister(reg3));
5179 if (opt == INS_OPTS_NONE)
5181 elemsize = EA_1BYTE;
5182 opt = optMakeArrangement(size, elemsize);
5184 assert(isValidArrangement(size, opt));
5193 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, INS_OPTS_NONE);
5199 assert(isValidVectorDatasize(size));
5200 assert(isVectorRegister(reg1));
5201 assert(isVectorRegister(reg2));
5202 assert(isVectorRegister(reg3));
5203 if (opt == INS_OPTS_NONE)
5205 elemsize = EA_1BYTE;
5206 opt = optMakeArrangement(size, elemsize);
5208 assert(isValidArrangement(size, opt));
5220 assert(isVectorRegister(reg1));
5221 assert(isVectorRegister(reg2));
5222 assert(isVectorRegister(reg3));
5223 if (insOptsAnyArrangement(opt))
5226 assert(isValidVectorDatasize(size));
5227 assert(isValidArrangement(size, opt));
5228 elemsize = optGetElemsize(opt);
5229 assert(isValidVectorElemsizeFloat(elemsize));
5230 assert(opt != INS_OPTS_1D); // Reserved encoding
5236 assert(insOptsNone(opt));
5237 assert(isValidScalarDatasize(size));
5244 assert(insOptsNone(opt));
5245 assert(isVectorRegister(reg1));
5246 assert(isVectorRegister(reg2));
5247 assert(isVectorRegister(reg3));
5248 assert(isValidScalarDatasize(size));
5255 assert(isVectorRegister(reg1));
5256 assert(isVectorRegister(reg2));
5257 assert(isVectorRegister(reg3));
5258 assert(insOptsAnyArrangement(opt)); // no scalar encoding, use 4-operand 'fmadd' or 'fmsub'
5261 assert(isValidVectorDatasize(size));
5262 assert(isValidArrangement(size, opt));
5263 elemsize = optGetElemsize(opt);
5264 assert(isValidVectorElemsizeFloat(elemsize));
5265 assert(opt != INS_OPTS_1D); // Reserved encoding
5278 emitIns_R_R_R_Ext(ins, attr, reg1, reg2, reg3, opt);
5286 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0);
5295 assert(isGeneralRegisterOrZR(reg1));
5296 assert(isGeneralRegisterOrZR(reg2));
5297 assert(isGeneralRegisterOrSP(reg3));
5305 } // end switch (ins)
5307 assert(fmt != IF_NONE);
5309 instrDesc* id = emitNewInstr(attr);
5323 /*****************************************************************************
5325 * Add an instruction referencing three registers and a constant.
5328 void emitter::emitIns_R_R_R_I(instruction ins,
5334 insOpts opt /* = INS_OPTS_NONE */,
5335 emitAttr attrReg2 /* = EA_UNKNOWN */)
5337 emitAttr size = EA_SIZE(attr);
5338 emitAttr elemsize = EA_UNKNOWN;
5339 insFormat fmt = IF_NONE;
5340 bool isLdSt = false;
5341 bool isSIMD = false;
5342 bool isAddSub = false;
5343 bool setFlags = false;
5346 /* Figure out the encoding format of the instruction */
5350 assert(insOptsNone(opt));
5351 assert(isValidGeneralDatasize(size));
5352 assert(isGeneralRegister(reg1));
5353 assert(isGeneralRegister(reg2));
5354 assert(isGeneralRegister(reg3));
5355 assert(isValidImmShift(imm, size));
5367 assert(isValidGeneralDatasize(size));
5368 assert(isGeneralRegister(reg1));
5369 assert(isGeneralRegister(reg2));
5370 assert(isGeneralRegister(reg3));
5371 assert(isValidImmShift(imm, size));
5374 assert(insOptsNone(opt)); // a zero imm, means no shift kind
5379 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
5384 case INS_fmul: // by element, imm[0..3] selects the element of reg3
5388 assert(isVectorRegister(reg1));
5389 assert(isVectorRegister(reg2));
5390 assert(isVectorRegister(reg3));
5391 if (insOptsAnyArrangement(opt))
5394 assert(isValidVectorDatasize(size));
5395 assert(isValidArrangement(size, opt));
5396 elemsize = optGetElemsize(opt);
5397 assert(isValidVectorElemsizeFloat(elemsize));
5398 assert(isValidVectorIndex(size, elemsize, imm));
5399 assert(opt != INS_OPTS_1D); // Reserved encoding
5405 assert(insOptsNone(opt));
5406 assert(isValidScalarDatasize(size));
5408 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
5413 case INS_mul: // by element, imm[0..7] selects the element of reg3
5416 assert(isVectorRegister(reg1));
5417 assert(isVectorRegister(reg2));
5418 assert(isVectorRegister(reg3));
5420 assert(insOptsAnyArrangement(opt));
5421 assert(isValidVectorDatasize(size));
5422 assert(isValidArrangement(size, opt));
5423 elemsize = optGetElemsize(opt);
5424 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
5425 // Only has encodings for H or S elemsize
5426 assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE));
5427 // Only has encodings for V0..V15
5428 if ((elemsize == EA_2BYTE) && (reg3 >= REG_V16))
5430 noway_assert(!"Invalid reg3");
5454 assert(insOptsNone(opt)); // Can't use Pre/Post index on these two instructions
5459 // Is the target a vector register?
5460 if (isVectorRegister(reg1))
5462 scale = NaturalScale_helper(size);
5467 scale = (size == EA_8BYTE) ? 3 : 2;
5476 } // end switch (ins)
5481 assert(isGeneralRegisterOrSP(reg3));
5482 assert(insOptsNone(opt) || insOptsIndexed(opt));
5486 assert(isValidVectorLSPDatasize(size));
5487 assert(isVectorRegister(reg1));
5488 assert(isVectorRegister(reg2));
5489 assert((scale >= 2) && (scale <= 4));
5493 assert(isValidGeneralDatasize(size));
5494 assert(isGeneralRegisterOrZR(reg1));
5495 assert(isGeneralRegisterOrZR(reg2));
5496 assert((scale == 2) || (scale == 3));
5499 // Load/Store Pair reserved encodings:
5500 if (emitInsIsLoad(ins))
5502 assert(reg1 != reg2);
5504 if (insOptsIndexed(opt))
5506 assert(reg1 != reg3);
5507 assert(reg2 != reg3);
5510 reg3 = encodingSPtoZR(reg3);
5512 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
5515 assert(insOptsNone(opt)); // PRE/POST Index doesn't make sense with an immediate of zero
5521 if ((imm & mask) == 0)
5523 imm >>= scale; // The immediate is scaled by the size of the ld/st
5525 if ((imm >= -64) && (imm <= 63))
5531 if (fmt != IF_LS_3C)
5533 assert(!"Instruction cannot be encoded: IF_LS_3C");
5540 bool reg2IsSP = (reg2 == REG_SP);
5542 assert(isValidGeneralDatasize(size));
5543 assert(isGeneralRegister(reg3));
5545 if (setFlags || insOptsAluShift(opt)) // Can't encode SP in reg1 with setFlags or AluShift option
5547 assert(isGeneralRegisterOrZR(reg1));
5551 assert(isGeneralRegisterOrSP(reg1));
5552 reg1 = encodingSPtoZR(reg1);
5555 if (insOptsAluShift(opt)) // Can't encode SP in reg2 with AluShift option
5557 assert(isGeneralRegister(reg2));
5561 assert(isGeneralRegisterOrSP(reg2));
5562 reg2 = encodingSPtoZR(reg2);
5565 if (insOptsAnyExtend(opt))
5567 assert((imm >= 0) && (imm <= 4));
5571 else if (insOptsAluShift(opt))
5573 // imm should be non-zero and in [1..63]
5574 assert(isValidImmShift(imm, size) && (imm != 0));
5579 assert(insOptsNone(opt));
5583 // To encode the SP register as reg2 we must use the IF_DR_3C encoding
5584 // and also specify a LSL of zero (imm == 0)
5595 assert(!"Instruction cannot be encoded: Add/Sub IF_DR_3A");
5598 assert(fmt != IF_NONE);
5600 instrDesc* id = emitNewInstrCns(attr, imm);
5610 // Record the attribute for the second register in the pair
5611 id->idGCrefReg2(GCT_NONE);
5612 if (attrReg2 != EA_UNKNOWN)
5614 // Record the attribute for the second register in the pair
5615 assert((fmt == IF_LS_3B) || (fmt == IF_LS_3C));
5616 if (EA_IS_GCREF(attrReg2))
5618 id->idGCrefReg2(GCT_GCREF);
5620 else if (EA_IS_BYREF(attrReg2))
5622 id->idGCrefReg2(GCT_BYREF);
5630 /*****************************************************************************
5632 * Add an instruction referencing three registers, with an extend option
5635 void emitter::emitIns_R_R_R_Ext(instruction ins,
5640 insOpts opt, /* = INS_OPTS_NONE */
5641 int shiftAmount) /* = -1 -- unset */
5643 emitAttr size = EA_SIZE(attr);
5644 insFormat fmt = IF_NONE;
5645 bool isSIMD = false;
5648 /* Figure out the encoding format of the instruction */
5669 // Is the target a vector register?
5670 if (isVectorRegister(reg1))
5672 assert(isValidVectorLSDatasize(size));
5673 scale = NaturalScale_helper(size);
5678 assert(isValidGeneralDatasize(size));
5679 scale = (size == EA_8BYTE) ? 3 : 2;
5688 } // end switch (ins)
5690 assert(scale != -1);
5691 assert(insOptsLSExtend(opt));
5695 assert(isValidVectorLSDatasize(size));
5696 assert(isVectorRegister(reg1));
5700 assert(isValidGeneralLSDatasize(size));
5701 assert(isGeneralRegisterOrZR(reg1));
5704 assert(isGeneralRegisterOrSP(reg2));
5705 assert(isGeneralRegister(reg3));
5707 // Load/Store reserved encodings:
5708 if (insOptsIndexed(opt))
5710 assert(reg1 != reg2);
5713 if (shiftAmount == -1)
5715 shiftAmount = insOptsLSL(opt) ? scale : 0;
5717 assert((shiftAmount == scale) || (shiftAmount == 0));
5719 reg2 = encodingSPtoZR(reg2);
5722 instrDesc* id = emitNewInstr(attr);
5731 id->idReg3Scaled(shiftAmount == scale);
5737 /*****************************************************************************
5739 * Add an instruction referencing two registers and two constants.
5742 void emitter::emitIns_R_R_I_I(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, int imm1, int imm2)
5744 emitAttr size = EA_SIZE(attr);
5745 emitAttr elemsize = EA_UNKNOWN;
5746 insFormat fmt = IF_NONE;
5747 size_t immOut = 0; // composed from imm1 and imm2 and stored in the instrDesc
5749 /* Figure out the encoding format of the instruction */
5759 assert(isGeneralRegister(reg1));
5760 assert(isGeneralRegister(reg2));
5761 assert(isValidImmShift(imm1, size));
5762 assert(isValidImmShift(imm2, size));
5764 bmi.immN = (size == EA_8BYTE);
5767 immOut = bmi.immNRS;
5774 assert(isGeneralRegister(reg1));
5775 assert(isGeneralRegister(reg2));
5776 lsb = getBitWidth(size) - imm1;
5778 assert(isValidImmShift(lsb, size));
5779 assert(isValidImmShift(width, size));
5781 bmi.immN = (size == EA_8BYTE);
5784 immOut = bmi.immNRS;
5791 assert(isGeneralRegister(reg1));
5792 assert(isGeneralRegister(reg2));
5794 width = imm2 + imm1 - 1;
5795 assert(isValidImmShift(lsb, size));
5796 assert(isValidImmShift(width, size));
5798 bmi.immN = (size == EA_8BYTE);
5800 bmi.immS = imm2 + imm1 - 1;
5801 immOut = bmi.immNRS;
5807 assert(isVectorRegister(reg1));
5808 assert(isVectorRegister(reg2));
5810 assert(isValidVectorElemsize(elemsize));
5811 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm1));
5812 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm2));
5813 immOut = (imm1 << 4) + imm2;
5821 assert(fmt != IF_NONE);
5823 instrDesc* id = emitNewInstrSC(attr, immOut);
5835 /*****************************************************************************
5837 * Add an instruction referencing four registers.
5840 void emitter::emitIns_R_R_R_R(
5841 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, regNumber reg4)
5843 emitAttr size = EA_SIZE(attr);
5844 insFormat fmt = IF_NONE;
5846 /* Figure out the encoding format of the instruction */
5855 assert(isValidGeneralDatasize(size));
5856 assert(isGeneralRegister(reg1));
5857 assert(isGeneralRegister(reg2));
5858 assert(isGeneralRegister(reg3));
5859 assert(isGeneralRegister(reg4));
5868 assert(isValidScalarDatasize(size));
5869 assert(isVectorRegister(reg1));
5870 assert(isVectorRegister(reg2));
5871 assert(isVectorRegister(reg3));
5872 assert(isVectorRegister(reg4));
5884 assert(fmt != IF_NONE);
5886 instrDesc* id = emitNewInstr(attr);
5900 /*****************************************************************************
5902 * Add an instruction referencing a register and a condition code
5905 void emitter::emitIns_R_COND(instruction ins, emitAttr attr, regNumber reg, insCond cond)
5907 emitAttr size = EA_SIZE(attr);
5908 insFormat fmt = IF_NONE;
5912 /* Figure out the encoding format of the instruction */
5917 assert(isGeneralRegister(reg));
5926 } // end switch (ins)
5928 assert(fmt != IF_NONE);
5929 assert(isValidImmCond(cfi.immCFVal));
5931 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
5935 id->idInsOpt(INS_OPTS_NONE);
5943 /*****************************************************************************
5945 * Add an instruction referencing two registers and a condition code
5948 void emitter::emitIns_R_R_COND(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insCond cond)
5950 emitAttr size = EA_SIZE(attr);
5951 insFormat fmt = IF_NONE;
5955 /* Figure out the encoding format of the instruction */
5961 assert(isGeneralRegister(reg1));
5962 assert(isGeneralRegister(reg2));
5970 } // end switch (ins)
5972 assert(fmt != IF_NONE);
5973 assert(isValidImmCond(cfi.immCFVal));
5975 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
5979 id->idInsOpt(INS_OPTS_NONE);
5988 /*****************************************************************************
5990 * Add an instruction referencing two registers and a condition code
5993 void emitter::emitIns_R_R_R_COND(
5994 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insCond cond)
5996 emitAttr size = EA_SIZE(attr);
5997 insFormat fmt = IF_NONE;
6001 /* Figure out the encoding format of the instruction */
6008 assert(isGeneralRegister(reg1));
6009 assert(isGeneralRegister(reg2));
6010 assert(isGeneralRegister(reg3));
6019 } // end switch (ins)
6021 assert(fmt != IF_NONE);
6022 assert(isValidImmCond(cfi.immCFVal));
6024 instrDesc* id = emitNewInstr(attr);
6028 id->idInsOpt(INS_OPTS_NONE);
6033 id->idSmallCns(cfi.immCFVal);
6039 /*****************************************************************************
6041 * Add an instruction referencing two registers the flags and a condition code
6044 void emitter::emitIns_R_R_FLAGS_COND(
6045 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insCflags flags, insCond cond)
6047 emitAttr size = EA_SIZE(attr);
6048 insFormat fmt = IF_NONE;
6052 /* Figure out the encoding format of the instruction */
6057 assert(isGeneralRegister(reg1));
6058 assert(isGeneralRegister(reg2));
6066 } // end switch (ins)
6068 assert(fmt != IF_NONE);
6069 assert(isValidImmCondFlags(cfi.immCFVal));
6071 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6075 id->idInsOpt(INS_OPTS_NONE);
6084 /*****************************************************************************
6086 * Add an instruction referencing a register, an immediate, the flags and a condition code
6089 void emitter::emitIns_R_I_FLAGS_COND(
6090 instruction ins, emitAttr attr, regNumber reg, int imm, insCflags flags, insCond cond)
6092 emitAttr size = EA_SIZE(attr);
6093 insFormat fmt = IF_NONE;
6097 /* Figure out the encoding format of the instruction */
6102 assert(isGeneralRegister(reg));
6105 ins = insReverse(ins);
6108 if ((imm >= 0) && (imm <= 31))
6117 assert(!"Instruction cannot be encoded: ccmp/ccmn imm5");
6123 } // end switch (ins)
6125 assert(fmt != IF_NONE);
6126 assert(isValidImmCondFlagsImm5(cfi.immCFVal));
6128 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6132 id->idInsOpt(INS_OPTS_NONE);
6140 /*****************************************************************************
6142 * Add a memory barrier instruction with a 'barrier' immediate
6145 void emitter::emitIns_BARR(instruction ins, insBarrier barrier)
6147 insFormat fmt = IF_NONE;
6150 /* Figure out the encoding format of the instruction */
6158 imm = (ssize_t)barrier;
6163 } // end switch (ins)
6165 assert(fmt != IF_NONE);
6167 instrDesc* id = emitNewInstrSC(EA_8BYTE, imm);
6171 id->idInsOpt(INS_OPTS_NONE);
6177 /*****************************************************************************
6179 * Add an instruction with a static data member operand. If 'size' is 0, the
6180 * instruction operates on the address of the static member instead of its
6181 * value (e.g. "push offset clsvar", rather than "push dword ptr [clsvar]").
6184 void emitter::emitIns_C(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, int offs)
6189 /*****************************************************************************
6191 * Add an instruction referencing stack-based local variable.
6194 void emitter::emitIns_S(instruction ins, emitAttr attr, int varx, int offs)
6199 /*****************************************************************************
6201 * Add an instruction referencing a register and a stack-based local variable.
6203 void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
6205 emitAttr size = EA_SIZE(attr);
6206 insFormat fmt = IF_NONE;
6212 // TODO-ARM64-CQ: use unscaled loads?
6213 /* Figure out the encoding format of the instruction */
6234 assert(isValidGeneralDatasize(size) || isValidVectorDatasize(size));
6235 scale = genLog2(EA_SIZE_IN_BYTES(size));
6239 assert(size == EA_8BYTE);
6244 NYI("emitIns_R_S"); // FP locals?
6247 } // end switch (ins)
6249 /* Figure out the variable's frame position */
6254 base = emitComp->lvaFrameAddress(varx, &FPbased);
6256 assert((scale >= 0) && (scale <= 4));
6258 regNumber reg2 = FPbased ? REG_FPBASE : REG_SPBASE;
6259 reg2 = encodingSPtoZR(reg2);
6276 fmt = IF_DI_2A; // add reg1,reg2,#disp
6280 regNumber rsvdReg = codeGen->rsGetRsvdReg();
6281 codeGen->instGen_Set_Reg_To_Imm(size, rsvdReg, imm);
6282 fmt = IF_DR_3A; // add reg1,reg2,rsvdReg
6287 bool useRegForImm = false;
6288 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6295 else if ((imm < 0) || ((imm & mask) != 0))
6297 if ((imm >= -256) && (imm <= 255))
6303 useRegForImm = true;
6308 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
6310 imm >>= scale; // The immediate is scaled by the size of the ld/st
6316 useRegForImm = true;
6322 regNumber rsvdReg = codeGen->rsGetRsvdReg();
6323 codeGen->instGen_Set_Reg_To_Imm(size, rsvdReg, imm);
6328 assert(fmt != IF_NONE);
6330 instrDesc* id = emitNewInstrCns(attr, imm);
6334 id->idInsOpt(INS_OPTS_NONE);
6338 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6339 id->idSetIsLclVar();
6342 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6349 /*****************************************************************************
6351 * Add an instruction referencing two register and consectutive stack-based local variable slots.
6353 void emitter::emitIns_R_R_S_S(
6354 instruction ins, emitAttr attr1, emitAttr attr2, regNumber reg1, regNumber reg2, int varx, int offs)
6356 assert((ins == INS_ldp) || (ins == INS_ldnp));
6357 assert(EA_8BYTE == EA_SIZE(attr1));
6358 assert(EA_8BYTE == EA_SIZE(attr2));
6359 assert(isGeneralRegisterOrZR(reg1));
6360 assert(isGeneralRegisterOrZR(reg2));
6363 emitAttr size = EA_SIZE(attr1);
6364 insFormat fmt = IF_LS_3B;
6366 const unsigned scale = 3;
6368 /* Figure out the variable's frame position */
6372 base = emitComp->lvaFrameAddress(varx, &FPbased);
6375 // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6376 regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE;
6377 reg3 = encodingSPtoZR(reg3);
6379 bool useRegForAdr = true;
6381 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6384 useRegForAdr = false;
6388 if ((imm & mask) == 0)
6390 ssize_t immShift = imm >> scale; // The immediate is scaled by the size of the ld/st
6392 if ((immShift >= -64) && (immShift <= 63))
6395 useRegForAdr = false;
6403 regNumber rsvd = codeGen->rsGetRsvdReg();
6404 emitIns_R_R_Imm(INS_add, EA_8BYTE, rsvd, reg3, imm);
6409 assert(fmt != IF_NONE);
6411 instrDesc* id = emitNewInstrCns(attr1, imm);
6415 id->idInsOpt(INS_OPTS_NONE);
6417 // Record the attribute for the second register in the pair
6418 if (EA_IS_GCREF(attr2))
6420 id->idGCrefReg2(GCT_GCREF);
6422 else if (EA_IS_BYREF(attr2))
6424 id->idGCrefReg2(GCT_BYREF);
6428 id->idGCrefReg2(GCT_NONE);
6434 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6435 id->idSetIsLclVar();
6438 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6445 /*****************************************************************************
6447 * Add an instruction referencing a stack-based local variable and a register
6449 void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
6452 emitAttr size = EA_SIZE(attr);
6453 insFormat fmt = IF_NONE;
6456 bool isVectorStore = false;
6458 // TODO-ARM64-CQ: use unscaled loads?
6459 /* Figure out the encoding format of the instruction */
6464 assert(isGeneralRegisterOrZR(reg1));
6469 assert(isGeneralRegisterOrZR(reg1));
6473 if (isGeneralRegisterOrZR(reg1))
6475 assert(isValidGeneralDatasize(size));
6476 scale = (size == EA_8BYTE) ? 3 : 2;
6480 assert(isVectorRegister(reg1));
6481 assert(isValidVectorLSDatasize(size));
6482 scale = NaturalScale_helper(size);
6483 isVectorStore = true;
6488 NYI("emitIns_S_R"); // FP locals?
6491 } // end switch (ins)
6493 /* Figure out the variable's frame position */
6497 base = emitComp->lvaFrameAddress(varx, &FPbased);
6509 // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6510 regNumber reg2 = FPbased ? REG_FPBASE : REG_SPBASE;
6511 reg2 = encodingSPtoZR(reg2);
6513 bool useRegForImm = false;
6515 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6520 else if ((imm < 0) || ((imm & mask) != 0))
6522 if ((imm >= -256) && (imm <= 255))
6528 useRegForImm = true;
6533 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
6535 imm >>= scale; // The immediate is scaled by the size of the ld/st
6541 useRegForImm = true;
6547 // The reserved register is not stored in idReg3() since that field overlaps with iiaLclVar.
6548 // It is instead implicit when idSetIsLclVar() is set, with this encoding format.
6549 regNumber rsvdReg = codeGen->rsGetRsvdReg();
6550 codeGen->instGen_Set_Reg_To_Imm(size, rsvdReg, imm);
6554 assert(fmt != IF_NONE);
6556 instrDesc* id = emitNewInstrCns(attr, imm);
6560 id->idInsOpt(INS_OPTS_NONE);
6564 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6565 id->idSetIsLclVar();
6568 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6575 /*****************************************************************************
6577 * Add an instruction referencing consecutive stack-based local variable slots and two registers
6579 void emitter::emitIns_S_S_R_R(
6580 instruction ins, emitAttr attr1, emitAttr attr2, regNumber reg1, regNumber reg2, int varx, int offs)
6582 assert((ins == INS_stp) || (ins == INS_stnp));
6583 assert(EA_8BYTE == EA_SIZE(attr1));
6584 assert(EA_8BYTE == EA_SIZE(attr2));
6585 assert(isGeneralRegisterOrZR(reg1));
6586 assert(isGeneralRegisterOrZR(reg2));
6589 emitAttr size = EA_SIZE(attr1);
6590 insFormat fmt = IF_LS_3B;
6592 const unsigned scale = 3;
6594 /* Figure out the variable's frame position */
6598 base = emitComp->lvaFrameAddress(varx, &FPbased);
6601 // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6602 regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE;
6603 reg3 = encodingSPtoZR(reg3);
6605 bool useRegForAdr = true;
6607 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6610 useRegForAdr = false;
6614 if ((imm & mask) == 0)
6616 ssize_t immShift = imm >> scale; // The immediate is scaled by the size of the ld/st
6618 if ((immShift >= -64) && (immShift <= 63))
6621 useRegForAdr = false;
6629 regNumber rsvd = codeGen->rsGetRsvdReg();
6630 emitIns_R_R_Imm(INS_add, EA_8BYTE, rsvd, reg3, imm);
6635 assert(fmt != IF_NONE);
6637 instrDesc* id = emitNewInstrCns(attr1, imm);
6641 id->idInsOpt(INS_OPTS_NONE);
6643 // Record the attribute for the second register in the pair
6644 if (EA_IS_GCREF(attr2))
6646 id->idGCrefReg2(GCT_GCREF);
6648 else if (EA_IS_BYREF(attr2))
6650 id->idGCrefReg2(GCT_BYREF);
6654 id->idGCrefReg2(GCT_NONE);
6660 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6661 id->idSetIsLclVar();
6664 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6671 /*****************************************************************************
6673 * Add an instruction referencing stack-based local variable and an immediate
6675 void emitter::emitIns_S_I(instruction ins, emitAttr attr, int varx, int offs, int val)
6680 /*****************************************************************************
6682 * Add an instruction with a register + static member operands.
6683 * Constant is stored into JIT data which is adjacent to code.
6684 * No relocation is needed. PC-relative offset will be encoded directly into instruction.
6687 void emitter::emitIns_R_C(
6688 instruction ins, emitAttr attr, regNumber reg, regNumber addrReg, CORINFO_FIELD_HANDLE fldHnd, int offs)
6691 assert(instrDesc::fitsInSmallCns(offs));
6693 emitAttr size = EA_SIZE(attr);
6694 insFormat fmt = IF_NONE;
6696 instrDescJmp* id = emitNewInstrJmp();
6701 // This is case to get address to the constant data.
6703 assert(isGeneralRegister(reg));
6704 assert(isValidGeneralDatasize(size));
6709 if (isVectorRegister(reg))
6711 assert(isValidScalarDatasize(size));
6712 // For vector (float/double) register, we should have an integer address reg to
6713 // compute long address which consists of page address and page offset.
6714 // For integer constant, this is not needed since the dest reg can be used to
6715 // compute address as well as contain the final contents.
6716 assert(isGeneralRegister(reg) || (addrReg != REG_NA));
6720 assert(isGeneralRegister(reg));
6721 assert(isValidGeneralDatasize(size));
6728 assert(fmt != IF_NONE);
6732 id->idInsOpt(INS_OPTS_NONE);
6733 id->idSmallCns(offs);
6735 id->idAddr()->iiaFieldHnd = fldHnd;
6736 id->idSetIsBound(); // We won't patch address since we will know the exact distance once JIT code and data are
6737 // allocated together.
6739 id->idReg1(reg); // destination register that will get the constant value.
6740 if (addrReg != REG_NA)
6742 id->idReg2(addrReg); // integer register to compute long address (used for vector dest when we end up with long
6745 id->idjShort = false; // Assume loading constant from long address
6747 // Keep it long if it's in cold code.
6748 id->idjKeepLong = emitComp->fgIsBlockCold(emitComp->compCurBB);
6751 if (emitComp->opts.compLongAddress)
6752 id->idjKeepLong = 1;
6755 // If it's possible to be shortened, then put it in jump list
6756 // to be revisited by emitJumpDistBind.
6757 if (!id->idjKeepLong)
6759 /* Record the jump's IG and offset within it */
6760 id->idjIG = emitCurIG;
6761 id->idjOffs = emitCurIGsize;
6763 /* Append this jump to this IG's jump list */
6764 id->idjNext = emitCurIGjmpList;
6765 emitCurIGjmpList = id;
6776 /*****************************************************************************
6778 * Add an instruction with a static member + constant.
6781 void emitter::emitIns_C_I(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, ssize_t offs, ssize_t val)
6786 /*****************************************************************************
6788 * Add an instruction with a static member + register operands.
6791 void emitter::emitIns_C_R(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, regNumber reg, int offs)
6793 assert(!"emitIns_C_R not supported for RyuJIT backend");
6796 void emitter::emitIns_R_AR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
6798 NYI("emitIns_R_AR");
6801 // This computes address from the immediate which is relocatable.
6802 void emitter::emitIns_R_AI(instruction ins, emitAttr attr, regNumber ireg, ssize_t addr)
6804 assert(EA_IS_RELOC(attr));
6805 emitAttr size = EA_SIZE(attr);
6806 insFormat fmt = IF_DI_1E;
6807 bool needAdd = false;
6808 instrDescJmp* id = emitNewInstrJmp();
6813 // This computes page address.
6814 // page offset is needed using add.
6825 id->idInsOpt(INS_OPTS_NONE);
6827 id->idAddr()->iiaAddr = (BYTE*)addr;
6829 id->idSetIsDspReloc();
6836 // add reg, reg, imm
6839 instrDesc* id = emitAllocInstr(attr);
6840 assert(id->idIsReloc());
6844 id->idInsOpt(INS_OPTS_NONE);
6846 id->idAddr()->iiaAddr = (BYTE*)addr;
6855 void emitter::emitIns_AR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
6857 NYI("emitIns_AR_R");
6860 void emitter::emitIns_R_ARR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
6862 NYI("emitIns_R_ARR");
6865 void emitter::emitIns_ARR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
6867 NYI("emitIns_R_ARR");
6870 void emitter::emitIns_R_ARX(
6871 instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, unsigned mul, int disp)
6873 NYI("emitIns_R_ARR");
6876 /*****************************************************************************
6878 * Record that a jump instruction uses the short encoding
6881 void emitter::emitSetShortJump(instrDescJmp* id)
6883 if (id->idjKeepLong)
6886 insFormat fmt = IF_NONE;
6887 if (emitIsCondJump(id))
6889 switch (id->idIns())
6904 else if (emitIsLoadLabel(id))
6908 else if (emitIsLoadConstant(id))
6918 id->idjShort = true;
6921 /*****************************************************************************
6923 * Add a label instruction.
6926 void emitter::emitIns_R_L(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
6928 assert(dst->bbFlags & BBF_JMP_TARGET);
6930 insFormat fmt = IF_NONE;
6941 instrDescJmp* id = emitNewInstrJmp();
6945 id->idjShort = false;
6946 id->idAddr()->iiaBBlabel = dst;
6948 id->idOpSize(EA_PTRSIZE);
6951 // Mark the catch return
6952 if (emitComp->compCurBB->bbJumpKind == BBJ_EHCATCHRET)
6954 id->idDebugOnlyInfo()->idCatchRet = true;
6958 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
6961 if (emitComp->opts.compLongAddress)
6962 id->idjKeepLong = 1;
6965 /* Record the jump's IG and offset within it */
6967 id->idjIG = emitCurIG;
6968 id->idjOffs = emitCurIGsize;
6970 /* Append this jump to this IG's jump list */
6972 id->idjNext = emitCurIGjmpList;
6973 emitCurIGjmpList = id;
6983 /*****************************************************************************
6985 * Add a data label instruction.
6988 void emitter::emitIns_R_D(instruction ins, emitAttr attr, unsigned offs, regNumber reg)
6993 void emitter::emitIns_J_R(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
6995 assert((ins == INS_cbz) || (ins == INS_cbnz));
6997 assert(dst != nullptr);
6998 assert((dst->bbFlags & BBF_JMP_TARGET) != 0);
7000 insFormat fmt = IF_LARGEJMP;
7002 instrDescJmp* id = emitNewInstrJmp();
7007 id->idjShort = false;
7008 id->idOpSize(EA_SIZE(attr));
7010 id->idAddr()->iiaBBlabel = dst;
7011 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7013 /* Record the jump's IG and offset within it */
7015 id->idjIG = emitCurIG;
7016 id->idjOffs = emitCurIGsize;
7018 /* Append this jump to this IG's jump list */
7020 id->idjNext = emitCurIGjmpList;
7021 emitCurIGjmpList = id;
7031 void emitter::emitIns_J_R_I(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg, int imm)
7033 assert((ins == INS_tbz) || (ins == INS_tbnz));
7035 assert(dst != nullptr);
7036 assert((dst->bbFlags & BBF_JMP_TARGET) != 0);
7037 assert((EA_SIZE(attr) == EA_4BYTE) || (EA_SIZE(attr) == EA_8BYTE));
7038 assert(imm < ((EA_SIZE(attr) == EA_4BYTE) ? 32 : 64));
7040 insFormat fmt = IF_LARGEJMP;
7042 instrDescJmp* id = emitNewInstrJmp();
7047 id->idjShort = false;
7048 id->idSmallCns(imm);
7049 id->idOpSize(EA_SIZE(attr));
7051 id->idAddr()->iiaBBlabel = dst;
7052 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7054 /* Record the jump's IG and offset within it */
7056 id->idjIG = emitCurIG;
7057 id->idjOffs = emitCurIGsize;
7059 /* Append this jump to this IG's jump list */
7061 id->idjNext = emitCurIGjmpList;
7062 emitCurIGjmpList = id;
7072 void emitter::emitIns_J(instruction ins, BasicBlock* dst, int instrCount)
7074 insFormat fmt = IF_NONE;
7078 assert(dst->bbFlags & BBF_JMP_TARGET);
7082 assert(instrCount != 0);
7085 /* Figure out the encoding format of the instruction */
7087 bool idjShort = false;
7092 // Unconditional jump is a single form.
7111 // Assume conditional jump is long.
7120 instrDescJmp* id = emitNewInstrJmp();
7124 id->idjShort = idjShort;
7127 // Mark the finally call
7128 if (ins == INS_bl_local && emitComp->compCurBB->bbJumpKind == BBJ_CALLFINALLY)
7130 id->idDebugOnlyInfo()->idFinallyCall = true;
7136 id->idAddr()->iiaBBlabel = dst;
7138 // Skip unconditional jump that has a single form.
7139 // TODO-ARM64-NYI: enable hot/cold splittingNYI.
7140 // The target needs to be relocated.
7143 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7146 if (emitComp->opts.compLongAddress) // Force long branches
7147 id->idjKeepLong = 1;
7153 id->idAddr()->iiaSetInstrCount(instrCount);
7154 id->idjKeepLong = false;
7155 /* This jump must be short */
7156 emitSetShortJump(id);
7160 /* Record the jump's IG and offset within it */
7162 id->idjIG = emitCurIG;
7163 id->idjOffs = emitCurIGsize;
7165 /* Append this jump to this IG's jump list */
7167 id->idjNext = emitCurIGjmpList;
7168 emitCurIGjmpList = id;
7178 /*****************************************************************************
7180 * Add a call instruction (direct or indirect).
7181 * argSize<0 means that the caller will pop the arguments
7183 * The other arguments are interpreted depending on callType as shown:
7184 * Unless otherwise specified, ireg,xreg,xmul,disp should have default values.
7186 * EC_FUNC_TOKEN : addr is the method address
7187 * EC_FUNC_ADDR : addr is the absolute address of the function
7189 * If callType is one of these emitCallTypes, addr has to be NULL.
7190 * EC_INDIR_R : "call ireg".
7192 * For ARM xreg, xmul and disp are never used and should always be 0/REG_NA.
7194 * Please consult the "debugger team notification" comment in genFnProlog().
7197 void emitter::emitIns_Call(EmitCallType callType,
7198 CORINFO_METHOD_HANDLE methHnd,
7199 INDEBUG_LDISASM_COMMA(CORINFO_SIG_INFO* sigInfo) // used to report call sites to the EE
7203 emitAttr secondRetSize,
7204 VARSET_VALARG_TP ptrVars,
7205 regMaskTP gcrefRegs,
7206 regMaskTP byrefRegs,
7207 IL_OFFSETX ilOffset /* = BAD_IL_OFFSET */,
7208 regNumber ireg /* = REG_NA */,
7209 regNumber xreg /* = REG_NA */,
7210 unsigned xmul /* = 0 */,
7211 ssize_t disp /* = 0 */,
7212 bool isJump /* = false */,
7213 bool isNoGC /* = false */,
7214 bool isProfLeaveCB /* = false */)
7216 /* Sanity check the arguments depending on callType */
7218 assert(callType < EC_COUNT);
7219 assert((callType != EC_FUNC_TOKEN && callType != EC_FUNC_ADDR) ||
7220 (ireg == REG_NA && xreg == REG_NA && xmul == 0 && disp == 0));
7221 assert(callType < EC_INDIR_R || addr == NULL);
7222 assert(callType != EC_INDIR_R || (ireg < REG_COUNT && xreg == REG_NA && xmul == 0 && disp == 0));
7224 // ARM never uses these
7225 assert(xreg == REG_NA && xmul == 0 && disp == 0);
7227 // Our stack level should be always greater than the bytes of arguments we push. Just
7229 assert((unsigned)abs(argSize) <= codeGen->genStackLevel);
7234 /* This is the saved set of registers after a normal call */
7235 regMaskTP savedSet = RBM_CALLEE_SAVED;
7237 /* some special helper calls have a different saved set registers */
7241 assert(emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
7243 // Get the set of registers that this call kills and remove it from the saved set.
7244 savedSet = RBM_ALLINT & ~emitComp->compNoGCHelperCallKillSet(Compiler::eeGetHelperNum(methHnd));
7246 // In case of Leave profiler callback, we need to preserve liveness of REG_PROFILER_RET_SCRATCH
7249 savedSet |= RBM_PROFILER_RET_SCRATCH;
7254 assert(!emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
7257 /* Trim out any callee-trashed registers from the live set */
7259 gcrefRegs &= savedSet;
7260 byrefRegs &= savedSet;
7263 if (EMIT_GC_VERBOSE)
7265 printf("Call: GCvars=%s ", VarSetOps::ToString(emitComp, ptrVars));
7266 dumpConvertedVarSet(emitComp, ptrVars);
7267 printf(", gcrefRegs=");
7268 printRegMaskInt(gcrefRegs);
7269 emitDispRegSet(gcrefRegs);
7270 printf(", byrefRegs=");
7271 printRegMaskInt(byrefRegs);
7272 emitDispRegSet(byrefRegs);
7277 assert(argSize % REGSIZE_BYTES == 0);
7278 argCnt = (int)(argSize / (int)sizeof(void*));
7280 /* Managed RetVal: emit sequence point for the call */
7281 if (emitComp->opts.compDbgInfo && ilOffset != BAD_IL_OFFSET)
7283 codeGen->genIPmappingAdd(ilOffset, false);
7287 We need to allocate the appropriate instruction descriptor based
7288 on whether this is a direct/indirect call, and whether we need to
7289 record an updated set of live GC variables.
7292 if (callType >= EC_INDIR_R)
7294 /* Indirect call, virtual calls */
7296 assert(callType == EC_INDIR_R);
7298 id = emitNewInstrCallInd(argCnt, disp, ptrVars, gcrefRegs, byrefRegs, retSize, secondRetSize);
7302 /* Helper/static/nonvirtual/function calls (direct or through handle),
7303 and calls to an absolute addr. */
7305 assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
7307 id = emitNewInstrCallDir(argCnt, ptrVars, gcrefRegs, byrefRegs, retSize, secondRetSize);
7310 /* Update the emitter's live GC ref sets */
7312 VarSetOps::Assign(emitComp, emitThisGCrefVars, ptrVars);
7313 emitThisGCrefRegs = gcrefRegs;
7314 emitThisByrefRegs = byrefRegs;
7316 /* Set the instruction - special case jumping a function */
7318 insFormat fmt = IF_NONE;
7320 id->idSetIsNoGC(isNoGC);
7322 /* Record the address: method, indirection, or funcptr */
7324 if (callType > EC_FUNC_ADDR)
7326 /* This is an indirect call (either a virtual call or func ptr call) */
7330 case EC_INDIR_R: // the address is in a register
7332 id->idSetIsCallRegPtr();
7336 ins = INS_br_tail; // INS_br_tail Reg
7340 ins = INS_blr; // INS_blr Reg
7348 assert(xreg == REG_NA);
7352 NO_WAY("unexpected instruction");
7358 /* This is a simple direct call: "call helper/method/addr" */
7360 assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
7362 assert(addr != NULL);
7366 ins = INS_b_tail; // INS_b_tail imm28
7370 ins = INS_bl; // INS_bl imm28
7377 id->idAddr()->iiaAddr = (BYTE*)addr;
7379 if (callType == EC_FUNC_ADDR)
7381 id->idSetIsCallAddr();
7384 if (emitComp->opts.compReloc)
7386 id->idSetIsDspReloc();
7391 if (EMIT_GC_VERBOSE)
7393 if (id->idIsLargeCall())
7395 printf("[%02u] Rec call GC vars = %s\n", id->idDebugOnlyInfo()->idNum,
7396 VarSetOps::ToString(emitComp, ((instrDescCGCA*)id)->idcGCvars));
7400 id->idDebugOnlyInfo()->idMemCookie = (size_t)methHnd; // method token
7401 id->idDebugOnlyInfo()->idCallSig = sigInfo;
7405 if (addr != nullptr)
7407 codeGen->getDisAssembler().disSetMethod((size_t)addr, methHnd);
7409 #endif // LATE_DISASM
7415 /*****************************************************************************
7417 * Returns true if 'imm' is valid Cond encoding
7420 /*static*/ bool emitter::isValidImmCond(ssize_t imm)
7422 // range check the ssize_t value, to make sure it is a small unsigned value
7423 // and that only the bits in the cfi.cond are set
7424 if ((imm < 0) || (imm > 0xF))
7428 cfi.immCFVal = (unsigned)imm;
7430 return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7433 /*****************************************************************************
7435 * Returns true if 'imm' is valid Cond/Flags encoding
7438 /*static*/ bool emitter::isValidImmCondFlags(ssize_t imm)
7440 // range check the ssize_t value, to make sure it is a small unsigned value
7441 // and that only the bits in the cfi.cond or cfi.flags are set
7442 if ((imm < 0) || (imm > 0xFF))
7446 cfi.immCFVal = (unsigned)imm;
7448 return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7451 /*****************************************************************************
7453 * Returns true if 'imm' is valid Cond/Flags/Imm5 encoding
7456 /*static*/ bool emitter::isValidImmCondFlagsImm5(ssize_t imm)
7458 // range check the ssize_t value, to make sure it is a small unsigned value
7459 // and that only the bits in the cfi.cond, cfi.flags or cfi.imm5 are set
7460 if ((imm < 0) || (imm > 0x1FFF))
7464 cfi.immCFVal = (unsigned)imm;
7466 return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7469 /*****************************************************************************
7471 * Returns an encoding for the specified register used in the 'Rd' position
7474 /*static*/ emitter::code_t emitter::insEncodeReg_Rd(regNumber reg)
7476 assert(isIntegerRegister(reg));
7477 emitter::code_t ureg = (emitter::code_t)reg;
7478 assert((ureg >= 0) && (ureg <= 31));
7482 /*****************************************************************************
7484 * Returns an encoding for the specified register used in the 'Rt' position
7487 /*static*/ emitter::code_t emitter::insEncodeReg_Rt(regNumber reg)
7489 assert(isIntegerRegister(reg));
7490 emitter::code_t ureg = (emitter::code_t)reg;
7491 assert((ureg >= 0) && (ureg <= 31));
7495 /*****************************************************************************
7497 * Returns an encoding for the specified register used in the 'Rn' position
7500 /*static*/ emitter::code_t emitter::insEncodeReg_Rn(regNumber reg)
7502 assert(isIntegerRegister(reg));
7503 emitter::code_t ureg = (emitter::code_t)reg;
7504 assert((ureg >= 0) && (ureg <= 31));
7508 /*****************************************************************************
7510 * Returns an encoding for the specified register used in the 'Rm' position
7513 /*static*/ emitter::code_t emitter::insEncodeReg_Rm(regNumber reg)
7515 assert(isIntegerRegister(reg));
7516 emitter::code_t ureg = (emitter::code_t)reg;
7517 assert((ureg >= 0) && (ureg <= 31));
7521 /*****************************************************************************
7523 * Returns an encoding for the specified register used in the 'Ra' position
7526 /*static*/ emitter::code_t emitter::insEncodeReg_Ra(regNumber reg)
7528 assert(isIntegerRegister(reg));
7529 emitter::code_t ureg = (emitter::code_t)reg;
7530 assert((ureg >= 0) && (ureg <= 31));
7534 /*****************************************************************************
7536 * Returns an encoding for the specified register used in the 'Vd' position
7539 /*static*/ emitter::code_t emitter::insEncodeReg_Vd(regNumber reg)
7541 assert(emitter::isVectorRegister(reg));
7542 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7543 assert((ureg >= 0) && (ureg <= 31));
7547 /*****************************************************************************
7549 * Returns an encoding for the specified register used in the 'Vt' position
7552 /*static*/ emitter::code_t emitter::insEncodeReg_Vt(regNumber reg)
7554 assert(emitter::isVectorRegister(reg));
7555 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7556 assert((ureg >= 0) && (ureg <= 31));
7560 /*****************************************************************************
7562 * Returns an encoding for the specified register used in the 'Vn' position
7565 /*static*/ emitter::code_t emitter::insEncodeReg_Vn(regNumber reg)
7567 assert(emitter::isVectorRegister(reg));
7568 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7569 assert((ureg >= 0) && (ureg <= 31));
7573 /*****************************************************************************
7575 * Returns an encoding for the specified register used in the 'Vm' position
7578 /*static*/ emitter::code_t emitter::insEncodeReg_Vm(regNumber reg)
7580 assert(emitter::isVectorRegister(reg));
7581 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7582 assert((ureg >= 0) && (ureg <= 31));
7586 /*****************************************************************************
7588 * Returns an encoding for the specified register used in the 'Va' position
7591 /*static*/ emitter::code_t emitter::insEncodeReg_Va(regNumber reg)
7593 assert(emitter::isVectorRegister(reg));
7594 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7595 assert((ureg >= 0) && (ureg <= 31));
7599 /*****************************************************************************
7601 * Returns an encoding for the specified condition code.
7604 /*static*/ emitter::code_t emitter::insEncodeCond(insCond cond)
7606 emitter::code_t uimm = (emitter::code_t)cond;
7610 /*****************************************************************************
7612 * Returns an encoding for the condition code with the lowest bit inverted (marked by invert(<cond>) in the
7613 * architecture manual).
7616 /*static*/ emitter::code_t emitter::insEncodeInvertedCond(insCond cond)
7618 emitter::code_t uimm = (emitter::code_t)cond;
7619 uimm ^= 1; // invert the lowest bit
7623 /*****************************************************************************
7625 * Returns an encoding for the specified flags.
7628 /*static*/ emitter::code_t emitter::insEncodeFlags(insCflags flags)
7630 emitter::code_t uimm = (emitter::code_t)flags;
7634 /*****************************************************************************
7636 * Returns the encoding for the Shift Count bits to be used for Arm64 encodings
7639 /*static*/ emitter::code_t emitter::insEncodeShiftCount(ssize_t imm, emitAttr size)
7641 assert((imm & 0x003F) == imm);
7642 assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
7644 return (emitter::code_t)imm << 10;
7647 /*****************************************************************************
7649 * Returns the encoding to select a 64-bit datasize for an Arm64 instruction
7652 /*static*/ emitter::code_t emitter::insEncodeDatasize(emitAttr size)
7654 if (size == EA_8BYTE)
7656 return 0x80000000; // set the bit at location 31
7660 assert(size == EA_4BYTE);
7665 /*****************************************************************************
7667 * Returns the encoding to select the datasize for the general load/store Arm64 instructions
7671 /*static*/ emitter::code_t emitter::insEncodeDatasizeLS(emitter::code_t code, emitAttr size)
7673 bool exclusive = ((code & 0x35000000) == 0);
7675 if ((code & 0x00800000) && !exclusive) // Is this a sign-extending opcode? (i.e. ldrsw, ldrsh, ldrsb)
7677 assert((size == EA_4BYTE) || (size == EA_8BYTE));
7678 if ((code & 0x80000000) == 0) // Is it a ldrsh or ldrsb and not ldrsw ?
7680 if (size == EA_4BYTE) // Do we need to encode the 32-bit Rt size bit?
7682 return 0x00400000; // set the bit at location 22
7686 else if (code & 0x80000000) // Is this a ldr/str/ldur/stur opcode?
7688 assert((size == EA_4BYTE) || (size == EA_8BYTE));
7689 if (size == EA_8BYTE) // Do we need to encode the 64-bit size bit?
7691 return 0x40000000; // set the bit at location 30
7697 /*****************************************************************************
7699 * Returns the encoding to select the datasize for the vector load/store Arm64 instructions
7703 /*static*/ emitter::code_t emitter::insEncodeDatasizeVLS(emitter::code_t code, emitAttr size)
7708 if ((code & 0x20000000) == 0)
7712 if (size == EA_16BYTE)
7714 // set the operation size in bit 31
7715 result = 0x80000000;
7717 else if (size == EA_8BYTE)
7719 // set the operation size in bit 30
7720 result = 0x40000000;
7724 assert(size == EA_4BYTE);
7726 result = 0x00000000;
7733 if (size == EA_16BYTE)
7735 // The operation size in bits 31 and 30 are zero
7736 // Bit 23 specifies a 128-bit Load/Store
7737 result = 0x00800000;
7739 else if (size == EA_8BYTE)
7741 // set the operation size in bits 31 and 30
7742 result = 0xC0000000;
7744 else if (size == EA_4BYTE)
7746 // set the operation size in bit 31
7747 result = 0x80000000;
7749 else if (size == EA_2BYTE)
7751 // set the operation size in bit 30
7752 result = 0x40000000;
7756 assert(size == EA_1BYTE);
7757 // The operation size in bits 31 and 30 are zero
7758 result = 0x00000000;
7762 // Or in bit 26 to indicate a Vector register is used as 'target'
7763 result |= 0x04000000;
7768 /*****************************************************************************
7770 * Returns the encoding to select the datasize for the vector load/store Arm64 instructions
7774 /*static*/ emitter::code_t emitter::insEncodeDatasizeVPLS(emitter::code_t code, emitAttr size)
7778 if (size == EA_16BYTE)
7780 // The operation size in bits 31 and 30 are zero
7781 // Bit 23 specifies a 128-bit Load/Store
7782 result = 0x80000000;
7784 else if (size == EA_8BYTE)
7786 // set the operation size in bits 31 and 30
7787 result = 0x40000000;
7789 else if (size == EA_4BYTE)
7791 // set the operation size in bit 31
7792 result = 0x00000000;
7795 // Or in bit 26 to indicate a Vector register is used as 'target'
7796 result |= 0x04000000;
7801 /*****************************************************************************
7803 * Returns the encoding to set the size bit and the N bits for a 'bitfield' instruction
7807 /*static*/ emitter::code_t emitter::insEncodeDatasizeBF(emitter::code_t code, emitAttr size)
7809 // is bit 30 equal to 0?
7810 if ((code & 0x40000000) == 0) // is the opcode one of extr, sxtb, sxth or sxtw
7812 if (size == EA_8BYTE) // Do we need to set the sf and N bits?
7814 return 0x80400000; // set the sf-bit at location 31 and the N-bit at location 22
7817 return 0; // don't set any bits
7820 /*****************************************************************************
7822 * Returns the encoding to select the 64/128-bit datasize for an Arm64 vector instruction
7825 /*static*/ emitter::code_t emitter::insEncodeVectorsize(emitAttr size)
7827 if (size == EA_16BYTE)
7829 return 0x40000000; // set the bit at location 30
7833 assert(size == EA_8BYTE);
7838 /*****************************************************************************
7840 * Returns the encoding to select 'index' for an Arm64 vector elem instruction
7842 /*static*/ emitter::code_t emitter::insEncodeVectorIndex(emitAttr elemsize, ssize_t index)
7844 code_t bits = (code_t)index;
7845 if (elemsize == EA_1BYTE)
7850 else if (elemsize == EA_2BYTE)
7855 else if (elemsize == EA_4BYTE)
7862 assert(elemsize == EA_8BYTE);
7866 assert((bits >= 1) && (bits <= 0x1f));
7868 return (bits << 16); // bits at locations [20,19,18,17,16]
7871 /*****************************************************************************
7873 * Returns the encoding to select 'index2' for an Arm64 'ins' elem instruction
7875 /*static*/ emitter::code_t emitter::insEncodeVectorIndex2(emitAttr elemsize, ssize_t index2)
7877 code_t bits = (code_t)index2;
7878 if (elemsize == EA_1BYTE)
7882 else if (elemsize == EA_2BYTE)
7886 else if (elemsize == EA_4BYTE)
7892 assert(elemsize == EA_8BYTE);
7895 assert((bits >= 0) && (bits <= 0xf));
7897 return (bits << 11); // bits at locations [14,13,12,11]
7900 /*****************************************************************************
7902 * Returns the encoding to select the 'index' for an Arm64 'mul' by elem instruction
7904 /*static*/ emitter::code_t emitter::insEncodeVectorIndexLMH(emitAttr elemsize, ssize_t index)
7908 if (elemsize == EA_2BYTE)
7910 assert((index >= 0) && (index <= 7));
7913 bits |= (1 << 11); // set bit 11 'H'
7917 bits |= (1 << 21); // set bit 21 'L'
7921 bits |= (1 << 20); // set bit 20 'M'
7924 else if (elemsize == EA_4BYTE)
7926 assert((index >= 0) && (index <= 3));
7929 bits |= (1 << 11); // set bit 11 'H'
7933 bits |= (1 << 21); // set bit 21 'L'
7938 assert(!"Invalid 'elemsize' value");
7944 /*****************************************************************************
7946 * Returns the encoding to shift by 'shift' for an Arm64 vector or scalar instruction
7949 /*static*/ emitter::code_t emitter::insEncodeVectorShift(emitAttr size, ssize_t shift)
7951 assert(shift < getBitWidth(size));
7953 code_t imm = (code_t)(getBitWidth(size) + shift);
7958 /*****************************************************************************
7960 * Returns the encoding to select the 1/2/4/8 byte elemsize for an Arm64 vector instruction
7963 /*static*/ emitter::code_t emitter::insEncodeElemsize(emitAttr size)
7965 if (size == EA_8BYTE)
7967 return 0x00C00000; // set the bit at location 23 and 22
7969 else if (size == EA_4BYTE)
7971 return 0x00800000; // set the bit at location 23
7973 else if (size == EA_2BYTE)
7975 return 0x00400000; // set the bit at location 22
7977 assert(size == EA_1BYTE);
7981 /*****************************************************************************
7983 * Returns the encoding to select the 4/8 byte elemsize for an Arm64 float vector instruction
7986 /*static*/ emitter::code_t emitter::insEncodeFloatElemsize(emitAttr size)
7988 if (size == EA_8BYTE)
7990 return 0x00400000; // set the bit at location 22
7992 assert(size == EA_4BYTE);
7996 // Returns the encoding to select the index for an Arm64 float vector by elem instruction
7997 /*static*/ emitter::code_t emitter::insEncodeFloatIndex(emitAttr elemsize, ssize_t index)
7999 code_t result = 0x00000000;
8000 if (elemsize == EA_8BYTE)
8002 assert((index >= 0) && (index <= 1));
8005 result |= 0x00000800; // 'H' - set the bit at location 11
8010 assert(elemsize == EA_4BYTE);
8011 assert((index >= 0) && (index <= 3));
8014 result |= 0x00000800; // 'H' - set the bit at location 11
8018 result |= 0x00200000; // 'L' - set the bit at location 21
8024 /*****************************************************************************
8026 * Returns the encoding to select the fcvt operation for Arm64 instructions
8028 /*static*/ emitter::code_t emitter::insEncodeConvertOpt(insFormat fmt, insOpts conversion)
8033 case INS_OPTS_S_TO_D: // Single to Double
8034 assert(fmt == IF_DV_2J);
8035 result = 0x00008000; // type=00, opc=01
8038 case INS_OPTS_D_TO_S: // Double to Single
8039 assert(fmt == IF_DV_2J);
8040 result = 0x00400000; // type=01, opc=00
8043 case INS_OPTS_H_TO_S: // Half to Single
8044 assert(fmt == IF_DV_2J);
8045 result = 0x00C00000; // type=11, opc=00
8048 case INS_OPTS_H_TO_D: // Half to Double
8049 assert(fmt == IF_DV_2J);
8050 result = 0x00C08000; // type=11, opc=01
8053 case INS_OPTS_S_TO_H: // Single to Half
8054 assert(fmt == IF_DV_2J);
8055 result = 0x00018000; // type=00, opc=11
8058 case INS_OPTS_D_TO_H: // Double to Half
8059 assert(fmt == IF_DV_2J);
8060 result = 0x00418000; // type=01, opc=11
8063 case INS_OPTS_S_TO_4BYTE: // Single to INT32
8064 assert(fmt == IF_DV_2H);
8065 result = 0x00000000; // sf=0, type=00
8068 case INS_OPTS_D_TO_4BYTE: // Double to INT32
8069 assert(fmt == IF_DV_2H);
8070 result = 0x00400000; // sf=0, type=01
8073 case INS_OPTS_S_TO_8BYTE: // Single to INT64
8074 assert(fmt == IF_DV_2H);
8075 result = 0x80000000; // sf=1, type=00
8078 case INS_OPTS_D_TO_8BYTE: // Double to INT64
8079 assert(fmt == IF_DV_2H);
8080 result = 0x80400000; // sf=1, type=01
8083 case INS_OPTS_4BYTE_TO_S: // INT32 to Single
8084 assert(fmt == IF_DV_2I);
8085 result = 0x00000000; // sf=0, type=00
8088 case INS_OPTS_4BYTE_TO_D: // INT32 to Double
8089 assert(fmt == IF_DV_2I);
8090 result = 0x00400000; // sf=0, type=01
8093 case INS_OPTS_8BYTE_TO_S: // INT64 to Single
8094 assert(fmt == IF_DV_2I);
8095 result = 0x80000000; // sf=1, type=00
8098 case INS_OPTS_8BYTE_TO_D: // INT64 to Double
8099 assert(fmt == IF_DV_2I);
8100 result = 0x80400000; // sf=1, type=01
8104 assert(!"Invalid 'conversion' value");
8110 /*****************************************************************************
8112 * Returns the encoding to have the Rn register be updated Pre/Post indexed
8116 /*static*/ emitter::code_t emitter::insEncodeIndexedOpt(insOpts opt)
8118 assert(emitter::insOptsNone(opt) || emitter::insOptsIndexed(opt));
8120 if (emitter::insOptsIndexed(opt))
8122 if (emitter::insOptsPostIndex(opt))
8124 return 0x00000400; // set the bit at location 10
8128 assert(emitter::insOptsPreIndex(opt));
8129 return 0x00000C00; // set the bit at location 10 and 11
8134 assert(emitter::insOptsNone(opt));
8135 return 0; // bits 10 and 11 are zero
8139 /*****************************************************************************
8141 * Returns the encoding for a ldp/stp instruction to have the Rn register
8142 * be updated Pre/Post indexed or not updated
8145 /*static*/ emitter::code_t emitter::insEncodePairIndexedOpt(instruction ins, insOpts opt)
8147 assert(emitter::insOptsNone(opt) || emitter::insOptsIndexed(opt));
8149 if ((ins == INS_ldnp) || (ins == INS_stnp))
8151 assert(emitter::insOptsNone(opt));
8152 return 0; // bits 23 and 24 are zero
8156 if (emitter::insOptsIndexed(opt))
8158 if (emitter::insOptsPostIndex(opt))
8160 return 0x00800000; // set the bit at location 23
8164 assert(emitter::insOptsPreIndex(opt));
8165 return 0x01800000; // set the bit at location 24 and 23
8170 assert(emitter::insOptsNone(opt));
8171 return 0x01000000; // set the bit at location 24
8176 /*****************************************************************************
8178 * Returns the encoding to apply a Shift Type on the Rm register
8181 /*static*/ emitter::code_t emitter::insEncodeShiftType(insOpts opt)
8183 if (emitter::insOptsNone(opt))
8185 // None implies the we encode LSL (with a zero immediate)
8188 assert(emitter::insOptsAnyShift(opt));
8190 emitter::code_t option = (emitter::code_t)opt - (emitter::code_t)INS_OPTS_LSL;
8191 assert(option <= 3);
8193 return option << 22; // bits 23, 22
8196 /*****************************************************************************
8198 * Returns the encoding to apply a 12 bit left shift to the immediate
8201 /*static*/ emitter::code_t emitter::insEncodeShiftImm12(insOpts opt)
8203 if (emitter::insOptsLSL12(opt))
8205 return 0x00400000; // set the bit at location 22
8210 /*****************************************************************************
8212 * Returns the encoding to have the Rm register use an extend operation
8215 /*static*/ emitter::code_t emitter::insEncodeExtend(insOpts opt)
8217 if (emitter::insOptsNone(opt) || (opt == INS_OPTS_LSL))
8219 // None or LSL implies the we encode UXTX
8220 opt = INS_OPTS_UXTX;
8222 assert(emitter::insOptsAnyExtend(opt));
8224 emitter::code_t option = (emitter::code_t)opt - (emitter::code_t)INS_OPTS_UXTB;
8225 assert(option <= 7);
8227 return option << 13; // bits 15,14,13
8230 /*****************************************************************************
8232 * Returns the encoding to scale the Rm register by {0,1,2,3,4}
8233 * when using an extend operation
8236 /*static*/ emitter::code_t emitter::insEncodeExtendScale(ssize_t imm)
8238 assert((imm >= 0) && (imm <= 4));
8240 return (emitter::code_t)imm << 10; // bits 12,11,10
8243 /*****************************************************************************
8245 * Returns the encoding to have the Rm register be auto scaled by the ld/st size
8248 /*static*/ emitter::code_t emitter::insEncodeReg3Scale(bool isScaled)
8252 return 0x00001000; // set the bit at location 12
8260 BYTE* emitter::emitOutputLoadLabel(BYTE* dst, BYTE* srcAddr, BYTE* dstAddr, instrDescJmp* id)
8262 instruction ins = id->idIns();
8263 insFormat fmt = id->idInsFmt();
8264 regNumber dstReg = id->idReg1();
8267 // adr x, [rel addr] -- compute address: current addr(ip) + rel addr.
8268 assert(ins == INS_adr);
8269 assert(fmt == IF_DI_1E);
8270 ssize_t distVal = (ssize_t)(dstAddr - srcAddr);
8271 dst = emitOutputShortAddress(dst, ins, fmt, distVal, dstReg);
8275 // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8276 assert(fmt == IF_LARGEADR);
8277 ssize_t relPageAddr =
8278 (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8279 dst = emitOutputShortAddress(dst, INS_adrp, IF_DI_1E, relPageAddr, dstReg);
8281 // add x, x, page offs -- compute address = page addr + page offs
8282 ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8283 assert(isValidUimm12(imm12));
8285 emitInsCode(INS_add, IF_DI_2A); // DI_2A X0010001shiiiiii iiiiiinnnnnddddd 1100 0000 imm(i12, sh)
8286 code |= insEncodeDatasize(EA_8BYTE); // X
8287 code |= ((code_t)imm12 << 10); // iiiiiiiiiiii
8288 code |= insEncodeReg_Rd(dstReg); // ddddd
8289 code |= insEncodeReg_Rn(dstReg); // nnnnn
8290 dst += emitOutput_Instr(dst, code);
8295 /*****************************************************************************
8297 * Output a local jump or other instruction with a pc-relative immediate.
8298 * Note that this may be invoked to overwrite an existing jump instruction at 'dst'
8299 * to handle forward branch patching.
8302 BYTE* emitter::emitOutputLJ(insGroup* ig, BYTE* dst, instrDesc* i)
8304 instrDescJmp* id = (instrDescJmp*)i;
8313 // Set default ins/fmt from id.
8314 instruction ins = id->idIns();
8315 insFormat fmt = id->idInsFmt();
8317 bool loadLabel = false;
8318 bool isJump = false;
8319 bool loadConstant = false;
8336 loadConstant = true;
8345 /* Figure out the distance to the target */
8347 srcOffs = emitCurCodeOffs(dst);
8348 srcAddr = emitOffsetToPtr(srcOffs);
8350 if (id->idAddr()->iiaIsJitDataOffset())
8352 assert(loadConstant || loadLabel);
8353 int doff = id->idAddr()->iiaGetJitDataOffset();
8355 ssize_t imm = emitGetInsSC(id);
8356 assert((imm >= 0) && (imm < 0x1000)); // 0x1000 is arbitrary, currently 'imm' is always 0
8358 unsigned dataOffs = (unsigned)(doff + imm);
8359 assert(dataOffs < emitDataSize());
8360 dstAddr = emitDataOffsetToPtr(dataOffs);
8362 regNumber dstReg = id->idReg1();
8363 regNumber addrReg = dstReg; // an integer register to compute long address.
8364 emitAttr opSize = id->idOpSize();
8370 // ldr x/v, [rel addr] -- load constant from current addr(ip) + rel addr.
8371 assert(ins == INS_ldr);
8372 assert(fmt == IF_LS_1A);
8373 distVal = (ssize_t)(dstAddr - srcAddr);
8374 dst = emitOutputShortConstant(dst, ins, fmt, distVal, dstReg, opSize);
8378 // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8379 assert(fmt == IF_LARGELDC);
8380 ssize_t relPageAddr =
8381 (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8382 if (isVectorRegister(dstReg))
8384 // Update addrReg with the reserved integer register
8385 // since we cannot use dstReg (vector) to load constant directly from memory.
8386 addrReg = id->idReg2();
8387 assert(isGeneralRegister(addrReg));
8391 dst = emitOutputShortAddress(dst, ins, fmt, relPageAddr, addrReg);
8393 // ldr x, [x, page offs] -- load constant from page address + page offset into integer register.
8394 ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8395 assert(isValidUimm12(imm12));
8398 dst = emitOutputShortConstant(dst, ins, fmt, imm12, addrReg, opSize);
8400 // fmov v, d -- copy constant in integer register to vector register.
8401 // This is needed only for vector constant.
8402 if (addrReg != dstReg)
8404 // fmov Vd,Rn DV_2I X00111100X100111 000000nnnnnddddd 1E27 0000 Vd,Rn
8405 // (scalar, from general)
8406 assert(isVectorRegister(dstReg) && isGeneralRegister(addrReg));
8409 code_t code = emitInsCode(ins, fmt);
8411 code |= insEncodeReg_Vd(dstReg); // ddddd
8412 code |= insEncodeReg_Rn(addrReg); // nnnnn
8413 if (id->idOpSize() == EA_8BYTE)
8415 code |= 0x80400000; // X ... X
8417 dst += emitOutput_Instr(dst, code);
8424 dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8430 assert(loadLabel || isJump);
8432 if (id->idAddr()->iiaHasInstrCount())
8435 int instrCount = id->idAddr()->iiaGetInstrCount();
8436 unsigned insNum = emitFindInsNum(ig, id);
8439 // Backward branches using instruction count must be within the same instruction group.
8440 assert(insNum + 1 >= (unsigned)(-instrCount));
8442 dstOffs = ig->igOffs + emitFindOffset(ig, (insNum + 1 + instrCount));
8443 dstAddr = emitOffsetToPtr(dstOffs);
8447 dstOffs = id->idAddr()->iiaIGlabel->igOffs;
8448 dstAddr = emitOffsetToPtr(dstOffs);
8451 distVal = (ssize_t)(dstAddr - srcAddr);
8453 if (dstOffs <= srcOffs)
8456 /* This is a backward jump - distance is known at this point */
8458 if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8460 size_t blkOffs = id->idjIG->igOffs;
8462 if (INTERESTING_JUMP_NUM == 0)
8463 printf("[3] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8464 printf("[3] Jump block is at %08X - %02X = %08X\n", blkOffs, emitOffsAdj, blkOffs - emitOffsAdj);
8465 printf("[3] Jump is at %08X - %02X = %08X\n", srcOffs, emitOffsAdj, srcOffs - emitOffsAdj);
8466 printf("[3] Label block is at %08X - %02X = %08X\n", dstOffs, emitOffsAdj, dstOffs - emitOffsAdj);
8472 /* This is a forward jump - distance will be an upper limit */
8474 emitFwdJumps = true;
8476 /* The target offset will be closer by at least 'emitOffsAdj', but only if this
8477 jump doesn't cross the hot-cold boundary. */
8479 if (!emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8481 dstOffs -= emitOffsAdj;
8482 distVal -= emitOffsAdj;
8485 /* Record the location of the jump for later patching */
8487 id->idjOffs = dstOffs;
8489 /* Are we overflowing the id->idjOffs bitfield? */
8490 if (id->idjOffs != dstOffs)
8491 IMPL_LIMITATION("Method is too large");
8494 if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8496 size_t blkOffs = id->idjIG->igOffs;
8498 if (INTERESTING_JUMP_NUM == 0)
8499 printf("[4] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8500 printf("[4] Jump block is at %08X\n", blkOffs);
8501 printf("[4] Jump is at %08X\n", srcOffs);
8502 printf("[4] Label block is at %08X - %02X = %08X\n", dstOffs + emitOffsAdj, emitOffsAdj, dstOffs);
8508 if (0 && emitComp->verbose)
8511 int distValSize = id->idjShort ? 4 : 8;
8512 printf("; %s jump [%08X/%03u] from %0*X to %0*X: dist = %08XH\n", (dstOffs <= srcOffs) ? "Fwd" : "Bwd",
8513 dspPtr(id), id->idDebugOnlyInfo()->idNum, distValSize, srcOffs + sz, distValSize, dstOffs, distVal);
8517 /* For forward jumps, record the address of the distance value */
8518 id->idjTemp.idjAddr = (distVal > 0) ? dst : NULL;
8520 if (emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8522 assert(!id->idjShort);
8523 NYI_ARM64("Relocation Support for long address");
8526 assert(insOptsNone(id->idInsOpt()));
8532 // Short conditional/unconditional jump
8533 assert(!id->idjKeepLong);
8534 assert(emitJumpCrossHotColdBoundary(srcOffs, dstOffs) == false);
8535 assert((fmt == IF_BI_0A) || (fmt == IF_BI_0B) || (fmt == IF_BI_1A) || (fmt == IF_BI_1B));
8539 // Long conditional jump
8540 assert(fmt == IF_LARGEJMP);
8541 // This is a pseudo-instruction format representing a large conditional branch, to allow
8542 // us to get a greater branch target range than we can get by using a straightforward conditional
8543 // branch. It is encoded as a short conditional branch that branches around a long unconditional
8546 // Conceptually, we have:
8550 // The code we emit is:
8552 // b<!cond> L_not // 4 bytes. Note that we reverse the condition.
8553 // b L_target // 4 bytes
8556 // Note that we don't actually insert any blocks: we simply encode "b <!cond> L_not" as a branch with
8557 // the correct offset. Note also that this works for both integer and floating-point conditions, because
8558 // the condition inversion takes ordered/unordered into account, preserving NaN behavior. For example,
8559 // "GT" (greater than) is inverted to "LE" (less than, equal, or unordered).
8561 instruction reverseIns;
8562 insFormat reverseFmt;
8567 reverseIns = INS_cbnz;
8568 reverseFmt = IF_BI_1A;
8571 reverseIns = INS_cbz;
8572 reverseFmt = IF_BI_1A;
8575 reverseIns = INS_tbnz;
8576 reverseFmt = IF_BI_1B;
8579 reverseIns = INS_tbz;
8580 reverseFmt = IF_BI_1B;
8583 reverseIns = emitJumpKindToIns(emitReverseJumpKind(emitInsToJumpKind(ins)));
8584 reverseFmt = IF_BI_0B;
8588 emitOutputShortBranch(dst,
8589 reverseIns, // reverse the conditional instruction
8591 8, /* 8 bytes from start of this large conditional pseudo-instruction to L_not. */
8594 // Now, pretend we've got a normal unconditional branch, and fall through to the code to emit that.
8598 // The distVal was computed based on the beginning of the pseudo-instruction,
8599 // So subtract the size of the conditional branch so that it is relative to the
8600 // unconditional branch.
8604 dst = emitOutputShortBranch(dst, ins, fmt, distVal, id);
8608 dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8614 /*****************************************************************************
8616 * Output a short branch instruction.
8618 BYTE* emitter::emitOutputShortBranch(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, instrDescJmp* id)
8620 code_t code = emitInsCode(ins, fmt);
8622 ssize_t loBits = (distVal & 3);
8623 noway_assert(loBits == 0);
8624 distVal >>= 2; // branch offset encodings are scaled by 4.
8626 if (fmt == IF_BI_0A)
8628 // INS_b or INS_bl_local
8629 noway_assert(isValidSimm26(distVal));
8630 distVal &= 0x3FFFFFFLL;
8633 else if (fmt == IF_BI_0B) // BI_0B 01010100iiiiiiii iiiiiiiiiiiXXXXX simm19:00
8635 // INS_beq, INS_bne, etc...
8636 noway_assert(isValidSimm19(distVal));
8637 distVal &= 0x7FFFFLL;
8638 code |= distVal << 5;
8640 else if (fmt == IF_BI_1A) // BI_1A X.......iiiiiiii iiiiiiiiiiittttt Rt simm19:00
8642 // INS_cbz or INS_cbnz
8643 assert(id != nullptr);
8644 code |= insEncodeDatasize(id->idOpSize()); // X
8645 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
8647 noway_assert(isValidSimm19(distVal));
8648 distVal &= 0x7FFFFLL; // 19 bits
8649 code |= distVal << 5;
8651 else if (fmt == IF_BI_1B) // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
8653 // INS_tbz or INS_tbnz
8654 assert(id != nullptr);
8655 ssize_t imm = emitGetInsSC(id);
8656 assert(isValidImmShift(imm, id->idOpSize()));
8658 if (imm & 0x20) // test bit 32-63 ?
8660 code |= 0x80000000; // B
8662 code |= ((imm & 0x1F) << 19); // bbbbb
8663 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
8665 noway_assert(isValidSimm14(distVal));
8666 distVal &= 0x3FFFLL; // 14 bits
8667 code |= distVal << 5;
8671 assert(!"Unknown fmt for emitOutputShortBranch");
8674 dst += emitOutput_Instr(dst, code);
8679 /*****************************************************************************
8681 * Output a short address instruction.
8683 BYTE* emitter::emitOutputShortAddress(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, regNumber reg)
8685 ssize_t loBits = (distVal & 3);
8688 code_t code = emitInsCode(ins, fmt);
8689 if (fmt == IF_DI_1E) // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
8691 // INS_adr or INS_adrp
8692 code |= insEncodeReg_Rd(reg); // ddddd
8694 noway_assert(isValidSimm19(distVal));
8695 distVal &= 0x7FFFFLL; // 19 bits
8696 code |= distVal << 5;
8697 code |= loBits << 29; // 2 bits
8701 assert(!"Unknown fmt for emitOutputShortAddress");
8704 dst += emitOutput_Instr(dst, code);
8709 /*****************************************************************************
8711 * Output a short constant instruction.
8713 BYTE* emitter::emitOutputShortConstant(
8714 BYTE* dst, instruction ins, insFormat fmt, ssize_t imm, regNumber reg, emitAttr opSize)
8716 code_t code = emitInsCode(ins, fmt);
8718 if (fmt == IF_LS_1A)
8720 // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt simm21
8721 // INS_ldr or INS_ldrsw (PC-Relative)
8723 ssize_t loBits = (imm & 3);
8724 noway_assert(loBits == 0);
8725 ssize_t distVal = imm >>= 2; // load offset encodings are scaled by 4.
8727 noway_assert(isValidSimm19(distVal));
8729 // Is the target a vector register?
8730 if (isVectorRegister(reg))
8732 code |= insEncodeDatasizeVLS(code, opSize); // XX V
8733 code |= insEncodeReg_Vt(reg); // ttttt
8737 assert(isGeneralRegister(reg));
8738 // insEncodeDatasizeLS is not quite right for this case.
8739 // So just specialize it.
8740 if ((ins == INS_ldr) && (opSize == EA_8BYTE))
8742 // set the operation size in bit 30
8746 code |= insEncodeReg_Rt(reg); // ttttt
8749 distVal &= 0x7FFFFLL; // 19 bits
8750 code |= distVal << 5;
8752 else if (fmt == IF_LS_2B)
8754 // ldr Rt,[Xn+pimm12] LS_2B 1X11100101iiiiii iiiiiinnnnnttttt B940 0000 imm(0-4095<<{2,3})
8755 // INS_ldr or INS_ldrsw (PC-Relative)
8756 noway_assert(isValidUimm12(imm));
8757 assert(isGeneralRegister(reg));
8759 if (opSize == EA_8BYTE)
8761 // insEncodeDatasizeLS is not quite right for this case.
8762 // So just specialize it.
8765 // set the operation size in bit 30
8768 // Low 3 bits should be 0 -- 8 byte JIT data should be aligned on 8 byte.
8769 assert((imm & 7) == 0);
8774 assert(opSize == EA_4BYTE);
8775 // Low 2 bits should be 0 -- 4 byte aligned data.
8776 assert((imm & 3) == 0);
8780 code |= insEncodeReg_Rt(reg); // ttttt
8781 code |= insEncodeReg_Rn(reg); // nnnnn
8786 assert(!"Unknown fmt for emitOutputShortConstant");
8789 dst += emitOutput_Instr(dst, code);
8793 /*****************************************************************************
8795 * Output a call instruction.
8798 unsigned emitter::emitOutputCall(insGroup* ig, BYTE* dst, instrDesc* id, code_t code)
8800 const unsigned char callInstrSize = sizeof(code_t); // 4 bytes
8801 regMaskTP gcrefRegs;
8802 regMaskTP byrefRegs;
8804 VARSET_TP GCvars(VarSetOps::UninitVal());
8806 // Is this a "fat" call descriptor?
8807 if (id->idIsLargeCall())
8809 instrDescCGCA* idCall = (instrDescCGCA*)id;
8810 gcrefRegs = idCall->idcGcrefRegs;
8811 byrefRegs = idCall->idcByrefRegs;
8812 VarSetOps::Assign(emitComp, GCvars, idCall->idcGCvars);
8816 assert(!id->idIsLargeDsp());
8817 assert(!id->idIsLargeCns());
8819 gcrefRegs = emitDecodeCallGCregs(id);
8821 VarSetOps::AssignNoCopy(emitComp, GCvars, VarSetOps::MakeEmpty(emitComp));
8824 /* We update the GC info before the call as the variables cannot be
8825 used by the call. Killing variables before the call helps with
8826 boundary conditions if the call is CORINFO_HELP_THROW - see bug 50029.
8827 If we ever track aliased variables (which could be used by the
8828 call), we would have to keep them alive past the call. */
8830 emitUpdateLiveGCvars(GCvars, dst);
8832 // Now output the call instruction and update the 'dst' pointer
8834 unsigned outputInstrSize = emitOutput_Instr(dst, code);
8835 dst += outputInstrSize;
8837 // All call instructions are 4-byte in size on ARM64
8839 assert(outputInstrSize == callInstrSize);
8841 // If the method returns a GC ref, mark INTRET (R0) appropriately.
8842 if (id->idGCref() == GCT_GCREF)
8844 gcrefRegs |= RBM_INTRET;
8846 else if (id->idGCref() == GCT_BYREF)
8848 byrefRegs |= RBM_INTRET;
8851 // If is a multi-register return method is called, mark INTRET_1 (X1) appropriately
8852 if (id->idIsLargeCall())
8854 instrDescCGCA* idCall = (instrDescCGCA*)id;
8855 if (idCall->idSecondGCref() == GCT_GCREF)
8857 gcrefRegs |= RBM_INTRET_1;
8859 else if (idCall->idSecondGCref() == GCT_BYREF)
8861 byrefRegs |= RBM_INTRET_1;
8865 // If the GC register set has changed, report the new set.
8866 if (gcrefRegs != emitThisGCrefRegs)
8868 emitUpdateLiveGCregs(GCT_GCREF, gcrefRegs, dst);
8870 // If the Byref register set has changed, report the new set.
8871 if (byrefRegs != emitThisByrefRegs)
8873 emitUpdateLiveGCregs(GCT_BYREF, byrefRegs, dst);
8876 // Some helper calls may be marked as not requiring GC info to be recorded.
8877 if ((!id->idIsNoGC()))
8879 // On ARM64, as on AMD64, we don't change the stack pointer to push/pop args.
8880 // So we're not really doing a "stack pop" here (note that "args" is 0), but we use this mechanism
8881 // to record the call for GC info purposes. (It might be best to use an alternate call,
8882 // and protect "emitStackPop" under the EMIT_TRACK_STACK_DEPTH preprocessor variable.)
8883 emitStackPop(dst, /*isCall*/ true, callInstrSize, /*args*/ 0);
8885 // Do we need to record a call location for GC purposes?
8887 if (!emitFullGCinfo)
8889 emitRecordGCcall(dst, callInstrSize);
8892 return callInstrSize;
8895 /*****************************************************************************
8897 * Emit a 32-bit Arm64 instruction
8900 /*static*/ unsigned emitter::emitOutput_Instr(BYTE* dst, code_t code)
8902 assert(sizeof(code_t) == 4);
8903 *((code_t*)dst) = code;
8905 return sizeof(code_t);
8908 /*****************************************************************************
8910 * Append the machine code corresponding to the given instruction descriptor
8911 * to the code block at '*dp'; the base of the code block is 'bp', and 'ig'
8912 * is the instruction group that contains the instruction. Updates '*dp' to
8913 * point past the generated code, and returns the size of the instruction
8914 * descriptor in bytes.
8917 size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
8922 size_t sz = emitGetInstrDescSize(id); // TODO-ARM64-Cleanup: on ARM, this is set in each case. why?
8923 instruction ins = id->idIns();
8924 insFormat fmt = id->idInsFmt();
8925 emitAttr size = id->idOpSize();
8926 unsigned char callInstrSize = 0;
8931 bool dspOffs = emitComp->opts.dspGCtbls;
8933 bool dspOffs = !emitComp->opts.disDiffable;
8937 assert(REG_NA == (int)REG_NA);
8939 VARSET_TP GCvars(VarSetOps::UninitVal());
8941 /* What instruction format have we got? */
8956 case IF_BI_0A: // BI_0A ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
8957 case IF_BI_0B: // BI_0B ......iiiiiiiiii iiiiiiiiiii..... simm19:00
8959 assert(id->idGCref() == GCT_NONE);
8960 assert(id->idIsBound());
8961 dst = emitOutputLJ(ig, dst, id);
8962 sz = sizeof(instrDescJmp);
8965 case IF_BI_0C: // BI_0C ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
8966 code = emitInsCode(ins, fmt);
8967 sz = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
8968 dst += emitOutputCall(ig, dst, id, code);
8969 // Always call RecordRelocation so that we wire in a JumpStub when we don't reach
8970 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_BRANCH26);
8973 case IF_BI_1A: // BI_1A ......iiiiiiiiii iiiiiiiiiiittttt Rt simm19:00
8974 assert(insOptsNone(id->idInsOpt()));
8975 assert(id->idIsBound());
8977 dst = emitOutputLJ(ig, dst, id);
8978 sz = sizeof(instrDescJmp);
8981 case IF_BI_1B: // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
8982 assert(insOptsNone(id->idInsOpt()));
8983 assert(id->idIsBound());
8985 dst = emitOutputLJ(ig, dst, id);
8986 sz = sizeof(instrDescJmp);
8989 case IF_BR_1A: // BR_1A ................ ......nnnnn..... Rn
8990 assert(insOptsNone(id->idInsOpt()));
8991 assert((ins == INS_ret) || (ins == INS_br));
8992 code = emitInsCode(ins, fmt);
8993 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
8995 dst += emitOutput_Instr(dst, code);
8998 case IF_BR_1B: // BR_1B ................ ......nnnnn..... Rn
8999 assert(insOptsNone(id->idInsOpt()));
9000 assert((ins == INS_br_tail) || (ins == INS_blr));
9001 code = emitInsCode(ins, fmt);
9002 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9004 sz = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
9005 dst += emitOutputCall(ig, dst, id, code);
9008 case IF_LS_1A: // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB)
9010 assert(insOptsNone(id->idInsOpt()));
9011 assert(id->idIsBound());
9013 dst = emitOutputLJ(ig, dst, id);
9014 sz = sizeof(instrDescJmp);
9017 case IF_LS_2A: // LS_2A .X.......X...... ......nnnnnttttt Rt Rn
9018 assert(insOptsNone(id->idInsOpt()));
9019 code = emitInsCode(ins, fmt);
9020 // Is the target a vector register?
9021 if (isVectorRegister(id->idReg1()))
9023 code &= 0x3FFFFFFF; // clear the size bits
9024 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9025 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9029 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9030 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9032 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9033 dst += emitOutput_Instr(dst, code);
9036 case IF_LS_2B: // LS_2B .X.......Xiiiiii iiiiiinnnnnttttt Rt Rn imm(0-4095)
9037 assert(insOptsNone(id->idInsOpt()));
9038 imm = emitGetInsSC(id);
9039 assert(isValidUimm12(imm));
9040 code = emitInsCode(ins, fmt);
9041 // Is the target a vector register?
9042 if (isVectorRegister(id->idReg1()))
9044 code &= 0x3FFFFFFF; // clear the size bits
9045 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9046 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9050 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9051 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9053 code |= ((code_t)imm << 10); // iiiiiiiiiiii
9054 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9055 dst += emitOutput_Instr(dst, code);
9058 case IF_LS_2C: // LS_2C .X.......X.iiiii iiiiPPnnnnnttttt Rt Rn imm(-256..+255) no/pre/post inc
9059 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9060 imm = emitGetInsSC(id);
9061 assert((imm >= -256) && (imm <= 255)); // signed 9 bits
9062 imm &= 0x1ff; // force into unsigned 9 bit representation
9063 code = emitInsCode(ins, fmt);
9064 // Is the target a vector register?
9065 if (isVectorRegister(id->idReg1()))
9067 code &= 0x3FFFFFFF; // clear the size bits
9068 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9069 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9073 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9074 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9076 code |= insEncodeIndexedOpt(id->idInsOpt()); // PP
9077 code |= ((code_t)imm << 12); // iiiiiiiii
9078 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9079 dst += emitOutput_Instr(dst, code);
9082 case IF_LS_3A: // LS_3A .X.......X.mmmmm oooS..nnnnnttttt Rt Rn Rm ext(Rm) LSL {}
9083 assert(insOptsLSExtend(id->idInsOpt()));
9084 code = emitInsCode(ins, fmt);
9085 // Is the target a vector register?
9086 if (isVectorRegister(id->idReg1()))
9088 code &= 0x3FFFFFFF; // clear the size bits
9089 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9090 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9094 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9095 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9097 code |= insEncodeExtend(id->idInsOpt()); // ooo
9098 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9099 if (id->idIsLclVar())
9101 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9105 code |= insEncodeReg3Scale(id->idReg3Scaled()); // S
9106 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9108 dst += emitOutput_Instr(dst, code);
9111 case IF_LS_3B: // LS_3B X............... .aaaaannnnnddddd Rd Ra Rn
9112 assert(insOptsNone(id->idInsOpt()));
9113 code = emitInsCode(ins, fmt);
9114 // Is the target a vector register?
9115 if (isVectorRegister(id->idReg1()))
9117 code &= 0x3FFFFFFF; // clear the size bits
9118 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9119 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9120 code |= insEncodeReg_Va(id->idReg2()); // aaaaa
9124 code |= insEncodeDatasize(id->idOpSize()); // X
9125 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9126 code |= insEncodeReg_Ra(id->idReg2()); // aaaaa
9128 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9129 dst += emitOutput_Instr(dst, code);
9132 case IF_LS_3C: // LS_3C X......PP.iiiiii iaaaaannnnnddddd Rd Ra Rn imm(im7,sh)
9133 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9134 imm = emitGetInsSC(id);
9135 assert((imm >= -64) && (imm <= 63)); // signed 7 bits
9136 imm &= 0x7f; // force into unsigned 7 bit representation
9137 code = emitInsCode(ins, fmt);
9138 // Is the target a vector register?
9139 if (isVectorRegister(id->idReg1()))
9141 code &= 0x3FFFFFFF; // clear the size bits
9142 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9143 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9144 code |= insEncodeReg_Va(id->idReg2()); // aaaaa
9148 code |= insEncodeDatasize(id->idOpSize()); // X
9149 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9150 code |= insEncodeReg_Ra(id->idReg2()); // aaaaa
9152 code |= insEncodePairIndexedOpt(ins, id->idInsOpt()); // PP
9153 code |= ((code_t)imm << 15); // iiiiiiiii
9154 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9155 dst += emitOutput_Instr(dst, code);
9158 case IF_LS_3D: // LS_3D .X.......X.mmmmm ......nnnnnttttt Wm Rt Rn
9159 code = emitInsCode(ins, fmt);
9160 // Arm64 store exclusive unpredictable cases
9161 assert(id->idReg1() != id->idReg2());
9162 assert(id->idReg1() != id->idReg3());
9163 code |= insEncodeDatasizeLS(code, id->idOpSize()); // X
9164 code |= insEncodeReg_Rm(id->idReg1()); // mmmmm
9165 code |= insEncodeReg_Rt(id->idReg2()); // ttttt
9166 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9167 dst += emitOutput_Instr(dst, code);
9170 case IF_DI_1A: // DI_1A X.......shiiiiii iiiiiinnnnn..... Rn imm(i12,sh)
9171 assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9172 imm = emitGetInsSC(id);
9173 assert(isValidUimm12(imm));
9174 code = emitInsCode(ins, fmt);
9175 code |= insEncodeDatasize(id->idOpSize()); // X
9176 code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9177 code |= ((code_t)imm << 10); // iiiiiiiiiiii
9178 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9179 dst += emitOutput_Instr(dst, code);
9182 case IF_DI_1B: // DI_1B X........hwiiiii iiiiiiiiiiiddddd Rd imm(i16,hw)
9183 imm = emitGetInsSC(id);
9184 assert(isValidImmHWVal(imm, id->idOpSize()));
9185 code = emitInsCode(ins, fmt);
9186 code |= insEncodeDatasize(id->idOpSize()); // X
9187 code |= ((code_t)imm << 5); // hwiiiii iiiiiiiiiii
9188 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9189 dst += emitOutput_Instr(dst, code);
9192 case IF_DI_1C: // DI_1C X........Nrrrrrr ssssssnnnnn..... Rn imm(N,r,s)
9193 imm = emitGetInsSC(id);
9194 assert(isValidImmNRS(imm, id->idOpSize()));
9195 code = emitInsCode(ins, fmt);
9196 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9197 code |= insEncodeDatasize(id->idOpSize()); // X
9198 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9199 dst += emitOutput_Instr(dst, code);
9202 case IF_DI_1D: // DI_1D X........Nrrrrrr ssssss.....ddddd Rd imm(N,r,s)
9203 imm = emitGetInsSC(id);
9204 assert(isValidImmNRS(imm, id->idOpSize()));
9205 code = emitInsCode(ins, fmt);
9206 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9207 code |= insEncodeDatasize(id->idOpSize()); // X
9208 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9209 dst += emitOutput_Instr(dst, code);
9212 case IF_DI_1E: // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
9214 assert(insOptsNone(id->idInsOpt()));
9215 if (id->idIsReloc())
9217 code = emitInsCode(ins, fmt);
9218 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9219 dst += emitOutput_Instr(dst, code);
9220 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEBASE_REL21);
9224 // Local jmp/load case which does not need a relocation.
9225 assert(id->idIsBound());
9226 dst = emitOutputLJ(ig, dst, id);
9228 sz = sizeof(instrDescJmp);
9231 case IF_DI_1F: // DI_1F X..........iiiii cccc..nnnnn.nzcv Rn imm5 nzcv cond
9232 imm = emitGetInsSC(id);
9233 assert(isValidImmCondFlagsImm5(imm));
9236 cfi.immCFVal = (unsigned)imm;
9237 code = emitInsCode(ins, fmt);
9238 code |= insEncodeDatasize(id->idOpSize()); // X
9239 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9240 code |= ((code_t)cfi.imm5 << 16); // iiiii
9241 code |= insEncodeFlags(cfi.flags); // nzcv
9242 code |= insEncodeCond(cfi.cond); // cccc
9243 dst += emitOutput_Instr(dst, code);
9247 case IF_DI_2A: // DI_2A X.......shiiiiii iiiiiinnnnnddddd Rd Rn imm(i12,sh)
9248 assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9249 imm = emitGetInsSC(id);
9250 assert(isValidUimm12(imm));
9251 code = emitInsCode(ins, fmt);
9252 code |= insEncodeDatasize(id->idOpSize()); // X
9253 code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9254 code |= ((code_t)imm << 10); // iiiiiiiiiiii
9255 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9256 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9257 dst += emitOutput_Instr(dst, code);
9259 if (id->idIsReloc())
9261 assert(sz == sizeof(instrDesc));
9262 assert(id->idAddr()->iiaAddr != nullptr);
9263 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEOFFSET_12A);
9267 case IF_DI_2B: // DI_2B X.........Xnnnnn ssssssnnnnnddddd Rd Rn imm(0-63)
9268 code = emitInsCode(ins, fmt);
9269 imm = emitGetInsSC(id);
9270 assert(isValidImmShift(imm, id->idOpSize()));
9271 code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9272 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9273 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9274 code |= insEncodeReg_Rm(id->idReg2()); // Reg2 also in mmmmm
9275 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9276 dst += emitOutput_Instr(dst, code);
9279 case IF_DI_2C: // DI_2C X........Nrrrrrr ssssssnnnnnddddd Rd Rn imm(N,r,s)
9280 imm = emitGetInsSC(id);
9281 assert(isValidImmNRS(imm, id->idOpSize()));
9282 code = emitInsCode(ins, fmt);
9283 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9284 code |= insEncodeDatasize(id->idOpSize()); // X
9285 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9286 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9287 dst += emitOutput_Instr(dst, code);
9290 case IF_DI_2D: // DI_2D X........Nrrrrrr ssssssnnnnnddddd Rd Rn imr, imms (N,r,s)
9291 if (ins == INS_asr || ins == INS_lsl || ins == INS_lsr)
9293 imm = emitGetInsSC(id);
9294 assert(isValidImmShift(imm, id->idOpSize()));
9296 // Shift immediates are aliases of the SBFM/UBFM instructions
9297 // that actually take 2 registers and 2 constants,
9298 // Since we stored the shift immediate value
9299 // we need to calculate the N,R and S values here.
9304 bmi.immN = (size == EA_8BYTE) ? 1 : 0;
9306 bmi.immS = (size == EA_8BYTE) ? 0x3f : 0x1f;
9308 // immR and immS are now set correctly for INS_asr and INS_lsr
9309 // but for INS_lsl we have to adjust the values for immR and immS
9313 bmi.immR = -imm & bmi.immS;
9314 bmi.immS = bmi.immS - imm;
9317 // setup imm with the proper 13 bit value N:R:S
9323 // The other instructions have already have encoded N,R and S values
9324 imm = emitGetInsSC(id);
9326 assert(isValidImmNRS(imm, id->idOpSize()));
9328 code = emitInsCode(ins, fmt);
9329 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9330 code |= insEncodeDatasize(id->idOpSize()); // X
9331 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9332 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9333 dst += emitOutput_Instr(dst, code);
9336 case IF_DR_1D: // DR_1D X............... cccc.......ddddd Rd cond
9337 imm = emitGetInsSC(id);
9338 assert(isValidImmCond(imm));
9341 cfi.immCFVal = (unsigned)imm;
9342 code = emitInsCode(ins, fmt);
9343 code |= insEncodeDatasize(id->idOpSize()); // X
9344 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9345 code |= insEncodeInvertedCond(cfi.cond); // cccc
9346 dst += emitOutput_Instr(dst, code);
9350 case IF_DR_2A: // DR_2A X..........mmmmm ......nnnnn..... Rn Rm
9351 assert(insOptsNone(id->idInsOpt()));
9352 code = emitInsCode(ins, fmt);
9353 code |= insEncodeDatasize(id->idOpSize()); // X
9354 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9355 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9356 dst += emitOutput_Instr(dst, code);
9359 case IF_DR_2B: // DR_2B X.......sh.mmmmm ssssssnnnnn..... Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
9360 code = emitInsCode(ins, fmt);
9361 imm = emitGetInsSC(id);
9362 assert(isValidImmShift(imm, id->idOpSize()));
9363 code |= insEncodeDatasize(id->idOpSize()); // X
9364 code |= insEncodeShiftType(id->idInsOpt()); // sh
9365 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9366 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9367 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9368 dst += emitOutput_Instr(dst, code);
9371 case IF_DR_2C: // DR_2C X..........mmmmm ooosssnnnnn..... Rn Rm ext(Rm) LSL imm(0-4)
9372 code = emitInsCode(ins, fmt);
9373 imm = emitGetInsSC(id);
9374 assert((imm >= 0) && (imm <= 4)); // imm [0..4]
9375 code |= insEncodeDatasize(id->idOpSize()); // X
9376 code |= insEncodeExtend(id->idInsOpt()); // ooo
9377 code |= insEncodeExtendScale(imm); // sss
9378 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9379 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9380 dst += emitOutput_Instr(dst, code);
9383 case IF_DR_2D: // DR_2D X..........nnnnn cccc..nnnnnddddd Rd Rn cond
9384 imm = emitGetInsSC(id);
9385 assert(isValidImmCond(imm));
9388 cfi.immCFVal = (unsigned)imm;
9389 code = emitInsCode(ins, fmt);
9390 code |= insEncodeDatasize(id->idOpSize()); // X
9391 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9392 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9393 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9394 code |= insEncodeInvertedCond(cfi.cond); // cccc
9395 dst += emitOutput_Instr(dst, code);
9399 case IF_DR_2E: // DR_2E X..........mmmmm ...........ddddd Rd Rm
9400 code = emitInsCode(ins, fmt);
9401 code |= insEncodeDatasize(id->idOpSize()); // X
9402 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9403 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9404 dst += emitOutput_Instr(dst, code);
9407 case IF_DR_2F: // DR_2F X.......sh.mmmmm ssssss.....ddddd Rd Rm {LSL,LSR,ASR} imm(0-63)
9408 code = emitInsCode(ins, fmt);
9409 imm = emitGetInsSC(id);
9410 assert(isValidImmShift(imm, id->idOpSize()));
9411 code |= insEncodeDatasize(id->idOpSize()); // X
9412 code |= insEncodeShiftType(id->idInsOpt()); // sh
9413 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9414 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9415 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9416 dst += emitOutput_Instr(dst, code);
9419 case IF_DR_2G: // DR_2G X............... .....xnnnnnddddd Rd Rn
9420 code = emitInsCode(ins, fmt);
9421 code |= insEncodeDatasize(id->idOpSize()); // X
9424 if (size == EA_8BYTE)
9426 code |= 0x00000400; // x - bit at location 10
9429 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9430 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9431 dst += emitOutput_Instr(dst, code);
9434 case IF_DR_2H: // DR_2H X........X...... ......nnnnnddddd Rd Rn
9435 code = emitInsCode(ins, fmt);
9436 code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9437 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9438 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9439 dst += emitOutput_Instr(dst, code);
9442 case IF_DR_2I: // DR_2I X..........mmmmm cccc..nnnnn.nzcv Rn Rm nzcv cond
9443 imm = emitGetInsSC(id);
9444 assert(isValidImmCondFlags(imm));
9447 cfi.immCFVal = (unsigned)imm;
9448 code = emitInsCode(ins, fmt);
9449 code |= insEncodeDatasize(id->idOpSize()); // X
9450 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9451 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9452 code |= insEncodeFlags(cfi.flags); // nzcv
9453 code |= insEncodeCond(cfi.cond); // cccc
9454 dst += emitOutput_Instr(dst, code);
9458 case IF_DR_3A: // DR_3A X..........mmmmm ......nnnnnmmmmm Rd Rn Rm
9459 code = emitInsCode(ins, fmt);
9460 code |= insEncodeDatasize(id->idOpSize()); // X
9461 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9462 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9463 if (id->idIsLclVar())
9465 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9469 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9471 dst += emitOutput_Instr(dst, code);
9474 case IF_DR_3B: // DR_3B X.......sh.mmmmm ssssssnnnnnddddd Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
9475 code = emitInsCode(ins, fmt);
9476 imm = emitGetInsSC(id);
9477 assert(isValidImmShift(imm, id->idOpSize()));
9478 code |= insEncodeDatasize(id->idOpSize()); // X
9479 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9480 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9481 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9482 code |= insEncodeShiftType(id->idInsOpt()); // sh
9483 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9484 dst += emitOutput_Instr(dst, code);
9487 case IF_DR_3C: // DR_3C X..........mmmmm ooosssnnnnnddddd Rd Rn Rm ext(Rm) LSL imm(0-4)
9488 code = emitInsCode(ins, fmt);
9489 imm = emitGetInsSC(id);
9490 assert((imm >= 0) && (imm <= 4)); // imm [0..4]
9491 code |= insEncodeDatasize(id->idOpSize()); // X
9492 code |= insEncodeExtend(id->idInsOpt()); // ooo
9493 code |= insEncodeExtendScale(imm); // sss
9494 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9495 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9496 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9497 dst += emitOutput_Instr(dst, code);
9500 case IF_DR_3D: // DR_3D X..........mmmmm cccc..nnnnnddddd Rd Rn Rm cond
9501 imm = emitGetInsSC(id);
9502 assert(isValidImmCond(imm));
9505 cfi.immCFVal = (unsigned)imm;
9506 code = emitInsCode(ins, fmt);
9507 code |= insEncodeDatasize(id->idOpSize()); // X
9508 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9509 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9510 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9511 code |= insEncodeCond(cfi.cond); // cccc
9512 dst += emitOutput_Instr(dst, code);
9516 case IF_DR_3E: // DR_3E X........X.mmmmm ssssssnnnnnddddd Rd Rn Rm imm(0-63)
9517 code = emitInsCode(ins, fmt);
9518 imm = emitGetInsSC(id);
9519 assert(isValidImmShift(imm, id->idOpSize()));
9520 code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9521 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9522 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9523 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9524 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9525 dst += emitOutput_Instr(dst, code);
9528 case IF_DR_4A: // DR_4A X..........mmmmm .aaaaannnnnmmmmm Rd Rn Rm Ra
9529 code = emitInsCode(ins, fmt);
9530 code |= insEncodeDatasize(id->idOpSize()); // X
9531 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9532 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9533 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9534 code |= insEncodeReg_Ra(id->idReg4()); // aaaaa
9535 dst += emitOutput_Instr(dst, code);
9538 case IF_DV_1A: // DV_1A .........X.iiiii iii........ddddd Vd imm8 (fmov - immediate scalar)
9539 imm = emitGetInsSC(id);
9540 elemsize = id->idOpSize();
9541 code = emitInsCode(ins, fmt);
9542 code |= insEncodeFloatElemsize(elemsize); // X
9543 code |= ((code_t)imm << 13); // iiiii iii
9544 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9545 dst += emitOutput_Instr(dst, code);
9548 case IF_DV_1B: // DV_1B .QX..........iii cmod..iiiiiddddd Vd imm8 (immediate vector)
9549 imm = emitGetInsSC(id) & 0x0ff;
9550 immShift = (emitGetInsSC(id) & 0x700) >> 8;
9551 elemsize = optGetElemsize(id->idInsOpt());
9556 cmode = 0xE; // 1110
9560 cmode |= (immShift << 1); // 10x0
9566 cmode |= (immShift << 1); // 0xx0
9576 cmode = 0xE; // 1110
9583 code = emitInsCode(ins, fmt);
9584 code |= insEncodeVectorsize(id->idOpSize()); // Q
9585 if ((ins == INS_fmov) || (ins == INS_movi))
9587 if (elemsize == EA_8BYTE)
9589 code |= 0x20000000; // X
9592 if (ins != INS_fmov)
9594 assert((cmode >= 0) && (cmode <= 0xF));
9595 code |= (cmode << 12); // cmod
9597 code |= (((code_t)imm >> 5) << 16); // iii
9598 code |= (((code_t)imm & 0x1f) << 5); // iiiii
9599 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9600 dst += emitOutput_Instr(dst, code);
9603 case IF_DV_1C: // DV_1C .........X...... ......nnnnn..... Vn #0.0 (fcmp - with zero)
9604 elemsize = id->idOpSize();
9605 code = emitInsCode(ins, fmt);
9606 code |= insEncodeFloatElemsize(elemsize); // X
9607 code |= insEncodeReg_Vn(id->idReg1()); // nnnnn
9608 dst += emitOutput_Instr(dst, code);
9611 case IF_DV_2A: // DV_2A .Q.......X...... ......nnnnnddddd Vd Vn (fabs, fcvt - vector)
9612 elemsize = optGetElemsize(id->idInsOpt());
9613 code = emitInsCode(ins, fmt);
9614 code |= insEncodeVectorsize(id->idOpSize()); // Q
9615 code |= insEncodeFloatElemsize(elemsize); // X
9616 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9617 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9618 dst += emitOutput_Instr(dst, code);
9621 case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov/smov - to general)
9622 elemsize = id->idOpSize();
9623 index = emitGetInsSC(id);
9624 datasize = (elemsize == EA_8BYTE) ? EA_16BYTE : EA_8BYTE;
9625 if (ins == INS_smov)
9627 datasize = EA_16BYTE;
9629 code = emitInsCode(ins, fmt);
9630 code |= insEncodeVectorsize(datasize); // Q
9631 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9632 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9633 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9634 dst += emitOutput_Instr(dst, code);
9637 case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
9640 datasize = id->idOpSize();
9641 elemsize = optGetElemsize(id->idInsOpt());
9646 datasize = EA_16BYTE;
9647 elemsize = id->idOpSize();
9648 index = emitGetInsSC(id);
9650 code = emitInsCode(ins, fmt);
9651 code |= insEncodeVectorsize(datasize); // Q
9652 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9653 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9654 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9655 dst += emitOutput_Instr(dst, code);
9658 case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
9659 index = emitGetInsSC(id);
9660 elemsize = optGetElemsize(id->idInsOpt());
9661 code = emitInsCode(ins, fmt);
9662 code |= insEncodeVectorsize(id->idOpSize()); // Q
9663 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9664 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9665 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9666 dst += emitOutput_Instr(dst, code);
9669 case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
9670 index = emitGetInsSC(id);
9671 elemsize = id->idOpSize();
9672 code = emitInsCode(ins, fmt);
9673 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9674 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9675 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9676 dst += emitOutput_Instr(dst, code);
9679 case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
9680 elemsize = id->idOpSize();
9681 imm = emitGetInsSC(id);
9682 index = (imm >> 4) & 0xf;
9684 code = emitInsCode(ins, fmt);
9685 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9686 code |= insEncodeVectorIndex2(elemsize, index2); // jjjj
9687 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9688 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9689 dst += emitOutput_Instr(dst, code);
9692 case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov,fcvtXX - register)
9693 elemsize = id->idOpSize();
9694 code = emitInsCode(ins, fmt);
9695 code |= insEncodeFloatElemsize(elemsize); // X
9696 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9697 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9698 dst += emitOutput_Instr(dst, code);
9701 case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov - to general)
9702 elemsize = id->idOpSize();
9703 code = emitInsCode(ins, fmt);
9704 code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X X
9705 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9706 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9707 dst += emitOutput_Instr(dst, code);
9710 case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov - from general)
9711 elemsize = id->idOpSize();
9712 code = emitInsCode(ins, fmt);
9713 code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X X
9714 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9715 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9716 dst += emitOutput_Instr(dst, code);
9719 case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
9720 code = emitInsCode(ins, fmt);
9721 code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // SS DD
9722 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9723 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9724 dst += emitOutput_Instr(dst, code);
9727 case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
9728 elemsize = id->idOpSize();
9729 code = emitInsCode(ins, fmt);
9730 code |= insEncodeFloatElemsize(elemsize); // X
9731 code |= insEncodeReg_Vn(id->idReg1()); // nnnnn
9732 code |= insEncodeReg_Vm(id->idReg2()); // mmmmm
9733 dst += emitOutput_Instr(dst, code);
9736 case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
9737 elemsize = id->idOpSize();
9738 code = emitInsCode(ins, fmt);
9739 code |= insEncodeElemsize(elemsize); // XX
9740 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9741 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9742 dst += emitOutput_Instr(dst, code);
9745 case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
9746 elemsize = optGetElemsize(id->idInsOpt());
9747 code = emitInsCode(ins, fmt);
9748 code |= insEncodeVectorsize(id->idOpSize()); // Q
9749 code |= insEncodeElemsize(elemsize); // XX
9750 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9751 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9752 dst += emitOutput_Instr(dst, code);
9755 case IF_DV_2N: // DV_2N .........iiiiiii ......nnnnnddddd Vd Vn imm (shift - scalar)
9756 imm = emitGetInsSC(id);
9757 code = emitInsCode(ins, fmt);
9758 code |= insEncodeVectorShift(EA_8BYTE, imm); // iiiiiii
9759 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9760 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9761 dst += emitOutput_Instr(dst, code);
9764 case IF_DV_2O: // DV_2O .Q.......iiiiiii ......nnnnnddddd Vd Vn imm (shift - vector)
9765 imm = emitGetInsSC(id);
9766 elemsize = optGetElemsize(id->idInsOpt());
9767 code = emitInsCode(ins, fmt);
9768 code |= insEncodeVectorsize(id->idOpSize()); // Q
9769 code |= insEncodeVectorShift(elemsize, imm); // iiiiiii
9770 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9771 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9772 dst += emitOutput_Instr(dst, code);
9775 case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
9776 code = emitInsCode(ins, fmt);
9777 elemsize = optGetElemsize(id->idInsOpt());
9778 code |= insEncodeVectorsize(id->idOpSize()); // Q
9779 code |= insEncodeElemsize(elemsize); // XX
9780 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9781 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9782 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9783 dst += emitOutput_Instr(dst, code);
9786 case IF_DV_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector)
9787 code = emitInsCode(ins, fmt);
9788 imm = emitGetInsSC(id);
9789 elemsize = optGetElemsize(id->idInsOpt());
9790 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
9791 code |= insEncodeVectorsize(id->idOpSize()); // Q
9792 code |= insEncodeElemsize(elemsize); // XX
9793 code |= insEncodeVectorIndexLMH(elemsize, imm); // LM H
9794 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9795 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9796 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9797 dst += emitOutput_Instr(dst, code);
9800 case IF_DV_3B: // DV_3B .Q.......X.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
9801 code = emitInsCode(ins, fmt);
9802 elemsize = optGetElemsize(id->idInsOpt());
9803 code |= insEncodeVectorsize(id->idOpSize()); // Q
9804 code |= insEncodeFloatElemsize(elemsize); // X
9805 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9806 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9807 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9808 dst += emitOutput_Instr(dst, code);
9811 case IF_DV_3BI: // DV_3BI .Q.......XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
9812 code = emitInsCode(ins, fmt);
9813 imm = emitGetInsSC(id);
9814 elemsize = optGetElemsize(id->idInsOpt());
9815 assert(isValidVectorIndex(id->idOpSize(), elemsize, imm));
9816 code |= insEncodeVectorsize(id->idOpSize()); // Q
9817 code |= insEncodeFloatElemsize(elemsize); // X
9818 code |= insEncodeFloatIndex(elemsize, imm); // L H
9819 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9820 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9821 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9822 dst += emitOutput_Instr(dst, code);
9825 case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
9826 code = emitInsCode(ins, fmt);
9827 code |= insEncodeVectorsize(id->idOpSize()); // Q
9828 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9829 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9830 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9831 dst += emitOutput_Instr(dst, code);
9834 case IF_DV_3D: // DV_3D .........X.mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
9835 code = emitInsCode(ins, fmt);
9836 code |= insEncodeFloatElemsize(id->idOpSize()); // X
9837 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9838 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9839 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9840 dst += emitOutput_Instr(dst, code);
9843 case IF_DV_3DI: // DV_3DI .........XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (scalar by elem)
9844 code = emitInsCode(ins, fmt);
9845 imm = emitGetInsSC(id);
9846 elemsize = id->idOpSize();
9847 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
9848 code |= insEncodeFloatElemsize(elemsize); // X
9849 code |= insEncodeFloatIndex(elemsize, imm); // L H
9850 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9851 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9852 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9853 dst += emitOutput_Instr(dst, code);
9856 case IF_DV_3E: // DV_3E ...........mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
9857 code = emitInsCode(ins, fmt);
9858 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9859 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9860 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9861 dst += emitOutput_Instr(dst, code);
9864 case IF_DV_4A: // DV_4A .........X.mmmmm .aaaaannnnnddddd Vd Va Vn Vm (scalar)
9865 code = emitInsCode(ins, fmt);
9866 elemsize = id->idOpSize();
9867 code |= insEncodeFloatElemsize(elemsize); // X
9868 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9869 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9870 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9871 code |= insEncodeReg_Va(id->idReg4()); // aaaaa
9872 dst += emitOutput_Instr(dst, code);
9875 case IF_SN_0A: // SN_0A ................ ................
9876 code = emitInsCode(ins, fmt);
9877 dst += emitOutput_Instr(dst, code);
9880 case IF_SI_0A: // SI_0A ...........iiiii iiiiiiiiiii..... imm16
9881 imm = emitGetInsSC(id);
9882 assert(isValidUimm16(imm));
9883 code = emitInsCode(ins, fmt);
9884 code |= ((code_t)imm << 5); // iiiii iiiiiiiiiii
9885 dst += emitOutput_Instr(dst, code);
9888 case IF_SI_0B: // SI_0B ................ ....bbbb........ imm4 - barrier
9889 imm = emitGetInsSC(id);
9890 assert((imm >= 0) && (imm <= 15));
9891 code = emitInsCode(ins, fmt);
9892 code |= ((code_t)imm << 8); // bbbb
9893 dst += emitOutput_Instr(dst, code);
9897 assert(!"Unexpected format");
9901 // Determine if any registers now hold GC refs, or whether a register that was overwritten held a GC ref.
9902 // We assume here that "id->idGCref()" is not GC_NONE only if the instruction described by "id" writes a
9903 // GC ref to register "id->idReg1()". (It may, apparently, also not be GC_NONE in other cases, such as
9904 // for stores, but we ignore those cases here.)
9905 if (emitInsMayWriteToGCReg(id)) // True if "id->idIns()" writes to a register than can hold GC ref.
9907 // We assume that "idReg1" is the primary destination register for all instructions
9908 if (id->idGCref() != GCT_NONE)
9910 emitGCregLiveUpd(id->idGCref(), id->idReg1(), dst);
9914 emitGCregDeadUpd(id->idReg1(), dst);
9917 if (emitInsMayWriteMultipleRegs(id))
9920 // "idReg2" is the secondary destination register
9921 if (id->idGCrefReg2() != GCT_NONE)
9923 emitGCregLiveUpd(id->idGCrefReg2(), id->idReg2(), dst);
9927 emitGCregDeadUpd(id->idReg2(), dst);
9932 // Now we determine if the instruction has written to a (local variable) stack location, and either written a GC
9933 // ref or overwritten one.
9934 if (emitInsWritesToLclVarStackLoc(id) || emitInsWritesToLclVarStackLocPair(id))
9936 int varNum = id->idAddr()->iiaLclVar.lvaVarNum();
9937 unsigned ofs = AlignDown(id->idAddr()->iiaLclVar.lvaOffset(), sizeof(size_t));
9939 int adr = emitComp->lvaFrameAddress(varNum, &FPbased);
9940 if (id->idGCref() != GCT_NONE)
9942 emitGCvarLiveUpd(adr + ofs, varNum, id->idGCref(), dst);
9946 // If the type of the local is a gc ref type, update the liveness.
9950 // "Regular" (non-spill-temp) local.
9951 vt = var_types(emitComp->lvaTable[varNum].lvType);
9955 TempDsc* tmpDsc = emitComp->tmpFindNum(varNum);
9956 vt = tmpDsc->tdTempType();
9958 if (vt == TYP_REF || vt == TYP_BYREF)
9959 emitGCvarDeadUpd(adr + ofs, dst);
9961 if (emitInsWritesToLclVarStackLocPair(id))
9963 unsigned ofs2 = ofs + sizeof(size_t);
9964 if (id->idGCrefReg2() != GCT_NONE)
9966 emitGCvarLiveUpd(adr + ofs2, varNum, id->idGCrefReg2(), dst);
9970 // If the type of the local is a gc ref type, update the liveness.
9974 // "Regular" (non-spill-temp) local.
9975 vt = var_types(emitComp->lvaTable[varNum].lvType);
9979 TempDsc* tmpDsc = emitComp->tmpFindNum(varNum);
9980 vt = tmpDsc->tdTempType();
9982 if (vt == TYP_REF || vt == TYP_BYREF)
9983 emitGCvarDeadUpd(adr + ofs2, dst);
9989 /* Make sure we set the instruction descriptor size correctly */
9991 size_t expected = emitSizeOfInsDsc(id);
9992 assert(sz == expected);
9994 if (emitComp->opts.disAsm || emitComp->opts.dspEmit || emitComp->verbose)
9996 emitDispIns(id, false, dspOffs, true, emitCurCodeOffs(odst), *dp, (dst - *dp), ig);
9999 if (emitComp->compDebugBreak)
10001 // For example, set JitBreakEmitOutputInstr=a6 will break when this method is called for
10002 // emitting instruction a6, (i.e. IN00a6 in jitdump).
10003 if ((unsigned)JitConfig.JitBreakEmitOutputInstr() == id->idDebugOnlyInfo()->idNum)
10005 assert(!"JitBreakEmitOutputInstr reached");
10010 /* All instructions are expected to generate code */
10012 assert(*dp != dst);
10019 /*****************************************************************************/
10020 /*****************************************************************************/
10024 /*****************************************************************************
10026 * Display the instruction name
10028 void emitter::emitDispInst(instruction ins)
10030 const char* insstr = codeGen->genInsName(ins);
10031 size_t len = strlen(insstr);
10033 /* Display the instruction name */
10035 printf("%s", insstr);
10038 // Add at least one space after the instruction name
10039 // and add spaces until we have reach the normal size of 8
10047 /*****************************************************************************
10049 * Display an reloc value
10050 * If we are formatting for an assembly listing don't print the hex value
10051 * since it will prevent us from doing assembly diffs
10053 void emitter::emitDispReloc(int value, bool addComma)
10055 if (emitComp->opts.disAsm)
10061 printf("(reloc 0x%x)", dspPtr(value));
10068 /*****************************************************************************
10070 * Display an immediate value
10072 void emitter::emitDispImm(ssize_t imm, bool addComma, bool alwaysHex /* =false */)
10079 // Munge any pointers if we want diff-able disassembly
10080 if (emitComp->opts.disDiffable)
10082 ssize_t top44bits = (imm >> 20);
10083 if ((top44bits != 0) && (top44bits != -1))
10087 if (!alwaysHex && (imm > -1000) && (imm < 1000))
10093 if ((imm < 0) && ((imm & 0xFFFFFFFF00000000LL) == 0xFFFFFFFF00000000LL))
10099 if ((imm & 0xFFFFFFFF00000000LL) != 0)
10101 printf("0x%llx", imm);
10105 printf("0x%02x", imm);
10113 /*****************************************************************************
10115 * Display a float zero constant
10117 void emitter::emitDispFloatZero()
10126 /*****************************************************************************
10128 * Display an encoded float constant value
10130 void emitter::emitDispFloatImm(ssize_t imm8)
10132 assert((0 <= imm8) && (imm8 <= 0x0ff));
10139 fpImm.immFPIVal = (unsigned)imm8;
10140 double result = emitDecodeFloatImm8(fpImm);
10142 printf("%.4f", result);
10145 /*****************************************************************************
10147 * Display an immediate that is optionally LSL12.
10149 void emitter::emitDispImmOptsLSL12(ssize_t imm, insOpts opt)
10151 if (!strictArmAsm && insOptsLSL12(opt))
10155 emitDispImm(imm, false);
10156 if (strictArmAsm && insOptsLSL12(opt))
10158 printf(", LSL #12");
10162 /*****************************************************************************
10164 * Display an ARM64 condition code for the conditional instructions
10166 void emitter::emitDispCond(insCond cond)
10168 const static char* armCond[16] = {"eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc",
10169 "hi", "ls", "ge", "lt", "gt", "le", "AL", "NV"}; // The last two are invalid
10170 unsigned imm = (unsigned)cond;
10171 assert((0 <= imm) && (imm < ArrLen(armCond)));
10172 printf(armCond[imm]);
10175 /*****************************************************************************
10177 * Display an ARM64 flags for the conditional instructions
10179 void emitter::emitDispFlags(insCflags flags)
10181 const static char* armFlags[16] = {"0", "v", "c", "cv", "z", "zv", "zc", "zcv",
10182 "n", "nv", "nc", "ncv", "nz", "nzv", "nzc", "nzcv"};
10183 unsigned imm = (unsigned)flags;
10184 assert((0 <= imm) && (imm < ArrLen(armFlags)));
10185 printf(armFlags[imm]);
10188 /*****************************************************************************
10190 * Display an ARM64 'barrier' for the memory barrier instructions
10192 void emitter::emitDispBarrier(insBarrier barrier)
10194 const static char* armBarriers[16] = {"#0", "oshld", "oshst", "osh", "#4", "nshld", "nshst", "nsh",
10195 "#8", "ishld", "ishst", "ish", "#12", "ld", "st", "sy"};
10196 unsigned imm = (unsigned)barrier;
10197 assert((0 <= imm) && (imm < ArrLen(armBarriers)));
10198 printf(armBarriers[imm]);
10201 /*****************************************************************************
10203 * Prints the encoding for the Shift Type encoding
10206 void emitter::emitDispShiftOpts(insOpts opt)
10208 if (opt == INS_OPTS_LSL)
10210 else if (opt == INS_OPTS_LSR)
10212 else if (opt == INS_OPTS_ASR)
10214 else if (opt == INS_OPTS_ROR)
10216 else if (opt == INS_OPTS_MSL)
10219 assert(!"Bad value");
10222 /*****************************************************************************
10224 * Prints the encoding for the Extend Type encoding
10227 void emitter::emitDispExtendOpts(insOpts opt)
10229 if (opt == INS_OPTS_UXTB)
10231 else if (opt == INS_OPTS_UXTH)
10233 else if (opt == INS_OPTS_UXTW)
10235 else if (opt == INS_OPTS_UXTX)
10237 else if (opt == INS_OPTS_SXTB)
10239 else if (opt == INS_OPTS_SXTH)
10241 else if (opt == INS_OPTS_SXTW)
10243 else if (opt == INS_OPTS_SXTX)
10246 assert(!"Bad value");
10249 /*****************************************************************************
10251 * Prints the encoding for the Extend Type encoding in loads/stores
10254 void emitter::emitDispLSExtendOpts(insOpts opt)
10256 if (opt == INS_OPTS_LSL)
10258 else if (opt == INS_OPTS_UXTW)
10260 else if (opt == INS_OPTS_UXTX)
10262 else if (opt == INS_OPTS_SXTW)
10264 else if (opt == INS_OPTS_SXTX)
10267 assert(!"Bad value");
10270 /*****************************************************************************
10272 * Display a register
10274 void emitter::emitDispReg(regNumber reg, emitAttr attr, bool addComma)
10276 emitAttr size = EA_SIZE(attr);
10277 printf(emitRegName(reg, size));
10283 /*****************************************************************************
10285 * Display a vector register with an arrangement suffix
10287 void emitter::emitDispVectorReg(regNumber reg, insOpts opt, bool addComma)
10289 assert(isVectorRegister(reg));
10290 printf(emitVectorRegName(reg));
10291 emitDispArrangement(opt);
10297 /*****************************************************************************
10299 * Display an vector register index suffix
10301 void emitter::emitDispVectorRegIndex(regNumber reg, emitAttr elemsize, ssize_t index, bool addComma)
10303 assert(isVectorRegister(reg));
10304 printf(emitVectorRegName(reg));
10321 assert(!"invalid elemsize");
10325 printf("[%d]", index);
10331 /*****************************************************************************
10333 * Display an arrangement suffix
10335 void emitter::emitDispArrangement(insOpts opt)
10337 const char* str = "???";
10367 assert(!"Invalid insOpt for vector register");
10373 /*****************************************************************************
10375 * Display a register with an optional shift operation
10377 void emitter::emitDispShiftedReg(regNumber reg, insOpts opt, ssize_t imm, emitAttr attr)
10379 emitAttr size = EA_SIZE(attr);
10380 assert((imm & 0x003F) == imm);
10381 assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
10383 printf(emitRegName(reg, size));
10391 emitDispShiftOpts(opt);
10392 emitDispImm(imm, false);
10396 /*****************************************************************************
10398 * Display a register with an optional extend and scale operations
10400 void emitter::emitDispExtendReg(regNumber reg, insOpts opt, ssize_t imm)
10402 assert((imm >= 0) && (imm <= 4));
10403 assert(insOptsNone(opt) || insOptsAnyExtend(opt) || (opt == INS_OPTS_LSL));
10405 // size is based on the extend option, not the instr size.
10406 emitAttr size = insOpts32BitExtend(opt) ? EA_4BYTE : EA_8BYTE;
10410 if (insOptsNone(opt))
10412 emitDispReg(reg, size, false);
10416 emitDispReg(reg, size, true);
10417 if (opt == INS_OPTS_LSL)
10420 emitDispExtendOpts(opt);
10421 if ((imm > 0) || (opt == INS_OPTS_LSL))
10424 emitDispImm(imm, false);
10428 else // !strictArmAsm
10430 if (insOptsNone(opt))
10432 emitDispReg(reg, size, false);
10436 if (opt != INS_OPTS_LSL)
10438 emitDispExtendOpts(opt);
10440 emitDispReg(reg, size, false);
10447 emitDispImm(1 << imm, false);
10452 /*****************************************************************************
10454 * Display an addressing operand [reg + imm]
10456 void emitter::emitDispAddrRI(regNumber reg, insOpts opt, ssize_t imm)
10458 reg = encodingZRtoSP(reg); // ZR (R31) encodes the SP register
10464 emitDispReg(reg, EA_8BYTE, false);
10466 if (!insOptsPostIndex(opt) && (imm != 0))
10469 emitDispImm(imm, false);
10473 if (insOptsPreIndex(opt))
10477 else if (insOptsPostIndex(opt))
10480 emitDispImm(imm, false);
10483 else // !strictArmAsm
10487 const char* operStr = "++";
10494 if (insOptsPreIndex(opt))
10499 emitDispReg(reg, EA_8BYTE, false);
10501 if (insOptsPostIndex(opt))
10506 if (insOptsIndexed(opt))
10512 printf("%c", operStr[1]);
10514 emitDispImm(imm, false);
10519 /*****************************************************************************
10521 * Display an addressing operand [reg + extended reg]
10523 void emitter::emitDispAddrRRExt(regNumber reg1, regNumber reg2, insOpts opt, bool isScaled, emitAttr size)
10525 reg1 = encodingZRtoSP(reg1); // ZR (R31) encodes the SP register
10527 unsigned scale = 0;
10530 scale = NaturalScale_helper(size);
10537 emitDispReg(reg1, EA_8BYTE, true);
10538 emitDispExtendReg(reg2, opt, scale);
10540 else // !strictArmAsm
10542 emitDispReg(reg1, EA_8BYTE, false);
10544 emitDispExtendReg(reg2, opt, scale);
10550 /*****************************************************************************
10552 * Display (optionally) the instruction encoding in hex
10555 void emitter::emitDispInsHex(BYTE* code, size_t sz)
10557 // We do not display the instruction hex if we want diff-able disassembly
10558 if (!emitComp->opts.disDiffable)
10562 printf(" %08X ", (*((code_t*)code)));
10571 /****************************************************************************
10573 * Display the given instruction.
10576 void emitter::emitDispIns(
10577 instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* pCode, size_t sz, insGroup* ig)
10582 id->idDebugOnlyInfo()->idNum; // Do not remove this! It is needed for VisualStudio conditional breakpoints
10584 printf("IN%04x: ", idNum);
10590 if (!emitComp->opts.dspEmit && !isNew && !asmfm && sz)
10593 /* Display the instruction offset */
10595 emitDispInsOffs(offset, doffs);
10597 /* Display the instruction hex code */
10599 emitDispInsHex(pCode, sz);
10603 /* Get the instruction and format */
10605 instruction ins = id->idIns();
10606 insFormat fmt = id->idInsFmt();
10610 /* If this instruction has just been added, check its size */
10612 assert(isNew == false || (int)emitSizeOfInsDsc(id) == emitCurIGfreeNext - (BYTE*)id);
10614 /* Figure out the operand size */
10615 emitAttr size = id->idOpSize();
10616 emitAttr attr = size;
10617 if (id->idGCref() == GCT_GCREF)
10619 else if (id->idGCref() == GCT_BYREF)
10627 bool isExtendAlias;
10636 const char* methodName;
10644 case IF_BI_0A: // BI_0A ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
10645 case IF_BI_0B: // BI_0B ......iiiiiiiiii iiiiiiiiiii..... simm19:00
10648 if (fmt == IF_LARGEJMP)
10650 printf("(LARGEJMP)");
10652 if (id->idAddr()->iiaHasInstrCount())
10654 int instrCount = id->idAddr()->iiaGetInstrCount();
10658 printf("pc%s%d instructions", (instrCount >= 0) ? "+" : "", instrCount);
10662 unsigned insNum = emitFindInsNum(ig, id);
10663 UNATIVE_OFFSET srcOffs = ig->igOffs + emitFindOffset(ig, insNum + 1);
10664 UNATIVE_OFFSET dstOffs = ig->igOffs + emitFindOffset(ig, insNum + 1 + instrCount);
10665 ssize_t relOffs = (ssize_t)(emitOffsetToPtr(dstOffs) - emitOffsetToPtr(srcOffs));
10666 printf("pc%s%d (%d instructions)", (relOffs >= 0) ? "+" : "", relOffs, instrCount);
10669 else if (id->idIsBound())
10671 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10675 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10680 case IF_BI_0C: // BI_0C ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
10681 if (id->idIsCallAddr())
10683 offs = (ssize_t)id->idAddr()->iiaAddr;
10689 methodName = emitComp->eeGetMethodFullName((CORINFO_METHOD_HANDLE)id->idDebugOnlyInfo()->idMemCookie);
10694 if (id->idIsDspReloc())
10696 printf("%08X", offs);
10700 printf("%s", methodName);
10704 case IF_BI_1A: // BI_1A ......iiiiiiiiii iiiiiiiiiiittttt Rt simm19:00
10705 assert(insOptsNone(id->idInsOpt()));
10706 emitDispReg(id->idReg1(), size, true);
10707 if (id->idIsBound())
10709 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10713 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10717 case IF_BI_1B: // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
10718 assert(insOptsNone(id->idInsOpt()));
10719 emitDispReg(id->idReg1(), size, true);
10720 emitDispImm(emitGetInsSC(id), true);
10721 if (id->idIsBound())
10723 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10727 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10731 case IF_BR_1A: // BR_1A ................ ......nnnnn..... Rn
10732 assert(insOptsNone(id->idInsOpt()));
10733 emitDispReg(id->idReg1(), size, false);
10736 case IF_BR_1B: // BR_1B ................ ......nnnnn..... Rn
10737 assert(insOptsNone(id->idInsOpt()));
10738 emitDispReg(id->idReg3(), size, false);
10741 case IF_LS_1A: // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB)
10742 case IF_DI_1E: // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
10745 assert(insOptsNone(id->idInsOpt()));
10746 emitDispReg(id->idReg1(), size, true);
10747 imm = emitGetInsSC(id);
10749 /* Is this actually a reference to a data section? */
10750 if (fmt == IF_LARGEADR)
10752 printf("(LARGEADR)");
10754 else if (fmt == IF_LARGELDC)
10756 printf("(LARGELDC)");
10760 if (id->idAddr()->iiaIsJitDataOffset())
10762 doffs = Compiler::eeGetJitDataOffs(id->idAddr()->iiaFieldHnd);
10763 /* Display a data section reference */
10766 printf("@CNS%02u", doffs - 1);
10768 printf("@RWD%02u", doffs);
10771 printf("%+Id", imm);
10776 if (id->idIsReloc())
10779 emitDispImm((ssize_t)id->idAddr()->iiaAddr, false);
10781 else if (id->idIsBound())
10783 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10787 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10793 case IF_LS_2A: // LS_2A .X.......X...... ......nnnnnttttt Rt Rn
10794 assert(insOptsNone(id->idInsOpt()));
10795 assert(emitGetInsSC(id) == 0);
10796 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10797 emitDispAddrRI(id->idReg2(), id->idInsOpt(), 0);
10800 case IF_LS_2B: // LS_2B .X.......Xiiiiii iiiiiinnnnnttttt Rt Rn imm(0-4095)
10801 assert(insOptsNone(id->idInsOpt()));
10802 imm = emitGetInsSC(id);
10803 scale = NaturalScale_helper(emitInsLoadStoreSize(id));
10804 imm <<= scale; // The immediate is scaled by the size of the ld/st
10805 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10806 emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
10809 case IF_LS_2C: // LS_2C .X.......X.iiiii iiiiPPnnnnnttttt Rt Rn imm(-256..+255) no/pre/post inc
10810 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
10811 imm = emitGetInsSC(id);
10812 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10813 emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
10816 case IF_LS_3A: // LS_3A .X.......X.mmmmm oooS..nnnnnttttt Rt Rn Rm ext(Rm) LSL {}
10817 assert(insOptsLSExtend(id->idInsOpt()));
10818 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10819 if (id->idIsLclVar())
10821 emitDispAddrRRExt(id->idReg2(), codeGen->rsGetRsvdReg(), id->idInsOpt(), false, size);
10825 emitDispAddrRRExt(id->idReg2(), id->idReg3(), id->idInsOpt(), id->idReg3Scaled(), size);
10829 case IF_LS_3B: // LS_3B X............... .aaaaannnnnddddd Rt Ra Rn
10830 assert(insOptsNone(id->idInsOpt()));
10831 assert(emitGetInsSC(id) == 0);
10832 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10833 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10834 emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
10837 case IF_LS_3C: // LS_3C X.........iiiiii iaaaaannnnnddddd Rt Ra Rn imm(im7,sh)
10838 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
10839 imm = emitGetInsSC(id);
10840 scale = NaturalScale_helper(emitInsLoadStoreSize(id));
10842 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10843 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10844 emitDispAddrRI(id->idReg3(), id->idInsOpt(), imm);
10847 case IF_LS_3D: // LS_3D .X.......X.mmmmm ......nnnnnttttt Wm Rt Rn
10848 assert(insOptsNone(id->idInsOpt()));
10849 emitDispReg(id->idReg1(), EA_4BYTE, true);
10850 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10851 emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
10854 case IF_DI_1A: // DI_1A X.......shiiiiii iiiiiinnnnn..... Rn imm(i12,sh)
10855 emitDispReg(id->idReg1(), size, true);
10856 emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
10859 case IF_DI_1B: // DI_1B X........hwiiiii iiiiiiiiiiiddddd Rd imm(i16,hw)
10860 emitDispReg(id->idReg1(), size, true);
10861 hwi.immHWVal = (unsigned)emitGetInsSC(id);
10862 if (ins == INS_mov)
10864 emitDispImm(emitDecodeHalfwordImm(hwi, size), false);
10866 else // movz, movn, movk
10868 emitDispImm(hwi.immVal, false);
10869 if (hwi.immHW != 0)
10871 emitDispShiftOpts(INS_OPTS_LSL);
10872 emitDispImm(hwi.immHW * 16, false);
10877 case IF_DI_1C: // DI_1C X........Nrrrrrr ssssssnnnnn..... Rn imm(N,r,s)
10878 emitDispReg(id->idReg1(), size, true);
10879 bmi.immNRS = (unsigned)emitGetInsSC(id);
10880 emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
10883 case IF_DI_1D: // DI_1D X........Nrrrrrr ssssss.....ddddd Rd imm(N,r,s)
10884 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
10885 bmi.immNRS = (unsigned)emitGetInsSC(id);
10886 emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
10889 case IF_DI_2A: // DI_2A X.......shiiiiii iiiiiinnnnnddddd Rd Rn imm(i12,sh)
10890 if ((ins == INS_add) || (ins == INS_sub))
10892 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
10893 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
10897 emitDispReg(id->idReg1(), size, true);
10898 emitDispReg(id->idReg2(), size, true);
10900 emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
10903 case IF_DI_2B: // DI_2B X........X.nnnnn ssssssnnnnnddddd Rd Rn imm(0-63)
10904 emitDispReg(id->idReg1(), size, true);
10905 emitDispReg(id->idReg2(), size, true);
10906 emitDispImm(emitGetInsSC(id), false);
10909 case IF_DI_2C: // DI_2C X........Nrrrrrr ssssssnnnnnddddd Rd Rn imm(N,r,s)
10910 if (ins == INS_ands)
10912 emitDispReg(id->idReg1(), size, true);
10916 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
10918 emitDispReg(id->idReg2(), size, true);
10919 bmi.immNRS = (unsigned)emitGetInsSC(id);
10920 emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
10923 case IF_DI_2D: // DI_2D X........Nrrrrrr ssssssnnnnnddddd Rd Rn imr, ims (N,r,s)
10924 emitDispReg(id->idReg1(), size, true);
10925 emitDispReg(id->idReg2(), size, true);
10927 imm = emitGetInsSC(id);
10928 bmi.immNRS = (unsigned)imm;
10935 emitDispImm(bmi.immR, true);
10936 emitDispImm(bmi.immS, false);
10942 emitDispImm(getBitWidth(size) - bmi.immR, true);
10943 emitDispImm(bmi.immS + 1, false);
10949 emitDispImm(bmi.immR, true);
10950 emitDispImm(bmi.immS - bmi.immR + 1, false);
10956 emitDispImm(imm, false);
10960 assert(!"Unexpected instruction in IF_DI_2D");
10965 case IF_DI_1F: // DI_1F X..........iiiii cccc..nnnnn.nzcv Rn imm5 nzcv cond
10966 emitDispReg(id->idReg1(), size, true);
10967 cfi.immCFVal = (unsigned)emitGetInsSC(id);
10968 emitDispImm(cfi.imm5, true);
10969 emitDispFlags(cfi.flags);
10971 emitDispCond(cfi.cond);
10974 case IF_DR_1D: // DR_1D X............... cccc.......mmmmm Rd cond
10975 emitDispReg(id->idReg1(), size, true);
10976 cfi.immCFVal = (unsigned)emitGetInsSC(id);
10977 emitDispCond(cfi.cond);
10980 case IF_DR_2A: // DR_2A X..........mmmmm ......nnnnn..... Rn Rm
10981 emitDispReg(id->idReg1(), size, true);
10982 emitDispReg(id->idReg2(), size, false);
10985 case IF_DR_2B: // DR_2B X.......sh.mmmmm ssssssnnnnn..... Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
10986 emitDispReg(id->idReg1(), size, true);
10987 emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
10990 case IF_DR_2C: // DR_2C X..........mmmmm ooosssnnnnn..... Rn Rm ext(Rm) LSL imm(0-4)
10991 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
10992 imm = emitGetInsSC(id);
10993 emitDispExtendReg(id->idReg2(), id->idInsOpt(), imm);
10996 case IF_DR_2D: // DR_2D X..........nnnnn cccc..nnnnnddddd Rd Rn cond
10997 emitDispReg(id->idReg1(), size, true);
10998 emitDispReg(id->idReg2(), size, true);
10999 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11000 emitDispCond(cfi.cond);
11003 case IF_DR_2E: // DR_2E X..........mmmmm ...........ddddd Rd Rm
11004 emitDispReg(id->idReg1(), size, true);
11005 emitDispReg(id->idReg2(), size, false);
11008 case IF_DR_2F: // DR_2F X.......sh.mmmmm ssssss.....ddddd Rd Rm {LSL,LSR,ASR} imm(0-63)
11009 emitDispReg(id->idReg1(), size, true);
11010 emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
11013 case IF_DR_2G: // DR_2G X............... ......nnnnnddddd Rd Rn
11014 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11015 emitDispReg(encodingZRtoSP(id->idReg2()), size, false);
11018 case IF_DR_2H: // DR_2H X........X...... ......nnnnnddddd Rd Rn
11019 emitDispReg(id->idReg1(), size, true);
11020 emitDispReg(id->idReg2(), size, false);
11023 case IF_DR_2I: // DR_2I X..........mmmmm cccc..nnnnn.nzcv Rn Rm nzcv cond
11024 emitDispReg(id->idReg1(), size, true);
11025 emitDispReg(id->idReg2(), size, true);
11026 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11027 emitDispFlags(cfi.flags);
11029 emitDispCond(cfi.cond);
11032 case IF_DR_3A: // DR_3A X..........mmmmm ......nnnnnmmmmm Rd Rn Rm
11033 if ((ins == INS_add) || (ins == INS_sub))
11035 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11036 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11038 else if ((ins == INS_smull) || (ins == INS_smulh))
11040 // Rd is always 8 bytes
11041 emitDispReg(id->idReg1(), EA_8BYTE, true);
11043 // Rn, Rm effective size depends on instruction type
11044 size = (ins == INS_smulh) ? EA_8BYTE : EA_4BYTE;
11045 emitDispReg(id->idReg2(), size, true);
11049 emitDispReg(id->idReg1(), size, true);
11050 emitDispReg(id->idReg2(), size, true);
11052 if (id->idIsLclVar())
11054 emitDispReg(codeGen->rsGetRsvdReg(), size, false);
11058 emitDispReg(id->idReg3(), size, false);
11063 case IF_DR_3B: // DR_3B X.......sh.mmmmm ssssssnnnnnddddd Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
11064 emitDispReg(id->idReg1(), size, true);
11065 emitDispReg(id->idReg2(), size, true);
11066 emitDispShiftedReg(id->idReg3(), id->idInsOpt(), emitGetInsSC(id), size);
11069 case IF_DR_3C: // DR_3C X..........mmmmm ooosssnnnnnddddd Rd Rn Rm ext(Rm) LSL imm(0-4)
11070 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11071 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11072 imm = emitGetInsSC(id);
11073 emitDispExtendReg(id->idReg3(), id->idInsOpt(), imm);
11076 case IF_DR_3D: // DR_3D X..........mmmmm cccc..nnnnnmmmmm Rd Rn Rm cond
11077 emitDispReg(id->idReg1(), size, true);
11078 emitDispReg(id->idReg2(), size, true);
11079 emitDispReg(id->idReg3(), size, true);
11080 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11081 emitDispCond(cfi.cond);
11084 case IF_DR_3E: // DR_3E X........X.mmmmm ssssssnnnnnddddd Rd Rn Rm imm(0-63)
11085 emitDispReg(id->idReg1(), size, true);
11086 emitDispReg(id->idReg2(), size, true);
11087 emitDispReg(id->idReg3(), size, true);
11088 emitDispImm(emitGetInsSC(id), false);
11091 case IF_DR_4A: // DR_4A X..........mmmmm .aaaaannnnnmmmmm Rd Rn Rm Ra
11092 emitDispReg(id->idReg1(), size, true);
11093 emitDispReg(id->idReg2(), size, true);
11094 emitDispReg(id->idReg3(), size, true);
11095 emitDispReg(id->idReg4(), size, false);
11098 case IF_DV_1A: // DV_1A .........X.iiiii iii........ddddd Vd imm8 (fmov - immediate scalar)
11099 elemsize = id->idOpSize();
11100 emitDispReg(id->idReg1(), elemsize, true);
11101 emitDispFloatImm(emitGetInsSC(id));
11104 case IF_DV_1B: // DV_1B .QX..........iii cmod..iiiiiddddd Vd imm8 (immediate vector)
11105 imm = emitGetInsSC(id) & 0x0ff;
11106 immShift = (emitGetInsSC(id) & 0x700) >> 8;
11107 hasShift = (immShift != 0);
11108 elemsize = optGetElemsize(id->idInsOpt());
11109 if (id->idInsOpt() == INS_OPTS_1D)
11111 assert(elemsize == size);
11112 emitDispReg(id->idReg1(), size, true);
11116 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11118 if (ins == INS_fmov)
11120 emitDispFloatImm(imm);
11121 assert(hasShift == false);
11125 if (elemsize == EA_8BYTE)
11127 assert(ins == INS_movi);
11129 const ssize_t mask8 = 0xFF;
11130 for (unsigned b = 0; b < 8; b++)
11132 if (imm & (1 << b))
11134 imm64 |= (mask8 << (b * 8));
11137 emitDispImm(imm64, hasShift, true);
11141 emitDispImm(imm, hasShift, true);
11145 insOpts opt = (immShift & 0x4) ? INS_OPTS_MSL : INS_OPTS_LSL;
11146 unsigned shift = (immShift & 0x3) * 8;
11147 emitDispShiftOpts(opt);
11148 emitDispImm(shift, false);
11153 case IF_DV_1C: // DV_1C .........X...... ......nnnnn..... Vn #0.0 (fcmp - with zero)
11154 elemsize = id->idOpSize();
11155 emitDispReg(id->idReg1(), elemsize, true);
11156 emitDispFloatZero();
11159 case IF_DV_2A: // DV_2A .Q.......X...... ......nnnnnddddd Vd Vn (fabs, fcvt - vector)
11160 case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
11161 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11162 emitDispVectorReg(id->idReg2(), id->idInsOpt(), false);
11165 case IF_DV_2N: // DV_2N .........iiiiiii ......nnnnnddddd Vd Vn imm (shift - scalar)
11166 elemsize = id->idOpSize();
11167 emitDispReg(id->idReg1(), elemsize, true);
11168 emitDispReg(id->idReg2(), elemsize, true);
11169 emitDispImm(emitGetInsSC(id), false);
11172 case IF_DV_2O: // DV_2O .Q.......iiiiiii ......nnnnnddddd Vd Vn imm (shift - vector)
11173 imm = emitGetInsSC(id);
11174 // Do we have a sxtl or uxtl instruction?
11175 isExtendAlias = ((ins == INS_sxtl) || (ins == INS_sxtl2) || (ins == INS_uxtl) || (ins == INS_uxtl2));
11176 code = emitInsCode(ins, fmt);
11177 if (code & 0x00008000) // widen/narrow opcodes
11179 if (code & 0x00002000) // SHL opcodes
11181 emitDispVectorReg(id->idReg1(), optWidenElemsize(id->idInsOpt()), true);
11182 emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11184 else // SHR opcodes
11186 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11187 emitDispVectorReg(id->idReg2(), optWidenElemsize(id->idInsOpt()), !isExtendAlias);
11192 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11193 emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11195 // Print the immediate unless we have a sxtl or uxtl instruction
11196 if (!isExtendAlias)
11198 emitDispImm(imm, false);
11202 case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov/smov - to general)
11203 srcsize = id->idOpSize();
11204 index = emitGetInsSC(id);
11205 if (ins == INS_smov)
11207 dstsize = EA_8BYTE;
11209 else // INS_umov or INS_mov
11211 dstsize = (srcsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE;
11213 emitDispReg(id->idReg1(), dstsize, true);
11214 emitDispVectorRegIndex(id->idReg2(), srcsize, index, false);
11217 case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
11218 if (ins == INS_dup)
11220 datasize = id->idOpSize();
11221 assert(isValidVectorDatasize(datasize));
11222 assert(isValidArrangement(datasize, id->idInsOpt()));
11223 elemsize = optGetElemsize(id->idInsOpt());
11224 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11228 elemsize = id->idOpSize();
11229 index = emitGetInsSC(id);
11230 assert(isValidVectorElemsize(elemsize));
11231 emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11233 emitDispReg(id->idReg2(), (elemsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE, false);
11236 case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
11237 datasize = id->idOpSize();
11238 assert(isValidVectorDatasize(datasize));
11239 assert(isValidArrangement(datasize, id->idInsOpt()));
11240 elemsize = optGetElemsize(id->idInsOpt());
11241 index = emitGetInsSC(id);
11242 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11243 emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11246 case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
11247 elemsize = id->idOpSize();
11248 index = emitGetInsSC(id);
11249 emitDispReg(id->idReg1(), elemsize, true);
11250 emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11253 case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
11254 imm = emitGetInsSC(id);
11255 index = (imm >> 4) & 0xf;
11256 index2 = imm & 0xf;
11257 elemsize = id->idOpSize();
11258 emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11259 emitDispVectorRegIndex(id->idReg2(), elemsize, index2, false);
11262 case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov, fcvtXX - register)
11263 case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
11264 case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
11265 elemsize = id->idOpSize();
11266 emitDispReg(id->idReg1(), elemsize, true);
11267 emitDispReg(id->idReg2(), elemsize, false);
11270 case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov, fcvtXX - to general)
11271 case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov, Xcvtf - from general)
11272 case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
11273 dstsize = optGetDstsize(id->idInsOpt());
11274 srcsize = optGetSrcsize(id->idInsOpt());
11276 emitDispReg(id->idReg1(), dstsize, true);
11277 emitDispReg(id->idReg2(), srcsize, false);
11280 case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11281 case IF_DV_3B: // DV_3B .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11282 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11283 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11284 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11287 case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11288 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11289 if (ins != INS_mov)
11291 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11293 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11296 case IF_DV_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
11297 case IF_DV_3BI: // DV_3BI .Q........Lmmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
11298 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11299 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11300 elemsize = optGetElemsize(id->idInsOpt());
11301 emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11304 case IF_DV_3D: // DV_3D .........X.mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
11305 case IF_DV_3E: // DV_3E ...........mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
11306 emitDispReg(id->idReg1(), size, true);
11307 emitDispReg(id->idReg2(), size, true);
11308 emitDispReg(id->idReg3(), size, false);
11311 case IF_DV_3DI: // DV_3DI .........XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (scalar by elem)
11312 emitDispReg(id->idReg1(), size, true);
11313 emitDispReg(id->idReg2(), size, true);
11315 emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11318 case IF_DV_4A: // DV_4A .........X.mmmmm .aaaaannnnnddddd Vd Va Vn Vm (scalar)
11319 emitDispReg(id->idReg1(), size, true);
11320 emitDispReg(id->idReg2(), size, true);
11321 emitDispReg(id->idReg3(), size, true);
11322 emitDispReg(id->idReg4(), size, false);
11325 case IF_SN_0A: // SN_0A ................ ................
11328 case IF_SI_0A: // SI_0A ...........iiiii iiiiiiiiiii..... imm16
11329 emitDispImm(emitGetInsSC(id), false);
11332 case IF_SI_0B: // SI_0B ................ ....bbbb........ imm4 - barrier
11333 emitDispBarrier((insBarrier)emitGetInsSC(id));
11337 printf("unexpected format %s", emitIfName(id->idInsFmt()));
11338 assert(!"unexpectedFormat");
11342 if (id->idDebugOnlyInfo()->idVarRefOffs)
11345 emitDispFrameRef(id->idAddr()->iiaLclVar.lvaVarNum(), id->idAddr()->iiaLclVar.lvaOffset(),
11346 id->idDebugOnlyInfo()->idVarRefOffs, asmfm);
11352 /*****************************************************************************
11354 * Display a stack frame reference.
11357 void emitter::emitDispFrameRef(int varx, int disp, int offs, bool asmfm)
11362 printf("TEMP_%02u", -varx);
11364 emitComp->gtDispLclVar(+varx, false);
11367 printf("-0x%02x", -disp);
11369 printf("+0x%02x", +disp);
11373 if (varx >= 0 && emitComp->opts.varNames)
11376 const char* varName;
11378 assert((unsigned)varx < emitComp->lvaCount);
11379 varDsc = emitComp->lvaTable + varx;
11380 varName = emitComp->compLocalVarName(varx, offs);
11384 printf("'%s", varName);
11387 printf("-%d", -disp);
11389 printf("+%d", +disp);
11398 // Generate code for a load or store operation with a potentially complex addressing mode
11399 // This method handles the case of a GT_IND with contained GT_LEA op1 of the x86 form [base + index*sccale + offset]
11400 // Since Arm64 does not directly support this complex of an addressing mode
11401 // we may generates up to three instructions for this for Arm64
11403 void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataReg, GenTreeIndir* indir)
11405 emitAttr ldstAttr = isVectorRegister(dataReg) ? attr : emitInsAdjustLoadStoreAttr(ins, attr);
11407 GenTree* addr = indir->Addr();
11409 if (addr->isContained())
11411 assert(addr->OperGet() == GT_LCL_VAR_ADDR || addr->OperGet() == GT_LEA);
11416 if (addr->OperGet() == GT_LEA)
11418 offset = addr->AsAddrMode()->Offset();
11419 if (addr->AsAddrMode()->gtScale > 0)
11421 assert(isPow2(addr->AsAddrMode()->gtScale));
11422 BitScanForward(&lsl, addr->AsAddrMode()->gtScale);
11426 GenTree* memBase = indir->Base();
11428 if (indir->HasIndex())
11430 GenTree* index = indir->Index();
11434 regNumber tmpReg = indir->GetSingleTempReg();
11436 emitAttr addType = varTypeIsGC(memBase) ? EA_BYREF : EA_PTRSIZE;
11438 if (emitIns_valid_imm_for_add(offset, EA_8BYTE))
11442 // Generate code to set tmpReg = base + index*scale
11443 emitIns_R_R_R_I(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum, lsl,
11448 // Generate code to set tmpReg = base + index
11449 emitIns_R_R_R(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum);
11452 noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11454 // Then load/store dataReg from/to [tmpReg + offset]
11455 emitIns_R_R_I(ins, ldstAttr, dataReg, tmpReg, offset);
11457 else // large offset
11459 // First load/store tmpReg with the large offset constant
11460 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11461 // Then add the base register
11463 emitIns_R_R_R(INS_add, addType, tmpReg, tmpReg, memBase->gtRegNum);
11465 noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11466 noway_assert(tmpReg != index->gtRegNum);
11468 // Then load/store dataReg from/to [tmpReg + index*scale]
11469 emitIns_R_R_R_I(ins, ldstAttr, dataReg, tmpReg, index->gtRegNum, lsl, INS_OPTS_LSL);
11472 else // (offset == 0)
11476 // Then load/store dataReg from/to [memBase + index*scale]
11477 emitIns_R_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum, lsl, INS_OPTS_LSL);
11481 // Then load/store dataReg from/to [memBase + index]
11482 emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum);
11486 else // no Index register
11488 if (emitIns_valid_imm_for_ldst_offset(offset, EA_SIZE(attr)))
11490 // Then load/store dataReg from/to [memBase + offset]
11491 emitIns_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, offset);
11495 // We require a tmpReg to hold the offset
11496 regNumber tmpReg = indir->GetSingleTempReg();
11498 // First load/store tmpReg with the large offset constant
11499 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11501 // Then load/store dataReg from/to [memBase + tmpReg]
11502 emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, tmpReg);
11506 else // addr is not contained, so we evaluate it into a register
11508 // Then load/store dataReg from/to [addrReg]
11509 emitIns_R_R(ins, ldstAttr, dataReg, addr->gtRegNum);
11513 // Generates an integer data section constant and returns a field handle representing
11514 // the data offset to access the constant via a load instruction.
11515 // This is called during ngen for any relocatable constants
11517 CORINFO_FIELD_HANDLE emitter::emitLiteralConst(ssize_t cnsValIn, emitAttr attr /*=EA_8BYTE*/)
11519 ssize_t constValue = cnsValIn;
11520 void* cnsAddr = &constValue;
11523 if (attr == EA_4BYTE)
11529 assert(attr == EA_8BYTE);
11533 // Access to inline data is 'abstracted' by a special type of static member
11534 // (produced by eeFindJitDataOffs) which the emitter recognizes as being a reference
11535 // to constant data, not a real static field.
11537 UNATIVE_OFFSET cnsSize = (attr == EA_4BYTE) ? 4 : 8;
11538 UNATIVE_OFFSET cnum = emitDataConst(cnsAddr, cnsSize, dblAlign);
11539 return emitComp->eeFindJitDataOffs(cnum);
11542 // Generates a float or double data section constant and returns field handle representing
11543 // the data offset to access the constant. This is called by emitInsBinary() in case
11544 // of contained float of double constants.
11545 CORINFO_FIELD_HANDLE emitter::emitFltOrDblConst(GenTreeDblCon* tree, emitAttr attr /*=EA_UNKNOWN*/)
11547 if (attr == EA_UNKNOWN)
11549 attr = emitTypeSize(tree->TypeGet());
11553 assert(emitTypeSize(tree->TypeGet()) == attr);
11556 double constValue = tree->gtDblCon.gtDconVal;
11561 if (attr == EA_4BYTE)
11563 f = forceCastToFloat(constValue);
11569 cnsAddr = &constValue;
11573 // Access to inline data is 'abstracted' by a special type of static member
11574 // (produced by eeFindJitDataOffs) which the emitter recognizes as being a reference
11575 // to constant data, not a real static field.
11577 UNATIVE_OFFSET cnsSize = (attr == EA_4BYTE) ? 4 : 8;
11578 UNATIVE_OFFSET cnum = emitDataConst(cnsAddr, cnsSize, dblAlign);
11579 return emitComp->eeFindJitDataOffs(cnum);
11582 // The callee must call genConsumeReg() for any non-contained srcs
11583 // and genProduceReg() for any non-contained dsts.
11585 regNumber emitter::emitInsBinary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src)
11587 regNumber result = REG_NA;
11589 // dst can only be a reg
11590 assert(!dst->isContained());
11592 // src can be immed or reg
11593 assert(!src->isContained() || src->isContainedIntOrIImmed());
11595 // find immed (if any) - it cannot be a dst
11596 GenTreeIntConCommon* intConst = nullptr;
11597 if (src->isContainedIntOrIImmed())
11599 intConst = src->AsIntConCommon();
11604 emitIns_R_I(ins, attr, dst->gtRegNum, intConst->IconValue());
11605 return dst->gtRegNum;
11609 emitIns_R_R(ins, attr, dst->gtRegNum, src->gtRegNum);
11610 return dst->gtRegNum;
11614 // The callee must call genConsumeReg() for any non-contained srcs
11615 // and genProduceReg() for any non-contained dsts.
11617 regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src1, GenTree* src2)
11619 regNumber result = REG_NA;
11621 // dst can only be a reg
11622 assert(!dst->isContained());
11624 // find immed (if any) - it cannot be a dst
11625 // Only one src can be an int.
11626 GenTreeIntConCommon* intConst = nullptr;
11627 GenTree* nonIntReg = nullptr;
11629 if (varTypeIsFloating(dst))
11631 // src1 can only be a reg
11632 assert(!src1->isContained());
11633 // src2 can only be a reg
11634 assert(!src2->isContained());
11636 else // not floating point
11638 // src2 can be immed or reg
11639 assert(!src2->isContained() || src2->isContainedIntOrIImmed());
11641 // Check src2 first as we can always allow it to be a contained immediate
11642 if (src2->isContainedIntOrIImmed())
11644 intConst = src2->AsIntConCommon();
11647 // Only for commutative operations do we check src1 and allow it to be a contained immediate
11648 else if (dst->OperIsCommutative())
11650 // src1 can be immed or reg
11651 assert(!src1->isContained() || src1->isContainedIntOrIImmed());
11653 // Check src1 and allow it to be a contained immediate
11654 if (src1->isContainedIntOrIImmed())
11656 assert(!src2->isContainedIntOrIImmed());
11657 intConst = src1->AsIntConCommon();
11663 // src1 can only be a reg
11664 assert(!src1->isContained());
11668 bool isMulOverflow = false;
11669 if (dst->gtOverflowEx())
11671 if ((ins == INS_add) || (ins == INS_adds))
11675 else if ((ins == INS_sub) || (ins == INS_subs))
11679 else if (ins == INS_mul)
11681 isMulOverflow = true;
11682 assert(intConst == nullptr); // overflow format doesn't support an int constant operand
11686 assert(!"Invalid ins for overflow check");
11689 if (intConst != nullptr)
11691 emitIns_R_R_I(ins, attr, dst->gtRegNum, nonIntReg->gtRegNum, intConst->IconValue());
11697 regNumber extraReg = dst->GetSingleTempReg();
11698 assert(extraReg != dst->gtRegNum);
11700 if ((dst->gtFlags & GTF_UNSIGNED) != 0)
11702 if (attr == EA_4BYTE)
11704 // Compute 8 byte results from 4 byte by 4 byte multiplication.
11705 emitIns_R_R_R(INS_umull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11707 // Get the high result by shifting dst.
11708 emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11712 assert(attr == EA_8BYTE);
11713 // Compute the high result.
11714 emitIns_R_R_R(INS_umulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11716 // Now multiply without skewing the high result.
11717 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11720 // zero-sign bit comparison to detect overflow.
11721 emitIns_R_I(INS_cmp, attr, extraReg, 0);
11726 if (attr == EA_4BYTE)
11728 // Compute 8 byte results from 4 byte by 4 byte multiplication.
11729 emitIns_R_R_R(INS_smull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11731 // Get the high result by shifting dst.
11732 emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11738 assert(attr == EA_8BYTE);
11739 // Save the high result in a temporary register.
11740 emitIns_R_R_R(INS_smulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11742 // Now multiply without skewing the high result.
11743 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11748 // Sign bit comparison to detect overflow.
11749 emitIns_R_R_I(INS_cmp, attr, extraReg, dst->gtRegNum, bitShift, INS_OPTS_ASR);
11754 // We can just multiply.
11755 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11759 if (dst->gtOverflowEx())
11761 assert(!varTypeIsFloating(dst));
11762 codeGen->genCheckOverflow(dst);
11765 return dst->gtRegNum;
11768 #endif // defined(_TARGET_ARM64_)