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));
3826 assert(isValidVectorDatasize(size));
3827 // Bitwise behavior is independent of element size, but is always encoded as 1 Byte
3828 opt = optMakeArrangement(size, EA_1BYTE);
3830 if (insOptsNone(opt))
3833 assert(size == EA_8BYTE); // Only type D is supported
3839 assert(insOptsAnyArrangement(opt));
3840 assert(isValidVectorDatasize(size));
3841 assert(isValidArrangement(size, opt));
3842 elemsize = optGetElemsize(opt);
3849 if (isVectorRegister(reg1))
3851 assert(isVectorRegister(reg2));
3854 assert(isValidVectorDatasize(size));
3855 // Bitwise behavior is independent of element size, but is always encoded as 1 Byte
3856 opt = optMakeArrangement(size, EA_1BYTE);
3858 if (insOptsNone(opt))
3861 assert(size == EA_8BYTE); // Only type D is supported
3867 assert(isValidVectorDatasize(size));
3868 assert(isValidArrangement(size, opt));
3869 elemsize = optGetElemsize(opt);
3877 assert(insOptsNone(opt));
3878 assert(isGeneralRegister(reg1));
3879 assert(isGeneralRegisterOrZR(reg2));
3884 assert(size == EA_8BYTE);
3891 assert(insOptsNone(opt));
3892 assert(isValidGeneralDatasize(size));
3893 assert(isGeneralRegister(reg1));
3894 assert(isGeneralRegister(reg2));
3902 return emitIns_R_R_I(ins, size, reg1, reg2, 0, opt);
3910 if (isVectorRegister(reg1))
3912 assert(isVectorRegister(reg2));
3913 assert(isValidVectorDatasize(size));
3914 assert(isValidArrangement(size, opt));
3915 elemsize = optGetElemsize(opt);
3916 if ((ins == INS_cls) || (ins == INS_clz))
3918 assert(elemsize != EA_8BYTE); // No encoding for type D
3920 else if (ins == INS_rev32)
3922 assert((elemsize == EA_2BYTE) || (elemsize == EA_1BYTE));
3926 assert(elemsize == EA_1BYTE); // Only supports 8B or 16B
3933 // Doesn't have general register version(s)
3940 assert(insOptsNone(opt));
3941 assert(isGeneralRegister(reg1));
3942 assert(isGeneralRegister(reg2));
3943 if (ins == INS_rev32)
3945 assert(size == EA_8BYTE);
3949 assert(isValidGeneralDatasize(size));
3962 assert(isVectorRegister(reg1));
3963 assert(isVectorRegister(reg2));
3964 assert(isValidVectorDatasize(size));
3965 assert(isValidArrangement(size, opt));
3966 elemsize = optGetElemsize(opt);
3967 assert(elemsize != EA_8BYTE); // No encoding for type D
3973 assert(isVectorRegister(reg1));
3974 assert(isVectorRegister(reg2));
3975 assert(isValidVectorDatasize(size));
3976 assert(isValidArrangement(size, opt));
3977 elemsize = optGetElemsize(opt);
3978 // size is determined by instruction
3981 assert(size == EA_8BYTE);
3983 else // ins == INS_xtn2
3985 assert(size == EA_16BYTE);
3987 assert(elemsize != EA_8BYTE); // Narrowing must not end with 8 byte data
3995 assert(isValidGeneralDatasize(size));
4007 assert(isValidGeneralLSDatasize(size));
4008 assert(isGeneralRegisterOrZR(reg1));
4009 assert(isGeneralRegisterOrSP(reg2));
4010 assert(insOptsNone(opt));
4012 reg2 = encodingSPtoZR(reg2);
4030 assert(insOptsNone(opt));
4031 emitIns_R_R_I(ins, attr, reg1, reg2, 0, INS_OPTS_NONE);
4035 assert(isValidVectorElemsizeFloat(size));
4037 // Is the mov even necessary?
4043 if (isVectorRegister(reg1))
4045 if (isVectorRegister(reg2))
4047 assert(insOptsNone(opt));
4052 assert(isGeneralRegister(reg2));
4054 // if the optional conversion specifier is not present we calculate it
4055 if (opt == INS_OPTS_NONE)
4057 opt = (size == EA_4BYTE) ? INS_OPTS_4BYTE_TO_S : INS_OPTS_8BYTE_TO_D;
4059 assert(insOptsConvertIntToFloat(opt));
4066 assert(isGeneralRegister(reg1));
4067 assert(isVectorRegister(reg2));
4069 // if the optional conversion specifier is not present we calculate it
4070 if (opt == INS_OPTS_NONE)
4072 opt = (size == EA_4BYTE) ? INS_OPTS_S_TO_4BYTE : INS_OPTS_D_TO_8BYTE;
4074 assert(insOptsConvertFloatToInt(opt));
4082 assert(insOptsNone(opt));
4083 assert(isValidVectorElemsizeFloat(size));
4084 assert(isVectorRegister(reg1));
4085 assert(isVectorRegister(reg2));
4099 if (insOptsAnyArrangement(opt))
4102 assert(isVectorRegister(reg1));
4103 assert(isVectorRegister(reg2));
4104 assert(isValidVectorDatasize(size));
4105 assert(isValidArrangement(size, opt));
4106 elemsize = optGetElemsize(opt);
4107 assert(isValidVectorElemsizeFloat(elemsize));
4108 assert(opt != INS_OPTS_1D); // Reserved encoding
4114 assert(isVectorRegister(reg2));
4115 if (isVectorRegister(reg1))
4117 assert(insOptsNone(opt));
4118 assert(isValidVectorElemsizeFloat(size));
4123 assert(isGeneralRegister(reg1));
4124 assert(insOptsConvertFloatToInt(opt));
4125 assert(isValidVectorElemsizeFloat(size));
4135 assert(isVectorRegister(reg1));
4136 assert(isVectorRegister(reg2));
4137 assert(isValidVectorDatasize(size));
4138 assert(insOptsNone(opt));
4139 assert(size == EA_8BYTE); // Narrowing from Double or Widening to Double (Half not supported)
4145 if (insOptsAnyArrangement(opt))
4148 assert(isVectorRegister(reg1));
4149 assert(isVectorRegister(reg2));
4150 assert(isValidVectorDatasize(size));
4151 assert(isValidArrangement(size, opt));
4152 elemsize = optGetElemsize(opt);
4153 assert(isValidVectorElemsizeFloat(elemsize));
4154 assert(opt != INS_OPTS_1D); // Reserved encoding
4160 assert(isVectorRegister(reg1));
4161 if (isVectorRegister(reg2))
4163 assert(insOptsNone(opt));
4164 assert(isValidVectorElemsizeFloat(size));
4169 assert(isGeneralRegister(reg2));
4170 assert(insOptsConvertIntToFloat(opt));
4171 assert(isValidVectorElemsizeFloat(size));
4187 if (insOptsAnyArrangement(opt))
4190 assert(isVectorRegister(reg1));
4191 assert(isVectorRegister(reg2));
4192 assert(isValidVectorDatasize(size));
4193 assert(isValidArrangement(size, opt));
4194 elemsize = optGetElemsize(opt);
4195 assert(isValidVectorElemsizeFloat(elemsize));
4196 assert(opt != INS_OPTS_1D); // Reserved encoding
4202 assert(insOptsNone(opt));
4203 assert(isValidVectorElemsizeFloat(size));
4204 assert(isVectorRegister(reg1));
4205 assert(isVectorRegister(reg2));
4212 assert(insOptsNone(opt));
4213 assert(isValidVectorElemsizeFloat(size));
4214 assert(isVectorRegister(reg1));
4215 assert(isVectorRegister(reg2));
4220 assert(insOptsConvertFloatToFloat(opt));
4221 assert(isValidVectorFcvtsize(size));
4222 assert(isVectorRegister(reg1));
4223 assert(isVectorRegister(reg2));
4232 assert(isVectorRegister(reg1));
4233 assert(isVectorRegister(reg2));
4235 if (isValidVectorDatasize(size))
4238 assert(insOptsAnyArrangement(opt));
4239 assert(isValidArrangement(size, opt));
4240 elemsize = optGetElemsize(opt);
4247 assert(size == EA_8BYTE); // Only Double supported
4257 assert(isVectorRegister(reg1));
4258 assert(isVectorRegister(reg2));
4260 if (isValidVectorDatasize(size))
4263 assert(insOptsAnyArrangement(opt));
4264 assert(isValidArrangement(size, opt));
4265 elemsize = optGetElemsize(opt);
4266 assert((elemsize == EA_8BYTE) || (elemsize == EA_4BYTE)); // Only Double/Float supported
4267 assert(opt != INS_OPTS_1D); // Reserved encoding
4274 assert((size == EA_8BYTE) || (size == EA_4BYTE)); // Only Double/Float supported
4283 } // end switch (ins)
4285 assert(fmt != IF_NONE);
4287 instrDesc* id = emitNewInstrSmall(attr);
4300 /*****************************************************************************
4302 * Add an instruction referencing a register and two constants.
4305 void emitter::emitIns_R_I_I(
4306 instruction ins, emitAttr attr, regNumber reg, ssize_t imm1, ssize_t imm2, insOpts opt /* = INS_OPTS_NONE */)
4308 emitAttr size = EA_SIZE(attr);
4309 insFormat fmt = IF_NONE;
4310 size_t immOut = 0; // composed from imm1 and imm2 and stored in the instrDesc
4312 /* Figure out the encoding format of the instruction */
4319 ins = INS_movz; // INS_mov with LSL is an alias for INS_movz LSL
4325 assert(isValidGeneralDatasize(size));
4326 assert(isGeneralRegister(reg));
4327 assert(isValidUimm16(imm1));
4328 assert(insOptsLSL(opt)); // Must be INS_OPTS_LSL
4330 if (size == EA_8BYTE)
4332 assert((imm2 == 0) || (imm2 == 16) || // shift amount: 0, 16, 32 or 48
4333 (imm2 == 32) || (imm2 == 48));
4337 assert((imm2 == 0) || (imm2 == 16)); // shift amount: 0 or 16
4372 immOut = hwi.immHWVal;
4373 assert(isValidImmHWVal(immOut, size));
4382 } // end switch (ins)
4384 assert(fmt != IF_NONE);
4386 instrDesc* id = emitNewInstrSC(attr, immOut);
4397 /*****************************************************************************
4399 * Add an instruction referencing two registers and a constant.
4402 void emitter::emitIns_R_R_I(
4403 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm, insOpts opt /* = INS_OPTS_NONE */)
4405 emitAttr size = EA_SIZE(attr);
4406 emitAttr elemsize = EA_UNKNOWN;
4407 insFormat fmt = IF_NONE;
4408 bool isLdSt = false;
4409 bool isSIMD = false;
4410 bool isAddSub = false;
4411 bool setFlags = false;
4413 bool unscaledOp = false;
4415 /* Figure out the encoding format of the instruction */
4422 // Check for the 'mov' aliases for the vector registers
4423 assert(insOptsNone(opt));
4424 assert(isValidVectorElemsize(size));
4426 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4428 if (isVectorRegister(reg1))
4430 if (isGeneralRegisterOrZR(reg2))
4432 fmt = IF_DV_2C; // Alias for 'ins'
4435 else if (isVectorRegister(reg2))
4437 fmt = IF_DV_2E; // Alias for 'dup'
4441 else // isGeneralRegister(reg1)
4443 assert(isGeneralRegister(reg1));
4444 if (isVectorRegister(reg2))
4446 fmt = IF_DV_2B; // Alias for 'umov'
4450 assert(!" invalid INS_mov operands");
4456 assert(insOptsNone(opt));
4457 assert(isValidGeneralDatasize(size));
4458 assert(isGeneralRegister(reg1));
4459 assert(isGeneralRegister(reg2));
4460 assert(isValidImmShift(imm, size));
4465 assert(insOptsNone(opt));
4466 assert(isValidGeneralDatasize(size));
4467 assert(isGeneralRegister(reg1));
4468 assert(isGeneralRegister(reg2));
4469 assert(isValidImmShift(imm, size));
4484 assert(isVectorRegister(reg1));
4485 assert(isVectorRegister(reg2));
4486 if (insOptsAnyArrangement(opt))
4489 assert(isValidVectorDatasize(size));
4490 assert(isValidArrangement(size, opt));
4491 elemsize = optGetElemsize(opt);
4492 assert(isValidVectorElemsize(elemsize));
4493 assert(isValidImmShift(imm, elemsize));
4494 assert(opt != INS_OPTS_1D); // Reserved encoding
4501 assert(insOptsNone(opt));
4502 assert(size == EA_8BYTE); // only supported size
4503 assert(isValidImmShift(imm, size));
4517 assert(isVectorRegister(reg1));
4518 assert(isVectorRegister(reg2));
4520 assert(size == EA_8BYTE);
4521 assert(isValidArrangement(size, opt));
4522 elemsize = optGetElemsize(opt);
4523 assert(elemsize != EA_8BYTE); // Reserved encodings
4524 assert(isValidVectorElemsize(elemsize));
4525 assert(isValidImmShift(imm, elemsize));
4538 assert(isVectorRegister(reg1));
4539 assert(isVectorRegister(reg2));
4541 assert(size == EA_16BYTE);
4542 assert(isValidArrangement(size, opt));
4543 elemsize = optGetElemsize(opt);
4544 assert(elemsize != EA_8BYTE); // Reserved encodings
4545 assert(isValidVectorElemsize(elemsize));
4546 assert(isValidImmShift(imm, elemsize));
4553 assert(isValidGeneralDatasize(size));
4554 assert(isGeneralRegister(reg1));
4555 assert(isGeneralRegisterOrZR(reg2));
4559 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4567 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
4571 assert(insOptsAluShift(opt)); // a non-zero imm, must select shift kind, can't use ROR
4573 assert(isValidImmShift(imm, size));
4579 assert(isValidGeneralDatasize(size));
4580 assert(isGeneralRegisterOrZR(reg1));
4581 assert(isGeneralRegister(reg2));
4583 if (insOptsAnyShift(opt))
4585 assert(isValidImmShift(imm, size) && (imm != 0));
4590 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4598 assert(isValidGeneralDatasize(size));
4599 assert(isGeneralRegisterOrSP(reg1));
4600 assert(isGeneralRegister(reg2));
4602 reg1 = encodingSPtoZR(reg1);
4603 if (insOptsAnyExtend(opt))
4605 assert((imm >= 0) && (imm <= 4));
4611 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4617 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
4618 assert(isValidImmShift(imm, size));
4627 assert(insOptsNone(opt));
4628 assert(isGeneralRegister(reg2));
4629 if (ins == INS_ands)
4631 assert(isGeneralRegister(reg1));
4635 assert(isGeneralRegisterOrSP(reg1));
4636 reg1 = encodingSPtoZR(reg1);
4640 canEncode = canEncodeBitMaskImm(imm, size, &bmi);
4644 assert(isValidImmNRS(imm, size));
4649 case INS_dup: // by element, imm selects the element of reg2
4650 assert(isVectorRegister(reg1));
4651 if (isVectorRegister(reg2))
4653 if (insOptsAnyArrangement(opt))
4656 assert(isValidVectorDatasize(size));
4657 assert(isValidArrangement(size, opt));
4658 elemsize = optGetElemsize(opt);
4659 assert(isValidVectorElemsize(elemsize));
4660 assert(isValidVectorIndex(size, elemsize, imm));
4661 assert(opt != INS_OPTS_1D); // Reserved encoding
4668 assert(insOptsNone(opt));
4670 assert(isValidVectorElemsize(elemsize));
4671 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4678 case INS_ins: // (MOV from general)
4679 assert(insOptsNone(opt));
4680 assert(isValidVectorElemsize(size));
4681 assert(isVectorRegister(reg1));
4682 assert(isGeneralRegisterOrZR(reg2));
4684 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4688 case INS_umov: // (MOV to general)
4689 assert(insOptsNone(opt));
4690 assert(isValidVectorElemsize(size));
4691 assert(isGeneralRegister(reg1));
4692 assert(isVectorRegister(reg2));
4694 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4699 assert(insOptsNone(opt));
4700 assert(isValidVectorElemsize(size));
4701 assert(size != EA_8BYTE); // no encoding, use INS_umov
4702 assert(isGeneralRegister(reg1));
4703 assert(isVectorRegister(reg2));
4705 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4723 // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4724 assert(isValidGeneralDatasize(size));
4725 unscaledOp = (ins == INS_ldursb);
4732 // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4733 assert(isValidGeneralDatasize(size));
4734 unscaledOp = (ins == INS_ldursh);
4741 // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4742 assert(size == EA_8BYTE);
4743 unscaledOp = (ins == INS_ldursw);
4782 // Is the target a vector register?
4783 if (isVectorRegister(reg1))
4785 assert(isValidVectorLSDatasize(size));
4786 assert(isGeneralRegisterOrSP(reg2));
4791 assert(isValidGeneralDatasize(size));
4794 scale = NaturalScale_helper(size);
4800 // Is the target a vector register?
4801 if (isVectorRegister(reg1))
4803 assert(isValidVectorLSDatasize(size));
4804 assert(isGeneralRegisterOrSP(reg2));
4809 assert(isValidGeneralDatasize(size));
4820 } // end switch (ins)
4828 assert(isValidVectorLSDatasize(size));
4829 assert(isVectorRegister(reg1));
4830 assert((scale >= 0) && (scale <= 4));
4834 assert(isValidGeneralLSDatasize(size));
4835 assert(isGeneralRegisterOrZR(reg1));
4836 assert((scale >= 0) && (scale <= 3));
4839 assert(isGeneralRegisterOrSP(reg2));
4841 // Load/Store reserved encodings:
4842 if (insOptsIndexed(opt))
4844 assert(reg1 != reg2);
4847 reg2 = encodingSPtoZR(reg2);
4849 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
4852 assert(insOptsNone(opt)); // PRE/POST Index doesn't make sense with an immediate of zero
4856 else if (insOptsIndexed(opt) || unscaledOp || (imm < 0) || ((imm & mask) != 0))
4858 if ((imm >= -256) && (imm <= 255))
4864 assert(!"Instruction cannot be encoded: IF_LS_2C");
4869 assert(insOptsNone(opt));
4870 assert(!unscaledOp);
4872 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
4874 imm >>= scale; // The immediate is scaled by the size of the ld/st
4880 assert(!"Instruction cannot be encoded: IF_LS_2B");
4887 assert(insOptsNone(opt));
4889 if (setFlags) // Can't encode SP with setFlags
4891 assert(isGeneralRegister(reg1));
4892 assert(isGeneralRegister(reg2));
4896 assert(isGeneralRegisterOrSP(reg1));
4897 assert(isGeneralRegisterOrSP(reg2));
4899 // Is it just a mov?
4902 // Is the mov even necessary?
4905 emitIns_R_R(INS_mov, attr, reg1, reg2);
4910 reg1 = encodingSPtoZR(reg1);
4911 reg2 = encodingSPtoZR(reg2);
4914 if (unsigned_abs(imm) <= 0x0fff)
4918 ins = insReverse(ins);
4921 assert(isValidUimm12(imm));
4924 else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
4926 // Encoding will use a 12-bit left shift of the immediate
4927 opt = INS_OPTS_LSL12;
4930 ins = insReverse(ins);
4933 assert((imm & 0xfff) == 0);
4935 assert(isValidUimm12(imm));
4940 assert(!"Instruction cannot be encoded: IF_DI_2A");
4944 assert(fmt != IF_NONE);
4946 instrDesc* id = emitNewInstrSC(attr, imm);
4959 /*****************************************************************************
4961 * Add an instruction referencing two registers and a constant.
4962 * Also checks for a large immediate that needs a second instruction
4963 * and will load it in reg1
4965 * - Supports instructions: add, adds, sub, subs, and, ands, eor and orr
4966 * - Requires that reg1 is a general register and not SP or ZR
4967 * - Requires that reg1 != reg2
4969 void emitter::emitIns_R_R_Imm(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm)
4971 assert(isGeneralRegister(reg1));
4972 assert(reg1 != reg2);
4974 bool immFits = true;
4982 immFits = emitter::emitIns_valid_imm_for_add(imm, attr);
4989 immFits = emitter::emitIns_valid_imm_for_alu(imm, attr);
4993 assert(!"Unsupported instruction in emitIns_R_R_Imm");
4998 emitIns_R_R_I(ins, attr, reg1, reg2, imm);
5002 // Load 'imm' into the reg1 register
5003 // then issue: 'ins' reg1, reg2, reg1
5005 codeGen->instGen_Set_Reg_To_Imm(attr, reg1, imm);
5006 emitIns_R_R_R(ins, attr, reg1, reg2, reg1);
5010 /*****************************************************************************
5012 * Add an instruction referencing three registers.
5015 void emitter::emitIns_R_R_R(
5016 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insOpts opt) /* = INS_OPTS_NONE */
5018 emitAttr size = EA_SIZE(attr);
5019 emitAttr elemsize = EA_UNKNOWN;
5020 insFormat fmt = IF_NONE;
5022 /* Figure out the encoding format of the instruction */
5046 assert(insOptsNone(opt));
5047 assert(isValidGeneralDatasize(size));
5048 assert(isGeneralRegister(reg1));
5049 assert(isGeneralRegister(reg2));
5050 assert(isGeneralRegister(reg3));
5055 if (insOptsNone(opt))
5058 assert(isValidGeneralDatasize(size));
5059 assert(isGeneralRegister(reg1));
5060 assert(isGeneralRegister(reg2));
5061 assert(isGeneralRegister(reg3));
5070 assert(insOptsAnyArrangement(opt));
5071 assert(isVectorRegister(reg1));
5072 assert(isVectorRegister(reg2));
5073 assert(isVectorRegister(reg3));
5074 assert(isValidVectorDatasize(size));
5075 assert(isValidArrangement(size, opt));
5076 elemsize = optGetElemsize(opt);
5077 if (ins == INS_pmul)
5079 assert(elemsize == EA_1BYTE); // only supports 8B or 16B
5081 else // INS_mul, INS_mla, INS_mls
5083 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
5090 if (isVectorRegister(reg1))
5092 assert(isVectorRegister(reg2));
5093 assert(isVectorRegister(reg3));
5095 if (insOptsAnyArrangement(opt))
5098 assert(opt != INS_OPTS_1D); // Reserved encoding
5099 assert(isValidVectorDatasize(size));
5100 assert(isValidArrangement(size, opt));
5106 assert(insOptsNone(opt));
5107 assert(size == EA_8BYTE);
5116 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, INS_OPTS_NONE);
5125 assert(isVectorRegister(reg1));
5126 assert(isVectorRegister(reg2));
5127 assert(isVectorRegister(reg3));
5129 if (isValidVectorDatasize(size))
5132 assert(insOptsAnyArrangement(opt));
5133 assert(isValidArrangement(size, opt));
5134 elemsize = optGetElemsize(opt);
5141 assert(size == EA_8BYTE); // Only Double supported
5149 assert(isVectorRegister(reg1));
5150 assert(isVectorRegister(reg2));
5151 assert(isVectorRegister(reg3));
5153 if (isValidVectorDatasize(size))
5156 assert(insOptsAnyArrangement(opt));
5157 assert(isValidArrangement(size, opt));
5158 elemsize = optGetElemsize(opt);
5159 assert((elemsize == EA_8BYTE) || (elemsize == EA_4BYTE)); // Only Double/Float supported
5160 assert(opt != INS_OPTS_1D); // Reserved encoding
5167 assert((size == EA_8BYTE) || (size == EA_4BYTE)); // Only Double/Float supported
5180 assert(isVectorRegister(reg1));
5181 assert(isVectorRegister(reg2));
5182 assert(isVectorRegister(reg3));
5183 assert(insOptsAnyArrangement(opt));
5186 assert(isValidVectorDatasize(size));
5187 assert(isValidArrangement(size, opt));
5188 elemsize = optGetElemsize(opt);
5189 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
5195 assert(isVectorRegister(reg1));
5196 assert(isVectorRegister(reg2));
5197 assert(reg2 == reg3);
5198 assert(isValidVectorDatasize(size));
5199 // INS_mov is an alias for INS_orr (vector register)
5200 if (opt == INS_OPTS_NONE)
5202 elemsize = EA_1BYTE;
5203 opt = optMakeArrangement(size, elemsize);
5205 assert(isValidArrangement(size, opt));
5214 if (isVectorRegister(reg1))
5216 assert(isValidVectorDatasize(size));
5217 assert(isVectorRegister(reg2));
5218 assert(isVectorRegister(reg3));
5219 if (opt == INS_OPTS_NONE)
5221 elemsize = EA_1BYTE;
5222 opt = optMakeArrangement(size, elemsize);
5224 assert(isValidArrangement(size, opt));
5233 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, INS_OPTS_NONE);
5239 assert(isValidVectorDatasize(size));
5240 assert(isVectorRegister(reg1));
5241 assert(isVectorRegister(reg2));
5242 assert(isVectorRegister(reg3));
5243 if (opt == INS_OPTS_NONE)
5245 elemsize = EA_1BYTE;
5246 opt = optMakeArrangement(size, elemsize);
5248 assert(isValidArrangement(size, opt));
5260 assert(isVectorRegister(reg1));
5261 assert(isVectorRegister(reg2));
5262 assert(isVectorRegister(reg3));
5263 if (insOptsAnyArrangement(opt))
5266 assert(isValidVectorDatasize(size));
5267 assert(isValidArrangement(size, opt));
5268 elemsize = optGetElemsize(opt);
5269 assert(isValidVectorElemsizeFloat(elemsize));
5270 assert(opt != INS_OPTS_1D); // Reserved encoding
5276 assert(insOptsNone(opt));
5277 assert(isValidScalarDatasize(size));
5284 assert(insOptsNone(opt));
5285 assert(isVectorRegister(reg1));
5286 assert(isVectorRegister(reg2));
5287 assert(isVectorRegister(reg3));
5288 assert(isValidScalarDatasize(size));
5295 assert(isVectorRegister(reg1));
5296 assert(isVectorRegister(reg2));
5297 assert(isVectorRegister(reg3));
5298 assert(insOptsAnyArrangement(opt)); // no scalar encoding, use 4-operand 'fmadd' or 'fmsub'
5301 assert(isValidVectorDatasize(size));
5302 assert(isValidArrangement(size, opt));
5303 elemsize = optGetElemsize(opt);
5304 assert(isValidVectorElemsizeFloat(elemsize));
5305 assert(opt != INS_OPTS_1D); // Reserved encoding
5318 emitIns_R_R_R_Ext(ins, attr, reg1, reg2, reg3, opt);
5326 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0);
5335 assert(isGeneralRegisterOrZR(reg1));
5336 assert(isGeneralRegisterOrZR(reg2));
5337 assert(isGeneralRegisterOrSP(reg3));
5345 } // end switch (ins)
5347 assert(fmt != IF_NONE);
5349 instrDesc* id = emitNewInstr(attr);
5363 /*****************************************************************************
5365 * Add an instruction referencing three registers and a constant.
5368 void emitter::emitIns_R_R_R_I(instruction ins,
5374 insOpts opt /* = INS_OPTS_NONE */,
5375 emitAttr attrReg2 /* = EA_UNKNOWN */)
5377 emitAttr size = EA_SIZE(attr);
5378 emitAttr elemsize = EA_UNKNOWN;
5379 insFormat fmt = IF_NONE;
5380 bool isLdSt = false;
5381 bool isSIMD = false;
5382 bool isAddSub = false;
5383 bool setFlags = false;
5386 /* Figure out the encoding format of the instruction */
5390 assert(insOptsNone(opt));
5391 assert(isValidGeneralDatasize(size));
5392 assert(isGeneralRegister(reg1));
5393 assert(isGeneralRegister(reg2));
5394 assert(isGeneralRegister(reg3));
5395 assert(isValidImmShift(imm, size));
5407 assert(isValidGeneralDatasize(size));
5408 assert(isGeneralRegister(reg1));
5409 assert(isGeneralRegister(reg2));
5410 assert(isGeneralRegister(reg3));
5411 assert(isValidImmShift(imm, size));
5414 assert(insOptsNone(opt)); // a zero imm, means no shift kind
5419 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
5424 case INS_fmul: // by element, imm[0..3] selects the element of reg3
5428 assert(isVectorRegister(reg1));
5429 assert(isVectorRegister(reg2));
5430 assert(isVectorRegister(reg3));
5431 if (insOptsAnyArrangement(opt))
5434 assert(isValidVectorDatasize(size));
5435 assert(isValidArrangement(size, opt));
5436 elemsize = optGetElemsize(opt);
5437 assert(isValidVectorElemsizeFloat(elemsize));
5438 assert(isValidVectorIndex(size, elemsize, imm));
5439 assert(opt != INS_OPTS_1D); // Reserved encoding
5445 assert(insOptsNone(opt));
5446 assert(isValidScalarDatasize(size));
5448 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
5453 case INS_mul: // by element, imm[0..7] selects the element of reg3
5456 assert(isVectorRegister(reg1));
5457 assert(isVectorRegister(reg2));
5458 assert(isVectorRegister(reg3));
5460 assert(insOptsAnyArrangement(opt));
5461 assert(isValidVectorDatasize(size));
5462 assert(isValidArrangement(size, opt));
5463 elemsize = optGetElemsize(opt);
5464 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
5465 // Only has encodings for H or S elemsize
5466 assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE));
5467 // Only has encodings for V0..V15
5468 if ((elemsize == EA_2BYTE) && (reg3 >= REG_V16))
5470 noway_assert(!"Invalid reg3");
5494 assert(insOptsNone(opt)); // Can't use Pre/Post index on these two instructions
5499 // Is the target a vector register?
5500 if (isVectorRegister(reg1))
5502 scale = NaturalScale_helper(size);
5507 scale = (size == EA_8BYTE) ? 3 : 2;
5516 } // end switch (ins)
5521 assert(isGeneralRegisterOrSP(reg3));
5522 assert(insOptsNone(opt) || insOptsIndexed(opt));
5526 assert(isValidVectorLSPDatasize(size));
5527 assert(isVectorRegister(reg1));
5528 assert(isVectorRegister(reg2));
5529 assert((scale >= 2) && (scale <= 4));
5533 assert(isValidGeneralDatasize(size));
5534 assert(isGeneralRegisterOrZR(reg1));
5535 assert(isGeneralRegisterOrZR(reg2));
5536 assert((scale == 2) || (scale == 3));
5539 // Load/Store Pair reserved encodings:
5540 if (emitInsIsLoad(ins))
5542 assert(reg1 != reg2);
5544 if (insOptsIndexed(opt))
5546 assert(reg1 != reg3);
5547 assert(reg2 != reg3);
5550 reg3 = encodingSPtoZR(reg3);
5552 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
5555 assert(insOptsNone(opt)); // PRE/POST Index doesn't make sense with an immediate of zero
5561 if ((imm & mask) == 0)
5563 imm >>= scale; // The immediate is scaled by the size of the ld/st
5565 if ((imm >= -64) && (imm <= 63))
5571 if (fmt != IF_LS_3C)
5573 assert(!"Instruction cannot be encoded: IF_LS_3C");
5580 bool reg2IsSP = (reg2 == REG_SP);
5582 assert(isValidGeneralDatasize(size));
5583 assert(isGeneralRegister(reg3));
5585 if (setFlags || insOptsAluShift(opt)) // Can't encode SP in reg1 with setFlags or AluShift option
5587 assert(isGeneralRegisterOrZR(reg1));
5591 assert(isGeneralRegisterOrSP(reg1));
5592 reg1 = encodingSPtoZR(reg1);
5595 if (insOptsAluShift(opt)) // Can't encode SP in reg2 with AluShift option
5597 assert(isGeneralRegister(reg2));
5601 assert(isGeneralRegisterOrSP(reg2));
5602 reg2 = encodingSPtoZR(reg2);
5605 if (insOptsAnyExtend(opt))
5607 assert((imm >= 0) && (imm <= 4));
5611 else if (insOptsAluShift(opt))
5613 // imm should be non-zero and in [1..63]
5614 assert(isValidImmShift(imm, size) && (imm != 0));
5619 assert(insOptsNone(opt));
5623 // To encode the SP register as reg2 we must use the IF_DR_3C encoding
5624 // and also specify a LSL of zero (imm == 0)
5635 assert(!"Instruction cannot be encoded: Add/Sub IF_DR_3A");
5638 assert(fmt != IF_NONE);
5640 instrDesc* id = emitNewInstrCns(attr, imm);
5650 // Record the attribute for the second register in the pair
5651 id->idGCrefReg2(GCT_NONE);
5652 if (attrReg2 != EA_UNKNOWN)
5654 // Record the attribute for the second register in the pair
5655 assert((fmt == IF_LS_3B) || (fmt == IF_LS_3C));
5656 if (EA_IS_GCREF(attrReg2))
5658 id->idGCrefReg2(GCT_GCREF);
5660 else if (EA_IS_BYREF(attrReg2))
5662 id->idGCrefReg2(GCT_BYREF);
5670 /*****************************************************************************
5672 * Add an instruction referencing three registers, with an extend option
5675 void emitter::emitIns_R_R_R_Ext(instruction ins,
5680 insOpts opt, /* = INS_OPTS_NONE */
5681 int shiftAmount) /* = -1 -- unset */
5683 emitAttr size = EA_SIZE(attr);
5684 insFormat fmt = IF_NONE;
5685 bool isSIMD = false;
5688 /* Figure out the encoding format of the instruction */
5709 // Is the target a vector register?
5710 if (isVectorRegister(reg1))
5712 assert(isValidVectorLSDatasize(size));
5713 scale = NaturalScale_helper(size);
5718 assert(isValidGeneralDatasize(size));
5719 scale = (size == EA_8BYTE) ? 3 : 2;
5728 } // end switch (ins)
5730 assert(scale != -1);
5731 assert(insOptsLSExtend(opt));
5735 assert(isValidVectorLSDatasize(size));
5736 assert(isVectorRegister(reg1));
5740 assert(isValidGeneralLSDatasize(size));
5741 assert(isGeneralRegisterOrZR(reg1));
5744 assert(isGeneralRegisterOrSP(reg2));
5745 assert(isGeneralRegister(reg3));
5747 // Load/Store reserved encodings:
5748 if (insOptsIndexed(opt))
5750 assert(reg1 != reg2);
5753 if (shiftAmount == -1)
5755 shiftAmount = insOptsLSL(opt) ? scale : 0;
5757 assert((shiftAmount == scale) || (shiftAmount == 0));
5759 reg2 = encodingSPtoZR(reg2);
5762 instrDesc* id = emitNewInstr(attr);
5771 id->idReg3Scaled(shiftAmount == scale);
5777 /*****************************************************************************
5779 * Add an instruction referencing two registers and two constants.
5782 void emitter::emitIns_R_R_I_I(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, int imm1, int imm2)
5784 emitAttr size = EA_SIZE(attr);
5785 emitAttr elemsize = EA_UNKNOWN;
5786 insFormat fmt = IF_NONE;
5787 size_t immOut = 0; // composed from imm1 and imm2 and stored in the instrDesc
5789 /* Figure out the encoding format of the instruction */
5799 assert(isGeneralRegister(reg1));
5800 assert(isGeneralRegister(reg2));
5801 assert(isValidImmShift(imm1, size));
5802 assert(isValidImmShift(imm2, size));
5804 bmi.immN = (size == EA_8BYTE);
5807 immOut = bmi.immNRS;
5814 assert(isGeneralRegister(reg1));
5815 assert(isGeneralRegister(reg2));
5816 lsb = getBitWidth(size) - imm1;
5818 assert(isValidImmShift(lsb, size));
5819 assert(isValidImmShift(width, size));
5821 bmi.immN = (size == EA_8BYTE);
5824 immOut = bmi.immNRS;
5831 assert(isGeneralRegister(reg1));
5832 assert(isGeneralRegister(reg2));
5834 width = imm2 + imm1 - 1;
5835 assert(isValidImmShift(lsb, size));
5836 assert(isValidImmShift(width, size));
5838 bmi.immN = (size == EA_8BYTE);
5840 bmi.immS = imm2 + imm1 - 1;
5841 immOut = bmi.immNRS;
5847 assert(isVectorRegister(reg1));
5848 assert(isVectorRegister(reg2));
5850 assert(isValidVectorElemsize(elemsize));
5851 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm1));
5852 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm2));
5853 immOut = (imm1 << 4) + imm2;
5861 assert(fmt != IF_NONE);
5863 instrDesc* id = emitNewInstrSC(attr, immOut);
5875 /*****************************************************************************
5877 * Add an instruction referencing four registers.
5880 void emitter::emitIns_R_R_R_R(
5881 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, regNumber reg4)
5883 emitAttr size = EA_SIZE(attr);
5884 insFormat fmt = IF_NONE;
5886 /* Figure out the encoding format of the instruction */
5895 assert(isValidGeneralDatasize(size));
5896 assert(isGeneralRegister(reg1));
5897 assert(isGeneralRegister(reg2));
5898 assert(isGeneralRegister(reg3));
5899 assert(isGeneralRegister(reg4));
5908 assert(isValidScalarDatasize(size));
5909 assert(isVectorRegister(reg1));
5910 assert(isVectorRegister(reg2));
5911 assert(isVectorRegister(reg3));
5912 assert(isVectorRegister(reg4));
5924 assert(fmt != IF_NONE);
5926 instrDesc* id = emitNewInstr(attr);
5940 /*****************************************************************************
5942 * Add an instruction referencing a register and a condition code
5945 void emitter::emitIns_R_COND(instruction ins, emitAttr attr, regNumber reg, insCond cond)
5947 emitAttr size = EA_SIZE(attr);
5948 insFormat fmt = IF_NONE;
5952 /* Figure out the encoding format of the instruction */
5957 assert(isGeneralRegister(reg));
5966 } // end switch (ins)
5968 assert(fmt != IF_NONE);
5969 assert(isValidImmCond(cfi.immCFVal));
5971 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
5975 id->idInsOpt(INS_OPTS_NONE);
5983 /*****************************************************************************
5985 * Add an instruction referencing two registers and a condition code
5988 void emitter::emitIns_R_R_COND(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insCond cond)
5990 emitAttr size = EA_SIZE(attr);
5991 insFormat fmt = IF_NONE;
5995 /* Figure out the encoding format of the instruction */
6001 assert(isGeneralRegister(reg1));
6002 assert(isGeneralRegister(reg2));
6010 } // end switch (ins)
6012 assert(fmt != IF_NONE);
6013 assert(isValidImmCond(cfi.immCFVal));
6015 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6019 id->idInsOpt(INS_OPTS_NONE);
6028 /*****************************************************************************
6030 * Add an instruction referencing two registers and a condition code
6033 void emitter::emitIns_R_R_R_COND(
6034 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insCond cond)
6036 emitAttr size = EA_SIZE(attr);
6037 insFormat fmt = IF_NONE;
6041 /* Figure out the encoding format of the instruction */
6048 assert(isGeneralRegister(reg1));
6049 assert(isGeneralRegister(reg2));
6050 assert(isGeneralRegister(reg3));
6059 } // end switch (ins)
6061 assert(fmt != IF_NONE);
6062 assert(isValidImmCond(cfi.immCFVal));
6064 instrDesc* id = emitNewInstr(attr);
6068 id->idInsOpt(INS_OPTS_NONE);
6073 id->idSmallCns(cfi.immCFVal);
6079 /*****************************************************************************
6081 * Add an instruction referencing two registers the flags and a condition code
6084 void emitter::emitIns_R_R_FLAGS_COND(
6085 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insCflags flags, insCond cond)
6087 emitAttr size = EA_SIZE(attr);
6088 insFormat fmt = IF_NONE;
6092 /* Figure out the encoding format of the instruction */
6097 assert(isGeneralRegister(reg1));
6098 assert(isGeneralRegister(reg2));
6106 } // end switch (ins)
6108 assert(fmt != IF_NONE);
6109 assert(isValidImmCondFlags(cfi.immCFVal));
6111 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6115 id->idInsOpt(INS_OPTS_NONE);
6124 /*****************************************************************************
6126 * Add an instruction referencing a register, an immediate, the flags and a condition code
6129 void emitter::emitIns_R_I_FLAGS_COND(
6130 instruction ins, emitAttr attr, regNumber reg, int imm, insCflags flags, insCond cond)
6132 emitAttr size = EA_SIZE(attr);
6133 insFormat fmt = IF_NONE;
6137 /* Figure out the encoding format of the instruction */
6142 assert(isGeneralRegister(reg));
6145 ins = insReverse(ins);
6148 if ((imm >= 0) && (imm <= 31))
6157 assert(!"Instruction cannot be encoded: ccmp/ccmn imm5");
6163 } // end switch (ins)
6165 assert(fmt != IF_NONE);
6166 assert(isValidImmCondFlagsImm5(cfi.immCFVal));
6168 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6172 id->idInsOpt(INS_OPTS_NONE);
6180 /*****************************************************************************
6182 * Add a memory barrier instruction with a 'barrier' immediate
6185 void emitter::emitIns_BARR(instruction ins, insBarrier barrier)
6187 insFormat fmt = IF_NONE;
6190 /* Figure out the encoding format of the instruction */
6198 imm = (ssize_t)barrier;
6203 } // end switch (ins)
6205 assert(fmt != IF_NONE);
6207 instrDesc* id = emitNewInstrSC(EA_8BYTE, imm);
6211 id->idInsOpt(INS_OPTS_NONE);
6217 /*****************************************************************************
6219 * Add an instruction with a static data member operand. If 'size' is 0, the
6220 * instruction operates on the address of the static member instead of its
6221 * value (e.g. "push offset clsvar", rather than "push dword ptr [clsvar]").
6224 void emitter::emitIns_C(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, int offs)
6229 /*****************************************************************************
6231 * Add an instruction referencing stack-based local variable.
6234 void emitter::emitIns_S(instruction ins, emitAttr attr, int varx, int offs)
6239 /*****************************************************************************
6241 * Add an instruction referencing a register and a stack-based local variable.
6243 void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
6245 emitAttr size = EA_SIZE(attr);
6246 insFormat fmt = IF_NONE;
6252 // TODO-ARM64-CQ: use unscaled loads?
6253 /* Figure out the encoding format of the instruction */
6274 assert(isValidGeneralDatasize(size) || isValidVectorDatasize(size));
6275 scale = genLog2(EA_SIZE_IN_BYTES(size));
6279 assert(size == EA_8BYTE);
6284 NYI("emitIns_R_S"); // FP locals?
6287 } // end switch (ins)
6289 /* Figure out the variable's frame position */
6294 base = emitComp->lvaFrameAddress(varx, &FPbased);
6296 assert((scale >= 0) && (scale <= 4));
6298 regNumber reg2 = FPbased ? REG_FPBASE : REG_SPBASE;
6299 reg2 = encodingSPtoZR(reg2);
6316 fmt = IF_DI_2A; // add reg1,reg2,#disp
6320 regNumber rsvdReg = codeGen->rsGetRsvdReg();
6321 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6322 fmt = IF_DR_3A; // add reg1,reg2,rsvdReg
6327 bool useRegForImm = false;
6328 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6335 else if ((imm < 0) || ((imm & mask) != 0))
6337 if ((imm >= -256) && (imm <= 255))
6343 useRegForImm = true;
6348 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
6350 imm >>= scale; // The immediate is scaled by the size of the ld/st
6356 useRegForImm = true;
6362 regNumber rsvdReg = codeGen->rsGetRsvdReg();
6363 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6368 assert(fmt != IF_NONE);
6370 instrDesc* id = emitNewInstrCns(attr, imm);
6374 id->idInsOpt(INS_OPTS_NONE);
6378 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6379 id->idSetIsLclVar();
6382 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6389 /*****************************************************************************
6391 * Add an instruction referencing two register and consectutive stack-based local variable slots.
6393 void emitter::emitIns_R_R_S_S(
6394 instruction ins, emitAttr attr1, emitAttr attr2, regNumber reg1, regNumber reg2, int varx, int offs)
6396 assert((ins == INS_ldp) || (ins == INS_ldnp));
6397 assert(EA_8BYTE == EA_SIZE(attr1));
6398 assert(EA_8BYTE == EA_SIZE(attr2));
6399 assert(isGeneralRegisterOrZR(reg1));
6400 assert(isGeneralRegisterOrZR(reg2));
6403 insFormat fmt = IF_LS_3B;
6405 const unsigned scale = 3;
6407 /* Figure out the variable's frame position */
6411 base = emitComp->lvaFrameAddress(varx, &FPbased);
6414 // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6415 regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE;
6416 reg3 = encodingSPtoZR(reg3);
6418 bool useRegForAdr = true;
6420 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6423 useRegForAdr = false;
6427 if ((imm & mask) == 0)
6429 ssize_t immShift = imm >> scale; // The immediate is scaled by the size of the ld/st
6431 if ((immShift >= -64) && (immShift <= 63))
6434 useRegForAdr = false;
6442 regNumber rsvd = codeGen->rsGetRsvdReg();
6443 emitIns_R_R_Imm(INS_add, EA_PTRSIZE, rsvd, reg3, imm);
6448 assert(fmt != IF_NONE);
6450 instrDesc* id = emitNewInstrCns(attr1, imm);
6454 id->idInsOpt(INS_OPTS_NONE);
6456 // Record the attribute for the second register in the pair
6457 if (EA_IS_GCREF(attr2))
6459 id->idGCrefReg2(GCT_GCREF);
6461 else if (EA_IS_BYREF(attr2))
6463 id->idGCrefReg2(GCT_BYREF);
6467 id->idGCrefReg2(GCT_NONE);
6473 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6474 id->idSetIsLclVar();
6477 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6484 /*****************************************************************************
6486 * Add an instruction referencing a stack-based local variable and a register
6488 void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
6491 emitAttr size = EA_SIZE(attr);
6492 insFormat fmt = IF_NONE;
6495 bool isVectorStore = false;
6497 // TODO-ARM64-CQ: use unscaled loads?
6498 /* Figure out the encoding format of the instruction */
6503 assert(isGeneralRegisterOrZR(reg1));
6508 assert(isGeneralRegisterOrZR(reg1));
6512 if (isGeneralRegisterOrZR(reg1))
6514 assert(isValidGeneralDatasize(size));
6515 scale = (size == EA_8BYTE) ? 3 : 2;
6519 assert(isVectorRegister(reg1));
6520 assert(isValidVectorLSDatasize(size));
6521 scale = NaturalScale_helper(size);
6522 isVectorStore = true;
6527 NYI("emitIns_S_R"); // FP locals?
6530 } // end switch (ins)
6532 /* Figure out the variable's frame position */
6536 base = emitComp->lvaFrameAddress(varx, &FPbased);
6548 // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6549 regNumber reg2 = FPbased ? REG_FPBASE : REG_SPBASE;
6550 reg2 = encodingSPtoZR(reg2);
6552 bool useRegForImm = false;
6554 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6559 else if ((imm < 0) || ((imm & mask) != 0))
6561 if ((imm >= -256) && (imm <= 255))
6567 useRegForImm = true;
6572 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
6574 imm >>= scale; // The immediate is scaled by the size of the ld/st
6580 useRegForImm = true;
6586 // The reserved register is not stored in idReg3() since that field overlaps with iiaLclVar.
6587 // It is instead implicit when idSetIsLclVar() is set, with this encoding format.
6588 regNumber rsvdReg = codeGen->rsGetRsvdReg();
6589 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6593 assert(fmt != IF_NONE);
6595 instrDesc* id = emitNewInstrCns(attr, imm);
6599 id->idInsOpt(INS_OPTS_NONE);
6603 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6604 id->idSetIsLclVar();
6607 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6614 /*****************************************************************************
6616 * Add an instruction referencing consecutive stack-based local variable slots and two registers
6618 void emitter::emitIns_S_S_R_R(
6619 instruction ins, emitAttr attr1, emitAttr attr2, regNumber reg1, regNumber reg2, int varx, int offs)
6621 assert((ins == INS_stp) || (ins == INS_stnp));
6622 assert(EA_8BYTE == EA_SIZE(attr1));
6623 assert(EA_8BYTE == EA_SIZE(attr2));
6624 assert(isGeneralRegisterOrZR(reg1));
6625 assert(isGeneralRegisterOrZR(reg2));
6628 insFormat fmt = IF_LS_3B;
6630 const unsigned scale = 3;
6632 /* Figure out the variable's frame position */
6636 base = emitComp->lvaFrameAddress(varx, &FPbased);
6639 // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6640 regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE;
6641 reg3 = encodingSPtoZR(reg3);
6643 bool useRegForAdr = true;
6645 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6648 useRegForAdr = false;
6652 if ((imm & mask) == 0)
6654 ssize_t immShift = imm >> scale; // The immediate is scaled by the size of the ld/st
6656 if ((immShift >= -64) && (immShift <= 63))
6659 useRegForAdr = false;
6667 regNumber rsvd = codeGen->rsGetRsvdReg();
6668 emitIns_R_R_Imm(INS_add, EA_PTRSIZE, rsvd, reg3, imm);
6673 assert(fmt != IF_NONE);
6675 instrDesc* id = emitNewInstrCns(attr1, imm);
6679 id->idInsOpt(INS_OPTS_NONE);
6681 // Record the attribute for the second register in the pair
6682 if (EA_IS_GCREF(attr2))
6684 id->idGCrefReg2(GCT_GCREF);
6686 else if (EA_IS_BYREF(attr2))
6688 id->idGCrefReg2(GCT_BYREF);
6692 id->idGCrefReg2(GCT_NONE);
6698 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6699 id->idSetIsLclVar();
6702 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6709 /*****************************************************************************
6711 * Add an instruction referencing stack-based local variable and an immediate
6713 void emitter::emitIns_S_I(instruction ins, emitAttr attr, int varx, int offs, int val)
6718 /*****************************************************************************
6720 * Add an instruction with a register + static member operands.
6721 * Constant is stored into JIT data which is adjacent to code.
6722 * No relocation is needed. PC-relative offset will be encoded directly into instruction.
6725 void emitter::emitIns_R_C(
6726 instruction ins, emitAttr attr, regNumber reg, regNumber addrReg, CORINFO_FIELD_HANDLE fldHnd, int offs)
6729 assert(instrDesc::fitsInSmallCns(offs));
6731 emitAttr size = EA_SIZE(attr);
6732 insFormat fmt = IF_NONE;
6734 instrDescJmp* id = emitNewInstrJmp();
6739 // This is case to get address to the constant data.
6741 assert(isGeneralRegister(reg));
6742 assert(isValidGeneralDatasize(size));
6747 if (isVectorRegister(reg))
6749 assert(isValidScalarDatasize(size));
6750 // For vector (float/double) register, we should have an integer address reg to
6751 // compute long address which consists of page address and page offset.
6752 // For integer constant, this is not needed since the dest reg can be used to
6753 // compute address as well as contain the final contents.
6754 assert(isGeneralRegister(reg) || (addrReg != REG_NA));
6758 assert(isGeneralRegister(reg));
6759 assert(isValidGeneralDatasize(size));
6766 assert(fmt != IF_NONE);
6770 id->idInsOpt(INS_OPTS_NONE);
6771 id->idSmallCns(offs);
6773 id->idAddr()->iiaFieldHnd = fldHnd;
6774 id->idSetIsBound(); // We won't patch address since we will know the exact distance once JIT code and data are
6775 // allocated together.
6777 id->idReg1(reg); // destination register that will get the constant value.
6778 if (addrReg != REG_NA)
6780 id->idReg2(addrReg); // integer register to compute long address (used for vector dest when we end up with long
6783 id->idjShort = false; // Assume loading constant from long address
6785 // Keep it long if it's in cold code.
6786 id->idjKeepLong = emitComp->fgIsBlockCold(emitComp->compCurBB);
6789 if (emitComp->opts.compLongAddress)
6790 id->idjKeepLong = 1;
6793 // If it's possible to be shortened, then put it in jump list
6794 // to be revisited by emitJumpDistBind.
6795 if (!id->idjKeepLong)
6797 /* Record the jump's IG and offset within it */
6798 id->idjIG = emitCurIG;
6799 id->idjOffs = emitCurIGsize;
6801 /* Append this jump to this IG's jump list */
6802 id->idjNext = emitCurIGjmpList;
6803 emitCurIGjmpList = id;
6814 /*****************************************************************************
6816 * Add an instruction with a static member + constant.
6819 void emitter::emitIns_C_I(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, ssize_t offs, ssize_t val)
6824 /*****************************************************************************
6826 * Add an instruction with a static member + register operands.
6829 void emitter::emitIns_C_R(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, regNumber reg, int offs)
6831 assert(!"emitIns_C_R not supported for RyuJIT backend");
6834 void emitter::emitIns_R_AR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
6836 NYI("emitIns_R_AR");
6839 // This computes address from the immediate which is relocatable.
6840 void emitter::emitIns_R_AI(instruction ins, emitAttr attr, regNumber ireg, ssize_t addr)
6842 assert(EA_IS_RELOC(attr));
6843 emitAttr size = EA_SIZE(attr);
6844 insFormat fmt = IF_DI_1E;
6845 bool needAdd = false;
6846 instrDescJmp* id = emitNewInstrJmp();
6851 // This computes page address.
6852 // page offset is needed using add.
6863 id->idInsOpt(INS_OPTS_NONE);
6865 id->idAddr()->iiaAddr = (BYTE*)addr;
6867 id->idSetIsDspReloc();
6874 // add reg, reg, imm
6877 instrDesc* id = emitAllocInstr(attr);
6878 assert(id->idIsReloc());
6882 id->idInsOpt(INS_OPTS_NONE);
6884 id->idAddr()->iiaAddr = (BYTE*)addr;
6893 void emitter::emitIns_AR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
6895 NYI("emitIns_AR_R");
6898 void emitter::emitIns_R_ARR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
6900 NYI("emitIns_R_ARR");
6903 void emitter::emitIns_ARR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
6905 NYI("emitIns_R_ARR");
6908 void emitter::emitIns_R_ARX(
6909 instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, unsigned mul, int disp)
6911 NYI("emitIns_R_ARR");
6914 /*****************************************************************************
6916 * Record that a jump instruction uses the short encoding
6919 void emitter::emitSetShortJump(instrDescJmp* id)
6921 if (id->idjKeepLong)
6924 insFormat fmt = IF_NONE;
6925 if (emitIsCondJump(id))
6927 switch (id->idIns())
6942 else if (emitIsLoadLabel(id))
6946 else if (emitIsLoadConstant(id))
6956 id->idjShort = true;
6959 /*****************************************************************************
6961 * Add a label instruction.
6964 void emitter::emitIns_R_L(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
6966 assert(dst->bbFlags & BBF_JMP_TARGET);
6968 insFormat fmt = IF_NONE;
6979 instrDescJmp* id = emitNewInstrJmp();
6983 id->idjShort = false;
6984 id->idAddr()->iiaBBlabel = dst;
6986 id->idOpSize(EA_PTRSIZE);
6989 // Mark the catch return
6990 if (emitComp->compCurBB->bbJumpKind == BBJ_EHCATCHRET)
6992 id->idDebugOnlyInfo()->idCatchRet = true;
6996 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
6999 if (emitComp->opts.compLongAddress)
7000 id->idjKeepLong = 1;
7003 /* Record the jump's IG and offset within it */
7005 id->idjIG = emitCurIG;
7006 id->idjOffs = emitCurIGsize;
7008 /* Append this jump to this IG's jump list */
7010 id->idjNext = emitCurIGjmpList;
7011 emitCurIGjmpList = id;
7021 /*****************************************************************************
7023 * Add a data label instruction.
7026 void emitter::emitIns_R_D(instruction ins, emitAttr attr, unsigned offs, regNumber reg)
7031 void emitter::emitIns_J_R(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
7033 assert((ins == INS_cbz) || (ins == INS_cbnz));
7035 assert(dst != nullptr);
7036 assert((dst->bbFlags & BBF_JMP_TARGET) != 0);
7038 insFormat fmt = IF_LARGEJMP;
7040 instrDescJmp* id = emitNewInstrJmp();
7045 id->idjShort = false;
7046 id->idOpSize(EA_SIZE(attr));
7048 id->idAddr()->iiaBBlabel = dst;
7049 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7051 /* Record the jump's IG and offset within it */
7053 id->idjIG = emitCurIG;
7054 id->idjOffs = emitCurIGsize;
7056 /* Append this jump to this IG's jump list */
7058 id->idjNext = emitCurIGjmpList;
7059 emitCurIGjmpList = id;
7069 void emitter::emitIns_J_R_I(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg, int imm)
7071 assert((ins == INS_tbz) || (ins == INS_tbnz));
7073 assert(dst != nullptr);
7074 assert((dst->bbFlags & BBF_JMP_TARGET) != 0);
7075 assert((EA_SIZE(attr) == EA_4BYTE) || (EA_SIZE(attr) == EA_8BYTE));
7076 assert(imm < ((EA_SIZE(attr) == EA_4BYTE) ? 32 : 64));
7078 insFormat fmt = IF_LARGEJMP;
7080 instrDescJmp* id = emitNewInstrJmp();
7085 id->idjShort = false;
7086 id->idSmallCns(imm);
7087 id->idOpSize(EA_SIZE(attr));
7089 id->idAddr()->iiaBBlabel = dst;
7090 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7092 /* Record the jump's IG and offset within it */
7094 id->idjIG = emitCurIG;
7095 id->idjOffs = emitCurIGsize;
7097 /* Append this jump to this IG's jump list */
7099 id->idjNext = emitCurIGjmpList;
7100 emitCurIGjmpList = id;
7110 void emitter::emitIns_J(instruction ins, BasicBlock* dst, int instrCount)
7112 insFormat fmt = IF_NONE;
7116 assert(dst->bbFlags & BBF_JMP_TARGET);
7120 assert(instrCount != 0);
7123 /* Figure out the encoding format of the instruction */
7125 bool idjShort = false;
7130 // Unconditional jump is a single form.
7149 // Assume conditional jump is long.
7158 instrDescJmp* id = emitNewInstrJmp();
7162 id->idjShort = idjShort;
7165 // Mark the finally call
7166 if (ins == INS_bl_local && emitComp->compCurBB->bbJumpKind == BBJ_CALLFINALLY)
7168 id->idDebugOnlyInfo()->idFinallyCall = true;
7174 id->idAddr()->iiaBBlabel = dst;
7176 // Skip unconditional jump that has a single form.
7177 // TODO-ARM64-NYI: enable hot/cold splittingNYI.
7178 // The target needs to be relocated.
7181 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7184 if (emitComp->opts.compLongAddress) // Force long branches
7185 id->idjKeepLong = 1;
7191 id->idAddr()->iiaSetInstrCount(instrCount);
7192 id->idjKeepLong = false;
7193 /* This jump must be short */
7194 emitSetShortJump(id);
7198 /* Record the jump's IG and offset within it */
7200 id->idjIG = emitCurIG;
7201 id->idjOffs = emitCurIGsize;
7203 /* Append this jump to this IG's jump list */
7205 id->idjNext = emitCurIGjmpList;
7206 emitCurIGjmpList = id;
7216 /*****************************************************************************
7218 * Add a call instruction (direct or indirect).
7219 * argSize<0 means that the caller will pop the arguments
7221 * The other arguments are interpreted depending on callType as shown:
7222 * Unless otherwise specified, ireg,xreg,xmul,disp should have default values.
7224 * EC_FUNC_TOKEN : addr is the method address
7225 * EC_FUNC_ADDR : addr is the absolute address of the function
7227 * If callType is one of these emitCallTypes, addr has to be NULL.
7228 * EC_INDIR_R : "call ireg".
7230 * For ARM xreg, xmul and disp are never used and should always be 0/REG_NA.
7232 * Please consult the "debugger team notification" comment in genFnProlog().
7235 void emitter::emitIns_Call(EmitCallType callType,
7236 CORINFO_METHOD_HANDLE methHnd,
7237 INDEBUG_LDISASM_COMMA(CORINFO_SIG_INFO* sigInfo) // used to report call sites to the EE
7241 emitAttr secondRetSize,
7242 VARSET_VALARG_TP ptrVars,
7243 regMaskTP gcrefRegs,
7244 regMaskTP byrefRegs,
7245 IL_OFFSETX ilOffset /* = BAD_IL_OFFSET */,
7246 regNumber ireg /* = REG_NA */,
7247 regNumber xreg /* = REG_NA */,
7248 unsigned xmul /* = 0 */,
7249 ssize_t disp /* = 0 */,
7250 bool isJump /* = false */,
7251 bool isNoGC /* = false */,
7252 bool isProfLeaveCB /* = false */)
7254 /* Sanity check the arguments depending on callType */
7256 assert(callType < EC_COUNT);
7257 assert((callType != EC_FUNC_TOKEN && callType != EC_FUNC_ADDR) ||
7258 (ireg == REG_NA && xreg == REG_NA && xmul == 0 && disp == 0));
7259 assert(callType < EC_INDIR_R || addr == NULL);
7260 assert(callType != EC_INDIR_R || (ireg < REG_COUNT && xreg == REG_NA && xmul == 0 && disp == 0));
7262 // ARM never uses these
7263 assert(xreg == REG_NA && xmul == 0 && disp == 0);
7265 // Our stack level should be always greater than the bytes of arguments we push. Just
7267 assert((unsigned)abs(argSize) <= codeGen->genStackLevel);
7272 /* This is the saved set of registers after a normal call */
7273 regMaskTP savedSet = RBM_CALLEE_SAVED;
7275 /* some special helper calls have a different saved set registers */
7279 assert(emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
7281 // Get the set of registers that this call kills and remove it from the saved set.
7282 savedSet = RBM_ALLINT & ~emitComp->compNoGCHelperCallKillSet(Compiler::eeGetHelperNum(methHnd));
7284 // In case of Leave profiler callback, we need to preserve liveness of REG_PROFILER_RET_SCRATCH
7287 savedSet |= RBM_PROFILER_RET_SCRATCH;
7292 assert(!emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
7295 /* Trim out any callee-trashed registers from the live set */
7297 gcrefRegs &= savedSet;
7298 byrefRegs &= savedSet;
7301 if (EMIT_GC_VERBOSE)
7303 printf("Call: GCvars=%s ", VarSetOps::ToString(emitComp, ptrVars));
7304 dumpConvertedVarSet(emitComp, ptrVars);
7305 printf(", gcrefRegs=");
7306 printRegMaskInt(gcrefRegs);
7307 emitDispRegSet(gcrefRegs);
7308 printf(", byrefRegs=");
7309 printRegMaskInt(byrefRegs);
7310 emitDispRegSet(byrefRegs);
7315 assert(argSize % REGSIZE_BYTES == 0);
7316 argCnt = (int)(argSize / (int)REGSIZE_BYTES);
7318 /* Managed RetVal: emit sequence point for the call */
7319 if (emitComp->opts.compDbgInfo && ilOffset != BAD_IL_OFFSET)
7321 codeGen->genIPmappingAdd(ilOffset, false);
7325 We need to allocate the appropriate instruction descriptor based
7326 on whether this is a direct/indirect call, and whether we need to
7327 record an updated set of live GC variables.
7330 if (callType >= EC_INDIR_R)
7332 /* Indirect call, virtual calls */
7334 assert(callType == EC_INDIR_R);
7336 id = emitNewInstrCallInd(argCnt, disp, ptrVars, gcrefRegs, byrefRegs, retSize, secondRetSize);
7340 /* Helper/static/nonvirtual/function calls (direct or through handle),
7341 and calls to an absolute addr. */
7343 assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
7345 id = emitNewInstrCallDir(argCnt, ptrVars, gcrefRegs, byrefRegs, retSize, secondRetSize);
7348 /* Update the emitter's live GC ref sets */
7350 VarSetOps::Assign(emitComp, emitThisGCrefVars, ptrVars);
7351 emitThisGCrefRegs = gcrefRegs;
7352 emitThisByrefRegs = byrefRegs;
7354 /* Set the instruction - special case jumping a function */
7356 insFormat fmt = IF_NONE;
7358 id->idSetIsNoGC(isNoGC);
7360 /* Record the address: method, indirection, or funcptr */
7362 if (callType > EC_FUNC_ADDR)
7364 /* This is an indirect call (either a virtual call or func ptr call) */
7368 case EC_INDIR_R: // the address is in a register
7370 id->idSetIsCallRegPtr();
7374 ins = INS_br_tail; // INS_br_tail Reg
7378 ins = INS_blr; // INS_blr Reg
7386 assert(xreg == REG_NA);
7390 NO_WAY("unexpected instruction");
7396 /* This is a simple direct call: "call helper/method/addr" */
7398 assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
7400 assert(addr != NULL);
7404 ins = INS_b_tail; // INS_b_tail imm28
7408 ins = INS_bl; // INS_bl imm28
7415 id->idAddr()->iiaAddr = (BYTE*)addr;
7417 if (callType == EC_FUNC_ADDR)
7419 id->idSetIsCallAddr();
7422 if (emitComp->opts.compReloc)
7424 id->idSetIsDspReloc();
7429 if (EMIT_GC_VERBOSE)
7431 if (id->idIsLargeCall())
7433 printf("[%02u] Rec call GC vars = %s\n", id->idDebugOnlyInfo()->idNum,
7434 VarSetOps::ToString(emitComp, ((instrDescCGCA*)id)->idcGCvars));
7438 id->idDebugOnlyInfo()->idMemCookie = (size_t)methHnd; // method token
7439 id->idDebugOnlyInfo()->idCallSig = sigInfo;
7443 if (addr != nullptr)
7445 codeGen->getDisAssembler().disSetMethod((size_t)addr, methHnd);
7447 #endif // LATE_DISASM
7453 /*****************************************************************************
7455 * Returns true if 'imm' is valid Cond encoding
7458 /*static*/ bool emitter::isValidImmCond(ssize_t imm)
7460 // range check the ssize_t value, to make sure it is a small unsigned value
7461 // and that only the bits in the cfi.cond are set
7462 if ((imm < 0) || (imm > 0xF))
7466 cfi.immCFVal = (unsigned)imm;
7468 return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7471 /*****************************************************************************
7473 * Returns true if 'imm' is valid Cond/Flags encoding
7476 /*static*/ bool emitter::isValidImmCondFlags(ssize_t imm)
7478 // range check the ssize_t value, to make sure it is a small unsigned value
7479 // and that only the bits in the cfi.cond or cfi.flags are set
7480 if ((imm < 0) || (imm > 0xFF))
7484 cfi.immCFVal = (unsigned)imm;
7486 return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7489 /*****************************************************************************
7491 * Returns true if 'imm' is valid Cond/Flags/Imm5 encoding
7494 /*static*/ bool emitter::isValidImmCondFlagsImm5(ssize_t imm)
7496 // range check the ssize_t value, to make sure it is a small unsigned value
7497 // and that only the bits in the cfi.cond, cfi.flags or cfi.imm5 are set
7498 if ((imm < 0) || (imm > 0x1FFF))
7502 cfi.immCFVal = (unsigned)imm;
7504 return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7507 /*****************************************************************************
7509 * Returns an encoding for the specified register used in the 'Rd' position
7512 /*static*/ emitter::code_t emitter::insEncodeReg_Rd(regNumber reg)
7514 assert(isIntegerRegister(reg));
7515 emitter::code_t ureg = (emitter::code_t)reg;
7516 assert((ureg >= 0) && (ureg <= 31));
7520 /*****************************************************************************
7522 * Returns an encoding for the specified register used in the 'Rt' position
7525 /*static*/ emitter::code_t emitter::insEncodeReg_Rt(regNumber reg)
7527 assert(isIntegerRegister(reg));
7528 emitter::code_t ureg = (emitter::code_t)reg;
7529 assert((ureg >= 0) && (ureg <= 31));
7533 /*****************************************************************************
7535 * Returns an encoding for the specified register used in the 'Rn' position
7538 /*static*/ emitter::code_t emitter::insEncodeReg_Rn(regNumber reg)
7540 assert(isIntegerRegister(reg));
7541 emitter::code_t ureg = (emitter::code_t)reg;
7542 assert((ureg >= 0) && (ureg <= 31));
7546 /*****************************************************************************
7548 * Returns an encoding for the specified register used in the 'Rm' position
7551 /*static*/ emitter::code_t emitter::insEncodeReg_Rm(regNumber reg)
7553 assert(isIntegerRegister(reg));
7554 emitter::code_t ureg = (emitter::code_t)reg;
7555 assert((ureg >= 0) && (ureg <= 31));
7559 /*****************************************************************************
7561 * Returns an encoding for the specified register used in the 'Ra' position
7564 /*static*/ emitter::code_t emitter::insEncodeReg_Ra(regNumber reg)
7566 assert(isIntegerRegister(reg));
7567 emitter::code_t ureg = (emitter::code_t)reg;
7568 assert((ureg >= 0) && (ureg <= 31));
7572 /*****************************************************************************
7574 * Returns an encoding for the specified register used in the 'Vd' position
7577 /*static*/ emitter::code_t emitter::insEncodeReg_Vd(regNumber reg)
7579 assert(emitter::isVectorRegister(reg));
7580 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7581 assert((ureg >= 0) && (ureg <= 31));
7585 /*****************************************************************************
7587 * Returns an encoding for the specified register used in the 'Vt' position
7590 /*static*/ emitter::code_t emitter::insEncodeReg_Vt(regNumber reg)
7592 assert(emitter::isVectorRegister(reg));
7593 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7594 assert((ureg >= 0) && (ureg <= 31));
7598 /*****************************************************************************
7600 * Returns an encoding for the specified register used in the 'Vn' position
7603 /*static*/ emitter::code_t emitter::insEncodeReg_Vn(regNumber reg)
7605 assert(emitter::isVectorRegister(reg));
7606 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7607 assert((ureg >= 0) && (ureg <= 31));
7611 /*****************************************************************************
7613 * Returns an encoding for the specified register used in the 'Vm' position
7616 /*static*/ emitter::code_t emitter::insEncodeReg_Vm(regNumber reg)
7618 assert(emitter::isVectorRegister(reg));
7619 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7620 assert((ureg >= 0) && (ureg <= 31));
7624 /*****************************************************************************
7626 * Returns an encoding for the specified register used in the 'Va' position
7629 /*static*/ emitter::code_t emitter::insEncodeReg_Va(regNumber reg)
7631 assert(emitter::isVectorRegister(reg));
7632 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7633 assert((ureg >= 0) && (ureg <= 31));
7637 /*****************************************************************************
7639 * Returns an encoding for the specified condition code.
7642 /*static*/ emitter::code_t emitter::insEncodeCond(insCond cond)
7644 emitter::code_t uimm = (emitter::code_t)cond;
7648 /*****************************************************************************
7650 * Returns an encoding for the condition code with the lowest bit inverted (marked by invert(<cond>) in the
7651 * architecture manual).
7654 /*static*/ emitter::code_t emitter::insEncodeInvertedCond(insCond cond)
7656 emitter::code_t uimm = (emitter::code_t)cond;
7657 uimm ^= 1; // invert the lowest bit
7661 /*****************************************************************************
7663 * Returns an encoding for the specified flags.
7666 /*static*/ emitter::code_t emitter::insEncodeFlags(insCflags flags)
7668 emitter::code_t uimm = (emitter::code_t)flags;
7672 /*****************************************************************************
7674 * Returns the encoding for the Shift Count bits to be used for Arm64 encodings
7677 /*static*/ emitter::code_t emitter::insEncodeShiftCount(ssize_t imm, emitAttr size)
7679 assert((imm & 0x003F) == imm);
7680 assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
7682 return (emitter::code_t)imm << 10;
7685 /*****************************************************************************
7687 * Returns the encoding to select a 64-bit datasize for an Arm64 instruction
7690 /*static*/ emitter::code_t emitter::insEncodeDatasize(emitAttr size)
7692 if (size == EA_8BYTE)
7694 return 0x80000000; // set the bit at location 31
7698 assert(size == EA_4BYTE);
7703 /*****************************************************************************
7705 * Returns the encoding to select the datasize for the general load/store Arm64 instructions
7709 /*static*/ emitter::code_t emitter::insEncodeDatasizeLS(emitter::code_t code, emitAttr size)
7711 bool exclusive = ((code & 0x35000000) == 0);
7713 if ((code & 0x00800000) && !exclusive) // Is this a sign-extending opcode? (i.e. ldrsw, ldrsh, ldrsb)
7715 if ((code & 0x80000000) == 0) // Is it a ldrsh or ldrsb and not ldrsw ?
7717 if (EA_SIZE(size) != EA_8BYTE) // Do we need to encode the 32-bit Rt size bit?
7719 return 0x00400000; // set the bit at location 22
7723 else if (code & 0x80000000) // Is this a ldr/str/ldur/stur opcode?
7725 if (EA_SIZE(size) == EA_8BYTE) // Do we need to encode the 64-bit size bit?
7727 return 0x40000000; // set the bit at location 30
7733 /*****************************************************************************
7735 * Returns the encoding to select the datasize for the vector load/store Arm64 instructions
7739 /*static*/ emitter::code_t emitter::insEncodeDatasizeVLS(emitter::code_t code, emitAttr size)
7744 if ((code & 0x20000000) == 0)
7748 if (size == EA_16BYTE)
7750 // set the operation size in bit 31
7751 result = 0x80000000;
7753 else if (size == EA_8BYTE)
7755 // set the operation size in bit 30
7756 result = 0x40000000;
7760 assert(size == EA_4BYTE);
7762 result = 0x00000000;
7769 if (size == EA_16BYTE)
7771 // The operation size in bits 31 and 30 are zero
7772 // Bit 23 specifies a 128-bit Load/Store
7773 result = 0x00800000;
7775 else if (size == EA_8BYTE)
7777 // set the operation size in bits 31 and 30
7778 result = 0xC0000000;
7780 else if (size == EA_4BYTE)
7782 // set the operation size in bit 31
7783 result = 0x80000000;
7785 else if (size == EA_2BYTE)
7787 // set the operation size in bit 30
7788 result = 0x40000000;
7792 assert(size == EA_1BYTE);
7793 // The operation size in bits 31 and 30 are zero
7794 result = 0x00000000;
7798 // Or in bit 26 to indicate a Vector register is used as 'target'
7799 result |= 0x04000000;
7804 /*****************************************************************************
7806 * Returns the encoding to select the datasize for the vector load/store Arm64 instructions
7810 /*static*/ emitter::code_t emitter::insEncodeDatasizeVPLS(emitter::code_t code, emitAttr size)
7814 if (size == EA_16BYTE)
7816 // The operation size in bits 31 and 30 are zero
7817 // Bit 23 specifies a 128-bit Load/Store
7818 result = 0x80000000;
7820 else if (size == EA_8BYTE)
7822 // set the operation size in bits 31 and 30
7823 result = 0x40000000;
7825 else if (size == EA_4BYTE)
7827 // set the operation size in bit 31
7828 result = 0x00000000;
7831 // Or in bit 26 to indicate a Vector register is used as 'target'
7832 result |= 0x04000000;
7837 /*****************************************************************************
7839 * Returns the encoding to set the size bit and the N bits for a 'bitfield' instruction
7843 /*static*/ emitter::code_t emitter::insEncodeDatasizeBF(emitter::code_t code, emitAttr size)
7845 // is bit 30 equal to 0?
7846 if ((code & 0x40000000) == 0) // is the opcode one of extr, sxtb, sxth or sxtw
7848 if (size == EA_8BYTE) // Do we need to set the sf and N bits?
7850 return 0x80400000; // set the sf-bit at location 31 and the N-bit at location 22
7853 return 0; // don't set any bits
7856 /*****************************************************************************
7858 * Returns the encoding to select the 64/128-bit datasize for an Arm64 vector instruction
7861 /*static*/ emitter::code_t emitter::insEncodeVectorsize(emitAttr size)
7863 if (size == EA_16BYTE)
7865 return 0x40000000; // set the bit at location 30
7869 assert(size == EA_8BYTE);
7874 /*****************************************************************************
7876 * Returns the encoding to select 'index' for an Arm64 vector elem instruction
7878 /*static*/ emitter::code_t emitter::insEncodeVectorIndex(emitAttr elemsize, ssize_t index)
7880 code_t bits = (code_t)index;
7881 if (elemsize == EA_1BYTE)
7886 else if (elemsize == EA_2BYTE)
7891 else if (elemsize == EA_4BYTE)
7898 assert(elemsize == EA_8BYTE);
7902 assert((bits >= 1) && (bits <= 0x1f));
7904 return (bits << 16); // bits at locations [20,19,18,17,16]
7907 /*****************************************************************************
7909 * Returns the encoding to select 'index2' for an Arm64 'ins' elem instruction
7911 /*static*/ emitter::code_t emitter::insEncodeVectorIndex2(emitAttr elemsize, ssize_t index2)
7913 code_t bits = (code_t)index2;
7914 if (elemsize == EA_1BYTE)
7918 else if (elemsize == EA_2BYTE)
7922 else if (elemsize == EA_4BYTE)
7928 assert(elemsize == EA_8BYTE);
7931 assert((bits >= 0) && (bits <= 0xf));
7933 return (bits << 11); // bits at locations [14,13,12,11]
7936 /*****************************************************************************
7938 * Returns the encoding to select the 'index' for an Arm64 'mul' by elem instruction
7940 /*static*/ emitter::code_t emitter::insEncodeVectorIndexLMH(emitAttr elemsize, ssize_t index)
7944 if (elemsize == EA_2BYTE)
7946 assert((index >= 0) && (index <= 7));
7949 bits |= (1 << 11); // set bit 11 'H'
7953 bits |= (1 << 21); // set bit 21 'L'
7957 bits |= (1 << 20); // set bit 20 'M'
7960 else if (elemsize == EA_4BYTE)
7962 assert((index >= 0) && (index <= 3));
7965 bits |= (1 << 11); // set bit 11 'H'
7969 bits |= (1 << 21); // set bit 21 'L'
7974 assert(!"Invalid 'elemsize' value");
7980 /*****************************************************************************
7982 * Returns the encoding to shift by 'shift' for an Arm64 vector or scalar instruction
7985 /*static*/ emitter::code_t emitter::insEncodeVectorShift(emitAttr size, ssize_t shift)
7987 assert(shift < getBitWidth(size));
7989 code_t imm = (code_t)(getBitWidth(size) + shift);
7994 /*****************************************************************************
7996 * Returns the encoding to select the 1/2/4/8 byte elemsize for an Arm64 vector instruction
7999 /*static*/ emitter::code_t emitter::insEncodeElemsize(emitAttr size)
8001 if (size == EA_8BYTE)
8003 return 0x00C00000; // set the bit at location 23 and 22
8005 else if (size == EA_4BYTE)
8007 return 0x00800000; // set the bit at location 23
8009 else if (size == EA_2BYTE)
8011 return 0x00400000; // set the bit at location 22
8013 assert(size == EA_1BYTE);
8017 /*****************************************************************************
8019 * Returns the encoding to select the 4/8 byte elemsize for an Arm64 float vector instruction
8022 /*static*/ emitter::code_t emitter::insEncodeFloatElemsize(emitAttr size)
8024 if (size == EA_8BYTE)
8026 return 0x00400000; // set the bit at location 22
8028 assert(size == EA_4BYTE);
8032 // Returns the encoding to select the index for an Arm64 float vector by elem instruction
8033 /*static*/ emitter::code_t emitter::insEncodeFloatIndex(emitAttr elemsize, ssize_t index)
8035 code_t result = 0x00000000;
8036 if (elemsize == EA_8BYTE)
8038 assert((index >= 0) && (index <= 1));
8041 result |= 0x00000800; // 'H' - set the bit at location 11
8046 assert(elemsize == EA_4BYTE);
8047 assert((index >= 0) && (index <= 3));
8050 result |= 0x00000800; // 'H' - set the bit at location 11
8054 result |= 0x00200000; // 'L' - set the bit at location 21
8060 /*****************************************************************************
8062 * Returns the encoding to select the fcvt operation for Arm64 instructions
8064 /*static*/ emitter::code_t emitter::insEncodeConvertOpt(insFormat fmt, insOpts conversion)
8069 case INS_OPTS_S_TO_D: // Single to Double
8070 assert(fmt == IF_DV_2J);
8071 result = 0x00008000; // type=00, opc=01
8074 case INS_OPTS_D_TO_S: // Double to Single
8075 assert(fmt == IF_DV_2J);
8076 result = 0x00400000; // type=01, opc=00
8079 case INS_OPTS_H_TO_S: // Half to Single
8080 assert(fmt == IF_DV_2J);
8081 result = 0x00C00000; // type=11, opc=00
8084 case INS_OPTS_H_TO_D: // Half to Double
8085 assert(fmt == IF_DV_2J);
8086 result = 0x00C08000; // type=11, opc=01
8089 case INS_OPTS_S_TO_H: // Single to Half
8090 assert(fmt == IF_DV_2J);
8091 result = 0x00018000; // type=00, opc=11
8094 case INS_OPTS_D_TO_H: // Double to Half
8095 assert(fmt == IF_DV_2J);
8096 result = 0x00418000; // type=01, opc=11
8099 case INS_OPTS_S_TO_4BYTE: // Single to INT32
8100 assert(fmt == IF_DV_2H);
8101 result = 0x00000000; // sf=0, type=00
8104 case INS_OPTS_D_TO_4BYTE: // Double to INT32
8105 assert(fmt == IF_DV_2H);
8106 result = 0x00400000; // sf=0, type=01
8109 case INS_OPTS_S_TO_8BYTE: // Single to INT64
8110 assert(fmt == IF_DV_2H);
8111 result = 0x80000000; // sf=1, type=00
8114 case INS_OPTS_D_TO_8BYTE: // Double to INT64
8115 assert(fmt == IF_DV_2H);
8116 result = 0x80400000; // sf=1, type=01
8119 case INS_OPTS_4BYTE_TO_S: // INT32 to Single
8120 assert(fmt == IF_DV_2I);
8121 result = 0x00000000; // sf=0, type=00
8124 case INS_OPTS_4BYTE_TO_D: // INT32 to Double
8125 assert(fmt == IF_DV_2I);
8126 result = 0x00400000; // sf=0, type=01
8129 case INS_OPTS_8BYTE_TO_S: // INT64 to Single
8130 assert(fmt == IF_DV_2I);
8131 result = 0x80000000; // sf=1, type=00
8134 case INS_OPTS_8BYTE_TO_D: // INT64 to Double
8135 assert(fmt == IF_DV_2I);
8136 result = 0x80400000; // sf=1, type=01
8140 assert(!"Invalid 'conversion' value");
8146 /*****************************************************************************
8148 * Returns the encoding to have the Rn register be updated Pre/Post indexed
8152 /*static*/ emitter::code_t emitter::insEncodeIndexedOpt(insOpts opt)
8154 assert(emitter::insOptsNone(opt) || emitter::insOptsIndexed(opt));
8156 if (emitter::insOptsIndexed(opt))
8158 if (emitter::insOptsPostIndex(opt))
8160 return 0x00000400; // set the bit at location 10
8164 assert(emitter::insOptsPreIndex(opt));
8165 return 0x00000C00; // set the bit at location 10 and 11
8170 assert(emitter::insOptsNone(opt));
8171 return 0; // bits 10 and 11 are zero
8175 /*****************************************************************************
8177 * Returns the encoding for a ldp/stp instruction to have the Rn register
8178 * be updated Pre/Post indexed or not updated
8181 /*static*/ emitter::code_t emitter::insEncodePairIndexedOpt(instruction ins, insOpts opt)
8183 assert(emitter::insOptsNone(opt) || emitter::insOptsIndexed(opt));
8185 if ((ins == INS_ldnp) || (ins == INS_stnp))
8187 assert(emitter::insOptsNone(opt));
8188 return 0; // bits 23 and 24 are zero
8192 if (emitter::insOptsIndexed(opt))
8194 if (emitter::insOptsPostIndex(opt))
8196 return 0x00800000; // set the bit at location 23
8200 assert(emitter::insOptsPreIndex(opt));
8201 return 0x01800000; // set the bit at location 24 and 23
8206 assert(emitter::insOptsNone(opt));
8207 return 0x01000000; // set the bit at location 24
8212 /*****************************************************************************
8214 * Returns the encoding to apply a Shift Type on the Rm register
8217 /*static*/ emitter::code_t emitter::insEncodeShiftType(insOpts opt)
8219 if (emitter::insOptsNone(opt))
8221 // None implies the we encode LSL (with a zero immediate)
8224 assert(emitter::insOptsAnyShift(opt));
8226 emitter::code_t option = (emitter::code_t)opt - (emitter::code_t)INS_OPTS_LSL;
8227 assert(option <= 3);
8229 return option << 22; // bits 23, 22
8232 /*****************************************************************************
8234 * Returns the encoding to apply a 12 bit left shift to the immediate
8237 /*static*/ emitter::code_t emitter::insEncodeShiftImm12(insOpts opt)
8239 if (emitter::insOptsLSL12(opt))
8241 return 0x00400000; // set the bit at location 22
8246 /*****************************************************************************
8248 * Returns the encoding to have the Rm register use an extend operation
8251 /*static*/ emitter::code_t emitter::insEncodeExtend(insOpts opt)
8253 if (emitter::insOptsNone(opt) || (opt == INS_OPTS_LSL))
8255 // None or LSL implies the we encode UXTX
8256 opt = INS_OPTS_UXTX;
8258 assert(emitter::insOptsAnyExtend(opt));
8260 emitter::code_t option = (emitter::code_t)opt - (emitter::code_t)INS_OPTS_UXTB;
8261 assert(option <= 7);
8263 return option << 13; // bits 15,14,13
8266 /*****************************************************************************
8268 * Returns the encoding to scale the Rm register by {0,1,2,3,4}
8269 * when using an extend operation
8272 /*static*/ emitter::code_t emitter::insEncodeExtendScale(ssize_t imm)
8274 assert((imm >= 0) && (imm <= 4));
8276 return (emitter::code_t)imm << 10; // bits 12,11,10
8279 /*****************************************************************************
8281 * Returns the encoding to have the Rm register be auto scaled by the ld/st size
8284 /*static*/ emitter::code_t emitter::insEncodeReg3Scale(bool isScaled)
8288 return 0x00001000; // set the bit at location 12
8296 BYTE* emitter::emitOutputLoadLabel(BYTE* dst, BYTE* srcAddr, BYTE* dstAddr, instrDescJmp* id)
8298 instruction ins = id->idIns();
8299 insFormat fmt = id->idInsFmt();
8300 regNumber dstReg = id->idReg1();
8303 // adr x, [rel addr] -- compute address: current addr(ip) + rel addr.
8304 assert(ins == INS_adr);
8305 assert(fmt == IF_DI_1E);
8306 ssize_t distVal = (ssize_t)(dstAddr - srcAddr);
8307 dst = emitOutputShortAddress(dst, ins, fmt, distVal, dstReg);
8311 // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8312 assert(fmt == IF_LARGEADR);
8313 ssize_t relPageAddr =
8314 (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8315 dst = emitOutputShortAddress(dst, INS_adrp, IF_DI_1E, relPageAddr, dstReg);
8317 // add x, x, page offs -- compute address = page addr + page offs
8318 ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8319 assert(isValidUimm12(imm12));
8321 emitInsCode(INS_add, IF_DI_2A); // DI_2A X0010001shiiiiii iiiiiinnnnnddddd 1100 0000 imm(i12, sh)
8322 code |= insEncodeDatasize(EA_8BYTE); // X
8323 code |= ((code_t)imm12 << 10); // iiiiiiiiiiii
8324 code |= insEncodeReg_Rd(dstReg); // ddddd
8325 code |= insEncodeReg_Rn(dstReg); // nnnnn
8326 dst += emitOutput_Instr(dst, code);
8331 /*****************************************************************************
8333 * Output a local jump or other instruction with a pc-relative immediate.
8334 * Note that this may be invoked to overwrite an existing jump instruction at 'dst'
8335 * to handle forward branch patching.
8338 BYTE* emitter::emitOutputLJ(insGroup* ig, BYTE* dst, instrDesc* i)
8340 instrDescJmp* id = (instrDescJmp*)i;
8349 // Set default ins/fmt from id.
8350 instruction ins = id->idIns();
8351 insFormat fmt = id->idInsFmt();
8353 bool loadLabel = false;
8354 bool isJump = false;
8355 bool loadConstant = false;
8372 loadConstant = true;
8381 /* Figure out the distance to the target */
8383 srcOffs = emitCurCodeOffs(dst);
8384 srcAddr = emitOffsetToPtr(srcOffs);
8386 if (id->idAddr()->iiaIsJitDataOffset())
8388 assert(loadConstant || loadLabel);
8389 int doff = id->idAddr()->iiaGetJitDataOffset();
8391 ssize_t imm = emitGetInsSC(id);
8392 assert((imm >= 0) && (imm < 0x1000)); // 0x1000 is arbitrary, currently 'imm' is always 0
8394 unsigned dataOffs = (unsigned)(doff + imm);
8395 assert(dataOffs < emitDataSize());
8396 dstAddr = emitDataOffsetToPtr(dataOffs);
8398 regNumber dstReg = id->idReg1();
8399 regNumber addrReg = dstReg; // an integer register to compute long address.
8400 emitAttr opSize = id->idOpSize();
8406 // ldr x/v, [rel addr] -- load constant from current addr(ip) + rel addr.
8407 assert(ins == INS_ldr);
8408 assert(fmt == IF_LS_1A);
8409 distVal = (ssize_t)(dstAddr - srcAddr);
8410 dst = emitOutputShortConstant(dst, ins, fmt, distVal, dstReg, opSize);
8414 // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8415 assert(fmt == IF_LARGELDC);
8416 ssize_t relPageAddr =
8417 (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8418 if (isVectorRegister(dstReg))
8420 // Update addrReg with the reserved integer register
8421 // since we cannot use dstReg (vector) to load constant directly from memory.
8422 addrReg = id->idReg2();
8423 assert(isGeneralRegister(addrReg));
8427 dst = emitOutputShortAddress(dst, ins, fmt, relPageAddr, addrReg);
8429 // ldr x, [x, page offs] -- load constant from page address + page offset into integer register.
8430 ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8431 assert(isValidUimm12(imm12));
8434 dst = emitOutputShortConstant(dst, ins, fmt, imm12, addrReg, opSize);
8436 // fmov v, d -- copy constant in integer register to vector register.
8437 // This is needed only for vector constant.
8438 if (addrReg != dstReg)
8440 // fmov Vd,Rn DV_2I X00111100X100111 000000nnnnnddddd 1E27 0000 Vd,Rn
8441 // (scalar, from general)
8442 assert(isVectorRegister(dstReg) && isGeneralRegister(addrReg));
8445 code_t code = emitInsCode(ins, fmt);
8447 code |= insEncodeReg_Vd(dstReg); // ddddd
8448 code |= insEncodeReg_Rn(addrReg); // nnnnn
8449 if (id->idOpSize() == EA_8BYTE)
8451 code |= 0x80400000; // X ... X
8453 dst += emitOutput_Instr(dst, code);
8460 dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8466 assert(loadLabel || isJump);
8468 if (id->idAddr()->iiaHasInstrCount())
8471 int instrCount = id->idAddr()->iiaGetInstrCount();
8472 unsigned insNum = emitFindInsNum(ig, id);
8475 // Backward branches using instruction count must be within the same instruction group.
8476 assert(insNum + 1 >= (unsigned)(-instrCount));
8478 dstOffs = ig->igOffs + emitFindOffset(ig, (insNum + 1 + instrCount));
8479 dstAddr = emitOffsetToPtr(dstOffs);
8483 dstOffs = id->idAddr()->iiaIGlabel->igOffs;
8484 dstAddr = emitOffsetToPtr(dstOffs);
8487 distVal = (ssize_t)(dstAddr - srcAddr);
8489 if (dstOffs <= srcOffs)
8492 /* This is a backward jump - distance is known at this point */
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("[3] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8500 printf("[3] Jump block is at %08X - %02X = %08X\n", blkOffs, emitOffsAdj, blkOffs - emitOffsAdj);
8501 printf("[3] Jump is at %08X - %02X = %08X\n", srcOffs, emitOffsAdj, srcOffs - emitOffsAdj);
8502 printf("[3] Label block is at %08X - %02X = %08X\n", dstOffs, emitOffsAdj, dstOffs - emitOffsAdj);
8508 /* This is a forward jump - distance will be an upper limit */
8510 emitFwdJumps = true;
8512 /* The target offset will be closer by at least 'emitOffsAdj', but only if this
8513 jump doesn't cross the hot-cold boundary. */
8515 if (!emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8517 dstOffs -= emitOffsAdj;
8518 distVal -= emitOffsAdj;
8521 /* Record the location of the jump for later patching */
8523 id->idjOffs = dstOffs;
8525 /* Are we overflowing the id->idjOffs bitfield? */
8526 if (id->idjOffs != dstOffs)
8527 IMPL_LIMITATION("Method is too large");
8530 if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8532 size_t blkOffs = id->idjIG->igOffs;
8534 if (INTERESTING_JUMP_NUM == 0)
8535 printf("[4] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8536 printf("[4] Jump block is at %08X\n", blkOffs);
8537 printf("[4] Jump is at %08X\n", srcOffs);
8538 printf("[4] Label block is at %08X - %02X = %08X\n", dstOffs + emitOffsAdj, emitOffsAdj, dstOffs);
8544 if (0 && emitComp->verbose)
8547 int distValSize = id->idjShort ? 4 : 8;
8548 printf("; %s jump [%08X/%03u] from %0*X to %0*X: dist = %08XH\n", (dstOffs <= srcOffs) ? "Fwd" : "Bwd",
8549 dspPtr(id), id->idDebugOnlyInfo()->idNum, distValSize, srcOffs + sz, distValSize, dstOffs, distVal);
8553 /* For forward jumps, record the address of the distance value */
8554 id->idjTemp.idjAddr = (distVal > 0) ? dst : NULL;
8556 if (emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8558 assert(!id->idjShort);
8559 NYI_ARM64("Relocation Support for long address");
8562 assert(insOptsNone(id->idInsOpt()));
8568 // Short conditional/unconditional jump
8569 assert(!id->idjKeepLong);
8570 assert(emitJumpCrossHotColdBoundary(srcOffs, dstOffs) == false);
8571 assert((fmt == IF_BI_0A) || (fmt == IF_BI_0B) || (fmt == IF_BI_1A) || (fmt == IF_BI_1B));
8575 // Long conditional jump
8576 assert(fmt == IF_LARGEJMP);
8577 // This is a pseudo-instruction format representing a large conditional branch, to allow
8578 // us to get a greater branch target range than we can get by using a straightforward conditional
8579 // branch. It is encoded as a short conditional branch that branches around a long unconditional
8582 // Conceptually, we have:
8586 // The code we emit is:
8588 // b<!cond> L_not // 4 bytes. Note that we reverse the condition.
8589 // b L_target // 4 bytes
8592 // Note that we don't actually insert any blocks: we simply encode "b <!cond> L_not" as a branch with
8593 // the correct offset. Note also that this works for both integer and floating-point conditions, because
8594 // the condition inversion takes ordered/unordered into account, preserving NaN behavior. For example,
8595 // "GT" (greater than) is inverted to "LE" (less than, equal, or unordered).
8597 instruction reverseIns;
8598 insFormat reverseFmt;
8603 reverseIns = INS_cbnz;
8604 reverseFmt = IF_BI_1A;
8607 reverseIns = INS_cbz;
8608 reverseFmt = IF_BI_1A;
8611 reverseIns = INS_tbnz;
8612 reverseFmt = IF_BI_1B;
8615 reverseIns = INS_tbz;
8616 reverseFmt = IF_BI_1B;
8619 reverseIns = emitJumpKindToIns(emitReverseJumpKind(emitInsToJumpKind(ins)));
8620 reverseFmt = IF_BI_0B;
8624 emitOutputShortBranch(dst,
8625 reverseIns, // reverse the conditional instruction
8627 8, /* 8 bytes from start of this large conditional pseudo-instruction to L_not. */
8630 // Now, pretend we've got a normal unconditional branch, and fall through to the code to emit that.
8634 // The distVal was computed based on the beginning of the pseudo-instruction,
8635 // So subtract the size of the conditional branch so that it is relative to the
8636 // unconditional branch.
8640 dst = emitOutputShortBranch(dst, ins, fmt, distVal, id);
8644 dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8650 /*****************************************************************************
8652 * Output a short branch instruction.
8654 BYTE* emitter::emitOutputShortBranch(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, instrDescJmp* id)
8656 code_t code = emitInsCode(ins, fmt);
8658 ssize_t loBits = (distVal & 3);
8659 noway_assert(loBits == 0);
8660 distVal >>= 2; // branch offset encodings are scaled by 4.
8662 if (fmt == IF_BI_0A)
8664 // INS_b or INS_bl_local
8665 noway_assert(isValidSimm26(distVal));
8666 distVal &= 0x3FFFFFFLL;
8669 else if (fmt == IF_BI_0B) // BI_0B 01010100iiiiiiii iiiiiiiiiiiXXXXX simm19:00
8671 // INS_beq, INS_bne, etc...
8672 noway_assert(isValidSimm19(distVal));
8673 distVal &= 0x7FFFFLL;
8674 code |= distVal << 5;
8676 else if (fmt == IF_BI_1A) // BI_1A X.......iiiiiiii iiiiiiiiiiittttt Rt simm19:00
8678 // INS_cbz or INS_cbnz
8679 assert(id != nullptr);
8680 code |= insEncodeDatasize(id->idOpSize()); // X
8681 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
8683 noway_assert(isValidSimm19(distVal));
8684 distVal &= 0x7FFFFLL; // 19 bits
8685 code |= distVal << 5;
8687 else if (fmt == IF_BI_1B) // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
8689 // INS_tbz or INS_tbnz
8690 assert(id != nullptr);
8691 ssize_t imm = emitGetInsSC(id);
8692 assert(isValidImmShift(imm, id->idOpSize()));
8694 if (imm & 0x20) // test bit 32-63 ?
8696 code |= 0x80000000; // B
8698 code |= ((imm & 0x1F) << 19); // bbbbb
8699 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
8701 noway_assert(isValidSimm14(distVal));
8702 distVal &= 0x3FFFLL; // 14 bits
8703 code |= distVal << 5;
8707 assert(!"Unknown fmt for emitOutputShortBranch");
8710 dst += emitOutput_Instr(dst, code);
8715 /*****************************************************************************
8717 * Output a short address instruction.
8719 BYTE* emitter::emitOutputShortAddress(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, regNumber reg)
8721 ssize_t loBits = (distVal & 3);
8724 code_t code = emitInsCode(ins, fmt);
8725 if (fmt == IF_DI_1E) // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
8727 // INS_adr or INS_adrp
8728 code |= insEncodeReg_Rd(reg); // ddddd
8730 noway_assert(isValidSimm19(distVal));
8731 distVal &= 0x7FFFFLL; // 19 bits
8732 code |= distVal << 5;
8733 code |= loBits << 29; // 2 bits
8737 assert(!"Unknown fmt for emitOutputShortAddress");
8740 dst += emitOutput_Instr(dst, code);
8745 /*****************************************************************************
8747 * Output a short constant instruction.
8749 BYTE* emitter::emitOutputShortConstant(
8750 BYTE* dst, instruction ins, insFormat fmt, ssize_t imm, regNumber reg, emitAttr opSize)
8752 code_t code = emitInsCode(ins, fmt);
8754 if (fmt == IF_LS_1A)
8756 // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt simm21
8757 // INS_ldr or INS_ldrsw (PC-Relative)
8759 ssize_t loBits = (imm & 3);
8760 noway_assert(loBits == 0);
8761 ssize_t distVal = imm >>= 2; // load offset encodings are scaled by 4.
8763 noway_assert(isValidSimm19(distVal));
8765 // Is the target a vector register?
8766 if (isVectorRegister(reg))
8768 code |= insEncodeDatasizeVLS(code, opSize); // XX V
8769 code |= insEncodeReg_Vt(reg); // ttttt
8773 assert(isGeneralRegister(reg));
8774 // insEncodeDatasizeLS is not quite right for this case.
8775 // So just specialize it.
8776 if ((ins == INS_ldr) && (opSize == EA_8BYTE))
8778 // set the operation size in bit 30
8782 code |= insEncodeReg_Rt(reg); // ttttt
8785 distVal &= 0x7FFFFLL; // 19 bits
8786 code |= distVal << 5;
8788 else if (fmt == IF_LS_2B)
8790 // ldr Rt,[Xn+pimm12] LS_2B 1X11100101iiiiii iiiiiinnnnnttttt B940 0000 imm(0-4095<<{2,3})
8791 // INS_ldr or INS_ldrsw (PC-Relative)
8792 noway_assert(isValidUimm12(imm));
8793 assert(isGeneralRegister(reg));
8795 if (opSize == EA_8BYTE)
8797 // insEncodeDatasizeLS is not quite right for this case.
8798 // So just specialize it.
8801 // set the operation size in bit 30
8804 // Low 3 bits should be 0 -- 8 byte JIT data should be aligned on 8 byte.
8805 assert((imm & 7) == 0);
8810 assert(opSize == EA_4BYTE);
8811 // Low 2 bits should be 0 -- 4 byte aligned data.
8812 assert((imm & 3) == 0);
8816 code |= insEncodeReg_Rt(reg); // ttttt
8817 code |= insEncodeReg_Rn(reg); // nnnnn
8822 assert(!"Unknown fmt for emitOutputShortConstant");
8825 dst += emitOutput_Instr(dst, code);
8829 /*****************************************************************************
8831 * Output a call instruction.
8834 unsigned emitter::emitOutputCall(insGroup* ig, BYTE* dst, instrDesc* id, code_t code)
8836 const unsigned char callInstrSize = sizeof(code_t); // 4 bytes
8837 regMaskTP gcrefRegs;
8838 regMaskTP byrefRegs;
8840 VARSET_TP GCvars(VarSetOps::UninitVal());
8842 // Is this a "fat" call descriptor?
8843 if (id->idIsLargeCall())
8845 instrDescCGCA* idCall = (instrDescCGCA*)id;
8846 gcrefRegs = idCall->idcGcrefRegs;
8847 byrefRegs = idCall->idcByrefRegs;
8848 VarSetOps::Assign(emitComp, GCvars, idCall->idcGCvars);
8852 assert(!id->idIsLargeDsp());
8853 assert(!id->idIsLargeCns());
8855 gcrefRegs = emitDecodeCallGCregs(id);
8857 VarSetOps::AssignNoCopy(emitComp, GCvars, VarSetOps::MakeEmpty(emitComp));
8860 /* We update the GC info before the call as the variables cannot be
8861 used by the call. Killing variables before the call helps with
8862 boundary conditions if the call is CORINFO_HELP_THROW - see bug 50029.
8863 If we ever track aliased variables (which could be used by the
8864 call), we would have to keep them alive past the call. */
8866 emitUpdateLiveGCvars(GCvars, dst);
8868 // Now output the call instruction and update the 'dst' pointer
8870 unsigned outputInstrSize = emitOutput_Instr(dst, code);
8871 dst += outputInstrSize;
8873 // All call instructions are 4-byte in size on ARM64
8875 assert(outputInstrSize == callInstrSize);
8877 // If the method returns a GC ref, mark INTRET (R0) appropriately.
8878 if (id->idGCref() == GCT_GCREF)
8880 gcrefRegs |= RBM_INTRET;
8882 else if (id->idGCref() == GCT_BYREF)
8884 byrefRegs |= RBM_INTRET;
8887 // If is a multi-register return method is called, mark INTRET_1 (X1) appropriately
8888 if (id->idIsLargeCall())
8890 instrDescCGCA* idCall = (instrDescCGCA*)id;
8891 if (idCall->idSecondGCref() == GCT_GCREF)
8893 gcrefRegs |= RBM_INTRET_1;
8895 else if (idCall->idSecondGCref() == GCT_BYREF)
8897 byrefRegs |= RBM_INTRET_1;
8901 // If the GC register set has changed, report the new set.
8902 if (gcrefRegs != emitThisGCrefRegs)
8904 emitUpdateLiveGCregs(GCT_GCREF, gcrefRegs, dst);
8906 // If the Byref register set has changed, report the new set.
8907 if (byrefRegs != emitThisByrefRegs)
8909 emitUpdateLiveGCregs(GCT_BYREF, byrefRegs, dst);
8912 // Some helper calls may be marked as not requiring GC info to be recorded.
8913 if ((!id->idIsNoGC()))
8915 // On ARM64, as on AMD64, we don't change the stack pointer to push/pop args.
8916 // So we're not really doing a "stack pop" here (note that "args" is 0), but we use this mechanism
8917 // to record the call for GC info purposes. (It might be best to use an alternate call,
8918 // and protect "emitStackPop" under the EMIT_TRACK_STACK_DEPTH preprocessor variable.)
8919 emitStackPop(dst, /*isCall*/ true, callInstrSize, /*args*/ 0);
8921 // Do we need to record a call location for GC purposes?
8923 if (!emitFullGCinfo)
8925 emitRecordGCcall(dst, callInstrSize);
8928 return callInstrSize;
8931 /*****************************************************************************
8933 * Emit a 32-bit Arm64 instruction
8936 /*static*/ unsigned emitter::emitOutput_Instr(BYTE* dst, code_t code)
8938 assert(sizeof(code_t) == 4);
8939 *((code_t*)dst) = code;
8941 return sizeof(code_t);
8944 /*****************************************************************************
8946 * Append the machine code corresponding to the given instruction descriptor
8947 * to the code block at '*dp'; the base of the code block is 'bp', and 'ig'
8948 * is the instruction group that contains the instruction. Updates '*dp' to
8949 * point past the generated code, and returns the size of the instruction
8950 * descriptor in bytes.
8953 size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
8958 size_t sz = emitGetInstrDescSize(id); // TODO-ARM64-Cleanup: on ARM, this is set in each case. why?
8959 instruction ins = id->idIns();
8960 insFormat fmt = id->idInsFmt();
8961 emitAttr size = id->idOpSize();
8962 unsigned char callInstrSize = 0;
8967 bool dspOffs = emitComp->opts.dspGCtbls;
8969 bool dspOffs = !emitComp->opts.disDiffable;
8973 assert(REG_NA == (int)REG_NA);
8975 VARSET_TP GCvars(VarSetOps::UninitVal());
8977 /* What instruction format have we got? */
8992 case IF_BI_0A: // BI_0A ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
8993 case IF_BI_0B: // BI_0B ......iiiiiiiiii iiiiiiiiiii..... simm19:00
8995 assert(id->idGCref() == GCT_NONE);
8996 assert(id->idIsBound());
8997 dst = emitOutputLJ(ig, dst, id);
8998 sz = sizeof(instrDescJmp);
9001 case IF_BI_0C: // BI_0C ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
9002 code = emitInsCode(ins, fmt);
9003 sz = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
9004 dst += emitOutputCall(ig, dst, id, code);
9005 // Always call RecordRelocation so that we wire in a JumpStub when we don't reach
9006 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_BRANCH26);
9009 case IF_BI_1A: // BI_1A ......iiiiiiiiii iiiiiiiiiiittttt Rt simm19:00
9010 assert(insOptsNone(id->idInsOpt()));
9011 assert(id->idIsBound());
9013 dst = emitOutputLJ(ig, dst, id);
9014 sz = sizeof(instrDescJmp);
9017 case IF_BI_1B: // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
9018 assert(insOptsNone(id->idInsOpt()));
9019 assert(id->idIsBound());
9021 dst = emitOutputLJ(ig, dst, id);
9022 sz = sizeof(instrDescJmp);
9025 case IF_BR_1A: // BR_1A ................ ......nnnnn..... Rn
9026 assert(insOptsNone(id->idInsOpt()));
9027 assert((ins == INS_ret) || (ins == INS_br));
9028 code = emitInsCode(ins, fmt);
9029 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9031 dst += emitOutput_Instr(dst, code);
9034 case IF_BR_1B: // BR_1B ................ ......nnnnn..... Rn
9035 assert(insOptsNone(id->idInsOpt()));
9036 assert((ins == INS_br_tail) || (ins == INS_blr));
9037 code = emitInsCode(ins, fmt);
9038 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9040 sz = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
9041 dst += emitOutputCall(ig, dst, id, code);
9044 case IF_LS_1A: // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB)
9046 assert(insOptsNone(id->idInsOpt()));
9047 assert(id->idIsBound());
9049 dst = emitOutputLJ(ig, dst, id);
9050 sz = sizeof(instrDescJmp);
9053 case IF_LS_2A: // LS_2A .X.......X...... ......nnnnnttttt Rt Rn
9054 assert(insOptsNone(id->idInsOpt()));
9055 code = emitInsCode(ins, fmt);
9056 // Is the target a vector register?
9057 if (isVectorRegister(id->idReg1()))
9059 code &= 0x3FFFFFFF; // clear the size bits
9060 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9061 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9065 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9066 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9068 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9069 dst += emitOutput_Instr(dst, code);
9072 case IF_LS_2B: // LS_2B .X.......Xiiiiii iiiiiinnnnnttttt Rt Rn imm(0-4095)
9073 assert(insOptsNone(id->idInsOpt()));
9074 imm = emitGetInsSC(id);
9075 assert(isValidUimm12(imm));
9076 code = emitInsCode(ins, fmt);
9077 // Is the target a vector register?
9078 if (isVectorRegister(id->idReg1()))
9080 code &= 0x3FFFFFFF; // clear the size bits
9081 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9082 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9086 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9087 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9089 code |= ((code_t)imm << 10); // iiiiiiiiiiii
9090 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9091 dst += emitOutput_Instr(dst, code);
9094 case IF_LS_2C: // LS_2C .X.......X.iiiii iiiiPPnnnnnttttt Rt Rn imm(-256..+255) no/pre/post inc
9095 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9096 imm = emitGetInsSC(id);
9097 assert((imm >= -256) && (imm <= 255)); // signed 9 bits
9098 imm &= 0x1ff; // force into unsigned 9 bit representation
9099 code = emitInsCode(ins, fmt);
9100 // Is the target a vector register?
9101 if (isVectorRegister(id->idReg1()))
9103 code &= 0x3FFFFFFF; // clear the size bits
9104 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9105 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9109 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9110 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9112 code |= insEncodeIndexedOpt(id->idInsOpt()); // PP
9113 code |= ((code_t)imm << 12); // iiiiiiiii
9114 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9115 dst += emitOutput_Instr(dst, code);
9118 case IF_LS_3A: // LS_3A .X.......X.mmmmm oooS..nnnnnttttt Rt Rn Rm ext(Rm) LSL {}
9119 assert(insOptsLSExtend(id->idInsOpt()));
9120 code = emitInsCode(ins, fmt);
9121 // Is the target a vector register?
9122 if (isVectorRegister(id->idReg1()))
9124 code &= 0x3FFFFFFF; // clear the size bits
9125 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9126 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9130 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9131 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9133 code |= insEncodeExtend(id->idInsOpt()); // ooo
9134 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9135 if (id->idIsLclVar())
9137 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9141 code |= insEncodeReg3Scale(id->idReg3Scaled()); // S
9142 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9144 dst += emitOutput_Instr(dst, code);
9147 case IF_LS_3B: // LS_3B X............... .aaaaannnnnddddd Rd Ra Rn
9148 assert(insOptsNone(id->idInsOpt()));
9149 code = emitInsCode(ins, fmt);
9150 // Is the target a vector register?
9151 if (isVectorRegister(id->idReg1()))
9153 code &= 0x3FFFFFFF; // clear the size bits
9154 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9155 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9156 code |= insEncodeReg_Va(id->idReg2()); // aaaaa
9160 code |= insEncodeDatasize(id->idOpSize()); // X
9161 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9162 code |= insEncodeReg_Ra(id->idReg2()); // aaaaa
9164 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9165 dst += emitOutput_Instr(dst, code);
9168 case IF_LS_3C: // LS_3C X......PP.iiiiii iaaaaannnnnddddd Rd Ra Rn imm(im7,sh)
9169 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9170 imm = emitGetInsSC(id);
9171 assert((imm >= -64) && (imm <= 63)); // signed 7 bits
9172 imm &= 0x7f; // force into unsigned 7 bit representation
9173 code = emitInsCode(ins, fmt);
9174 // Is the target a vector register?
9175 if (isVectorRegister(id->idReg1()))
9177 code &= 0x3FFFFFFF; // clear the size bits
9178 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9179 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9180 code |= insEncodeReg_Va(id->idReg2()); // aaaaa
9184 code |= insEncodeDatasize(id->idOpSize()); // X
9185 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9186 code |= insEncodeReg_Ra(id->idReg2()); // aaaaa
9188 code |= insEncodePairIndexedOpt(ins, id->idInsOpt()); // PP
9189 code |= ((code_t)imm << 15); // iiiiiiiii
9190 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9191 dst += emitOutput_Instr(dst, code);
9194 case IF_LS_3D: // LS_3D .X.......X.mmmmm ......nnnnnttttt Wm Rt Rn
9195 code = emitInsCode(ins, fmt);
9196 // Arm64 store exclusive unpredictable cases
9197 assert(id->idReg1() != id->idReg2());
9198 assert(id->idReg1() != id->idReg3());
9199 code |= insEncodeDatasizeLS(code, id->idOpSize()); // X
9200 code |= insEncodeReg_Rm(id->idReg1()); // mmmmm
9201 code |= insEncodeReg_Rt(id->idReg2()); // ttttt
9202 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9203 dst += emitOutput_Instr(dst, code);
9206 case IF_DI_1A: // DI_1A X.......shiiiiii iiiiiinnnnn..... Rn imm(i12,sh)
9207 assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9208 imm = emitGetInsSC(id);
9209 assert(isValidUimm12(imm));
9210 code = emitInsCode(ins, fmt);
9211 code |= insEncodeDatasize(id->idOpSize()); // X
9212 code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9213 code |= ((code_t)imm << 10); // iiiiiiiiiiii
9214 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9215 dst += emitOutput_Instr(dst, code);
9218 case IF_DI_1B: // DI_1B X........hwiiiii iiiiiiiiiiiddddd Rd imm(i16,hw)
9219 imm = emitGetInsSC(id);
9220 assert(isValidImmHWVal(imm, id->idOpSize()));
9221 code = emitInsCode(ins, fmt);
9222 code |= insEncodeDatasize(id->idOpSize()); // X
9223 code |= ((code_t)imm << 5); // hwiiiii iiiiiiiiiii
9224 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9225 dst += emitOutput_Instr(dst, code);
9228 case IF_DI_1C: // DI_1C X........Nrrrrrr ssssssnnnnn..... Rn imm(N,r,s)
9229 imm = emitGetInsSC(id);
9230 assert(isValidImmNRS(imm, id->idOpSize()));
9231 code = emitInsCode(ins, fmt);
9232 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9233 code |= insEncodeDatasize(id->idOpSize()); // X
9234 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9235 dst += emitOutput_Instr(dst, code);
9238 case IF_DI_1D: // DI_1D X........Nrrrrrr ssssss.....ddddd Rd imm(N,r,s)
9239 imm = emitGetInsSC(id);
9240 assert(isValidImmNRS(imm, id->idOpSize()));
9241 code = emitInsCode(ins, fmt);
9242 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9243 code |= insEncodeDatasize(id->idOpSize()); // X
9244 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9245 dst += emitOutput_Instr(dst, code);
9248 case IF_DI_1E: // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
9250 assert(insOptsNone(id->idInsOpt()));
9251 if (id->idIsReloc())
9253 code = emitInsCode(ins, fmt);
9254 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9255 dst += emitOutput_Instr(dst, code);
9256 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEBASE_REL21);
9260 // Local jmp/load case which does not need a relocation.
9261 assert(id->idIsBound());
9262 dst = emitOutputLJ(ig, dst, id);
9264 sz = sizeof(instrDescJmp);
9267 case IF_DI_1F: // DI_1F X..........iiiii cccc..nnnnn.nzcv Rn imm5 nzcv cond
9268 imm = emitGetInsSC(id);
9269 assert(isValidImmCondFlagsImm5(imm));
9272 cfi.immCFVal = (unsigned)imm;
9273 code = emitInsCode(ins, fmt);
9274 code |= insEncodeDatasize(id->idOpSize()); // X
9275 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9276 code |= ((code_t)cfi.imm5 << 16); // iiiii
9277 code |= insEncodeFlags(cfi.flags); // nzcv
9278 code |= insEncodeCond(cfi.cond); // cccc
9279 dst += emitOutput_Instr(dst, code);
9283 case IF_DI_2A: // DI_2A X.......shiiiiii iiiiiinnnnnddddd Rd Rn imm(i12,sh)
9284 assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9285 imm = emitGetInsSC(id);
9286 assert(isValidUimm12(imm));
9287 code = emitInsCode(ins, fmt);
9288 code |= insEncodeDatasize(id->idOpSize()); // X
9289 code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9290 code |= ((code_t)imm << 10); // iiiiiiiiiiii
9291 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9292 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9293 dst += emitOutput_Instr(dst, code);
9295 if (id->idIsReloc())
9297 assert(sz == sizeof(instrDesc));
9298 assert(id->idAddr()->iiaAddr != nullptr);
9299 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEOFFSET_12A);
9303 case IF_DI_2B: // DI_2B X.........Xnnnnn ssssssnnnnnddddd Rd Rn imm(0-63)
9304 code = emitInsCode(ins, fmt);
9305 imm = emitGetInsSC(id);
9306 assert(isValidImmShift(imm, id->idOpSize()));
9307 code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9308 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9309 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9310 code |= insEncodeReg_Rm(id->idReg2()); // Reg2 also in mmmmm
9311 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9312 dst += emitOutput_Instr(dst, code);
9315 case IF_DI_2C: // DI_2C X........Nrrrrrr ssssssnnnnnddddd Rd Rn imm(N,r,s)
9316 imm = emitGetInsSC(id);
9317 assert(isValidImmNRS(imm, id->idOpSize()));
9318 code = emitInsCode(ins, fmt);
9319 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9320 code |= insEncodeDatasize(id->idOpSize()); // X
9321 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9322 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9323 dst += emitOutput_Instr(dst, code);
9326 case IF_DI_2D: // DI_2D X........Nrrrrrr ssssssnnnnnddddd Rd Rn imr, imms (N,r,s)
9327 if (ins == INS_asr || ins == INS_lsl || ins == INS_lsr)
9329 imm = emitGetInsSC(id);
9330 assert(isValidImmShift(imm, id->idOpSize()));
9332 // Shift immediates are aliases of the SBFM/UBFM instructions
9333 // that actually take 2 registers and 2 constants,
9334 // Since we stored the shift immediate value
9335 // we need to calculate the N,R and S values here.
9340 bmi.immN = (size == EA_8BYTE) ? 1 : 0;
9342 bmi.immS = (size == EA_8BYTE) ? 0x3f : 0x1f;
9344 // immR and immS are now set correctly for INS_asr and INS_lsr
9345 // but for INS_lsl we have to adjust the values for immR and immS
9349 bmi.immR = -imm & bmi.immS;
9350 bmi.immS = bmi.immS - imm;
9353 // setup imm with the proper 13 bit value N:R:S
9359 // The other instructions have already have encoded N,R and S values
9360 imm = emitGetInsSC(id);
9362 assert(isValidImmNRS(imm, id->idOpSize()));
9364 code = emitInsCode(ins, fmt);
9365 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9366 code |= insEncodeDatasize(id->idOpSize()); // X
9367 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9368 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9369 dst += emitOutput_Instr(dst, code);
9372 case IF_DR_1D: // DR_1D X............... cccc.......ddddd Rd cond
9373 imm = emitGetInsSC(id);
9374 assert(isValidImmCond(imm));
9377 cfi.immCFVal = (unsigned)imm;
9378 code = emitInsCode(ins, fmt);
9379 code |= insEncodeDatasize(id->idOpSize()); // X
9380 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9381 code |= insEncodeInvertedCond(cfi.cond); // cccc
9382 dst += emitOutput_Instr(dst, code);
9386 case IF_DR_2A: // DR_2A X..........mmmmm ......nnnnn..... Rn Rm
9387 assert(insOptsNone(id->idInsOpt()));
9388 code = emitInsCode(ins, fmt);
9389 code |= insEncodeDatasize(id->idOpSize()); // X
9390 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9391 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9392 dst += emitOutput_Instr(dst, code);
9395 case IF_DR_2B: // DR_2B X.......sh.mmmmm ssssssnnnnn..... Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
9396 code = emitInsCode(ins, fmt);
9397 imm = emitGetInsSC(id);
9398 assert(isValidImmShift(imm, id->idOpSize()));
9399 code |= insEncodeDatasize(id->idOpSize()); // X
9400 code |= insEncodeShiftType(id->idInsOpt()); // sh
9401 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9402 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9403 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9404 dst += emitOutput_Instr(dst, code);
9407 case IF_DR_2C: // DR_2C X..........mmmmm ooosssnnnnn..... Rn Rm ext(Rm) LSL imm(0-4)
9408 code = emitInsCode(ins, fmt);
9409 imm = emitGetInsSC(id);
9410 assert((imm >= 0) && (imm <= 4)); // imm [0..4]
9411 code |= insEncodeDatasize(id->idOpSize()); // X
9412 code |= insEncodeExtend(id->idInsOpt()); // ooo
9413 code |= insEncodeExtendScale(imm); // sss
9414 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9415 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9416 dst += emitOutput_Instr(dst, code);
9419 case IF_DR_2D: // DR_2D X..........nnnnn cccc..nnnnnddddd Rd Rn cond
9420 imm = emitGetInsSC(id);
9421 assert(isValidImmCond(imm));
9424 cfi.immCFVal = (unsigned)imm;
9425 code = emitInsCode(ins, fmt);
9426 code |= insEncodeDatasize(id->idOpSize()); // X
9427 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9428 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9429 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9430 code |= insEncodeInvertedCond(cfi.cond); // cccc
9431 dst += emitOutput_Instr(dst, code);
9435 case IF_DR_2E: // DR_2E X..........mmmmm ...........ddddd Rd Rm
9436 code = emitInsCode(ins, fmt);
9437 code |= insEncodeDatasize(id->idOpSize()); // X
9438 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9439 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9440 dst += emitOutput_Instr(dst, code);
9443 case IF_DR_2F: // DR_2F X.......sh.mmmmm ssssss.....ddddd Rd Rm {LSL,LSR,ASR} imm(0-63)
9444 code = emitInsCode(ins, fmt);
9445 imm = emitGetInsSC(id);
9446 assert(isValidImmShift(imm, id->idOpSize()));
9447 code |= insEncodeDatasize(id->idOpSize()); // X
9448 code |= insEncodeShiftType(id->idInsOpt()); // sh
9449 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9450 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9451 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9452 dst += emitOutput_Instr(dst, code);
9455 case IF_DR_2G: // DR_2G X............... .....xnnnnnddddd Rd Rn
9456 code = emitInsCode(ins, fmt);
9457 code |= insEncodeDatasize(id->idOpSize()); // X
9460 if (size == EA_8BYTE)
9462 code |= 0x00000400; // x - bit at location 10
9465 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9466 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9467 dst += emitOutput_Instr(dst, code);
9470 case IF_DR_2H: // DR_2H X........X...... ......nnnnnddddd Rd Rn
9471 code = emitInsCode(ins, fmt);
9472 code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9473 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9474 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9475 dst += emitOutput_Instr(dst, code);
9478 case IF_DR_2I: // DR_2I X..........mmmmm cccc..nnnnn.nzcv Rn Rm nzcv cond
9479 imm = emitGetInsSC(id);
9480 assert(isValidImmCondFlags(imm));
9483 cfi.immCFVal = (unsigned)imm;
9484 code = emitInsCode(ins, fmt);
9485 code |= insEncodeDatasize(id->idOpSize()); // X
9486 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9487 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9488 code |= insEncodeFlags(cfi.flags); // nzcv
9489 code |= insEncodeCond(cfi.cond); // cccc
9490 dst += emitOutput_Instr(dst, code);
9494 case IF_DR_3A: // DR_3A X..........mmmmm ......nnnnnmmmmm Rd Rn Rm
9495 code = emitInsCode(ins, fmt);
9496 code |= insEncodeDatasize(id->idOpSize()); // X
9497 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9498 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9499 if (id->idIsLclVar())
9501 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9505 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9507 dst += emitOutput_Instr(dst, code);
9510 case IF_DR_3B: // DR_3B X.......sh.mmmmm ssssssnnnnnddddd Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
9511 code = emitInsCode(ins, fmt);
9512 imm = emitGetInsSC(id);
9513 assert(isValidImmShift(imm, id->idOpSize()));
9514 code |= insEncodeDatasize(id->idOpSize()); // X
9515 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9516 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9517 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9518 code |= insEncodeShiftType(id->idInsOpt()); // sh
9519 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9520 dst += emitOutput_Instr(dst, code);
9523 case IF_DR_3C: // DR_3C X..........mmmmm ooosssnnnnnddddd Rd Rn Rm ext(Rm) LSL imm(0-4)
9524 code = emitInsCode(ins, fmt);
9525 imm = emitGetInsSC(id);
9526 assert((imm >= 0) && (imm <= 4)); // imm [0..4]
9527 code |= insEncodeDatasize(id->idOpSize()); // X
9528 code |= insEncodeExtend(id->idInsOpt()); // ooo
9529 code |= insEncodeExtendScale(imm); // sss
9530 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9531 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9532 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9533 dst += emitOutput_Instr(dst, code);
9536 case IF_DR_3D: // DR_3D X..........mmmmm cccc..nnnnnddddd Rd Rn Rm cond
9537 imm = emitGetInsSC(id);
9538 assert(isValidImmCond(imm));
9541 cfi.immCFVal = (unsigned)imm;
9542 code = emitInsCode(ins, fmt);
9543 code |= insEncodeDatasize(id->idOpSize()); // X
9544 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9545 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9546 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9547 code |= insEncodeCond(cfi.cond); // cccc
9548 dst += emitOutput_Instr(dst, code);
9552 case IF_DR_3E: // DR_3E X........X.mmmmm ssssssnnnnnddddd Rd Rn Rm imm(0-63)
9553 code = emitInsCode(ins, fmt);
9554 imm = emitGetInsSC(id);
9555 assert(isValidImmShift(imm, id->idOpSize()));
9556 code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9557 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9558 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9559 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9560 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9561 dst += emitOutput_Instr(dst, code);
9564 case IF_DR_4A: // DR_4A X..........mmmmm .aaaaannnnnmmmmm Rd Rn Rm Ra
9565 code = emitInsCode(ins, fmt);
9566 code |= insEncodeDatasize(id->idOpSize()); // X
9567 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9568 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9569 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9570 code |= insEncodeReg_Ra(id->idReg4()); // aaaaa
9571 dst += emitOutput_Instr(dst, code);
9574 case IF_DV_1A: // DV_1A .........X.iiiii iii........ddddd Vd imm8 (fmov - immediate scalar)
9575 imm = emitGetInsSC(id);
9576 elemsize = id->idOpSize();
9577 code = emitInsCode(ins, fmt);
9578 code |= insEncodeFloatElemsize(elemsize); // X
9579 code |= ((code_t)imm << 13); // iiiii iii
9580 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9581 dst += emitOutput_Instr(dst, code);
9584 case IF_DV_1B: // DV_1B .QX..........iii cmod..iiiiiddddd Vd imm8 (immediate vector)
9585 imm = emitGetInsSC(id) & 0x0ff;
9586 immShift = (emitGetInsSC(id) & 0x700) >> 8;
9587 elemsize = optGetElemsize(id->idInsOpt());
9592 cmode = 0xE; // 1110
9596 cmode |= (immShift << 1); // 10x0
9602 cmode |= (immShift << 1); // 0xx0
9612 cmode = 0xE; // 1110
9619 code = emitInsCode(ins, fmt);
9620 code |= insEncodeVectorsize(id->idOpSize()); // Q
9621 if ((ins == INS_fmov) || (ins == INS_movi))
9623 if (elemsize == EA_8BYTE)
9625 code |= 0x20000000; // X
9628 if (ins != INS_fmov)
9630 assert((cmode >= 0) && (cmode <= 0xF));
9631 code |= (cmode << 12); // cmod
9633 code |= (((code_t)imm >> 5) << 16); // iii
9634 code |= (((code_t)imm & 0x1f) << 5); // iiiii
9635 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9636 dst += emitOutput_Instr(dst, code);
9639 case IF_DV_1C: // DV_1C .........X...... ......nnnnn..... Vn #0.0 (fcmp - with zero)
9640 elemsize = id->idOpSize();
9641 code = emitInsCode(ins, fmt);
9642 code |= insEncodeFloatElemsize(elemsize); // X
9643 code |= insEncodeReg_Vn(id->idReg1()); // nnnnn
9644 dst += emitOutput_Instr(dst, code);
9647 case IF_DV_2A: // DV_2A .Q.......X...... ......nnnnnddddd Vd Vn (fabs, fcvt - vector)
9648 elemsize = optGetElemsize(id->idInsOpt());
9649 code = emitInsCode(ins, fmt);
9650 code |= insEncodeVectorsize(id->idOpSize()); // Q
9651 code |= insEncodeFloatElemsize(elemsize); // X
9652 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9653 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9654 dst += emitOutput_Instr(dst, code);
9657 case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov/smov - to general)
9658 elemsize = id->idOpSize();
9659 index = emitGetInsSC(id);
9660 datasize = (elemsize == EA_8BYTE) ? EA_16BYTE : EA_8BYTE;
9661 if (ins == INS_smov)
9663 datasize = EA_16BYTE;
9665 code = emitInsCode(ins, fmt);
9666 code |= insEncodeVectorsize(datasize); // Q
9667 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9668 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9669 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9670 dst += emitOutput_Instr(dst, code);
9673 case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
9676 datasize = id->idOpSize();
9677 elemsize = optGetElemsize(id->idInsOpt());
9682 datasize = EA_16BYTE;
9683 elemsize = id->idOpSize();
9684 index = emitGetInsSC(id);
9686 code = emitInsCode(ins, fmt);
9687 code |= insEncodeVectorsize(datasize); // Q
9688 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9689 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9690 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9691 dst += emitOutput_Instr(dst, code);
9694 case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
9695 index = emitGetInsSC(id);
9696 elemsize = optGetElemsize(id->idInsOpt());
9697 code = emitInsCode(ins, fmt);
9698 code |= insEncodeVectorsize(id->idOpSize()); // Q
9699 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9700 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9701 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9702 dst += emitOutput_Instr(dst, code);
9705 case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
9706 index = emitGetInsSC(id);
9707 elemsize = id->idOpSize();
9708 code = emitInsCode(ins, fmt);
9709 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9710 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9711 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9712 dst += emitOutput_Instr(dst, code);
9715 case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
9716 elemsize = id->idOpSize();
9717 imm = emitGetInsSC(id);
9718 index = (imm >> 4) & 0xf;
9720 code = emitInsCode(ins, fmt);
9721 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9722 code |= insEncodeVectorIndex2(elemsize, index2); // jjjj
9723 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9724 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9725 dst += emitOutput_Instr(dst, code);
9728 case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov,fcvtXX - register)
9729 elemsize = id->idOpSize();
9730 code = emitInsCode(ins, fmt);
9731 code |= insEncodeFloatElemsize(elemsize); // X
9732 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9733 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9734 dst += emitOutput_Instr(dst, code);
9737 case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov - to general)
9738 elemsize = id->idOpSize();
9739 code = emitInsCode(ins, fmt);
9740 code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X X
9741 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9742 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9743 dst += emitOutput_Instr(dst, code);
9746 case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov - from general)
9747 elemsize = id->idOpSize();
9748 code = emitInsCode(ins, fmt);
9749 code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X X
9750 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9751 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9752 dst += emitOutput_Instr(dst, code);
9755 case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
9756 code = emitInsCode(ins, fmt);
9757 code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // SS DD
9758 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9759 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9760 dst += emitOutput_Instr(dst, code);
9763 case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
9764 elemsize = id->idOpSize();
9765 code = emitInsCode(ins, fmt);
9766 code |= insEncodeFloatElemsize(elemsize); // X
9767 code |= insEncodeReg_Vn(id->idReg1()); // nnnnn
9768 code |= insEncodeReg_Vm(id->idReg2()); // mmmmm
9769 dst += emitOutput_Instr(dst, code);
9772 case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
9773 elemsize = id->idOpSize();
9774 code = emitInsCode(ins, fmt);
9775 code |= insEncodeElemsize(elemsize); // XX
9776 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9777 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9778 dst += emitOutput_Instr(dst, code);
9781 case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
9782 elemsize = optGetElemsize(id->idInsOpt());
9783 code = emitInsCode(ins, fmt);
9784 code |= insEncodeVectorsize(id->idOpSize()); // Q
9785 code |= insEncodeElemsize(elemsize); // XX
9786 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9787 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9788 dst += emitOutput_Instr(dst, code);
9791 case IF_DV_2N: // DV_2N .........iiiiiii ......nnnnnddddd Vd Vn imm (shift - scalar)
9792 imm = emitGetInsSC(id);
9793 code = emitInsCode(ins, fmt);
9794 code |= insEncodeVectorShift(EA_8BYTE, imm); // iiiiiii
9795 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9796 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9797 dst += emitOutput_Instr(dst, code);
9800 case IF_DV_2O: // DV_2O .Q.......iiiiiii ......nnnnnddddd Vd Vn imm (shift - vector)
9801 imm = emitGetInsSC(id);
9802 elemsize = optGetElemsize(id->idInsOpt());
9803 code = emitInsCode(ins, fmt);
9804 code |= insEncodeVectorsize(id->idOpSize()); // Q
9805 code |= insEncodeVectorShift(elemsize, imm); // iiiiiii
9806 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9807 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9808 dst += emitOutput_Instr(dst, code);
9811 case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
9812 code = emitInsCode(ins, fmt);
9813 elemsize = optGetElemsize(id->idInsOpt());
9814 code |= insEncodeVectorsize(id->idOpSize()); // Q
9815 code |= insEncodeElemsize(elemsize); // XX
9816 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9817 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9818 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9819 dst += emitOutput_Instr(dst, code);
9822 case IF_DV_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector)
9823 code = emitInsCode(ins, fmt);
9824 imm = emitGetInsSC(id);
9825 elemsize = optGetElemsize(id->idInsOpt());
9826 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
9827 code |= insEncodeVectorsize(id->idOpSize()); // Q
9828 code |= insEncodeElemsize(elemsize); // XX
9829 code |= insEncodeVectorIndexLMH(elemsize, imm); // LM H
9830 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9831 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9832 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9833 dst += emitOutput_Instr(dst, code);
9836 case IF_DV_3B: // DV_3B .Q.......X.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
9837 code = emitInsCode(ins, fmt);
9838 elemsize = optGetElemsize(id->idInsOpt());
9839 code |= insEncodeVectorsize(id->idOpSize()); // Q
9840 code |= insEncodeFloatElemsize(elemsize); // X
9841 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9842 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9843 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9844 dst += emitOutput_Instr(dst, code);
9847 case IF_DV_3BI: // DV_3BI .Q.......XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
9848 code = emitInsCode(ins, fmt);
9849 imm = emitGetInsSC(id);
9850 elemsize = optGetElemsize(id->idInsOpt());
9851 assert(isValidVectorIndex(id->idOpSize(), elemsize, imm));
9852 code |= insEncodeVectorsize(id->idOpSize()); // Q
9853 code |= insEncodeFloatElemsize(elemsize); // X
9854 code |= insEncodeFloatIndex(elemsize, imm); // L H
9855 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9856 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9857 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9858 dst += emitOutput_Instr(dst, code);
9861 case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
9862 code = emitInsCode(ins, fmt);
9863 code |= insEncodeVectorsize(id->idOpSize()); // Q
9864 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9865 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9866 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9867 dst += emitOutput_Instr(dst, code);
9870 case IF_DV_3D: // DV_3D .........X.mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
9871 code = emitInsCode(ins, fmt);
9872 code |= insEncodeFloatElemsize(id->idOpSize()); // X
9873 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9874 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9875 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9876 dst += emitOutput_Instr(dst, code);
9879 case IF_DV_3DI: // DV_3DI .........XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (scalar by elem)
9880 code = emitInsCode(ins, fmt);
9881 imm = emitGetInsSC(id);
9882 elemsize = id->idOpSize();
9883 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
9884 code |= insEncodeFloatElemsize(elemsize); // X
9885 code |= insEncodeFloatIndex(elemsize, imm); // L H
9886 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9887 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9888 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9889 dst += emitOutput_Instr(dst, code);
9892 case IF_DV_3E: // DV_3E ...........mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
9893 code = emitInsCode(ins, fmt);
9894 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9895 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9896 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9897 dst += emitOutput_Instr(dst, code);
9900 case IF_DV_4A: // DV_4A .........X.mmmmm .aaaaannnnnddddd Vd Va Vn Vm (scalar)
9901 code = emitInsCode(ins, fmt);
9902 elemsize = id->idOpSize();
9903 code |= insEncodeFloatElemsize(elemsize); // X
9904 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9905 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9906 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9907 code |= insEncodeReg_Va(id->idReg4()); // aaaaa
9908 dst += emitOutput_Instr(dst, code);
9911 case IF_SN_0A: // SN_0A ................ ................
9912 code = emitInsCode(ins, fmt);
9913 dst += emitOutput_Instr(dst, code);
9916 case IF_SI_0A: // SI_0A ...........iiiii iiiiiiiiiii..... imm16
9917 imm = emitGetInsSC(id);
9918 assert(isValidUimm16(imm));
9919 code = emitInsCode(ins, fmt);
9920 code |= ((code_t)imm << 5); // iiiii iiiiiiiiiii
9921 dst += emitOutput_Instr(dst, code);
9924 case IF_SI_0B: // SI_0B ................ ....bbbb........ imm4 - barrier
9925 imm = emitGetInsSC(id);
9926 assert((imm >= 0) && (imm <= 15));
9927 code = emitInsCode(ins, fmt);
9928 code |= ((code_t)imm << 8); // bbbb
9929 dst += emitOutput_Instr(dst, code);
9933 assert(!"Unexpected format");
9937 // Determine if any registers now hold GC refs, or whether a register that was overwritten held a GC ref.
9938 // We assume here that "id->idGCref()" is not GC_NONE only if the instruction described by "id" writes a
9939 // GC ref to register "id->idReg1()". (It may, apparently, also not be GC_NONE in other cases, such as
9940 // for stores, but we ignore those cases here.)
9941 if (emitInsMayWriteToGCReg(id)) // True if "id->idIns()" writes to a register than can hold GC ref.
9943 // We assume that "idReg1" is the primary destination register for all instructions
9944 if (id->idGCref() != GCT_NONE)
9946 emitGCregLiveUpd(id->idGCref(), id->idReg1(), dst);
9950 emitGCregDeadUpd(id->idReg1(), dst);
9953 if (emitInsMayWriteMultipleRegs(id))
9956 // "idReg2" is the secondary destination register
9957 if (id->idGCrefReg2() != GCT_NONE)
9959 emitGCregLiveUpd(id->idGCrefReg2(), id->idReg2(), dst);
9963 emitGCregDeadUpd(id->idReg2(), dst);
9968 // Now we determine if the instruction has written to a (local variable) stack location, and either written a GC
9969 // ref or overwritten one.
9970 if (emitInsWritesToLclVarStackLoc(id) || emitInsWritesToLclVarStackLocPair(id))
9972 int varNum = id->idAddr()->iiaLclVar.lvaVarNum();
9973 unsigned ofs = AlignDown(id->idAddr()->iiaLclVar.lvaOffset(), TARGET_POINTER_SIZE);
9975 int adr = emitComp->lvaFrameAddress(varNum, &FPbased);
9976 if (id->idGCref() != GCT_NONE)
9978 emitGCvarLiveUpd(adr + ofs, varNum, id->idGCref(), dst);
9982 // If the type of the local is a gc ref type, update the liveness.
9986 // "Regular" (non-spill-temp) local.
9987 vt = var_types(emitComp->lvaTable[varNum].lvType);
9991 TempDsc* tmpDsc = emitComp->tmpFindNum(varNum);
9992 vt = tmpDsc->tdTempType();
9994 if (vt == TYP_REF || vt == TYP_BYREF)
9995 emitGCvarDeadUpd(adr + ofs, dst);
9997 if (emitInsWritesToLclVarStackLocPair(id))
9999 unsigned ofs2 = ofs + TARGET_POINTER_SIZE;
10000 if (id->idGCrefReg2() != GCT_NONE)
10002 emitGCvarLiveUpd(adr + ofs2, varNum, id->idGCrefReg2(), dst);
10006 // If the type of the local is a gc ref type, update the liveness.
10010 // "Regular" (non-spill-temp) local.
10011 vt = var_types(emitComp->lvaTable[varNum].lvType);
10015 TempDsc* tmpDsc = emitComp->tmpFindNum(varNum);
10016 vt = tmpDsc->tdTempType();
10018 if (vt == TYP_REF || vt == TYP_BYREF)
10019 emitGCvarDeadUpd(adr + ofs2, dst);
10025 /* Make sure we set the instruction descriptor size correctly */
10027 size_t expected = emitSizeOfInsDsc(id);
10028 assert(sz == expected);
10030 if (emitComp->opts.disAsm || emitComp->opts.dspEmit || emitComp->verbose)
10032 emitDispIns(id, false, dspOffs, true, emitCurCodeOffs(odst), *dp, (dst - *dp), ig);
10035 if (emitComp->compDebugBreak)
10037 // For example, set JitBreakEmitOutputInstr=a6 will break when this method is called for
10038 // emitting instruction a6, (i.e. IN00a6 in jitdump).
10039 if ((unsigned)JitConfig.JitBreakEmitOutputInstr() == id->idDebugOnlyInfo()->idNum)
10041 assert(!"JitBreakEmitOutputInstr reached");
10046 /* All instructions are expected to generate code */
10048 assert(*dp != dst);
10055 /*****************************************************************************/
10056 /*****************************************************************************/
10060 /*****************************************************************************
10062 * Display the instruction name
10064 void emitter::emitDispInst(instruction ins)
10066 const char* insstr = codeGen->genInsName(ins);
10067 size_t len = strlen(insstr);
10069 /* Display the instruction name */
10071 printf("%s", insstr);
10074 // Add at least one space after the instruction name
10075 // and add spaces until we have reach the normal size of 8
10083 /*****************************************************************************
10085 * Display an reloc value
10086 * If we are formatting for an assembly listing don't print the hex value
10087 * since it will prevent us from doing assembly diffs
10089 void emitter::emitDispReloc(int value, bool addComma)
10091 if (emitComp->opts.disAsm)
10097 printf("(reloc 0x%x)", dspPtr(value));
10104 /*****************************************************************************
10106 * Display an immediate value
10108 void emitter::emitDispImm(ssize_t imm, bool addComma, bool alwaysHex /* =false */)
10115 // Munge any pointers if we want diff-able disassembly.
10116 // Since some may be emitted as partial words, print as diffable anything that has
10117 // significant bits beyond the lowest 8-bits.
10118 if (emitComp->opts.disDiffable)
10120 ssize_t top56bits = (imm >> 8);
10121 if ((top56bits != 0) && (top56bits != -1))
10125 if (!alwaysHex && (imm > -1000) && (imm < 1000))
10131 if ((imm < 0) && ((imm & 0xFFFFFFFF00000000LL) == 0xFFFFFFFF00000000LL))
10137 if ((imm & 0xFFFFFFFF00000000LL) != 0)
10139 printf("0x%llx", imm);
10143 printf("0x%02x", imm);
10151 /*****************************************************************************
10153 * Display a float zero constant
10155 void emitter::emitDispFloatZero()
10164 /*****************************************************************************
10166 * Display an encoded float constant value
10168 void emitter::emitDispFloatImm(ssize_t imm8)
10170 assert((0 <= imm8) && (imm8 <= 0x0ff));
10177 fpImm.immFPIVal = (unsigned)imm8;
10178 double result = emitDecodeFloatImm8(fpImm);
10180 printf("%.4f", result);
10183 /*****************************************************************************
10185 * Display an immediate that is optionally LSL12.
10187 void emitter::emitDispImmOptsLSL12(ssize_t imm, insOpts opt)
10189 if (!strictArmAsm && insOptsLSL12(opt))
10193 emitDispImm(imm, false);
10194 if (strictArmAsm && insOptsLSL12(opt))
10196 printf(", LSL #12");
10200 /*****************************************************************************
10202 * Display an ARM64 condition code for the conditional instructions
10204 void emitter::emitDispCond(insCond cond)
10206 const static char* armCond[16] = {"eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc",
10207 "hi", "ls", "ge", "lt", "gt", "le", "AL", "NV"}; // The last two are invalid
10208 unsigned imm = (unsigned)cond;
10209 assert((0 <= imm) && (imm < ArrLen(armCond)));
10210 printf(armCond[imm]);
10213 /*****************************************************************************
10215 * Display an ARM64 flags for the conditional instructions
10217 void emitter::emitDispFlags(insCflags flags)
10219 const static char* armFlags[16] = {"0", "v", "c", "cv", "z", "zv", "zc", "zcv",
10220 "n", "nv", "nc", "ncv", "nz", "nzv", "nzc", "nzcv"};
10221 unsigned imm = (unsigned)flags;
10222 assert((0 <= imm) && (imm < ArrLen(armFlags)));
10223 printf(armFlags[imm]);
10226 /*****************************************************************************
10228 * Display an ARM64 'barrier' for the memory barrier instructions
10230 void emitter::emitDispBarrier(insBarrier barrier)
10232 const static char* armBarriers[16] = {"#0", "oshld", "oshst", "osh", "#4", "nshld", "nshst", "nsh",
10233 "#8", "ishld", "ishst", "ish", "#12", "ld", "st", "sy"};
10234 unsigned imm = (unsigned)barrier;
10235 assert((0 <= imm) && (imm < ArrLen(armBarriers)));
10236 printf(armBarriers[imm]);
10239 /*****************************************************************************
10241 * Prints the encoding for the Shift Type encoding
10244 void emitter::emitDispShiftOpts(insOpts opt)
10246 if (opt == INS_OPTS_LSL)
10248 else if (opt == INS_OPTS_LSR)
10250 else if (opt == INS_OPTS_ASR)
10252 else if (opt == INS_OPTS_ROR)
10254 else if (opt == INS_OPTS_MSL)
10257 assert(!"Bad value");
10260 /*****************************************************************************
10262 * Prints the encoding for the Extend Type encoding
10265 void emitter::emitDispExtendOpts(insOpts opt)
10267 if (opt == INS_OPTS_UXTB)
10269 else if (opt == INS_OPTS_UXTH)
10271 else if (opt == INS_OPTS_UXTW)
10273 else if (opt == INS_OPTS_UXTX)
10275 else if (opt == INS_OPTS_SXTB)
10277 else if (opt == INS_OPTS_SXTH)
10279 else if (opt == INS_OPTS_SXTW)
10281 else if (opt == INS_OPTS_SXTX)
10284 assert(!"Bad value");
10287 /*****************************************************************************
10289 * Prints the encoding for the Extend Type encoding in loads/stores
10292 void emitter::emitDispLSExtendOpts(insOpts opt)
10294 if (opt == INS_OPTS_LSL)
10296 else if (opt == INS_OPTS_UXTW)
10298 else if (opt == INS_OPTS_UXTX)
10300 else if (opt == INS_OPTS_SXTW)
10302 else if (opt == INS_OPTS_SXTX)
10305 assert(!"Bad value");
10308 /*****************************************************************************
10310 * Display a register
10312 void emitter::emitDispReg(regNumber reg, emitAttr attr, bool addComma)
10314 emitAttr size = EA_SIZE(attr);
10315 printf(emitRegName(reg, size));
10321 /*****************************************************************************
10323 * Display a vector register with an arrangement suffix
10325 void emitter::emitDispVectorReg(regNumber reg, insOpts opt, bool addComma)
10327 assert(isVectorRegister(reg));
10328 printf(emitVectorRegName(reg));
10329 emitDispArrangement(opt);
10335 /*****************************************************************************
10337 * Display an vector register index suffix
10339 void emitter::emitDispVectorRegIndex(regNumber reg, emitAttr elemsize, ssize_t index, bool addComma)
10341 assert(isVectorRegister(reg));
10342 printf(emitVectorRegName(reg));
10359 assert(!"invalid elemsize");
10363 printf("[%d]", index);
10369 /*****************************************************************************
10371 * Display an arrangement suffix
10373 void emitter::emitDispArrangement(insOpts opt)
10375 const char* str = "???";
10405 assert(!"Invalid insOpt for vector register");
10411 /*****************************************************************************
10413 * Display a register with an optional shift operation
10415 void emitter::emitDispShiftedReg(regNumber reg, insOpts opt, ssize_t imm, emitAttr attr)
10417 emitAttr size = EA_SIZE(attr);
10418 assert((imm & 0x003F) == imm);
10419 assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
10421 printf(emitRegName(reg, size));
10429 emitDispShiftOpts(opt);
10430 emitDispImm(imm, false);
10434 /*****************************************************************************
10436 * Display a register with an optional extend and scale operations
10438 void emitter::emitDispExtendReg(regNumber reg, insOpts opt, ssize_t imm)
10440 assert((imm >= 0) && (imm <= 4));
10441 assert(insOptsNone(opt) || insOptsAnyExtend(opt) || (opt == INS_OPTS_LSL));
10443 // size is based on the extend option, not the instr size.
10444 emitAttr size = insOpts32BitExtend(opt) ? EA_4BYTE : EA_8BYTE;
10448 if (insOptsNone(opt))
10450 emitDispReg(reg, size, false);
10454 emitDispReg(reg, size, true);
10455 if (opt == INS_OPTS_LSL)
10458 emitDispExtendOpts(opt);
10459 if ((imm > 0) || (opt == INS_OPTS_LSL))
10462 emitDispImm(imm, false);
10466 else // !strictArmAsm
10468 if (insOptsNone(opt))
10470 emitDispReg(reg, size, false);
10474 if (opt != INS_OPTS_LSL)
10476 emitDispExtendOpts(opt);
10478 emitDispReg(reg, size, false);
10485 emitDispImm(1 << imm, false);
10490 /*****************************************************************************
10492 * Display an addressing operand [reg + imm]
10494 void emitter::emitDispAddrRI(regNumber reg, insOpts opt, ssize_t imm)
10496 reg = encodingZRtoSP(reg); // ZR (R31) encodes the SP register
10502 emitDispReg(reg, EA_8BYTE, false);
10504 if (!insOptsPostIndex(opt) && (imm != 0))
10507 emitDispImm(imm, false);
10511 if (insOptsPreIndex(opt))
10515 else if (insOptsPostIndex(opt))
10518 emitDispImm(imm, false);
10521 else // !strictArmAsm
10525 const char* operStr = "++";
10532 if (insOptsPreIndex(opt))
10537 emitDispReg(reg, EA_8BYTE, false);
10539 if (insOptsPostIndex(opt))
10544 if (insOptsIndexed(opt))
10550 printf("%c", operStr[1]);
10552 emitDispImm(imm, false);
10557 /*****************************************************************************
10559 * Display an addressing operand [reg + extended reg]
10561 void emitter::emitDispAddrRRExt(regNumber reg1, regNumber reg2, insOpts opt, bool isScaled, emitAttr size)
10563 reg1 = encodingZRtoSP(reg1); // ZR (R31) encodes the SP register
10565 unsigned scale = 0;
10568 scale = NaturalScale_helper(size);
10575 emitDispReg(reg1, EA_8BYTE, true);
10576 emitDispExtendReg(reg2, opt, scale);
10578 else // !strictArmAsm
10580 emitDispReg(reg1, EA_8BYTE, false);
10582 emitDispExtendReg(reg2, opt, scale);
10588 /*****************************************************************************
10590 * Display (optionally) the instruction encoding in hex
10593 void emitter::emitDispInsHex(BYTE* code, size_t sz)
10595 // We do not display the instruction hex if we want diff-able disassembly
10596 if (!emitComp->opts.disDiffable)
10600 printf(" %08X ", (*((code_t*)code)));
10609 /****************************************************************************
10611 * Display the given instruction.
10614 void emitter::emitDispIns(
10615 instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* pCode, size_t sz, insGroup* ig)
10620 id->idDebugOnlyInfo()->idNum; // Do not remove this! It is needed for VisualStudio conditional breakpoints
10622 printf("IN%04x: ", idNum);
10628 if (!emitComp->opts.dspEmit && !isNew && !asmfm && sz)
10631 /* Display the instruction offset */
10633 emitDispInsOffs(offset, doffs);
10635 /* Display the instruction hex code */
10637 emitDispInsHex(pCode, sz);
10641 /* Get the instruction and format */
10643 instruction ins = id->idIns();
10644 insFormat fmt = id->idInsFmt();
10648 /* If this instruction has just been added, check its size */
10650 assert(isNew == false || (int)emitSizeOfInsDsc(id) == emitCurIGfreeNext - (BYTE*)id);
10652 /* Figure out the operand size */
10653 emitAttr size = id->idOpSize();
10654 emitAttr attr = size;
10655 if (id->idGCref() == GCT_GCREF)
10657 else if (id->idGCref() == GCT_BYREF)
10665 bool isExtendAlias;
10674 const char* methodName;
10682 case IF_BI_0A: // BI_0A ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
10683 case IF_BI_0B: // BI_0B ......iiiiiiiiii iiiiiiiiiii..... simm19:00
10686 if (fmt == IF_LARGEJMP)
10688 printf("(LARGEJMP)");
10690 if (id->idAddr()->iiaHasInstrCount())
10692 int instrCount = id->idAddr()->iiaGetInstrCount();
10696 printf("pc%s%d instructions", (instrCount >= 0) ? "+" : "", instrCount);
10700 unsigned insNum = emitFindInsNum(ig, id);
10701 UNATIVE_OFFSET srcOffs = ig->igOffs + emitFindOffset(ig, insNum + 1);
10702 UNATIVE_OFFSET dstOffs = ig->igOffs + emitFindOffset(ig, insNum + 1 + instrCount);
10703 ssize_t relOffs = (ssize_t)(emitOffsetToPtr(dstOffs) - emitOffsetToPtr(srcOffs));
10704 printf("pc%s%d (%d instructions)", (relOffs >= 0) ? "+" : "", relOffs, instrCount);
10707 else 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);
10718 case IF_BI_0C: // BI_0C ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
10719 if (id->idIsCallAddr())
10721 offs = (ssize_t)id->idAddr()->iiaAddr;
10727 methodName = emitComp->eeGetMethodFullName((CORINFO_METHOD_HANDLE)id->idDebugOnlyInfo()->idMemCookie);
10732 if (id->idIsDspReloc())
10734 printf("%08X", offs);
10738 printf("%s", methodName);
10742 case IF_BI_1A: // BI_1A ......iiiiiiiiii iiiiiiiiiiittttt Rt simm19:00
10743 assert(insOptsNone(id->idInsOpt()));
10744 emitDispReg(id->idReg1(), size, true);
10745 if (id->idIsBound())
10747 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10751 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10755 case IF_BI_1B: // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
10756 assert(insOptsNone(id->idInsOpt()));
10757 emitDispReg(id->idReg1(), size, true);
10758 emitDispImm(emitGetInsSC(id), true);
10759 if (id->idIsBound())
10761 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10765 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10769 case IF_BR_1A: // BR_1A ................ ......nnnnn..... Rn
10770 assert(insOptsNone(id->idInsOpt()));
10771 emitDispReg(id->idReg1(), size, false);
10774 case IF_BR_1B: // BR_1B ................ ......nnnnn..... Rn
10775 assert(insOptsNone(id->idInsOpt()));
10776 emitDispReg(id->idReg3(), size, false);
10779 case IF_LS_1A: // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB)
10780 case IF_DI_1E: // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
10783 assert(insOptsNone(id->idInsOpt()));
10784 emitDispReg(id->idReg1(), size, true);
10785 imm = emitGetInsSC(id);
10787 /* Is this actually a reference to a data section? */
10788 if (fmt == IF_LARGEADR)
10790 printf("(LARGEADR)");
10792 else if (fmt == IF_LARGELDC)
10794 printf("(LARGELDC)");
10798 if (id->idAddr()->iiaIsJitDataOffset())
10800 doffs = Compiler::eeGetJitDataOffs(id->idAddr()->iiaFieldHnd);
10801 /* Display a data section reference */
10804 printf("@CNS%02u", doffs - 1);
10806 printf("@RWD%02u", doffs);
10809 printf("%+Id", imm);
10814 if (id->idIsReloc())
10817 emitDispImm((ssize_t)id->idAddr()->iiaAddr, false);
10819 else if (id->idIsBound())
10821 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10825 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10831 case IF_LS_2A: // LS_2A .X.......X...... ......nnnnnttttt Rt Rn
10832 assert(insOptsNone(id->idInsOpt()));
10833 assert(emitGetInsSC(id) == 0);
10834 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10835 emitDispAddrRI(id->idReg2(), id->idInsOpt(), 0);
10838 case IF_LS_2B: // LS_2B .X.......Xiiiiii iiiiiinnnnnttttt Rt Rn imm(0-4095)
10839 assert(insOptsNone(id->idInsOpt()));
10840 imm = emitGetInsSC(id);
10841 scale = NaturalScale_helper(emitInsLoadStoreSize(id));
10842 imm <<= scale; // The immediate is scaled by the size of the ld/st
10843 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10844 emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
10847 case IF_LS_2C: // LS_2C .X.......X.iiiii iiiiPPnnnnnttttt Rt Rn imm(-256..+255) no/pre/post inc
10848 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
10849 imm = emitGetInsSC(id);
10850 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10851 emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
10854 case IF_LS_3A: // LS_3A .X.......X.mmmmm oooS..nnnnnttttt Rt Rn Rm ext(Rm) LSL {}
10855 assert(insOptsLSExtend(id->idInsOpt()));
10856 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10857 if (id->idIsLclVar())
10859 emitDispAddrRRExt(id->idReg2(), codeGen->rsGetRsvdReg(), id->idInsOpt(), false, size);
10863 emitDispAddrRRExt(id->idReg2(), id->idReg3(), id->idInsOpt(), id->idReg3Scaled(), size);
10867 case IF_LS_3B: // LS_3B X............... .aaaaannnnnddddd Rt Ra Rn
10868 assert(insOptsNone(id->idInsOpt()));
10869 assert(emitGetInsSC(id) == 0);
10870 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10871 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10872 emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
10875 case IF_LS_3C: // LS_3C X.........iiiiii iaaaaannnnnddddd Rt Ra Rn imm(im7,sh)
10876 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
10877 imm = emitGetInsSC(id);
10878 scale = NaturalScale_helper(emitInsLoadStoreSize(id));
10880 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10881 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10882 emitDispAddrRI(id->idReg3(), id->idInsOpt(), imm);
10885 case IF_LS_3D: // LS_3D .X.......X.mmmmm ......nnnnnttttt Wm Rt Rn
10886 assert(insOptsNone(id->idInsOpt()));
10887 emitDispReg(id->idReg1(), EA_4BYTE, true);
10888 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10889 emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
10892 case IF_DI_1A: // DI_1A X.......shiiiiii iiiiiinnnnn..... Rn imm(i12,sh)
10893 emitDispReg(id->idReg1(), size, true);
10894 emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
10897 case IF_DI_1B: // DI_1B X........hwiiiii iiiiiiiiiiiddddd Rd imm(i16,hw)
10898 emitDispReg(id->idReg1(), size, true);
10899 hwi.immHWVal = (unsigned)emitGetInsSC(id);
10900 if (ins == INS_mov)
10902 emitDispImm(emitDecodeHalfwordImm(hwi, size), false);
10904 else // movz, movn, movk
10906 emitDispImm(hwi.immVal, false);
10907 if (hwi.immHW != 0)
10909 emitDispShiftOpts(INS_OPTS_LSL);
10910 emitDispImm(hwi.immHW * 16, false);
10915 case IF_DI_1C: // DI_1C X........Nrrrrrr ssssssnnnnn..... Rn imm(N,r,s)
10916 emitDispReg(id->idReg1(), size, true);
10917 bmi.immNRS = (unsigned)emitGetInsSC(id);
10918 emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
10921 case IF_DI_1D: // DI_1D X........Nrrrrrr ssssss.....ddddd Rd imm(N,r,s)
10922 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
10923 bmi.immNRS = (unsigned)emitGetInsSC(id);
10924 emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
10927 case IF_DI_2A: // DI_2A X.......shiiiiii iiiiiinnnnnddddd Rd Rn imm(i12,sh)
10928 if ((ins == INS_add) || (ins == INS_sub))
10930 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
10931 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
10935 emitDispReg(id->idReg1(), size, true);
10936 emitDispReg(id->idReg2(), size, true);
10938 emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
10941 case IF_DI_2B: // DI_2B X........X.nnnnn ssssssnnnnnddddd Rd Rn imm(0-63)
10942 emitDispReg(id->idReg1(), size, true);
10943 emitDispReg(id->idReg2(), size, true);
10944 emitDispImm(emitGetInsSC(id), false);
10947 case IF_DI_2C: // DI_2C X........Nrrrrrr ssssssnnnnnddddd Rd Rn imm(N,r,s)
10948 if (ins == INS_ands)
10950 emitDispReg(id->idReg1(), size, true);
10954 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
10956 emitDispReg(id->idReg2(), size, true);
10957 bmi.immNRS = (unsigned)emitGetInsSC(id);
10958 emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
10961 case IF_DI_2D: // DI_2D X........Nrrrrrr ssssssnnnnnddddd Rd Rn imr, ims (N,r,s)
10962 emitDispReg(id->idReg1(), size, true);
10963 emitDispReg(id->idReg2(), size, true);
10965 imm = emitGetInsSC(id);
10966 bmi.immNRS = (unsigned)imm;
10973 emitDispImm(bmi.immR, true);
10974 emitDispImm(bmi.immS, false);
10980 emitDispImm(getBitWidth(size) - bmi.immR, true);
10981 emitDispImm(bmi.immS + 1, false);
10987 emitDispImm(bmi.immR, true);
10988 emitDispImm(bmi.immS - bmi.immR + 1, false);
10994 emitDispImm(imm, false);
10998 assert(!"Unexpected instruction in IF_DI_2D");
11003 case IF_DI_1F: // DI_1F X..........iiiii cccc..nnnnn.nzcv Rn imm5 nzcv cond
11004 emitDispReg(id->idReg1(), size, true);
11005 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11006 emitDispImm(cfi.imm5, true);
11007 emitDispFlags(cfi.flags);
11009 emitDispCond(cfi.cond);
11012 case IF_DR_1D: // DR_1D X............... cccc.......mmmmm Rd cond
11013 emitDispReg(id->idReg1(), size, true);
11014 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11015 emitDispCond(cfi.cond);
11018 case IF_DR_2A: // DR_2A X..........mmmmm ......nnnnn..... Rn Rm
11019 emitDispReg(id->idReg1(), size, true);
11020 emitDispReg(id->idReg2(), size, false);
11023 case IF_DR_2B: // DR_2B X.......sh.mmmmm ssssssnnnnn..... Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
11024 emitDispReg(id->idReg1(), size, true);
11025 emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
11028 case IF_DR_2C: // DR_2C X..........mmmmm ooosssnnnnn..... Rn Rm ext(Rm) LSL imm(0-4)
11029 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11030 imm = emitGetInsSC(id);
11031 emitDispExtendReg(id->idReg2(), id->idInsOpt(), imm);
11034 case IF_DR_2D: // DR_2D X..........nnnnn cccc..nnnnnddddd Rd Rn cond
11035 emitDispReg(id->idReg1(), size, true);
11036 emitDispReg(id->idReg2(), size, true);
11037 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11038 emitDispCond(cfi.cond);
11041 case IF_DR_2E: // DR_2E X..........mmmmm ...........ddddd Rd Rm
11042 emitDispReg(id->idReg1(), size, true);
11043 emitDispReg(id->idReg2(), size, false);
11046 case IF_DR_2F: // DR_2F X.......sh.mmmmm ssssss.....ddddd Rd Rm {LSL,LSR,ASR} imm(0-63)
11047 emitDispReg(id->idReg1(), size, true);
11048 emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
11051 case IF_DR_2G: // DR_2G X............... ......nnnnnddddd Rd Rn
11052 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11053 emitDispReg(encodingZRtoSP(id->idReg2()), size, false);
11056 case IF_DR_2H: // DR_2H X........X...... ......nnnnnddddd Rd Rn
11057 emitDispReg(id->idReg1(), size, true);
11058 emitDispReg(id->idReg2(), size, false);
11061 case IF_DR_2I: // DR_2I X..........mmmmm cccc..nnnnn.nzcv Rn Rm nzcv cond
11062 emitDispReg(id->idReg1(), size, true);
11063 emitDispReg(id->idReg2(), size, true);
11064 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11065 emitDispFlags(cfi.flags);
11067 emitDispCond(cfi.cond);
11070 case IF_DR_3A: // DR_3A X..........mmmmm ......nnnnnmmmmm Rd Rn Rm
11071 if ((ins == INS_add) || (ins == INS_sub))
11073 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11074 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11076 else if ((ins == INS_smull) || (ins == INS_smulh))
11078 // Rd is always 8 bytes
11079 emitDispReg(id->idReg1(), EA_8BYTE, true);
11081 // Rn, Rm effective size depends on instruction type
11082 size = (ins == INS_smulh) ? EA_8BYTE : EA_4BYTE;
11083 emitDispReg(id->idReg2(), size, true);
11087 emitDispReg(id->idReg1(), size, true);
11088 emitDispReg(id->idReg2(), size, true);
11090 if (id->idIsLclVar())
11092 emitDispReg(codeGen->rsGetRsvdReg(), size, false);
11096 emitDispReg(id->idReg3(), size, false);
11101 case IF_DR_3B: // DR_3B X.......sh.mmmmm ssssssnnnnnddddd Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
11102 emitDispReg(id->idReg1(), size, true);
11103 emitDispReg(id->idReg2(), size, true);
11104 emitDispShiftedReg(id->idReg3(), id->idInsOpt(), emitGetInsSC(id), size);
11107 case IF_DR_3C: // DR_3C X..........mmmmm ooosssnnnnnddddd Rd Rn Rm ext(Rm) LSL imm(0-4)
11108 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11109 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11110 imm = emitGetInsSC(id);
11111 emitDispExtendReg(id->idReg3(), id->idInsOpt(), imm);
11114 case IF_DR_3D: // DR_3D X..........mmmmm cccc..nnnnnmmmmm Rd Rn Rm cond
11115 emitDispReg(id->idReg1(), size, true);
11116 emitDispReg(id->idReg2(), size, true);
11117 emitDispReg(id->idReg3(), size, true);
11118 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11119 emitDispCond(cfi.cond);
11122 case IF_DR_3E: // DR_3E X........X.mmmmm ssssssnnnnnddddd Rd Rn Rm imm(0-63)
11123 emitDispReg(id->idReg1(), size, true);
11124 emitDispReg(id->idReg2(), size, true);
11125 emitDispReg(id->idReg3(), size, true);
11126 emitDispImm(emitGetInsSC(id), false);
11129 case IF_DR_4A: // DR_4A X..........mmmmm .aaaaannnnnmmmmm Rd Rn Rm Ra
11130 emitDispReg(id->idReg1(), size, true);
11131 emitDispReg(id->idReg2(), size, true);
11132 emitDispReg(id->idReg3(), size, true);
11133 emitDispReg(id->idReg4(), size, false);
11136 case IF_DV_1A: // DV_1A .........X.iiiii iii........ddddd Vd imm8 (fmov - immediate scalar)
11137 elemsize = id->idOpSize();
11138 emitDispReg(id->idReg1(), elemsize, true);
11139 emitDispFloatImm(emitGetInsSC(id));
11142 case IF_DV_1B: // DV_1B .QX..........iii cmod..iiiiiddddd Vd imm8 (immediate vector)
11143 imm = emitGetInsSC(id) & 0x0ff;
11144 immShift = (emitGetInsSC(id) & 0x700) >> 8;
11145 hasShift = (immShift != 0);
11146 elemsize = optGetElemsize(id->idInsOpt());
11147 if (id->idInsOpt() == INS_OPTS_1D)
11149 assert(elemsize == size);
11150 emitDispReg(id->idReg1(), size, true);
11154 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11156 if (ins == INS_fmov)
11158 emitDispFloatImm(imm);
11159 assert(hasShift == false);
11163 if (elemsize == EA_8BYTE)
11165 assert(ins == INS_movi);
11167 const ssize_t mask8 = 0xFF;
11168 for (unsigned b = 0; b < 8; b++)
11170 if (imm & (1 << b))
11172 imm64 |= (mask8 << (b * 8));
11175 emitDispImm(imm64, hasShift, true);
11179 emitDispImm(imm, hasShift, true);
11183 insOpts opt = (immShift & 0x4) ? INS_OPTS_MSL : INS_OPTS_LSL;
11184 unsigned shift = (immShift & 0x3) * 8;
11185 emitDispShiftOpts(opt);
11186 emitDispImm(shift, false);
11191 case IF_DV_1C: // DV_1C .........X...... ......nnnnn..... Vn #0.0 (fcmp - with zero)
11192 elemsize = id->idOpSize();
11193 emitDispReg(id->idReg1(), elemsize, true);
11194 emitDispFloatZero();
11197 case IF_DV_2A: // DV_2A .Q.......X...... ......nnnnnddddd Vd Vn (fabs, fcvt - vector)
11198 case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
11199 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11200 emitDispVectorReg(id->idReg2(), id->idInsOpt(), false);
11203 case IF_DV_2N: // DV_2N .........iiiiiii ......nnnnnddddd Vd Vn imm (shift - scalar)
11204 elemsize = id->idOpSize();
11205 emitDispReg(id->idReg1(), elemsize, true);
11206 emitDispReg(id->idReg2(), elemsize, true);
11207 emitDispImm(emitGetInsSC(id), false);
11210 case IF_DV_2O: // DV_2O .Q.......iiiiiii ......nnnnnddddd Vd Vn imm (shift - vector)
11211 imm = emitGetInsSC(id);
11212 // Do we have a sxtl or uxtl instruction?
11213 isExtendAlias = ((ins == INS_sxtl) || (ins == INS_sxtl2) || (ins == INS_uxtl) || (ins == INS_uxtl2));
11214 code = emitInsCode(ins, fmt);
11215 if (code & 0x00008000) // widen/narrow opcodes
11217 if (code & 0x00002000) // SHL opcodes
11219 emitDispVectorReg(id->idReg1(), optWidenElemsize(id->idInsOpt()), true);
11220 emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11222 else // SHR opcodes
11224 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11225 emitDispVectorReg(id->idReg2(), optWidenElemsize(id->idInsOpt()), !isExtendAlias);
11230 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11231 emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11233 // Print the immediate unless we have a sxtl or uxtl instruction
11234 if (!isExtendAlias)
11236 emitDispImm(imm, false);
11240 case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov/smov - to general)
11241 srcsize = id->idOpSize();
11242 index = emitGetInsSC(id);
11243 if (ins == INS_smov)
11245 dstsize = EA_8BYTE;
11247 else // INS_umov or INS_mov
11249 dstsize = (srcsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE;
11251 emitDispReg(id->idReg1(), dstsize, true);
11252 emitDispVectorRegIndex(id->idReg2(), srcsize, index, false);
11255 case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
11256 if (ins == INS_dup)
11258 datasize = id->idOpSize();
11259 assert(isValidVectorDatasize(datasize));
11260 assert(isValidArrangement(datasize, id->idInsOpt()));
11261 elemsize = optGetElemsize(id->idInsOpt());
11262 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11266 elemsize = id->idOpSize();
11267 index = emitGetInsSC(id);
11268 assert(isValidVectorElemsize(elemsize));
11269 emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11271 emitDispReg(id->idReg2(), (elemsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE, false);
11274 case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
11275 datasize = id->idOpSize();
11276 assert(isValidVectorDatasize(datasize));
11277 assert(isValidArrangement(datasize, id->idInsOpt()));
11278 elemsize = optGetElemsize(id->idInsOpt());
11279 index = emitGetInsSC(id);
11280 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11281 emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11284 case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
11285 elemsize = id->idOpSize();
11286 index = emitGetInsSC(id);
11287 emitDispReg(id->idReg1(), elemsize, true);
11288 emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11291 case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
11292 imm = emitGetInsSC(id);
11293 index = (imm >> 4) & 0xf;
11294 index2 = imm & 0xf;
11295 elemsize = id->idOpSize();
11296 emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11297 emitDispVectorRegIndex(id->idReg2(), elemsize, index2, false);
11300 case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov, fcvtXX - register)
11301 case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
11302 case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
11303 elemsize = id->idOpSize();
11304 emitDispReg(id->idReg1(), elemsize, true);
11305 emitDispReg(id->idReg2(), elemsize, false);
11308 case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov, fcvtXX - to general)
11309 case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov, Xcvtf - from general)
11310 case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
11311 dstsize = optGetDstsize(id->idInsOpt());
11312 srcsize = optGetSrcsize(id->idInsOpt());
11314 emitDispReg(id->idReg1(), dstsize, true);
11315 emitDispReg(id->idReg2(), srcsize, false);
11318 case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11319 case IF_DV_3B: // DV_3B .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11320 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11321 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11322 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11325 case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11326 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11327 if (ins != INS_mov)
11329 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11331 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11334 case IF_DV_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
11335 case IF_DV_3BI: // DV_3BI .Q........Lmmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
11336 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11337 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11338 elemsize = optGetElemsize(id->idInsOpt());
11339 emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11342 case IF_DV_3D: // DV_3D .........X.mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
11343 case IF_DV_3E: // DV_3E ...........mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
11344 emitDispReg(id->idReg1(), size, true);
11345 emitDispReg(id->idReg2(), size, true);
11346 emitDispReg(id->idReg3(), size, false);
11349 case IF_DV_3DI: // DV_3DI .........XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (scalar by elem)
11350 emitDispReg(id->idReg1(), size, true);
11351 emitDispReg(id->idReg2(), size, true);
11353 emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11356 case IF_DV_4A: // DV_4A .........X.mmmmm .aaaaannnnnddddd Vd Va Vn Vm (scalar)
11357 emitDispReg(id->idReg1(), size, true);
11358 emitDispReg(id->idReg2(), size, true);
11359 emitDispReg(id->idReg3(), size, true);
11360 emitDispReg(id->idReg4(), size, false);
11363 case IF_SN_0A: // SN_0A ................ ................
11366 case IF_SI_0A: // SI_0A ...........iiiii iiiiiiiiiii..... imm16
11367 emitDispImm(emitGetInsSC(id), false);
11370 case IF_SI_0B: // SI_0B ................ ....bbbb........ imm4 - barrier
11371 emitDispBarrier((insBarrier)emitGetInsSC(id));
11375 printf("unexpected format %s", emitIfName(id->idInsFmt()));
11376 assert(!"unexpectedFormat");
11380 if (id->idDebugOnlyInfo()->idVarRefOffs)
11383 emitDispFrameRef(id->idAddr()->iiaLclVar.lvaVarNum(), id->idAddr()->iiaLclVar.lvaOffset(),
11384 id->idDebugOnlyInfo()->idVarRefOffs, asmfm);
11390 /*****************************************************************************
11392 * Display a stack frame reference.
11395 void emitter::emitDispFrameRef(int varx, int disp, int offs, bool asmfm)
11400 printf("TEMP_%02u", -varx);
11402 emitComp->gtDispLclVar(+varx, false);
11405 printf("-0x%02x", -disp);
11407 printf("+0x%02x", +disp);
11411 if (varx >= 0 && emitComp->opts.varNames)
11414 const char* varName;
11416 assert((unsigned)varx < emitComp->lvaCount);
11417 varDsc = emitComp->lvaTable + varx;
11418 varName = emitComp->compLocalVarName(varx, offs);
11422 printf("'%s", varName);
11425 printf("-%d", -disp);
11427 printf("+%d", +disp);
11436 // Generate code for a load or store operation with a potentially complex addressing mode
11437 // This method handles the case of a GT_IND with contained GT_LEA op1 of the x86 form [base + index*sccale + offset]
11438 // Since Arm64 does not directly support this complex of an addressing mode
11439 // we may generates up to three instructions for this for Arm64
11441 void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataReg, GenTreeIndir* indir)
11443 emitAttr ldstAttr = isVectorRegister(dataReg) ? attr : emitInsAdjustLoadStoreAttr(ins, attr);
11445 GenTree* addr = indir->Addr();
11447 if (addr->isContained())
11449 assert(addr->OperGet() == GT_LCL_VAR_ADDR || addr->OperGet() == GT_LEA);
11454 if (addr->OperGet() == GT_LEA)
11456 offset = addr->AsAddrMode()->Offset();
11457 if (addr->AsAddrMode()->gtScale > 0)
11459 assert(isPow2(addr->AsAddrMode()->gtScale));
11460 BitScanForward(&lsl, addr->AsAddrMode()->gtScale);
11464 GenTree* memBase = indir->Base();
11466 if (indir->HasIndex())
11468 GenTree* index = indir->Index();
11472 regNumber tmpReg = indir->GetSingleTempReg();
11474 emitAttr addType = varTypeIsGC(memBase) ? EA_BYREF : EA_PTRSIZE;
11476 if (emitIns_valid_imm_for_add(offset, EA_8BYTE))
11480 // Generate code to set tmpReg = base + index*scale
11481 emitIns_R_R_R_I(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum, lsl,
11486 // Generate code to set tmpReg = base + index
11487 emitIns_R_R_R(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum);
11490 noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11492 // Then load/store dataReg from/to [tmpReg + offset]
11493 emitIns_R_R_I(ins, ldstAttr, dataReg, tmpReg, offset);
11495 else // large offset
11497 // First load/store tmpReg with the large offset constant
11498 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11499 // Then add the base register
11501 emitIns_R_R_R(INS_add, addType, tmpReg, tmpReg, memBase->gtRegNum);
11503 noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11504 noway_assert(tmpReg != index->gtRegNum);
11506 // Then load/store dataReg from/to [tmpReg + index*scale]
11507 emitIns_R_R_R_I(ins, ldstAttr, dataReg, tmpReg, index->gtRegNum, lsl, INS_OPTS_LSL);
11510 else // (offset == 0)
11514 // Then load/store dataReg from/to [memBase + index*scale]
11515 emitIns_R_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum, lsl, INS_OPTS_LSL);
11519 // Then load/store dataReg from/to [memBase + index]
11520 emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum);
11524 else // no Index register
11526 if (emitIns_valid_imm_for_ldst_offset(offset, EA_SIZE(attr)))
11528 // Then load/store dataReg from/to [memBase + offset]
11529 emitIns_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, offset);
11533 // We require a tmpReg to hold the offset
11534 regNumber tmpReg = indir->GetSingleTempReg();
11536 // First load/store tmpReg with the large offset constant
11537 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11539 // Then load/store dataReg from/to [memBase + tmpReg]
11540 emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, tmpReg);
11544 else // addr is not contained, so we evaluate it into a register
11546 // Then load/store dataReg from/to [addrReg]
11547 emitIns_R_R(ins, ldstAttr, dataReg, addr->gtRegNum);
11551 // The callee must call genConsumeReg() for any non-contained srcs
11552 // and genProduceReg() for any non-contained dsts.
11554 regNumber emitter::emitInsBinary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src)
11556 regNumber result = REG_NA;
11558 // dst can only be a reg
11559 assert(!dst->isContained());
11561 // src can be immed or reg
11562 assert(!src->isContained() || src->isContainedIntOrIImmed());
11564 // find immed (if any) - it cannot be a dst
11565 GenTreeIntConCommon* intConst = nullptr;
11566 if (src->isContainedIntOrIImmed())
11568 intConst = src->AsIntConCommon();
11573 emitIns_R_I(ins, attr, dst->gtRegNum, intConst->IconValue());
11574 return dst->gtRegNum;
11578 emitIns_R_R(ins, attr, dst->gtRegNum, src->gtRegNum);
11579 return dst->gtRegNum;
11583 // The callee must call genConsumeReg() for any non-contained srcs
11584 // and genProduceReg() for any non-contained dsts.
11586 regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src1, GenTree* src2)
11588 regNumber result = REG_NA;
11590 // dst can only be a reg
11591 assert(!dst->isContained());
11593 // find immed (if any) - it cannot be a dst
11594 // Only one src can be an int.
11595 GenTreeIntConCommon* intConst = nullptr;
11596 GenTree* nonIntReg = nullptr;
11598 if (varTypeIsFloating(dst))
11600 // src1 can only be a reg
11601 assert(!src1->isContained());
11602 // src2 can only be a reg
11603 assert(!src2->isContained());
11605 else // not floating point
11607 // src2 can be immed or reg
11608 assert(!src2->isContained() || src2->isContainedIntOrIImmed());
11610 // Check src2 first as we can always allow it to be a contained immediate
11611 if (src2->isContainedIntOrIImmed())
11613 intConst = src2->AsIntConCommon();
11616 // Only for commutative operations do we check src1 and allow it to be a contained immediate
11617 else if (dst->OperIsCommutative())
11619 // src1 can be immed or reg
11620 assert(!src1->isContained() || src1->isContainedIntOrIImmed());
11622 // Check src1 and allow it to be a contained immediate
11623 if (src1->isContainedIntOrIImmed())
11625 assert(!src2->isContainedIntOrIImmed());
11626 intConst = src1->AsIntConCommon();
11632 // src1 can only be a reg
11633 assert(!src1->isContained());
11637 bool isMulOverflow = false;
11638 if (dst->gtOverflowEx())
11640 if ((ins == INS_add) || (ins == INS_adds))
11644 else if ((ins == INS_sub) || (ins == INS_subs))
11648 else if (ins == INS_mul)
11650 isMulOverflow = true;
11651 assert(intConst == nullptr); // overflow format doesn't support an int constant operand
11655 assert(!"Invalid ins for overflow check");
11658 if (intConst != nullptr)
11660 emitIns_R_R_I(ins, attr, dst->gtRegNum, nonIntReg->gtRegNum, intConst->IconValue());
11666 regNumber extraReg = dst->GetSingleTempReg();
11667 assert(extraReg != dst->gtRegNum);
11669 if ((dst->gtFlags & GTF_UNSIGNED) != 0)
11671 if (attr == EA_4BYTE)
11673 // Compute 8 byte results from 4 byte by 4 byte multiplication.
11674 emitIns_R_R_R(INS_umull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11676 // Get the high result by shifting dst.
11677 emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11681 assert(attr == EA_8BYTE);
11682 // Compute the high result.
11683 emitIns_R_R_R(INS_umulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11685 // Now multiply without skewing the high result.
11686 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11689 // zero-sign bit comparison to detect overflow.
11690 emitIns_R_I(INS_cmp, attr, extraReg, 0);
11695 if (attr == EA_4BYTE)
11697 // Compute 8 byte results from 4 byte by 4 byte multiplication.
11698 emitIns_R_R_R(INS_smull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11700 // Get the high result by shifting dst.
11701 emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11707 assert(attr == EA_8BYTE);
11708 // Save the high result in a temporary register.
11709 emitIns_R_R_R(INS_smulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11711 // Now multiply without skewing the high result.
11712 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11717 // Sign bit comparison to detect overflow.
11718 emitIns_R_R_I(INS_cmp, attr, extraReg, dst->gtRegNum, bitShift, INS_OPTS_ASR);
11723 // We can just multiply.
11724 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11728 if (dst->gtOverflowEx())
11730 assert(!varTypeIsFloating(dst));
11731 codeGen->genCheckOverflow(dst);
11734 return dst->gtRegNum;
11737 #endif // defined(_TARGET_ARM64_)