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));
4231 } // end switch (ins)
4233 assert(fmt != IF_NONE);
4235 instrDesc* id = emitNewInstrSmall(attr);
4248 /*****************************************************************************
4250 * Add an instruction referencing a register and two constants.
4253 void emitter::emitIns_R_I_I(
4254 instruction ins, emitAttr attr, regNumber reg, ssize_t imm1, ssize_t imm2, insOpts opt /* = INS_OPTS_NONE */)
4256 emitAttr size = EA_SIZE(attr);
4257 insFormat fmt = IF_NONE;
4258 size_t immOut = 0; // composed from imm1 and imm2 and stored in the instrDesc
4260 /* Figure out the encoding format of the instruction */
4267 ins = INS_movz; // INS_mov with LSL is an alias for INS_movz LSL
4273 assert(isValidGeneralDatasize(size));
4274 assert(isGeneralRegister(reg));
4275 assert(isValidUimm16(imm1));
4276 assert(insOptsLSL(opt)); // Must be INS_OPTS_LSL
4278 if (size == EA_8BYTE)
4280 assert((imm2 == 0) || (imm2 == 16) || // shift amount: 0, 16, 32 or 48
4281 (imm2 == 32) || (imm2 == 48));
4285 assert((imm2 == 0) || (imm2 == 16)); // shift amount: 0 or 16
4320 immOut = hwi.immHWVal;
4321 assert(isValidImmHWVal(immOut, size));
4330 } // end switch (ins)
4332 assert(fmt != IF_NONE);
4334 instrDesc* id = emitNewInstrSC(attr, immOut);
4345 /*****************************************************************************
4347 * Add an instruction referencing two registers and a constant.
4350 void emitter::emitIns_R_R_I(
4351 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm, insOpts opt /* = INS_OPTS_NONE */)
4353 emitAttr size = EA_SIZE(attr);
4354 emitAttr elemsize = EA_UNKNOWN;
4355 insFormat fmt = IF_NONE;
4356 bool isLdSt = false;
4357 bool isSIMD = false;
4358 bool isAddSub = false;
4359 bool setFlags = false;
4361 bool unscaledOp = false;
4363 /* Figure out the encoding format of the instruction */
4370 // Check for the 'mov' aliases for the vector registers
4371 assert(insOptsNone(opt));
4372 assert(isValidVectorElemsize(size));
4374 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4376 if (isVectorRegister(reg1))
4378 if (isGeneralRegisterOrZR(reg2))
4380 fmt = IF_DV_2C; // Alias for 'ins'
4383 else if (isVectorRegister(reg2))
4385 fmt = IF_DV_2E; // Alias for 'dup'
4389 else // isGeneralRegister(reg1)
4391 assert(isGeneralRegister(reg1));
4392 if (isVectorRegister(reg2))
4394 fmt = IF_DV_2B; // Alias for 'umov'
4398 assert(!" invalid INS_mov operands");
4404 assert(insOptsNone(opt));
4405 assert(isValidGeneralDatasize(size));
4406 assert(isGeneralRegister(reg1));
4407 assert(isGeneralRegister(reg2));
4408 assert(isValidImmShift(imm, size));
4413 assert(insOptsNone(opt));
4414 assert(isValidGeneralDatasize(size));
4415 assert(isGeneralRegister(reg1));
4416 assert(isGeneralRegister(reg2));
4417 assert(isValidImmShift(imm, size));
4432 assert(isVectorRegister(reg1));
4433 assert(isVectorRegister(reg2));
4434 if (insOptsAnyArrangement(opt))
4437 assert(isValidVectorDatasize(size));
4438 assert(isValidArrangement(size, opt));
4439 elemsize = optGetElemsize(opt);
4440 assert(isValidVectorElemsize(elemsize));
4441 assert(isValidImmShift(imm, elemsize));
4442 assert(opt != INS_OPTS_1D); // Reserved encoding
4449 assert(insOptsNone(opt));
4450 assert(size == EA_8BYTE); // only supported size
4451 assert(isValidImmShift(imm, size));
4465 assert(isVectorRegister(reg1));
4466 assert(isVectorRegister(reg2));
4468 assert(size == EA_8BYTE);
4469 assert(isValidArrangement(size, opt));
4470 elemsize = optGetElemsize(opt);
4471 assert(elemsize != EA_8BYTE); // Reserved encodings
4472 assert(isValidVectorElemsize(elemsize));
4473 assert(isValidImmShift(imm, elemsize));
4486 assert(isVectorRegister(reg1));
4487 assert(isVectorRegister(reg2));
4489 assert(size == EA_16BYTE);
4490 assert(isValidArrangement(size, opt));
4491 elemsize = optGetElemsize(opt);
4492 assert(elemsize != EA_8BYTE); // Reserved encodings
4493 assert(isValidVectorElemsize(elemsize));
4494 assert(isValidImmShift(imm, elemsize));
4501 assert(isValidGeneralDatasize(size));
4502 assert(isGeneralRegister(reg1));
4503 assert(isGeneralRegisterOrZR(reg2));
4507 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4515 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
4519 assert(insOptsAluShift(opt)); // a non-zero imm, must select shift kind, can't use ROR
4521 assert(isValidImmShift(imm, size));
4527 assert(isValidGeneralDatasize(size));
4528 assert(isGeneralRegisterOrZR(reg1));
4529 assert(isGeneralRegister(reg2));
4531 if (insOptsAnyShift(opt))
4533 assert(isValidImmShift(imm, size) && (imm != 0));
4538 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4546 assert(isValidGeneralDatasize(size));
4547 assert(isGeneralRegisterOrSP(reg1));
4548 assert(isGeneralRegister(reg2));
4550 reg1 = encodingSPtoZR(reg1);
4551 if (insOptsAnyExtend(opt))
4553 assert((imm >= 0) && (imm <= 4));
4559 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4565 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
4566 assert(isValidImmShift(imm, size));
4575 assert(insOptsNone(opt));
4576 assert(isGeneralRegister(reg2));
4577 if (ins == INS_ands)
4579 assert(isGeneralRegister(reg1));
4583 assert(isGeneralRegisterOrSP(reg1));
4584 reg1 = encodingSPtoZR(reg1);
4588 canEncode = canEncodeBitMaskImm(imm, size, &bmi);
4592 assert(isValidImmNRS(imm, size));
4597 case INS_dup: // by element, imm selects the element of reg2
4598 assert(isVectorRegister(reg1));
4599 if (isVectorRegister(reg2))
4601 if (insOptsAnyArrangement(opt))
4604 assert(isValidVectorDatasize(size));
4605 assert(isValidArrangement(size, opt));
4606 elemsize = optGetElemsize(opt);
4607 assert(isValidVectorElemsize(elemsize));
4608 assert(isValidVectorIndex(size, elemsize, imm));
4609 assert(opt != INS_OPTS_1D); // Reserved encoding
4616 assert(insOptsNone(opt));
4618 assert(isValidVectorElemsize(elemsize));
4619 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4626 case INS_ins: // (MOV from general)
4627 assert(insOptsNone(opt));
4628 assert(isValidVectorElemsize(size));
4629 assert(isVectorRegister(reg1));
4630 assert(isGeneralRegisterOrZR(reg2));
4632 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4636 case INS_umov: // (MOV to general)
4637 assert(insOptsNone(opt));
4638 assert(isValidVectorElemsize(size));
4639 assert(isGeneralRegister(reg1));
4640 assert(isVectorRegister(reg2));
4642 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4647 assert(insOptsNone(opt));
4648 assert(isValidVectorElemsize(size));
4649 assert(size != EA_8BYTE); // no encoding, use INS_umov
4650 assert(isGeneralRegister(reg1));
4651 assert(isVectorRegister(reg2));
4653 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4671 // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4672 assert(isValidGeneralDatasize(size));
4673 unscaledOp = (ins == INS_ldursb);
4680 // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4681 assert(isValidGeneralDatasize(size));
4682 unscaledOp = (ins == INS_ldursh);
4689 // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4690 assert(size == EA_8BYTE);
4691 unscaledOp = (ins == INS_ldursw);
4730 // Is the target a vector register?
4731 if (isVectorRegister(reg1))
4733 assert(isValidVectorLSDatasize(size));
4734 assert(isGeneralRegisterOrSP(reg2));
4739 assert(isValidGeneralDatasize(size));
4742 scale = NaturalScale_helper(size);
4748 // Is the target a vector register?
4749 if (isVectorRegister(reg1))
4751 assert(isValidVectorLSDatasize(size));
4752 assert(isGeneralRegisterOrSP(reg2));
4757 assert(isValidGeneralDatasize(size));
4768 } // end switch (ins)
4776 assert(isValidVectorLSDatasize(size));
4777 assert(isVectorRegister(reg1));
4778 assert((scale >= 0) && (scale <= 4));
4782 assert(isValidGeneralLSDatasize(size));
4783 assert(isGeneralRegisterOrZR(reg1));
4784 assert((scale >= 0) && (scale <= 3));
4787 assert(isGeneralRegisterOrSP(reg2));
4789 // Load/Store reserved encodings:
4790 if (insOptsIndexed(opt))
4792 assert(reg1 != reg2);
4795 reg2 = encodingSPtoZR(reg2);
4797 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
4800 assert(insOptsNone(opt)); // PRE/POST Index doesn't make sense with an immediate of zero
4804 else if (insOptsIndexed(opt) || unscaledOp || (imm < 0) || ((imm & mask) != 0))
4806 if ((imm >= -256) && (imm <= 255))
4812 assert(!"Instruction cannot be encoded: IF_LS_2C");
4817 assert(insOptsNone(opt));
4818 assert(!unscaledOp);
4820 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
4822 imm >>= scale; // The immediate is scaled by the size of the ld/st
4828 assert(!"Instruction cannot be encoded: IF_LS_2B");
4835 assert(insOptsNone(opt));
4837 if (setFlags) // Can't encode SP with setFlags
4839 assert(isGeneralRegister(reg1));
4840 assert(isGeneralRegister(reg2));
4844 assert(isGeneralRegisterOrSP(reg1));
4845 assert(isGeneralRegisterOrSP(reg2));
4847 // Is it just a mov?
4850 // Is the mov even necessary?
4853 emitIns_R_R(INS_mov, attr, reg1, reg2);
4858 reg1 = encodingSPtoZR(reg1);
4859 reg2 = encodingSPtoZR(reg2);
4862 if (unsigned_abs(imm) <= 0x0fff)
4866 ins = insReverse(ins);
4869 assert(isValidUimm12(imm));
4872 else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
4874 // Encoding will use a 12-bit left shift of the immediate
4875 opt = INS_OPTS_LSL12;
4878 ins = insReverse(ins);
4881 assert((imm & 0xfff) == 0);
4883 assert(isValidUimm12(imm));
4888 assert(!"Instruction cannot be encoded: IF_DI_2A");
4892 assert(fmt != IF_NONE);
4894 instrDesc* id = emitNewInstrSC(attr, imm);
4907 /*****************************************************************************
4909 * Add an instruction referencing two registers and a constant.
4910 * Also checks for a large immediate that needs a second instruction
4911 * and will load it in reg1
4913 * - Supports instructions: add, adds, sub, subs, and, ands, eor and orr
4914 * - Requires that reg1 is a general register and not SP or ZR
4915 * - Requires that reg1 != reg2
4917 void emitter::emitIns_R_R_Imm(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm)
4919 assert(isGeneralRegister(reg1));
4920 assert(reg1 != reg2);
4922 bool immFits = true;
4930 immFits = emitter::emitIns_valid_imm_for_add(imm, attr);
4937 immFits = emitter::emitIns_valid_imm_for_alu(imm, attr);
4941 assert(!"Unsupported instruction in emitIns_R_R_Imm");
4946 emitIns_R_R_I(ins, attr, reg1, reg2, imm);
4950 // Load 'imm' into the reg1 register
4951 // then issue: 'ins' reg1, reg2, reg1
4953 codeGen->instGen_Set_Reg_To_Imm(attr, reg1, imm);
4954 emitIns_R_R_R(ins, attr, reg1, reg2, reg1);
4958 /*****************************************************************************
4960 * Add an instruction referencing three registers.
4963 void emitter::emitIns_R_R_R(
4964 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insOpts opt) /* = INS_OPTS_NONE */
4966 emitAttr size = EA_SIZE(attr);
4967 emitAttr elemsize = EA_UNKNOWN;
4968 insFormat fmt = IF_NONE;
4970 /* Figure out the encoding format of the instruction */
4994 assert(insOptsNone(opt));
4995 assert(isValidGeneralDatasize(size));
4996 assert(isGeneralRegister(reg1));
4997 assert(isGeneralRegister(reg2));
4998 assert(isGeneralRegister(reg3));
5003 if (insOptsNone(opt))
5006 assert(isValidGeneralDatasize(size));
5007 assert(isGeneralRegister(reg1));
5008 assert(isGeneralRegister(reg2));
5009 assert(isGeneralRegister(reg3));
5018 assert(insOptsAnyArrangement(opt));
5019 assert(isVectorRegister(reg1));
5020 assert(isVectorRegister(reg2));
5021 assert(isVectorRegister(reg3));
5022 assert(isValidVectorDatasize(size));
5023 assert(isValidArrangement(size, opt));
5024 elemsize = optGetElemsize(opt);
5025 if (ins == INS_pmul)
5027 assert(elemsize == EA_1BYTE); // only supports 8B or 16B
5029 else // INS_mul, INS_mla, INS_mls
5031 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
5038 if (isVectorRegister(reg1))
5040 assert(isVectorRegister(reg2));
5041 assert(isVectorRegister(reg3));
5043 if (insOptsAnyArrangement(opt))
5046 assert(opt != INS_OPTS_1D); // Reserved encoding
5047 assert(isValidVectorDatasize(size));
5048 assert(isValidArrangement(size, opt));
5054 assert(insOptsNone(opt));
5055 assert(size == EA_8BYTE);
5064 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, INS_OPTS_NONE);
5073 assert(isVectorRegister(reg1));
5074 assert(isVectorRegister(reg2));
5075 assert(isVectorRegister(reg3));
5077 if (isValidVectorDatasize(size))
5080 assert(insOptsAnyArrangement(opt));
5081 assert(isValidArrangement(size, opt));
5082 elemsize = optGetElemsize(opt);
5089 assert(size == EA_8BYTE); // Only Double supported
5097 assert(isVectorRegister(reg1));
5098 assert(isVectorRegister(reg2));
5099 assert(isVectorRegister(reg3));
5101 if (isValidVectorDatasize(size))
5104 assert(insOptsAnyArrangement(opt));
5105 assert(isValidArrangement(size, opt));
5106 elemsize = optGetElemsize(opt);
5107 assert((elemsize == EA_8BYTE) || (elemsize == EA_4BYTE)); // Only Double/Float supported
5108 assert(opt != INS_OPTS_1D); // Reserved encoding
5115 assert((size == EA_8BYTE) || (size == EA_4BYTE)); // Only Double/Float supported
5128 assert(isVectorRegister(reg1));
5129 assert(isVectorRegister(reg2));
5130 assert(isVectorRegister(reg3));
5131 assert(insOptsAnyArrangement(opt));
5134 assert(isValidVectorDatasize(size));
5135 assert(isValidArrangement(size, opt));
5136 elemsize = optGetElemsize(opt);
5137 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
5143 assert(isVectorRegister(reg1));
5144 assert(isVectorRegister(reg2));
5145 assert(reg2 == reg3);
5146 assert(isValidVectorDatasize(size));
5147 // INS_mov is an alias for INS_orr (vector register)
5148 if (opt == INS_OPTS_NONE)
5150 elemsize = EA_1BYTE;
5151 opt = optMakeArrangement(size, elemsize);
5153 assert(isValidArrangement(size, opt));
5162 if (isVectorRegister(reg1))
5164 assert(isValidVectorDatasize(size));
5165 assert(isVectorRegister(reg2));
5166 assert(isVectorRegister(reg3));
5167 if (opt == INS_OPTS_NONE)
5169 elemsize = EA_1BYTE;
5170 opt = optMakeArrangement(size, elemsize);
5172 assert(isValidArrangement(size, opt));
5181 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, INS_OPTS_NONE);
5187 assert(isValidVectorDatasize(size));
5188 assert(isVectorRegister(reg1));
5189 assert(isVectorRegister(reg2));
5190 assert(isVectorRegister(reg3));
5191 if (opt == INS_OPTS_NONE)
5193 elemsize = EA_1BYTE;
5194 opt = optMakeArrangement(size, elemsize);
5196 assert(isValidArrangement(size, opt));
5208 assert(isVectorRegister(reg1));
5209 assert(isVectorRegister(reg2));
5210 assert(isVectorRegister(reg3));
5211 if (insOptsAnyArrangement(opt))
5214 assert(isValidVectorDatasize(size));
5215 assert(isValidArrangement(size, opt));
5216 elemsize = optGetElemsize(opt);
5217 assert(isValidVectorElemsizeFloat(elemsize));
5218 assert(opt != INS_OPTS_1D); // Reserved encoding
5224 assert(insOptsNone(opt));
5225 assert(isValidScalarDatasize(size));
5232 assert(insOptsNone(opt));
5233 assert(isVectorRegister(reg1));
5234 assert(isVectorRegister(reg2));
5235 assert(isVectorRegister(reg3));
5236 assert(isValidScalarDatasize(size));
5243 assert(isVectorRegister(reg1));
5244 assert(isVectorRegister(reg2));
5245 assert(isVectorRegister(reg3));
5246 assert(insOptsAnyArrangement(opt)); // no scalar encoding, use 4-operand 'fmadd' or 'fmsub'
5249 assert(isValidVectorDatasize(size));
5250 assert(isValidArrangement(size, opt));
5251 elemsize = optGetElemsize(opt);
5252 assert(isValidVectorElemsizeFloat(elemsize));
5253 assert(opt != INS_OPTS_1D); // Reserved encoding
5266 emitIns_R_R_R_Ext(ins, attr, reg1, reg2, reg3, opt);
5274 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0);
5283 assert(isGeneralRegisterOrZR(reg1));
5284 assert(isGeneralRegisterOrZR(reg2));
5285 assert(isGeneralRegisterOrSP(reg3));
5293 } // end switch (ins)
5295 assert(fmt != IF_NONE);
5297 instrDesc* id = emitNewInstr(attr);
5311 /*****************************************************************************
5313 * Add an instruction referencing three registers and a constant.
5316 void emitter::emitIns_R_R_R_I(instruction ins,
5322 insOpts opt /* = INS_OPTS_NONE */,
5323 emitAttr attrReg2 /* = EA_UNKNOWN */)
5325 emitAttr size = EA_SIZE(attr);
5326 emitAttr elemsize = EA_UNKNOWN;
5327 insFormat fmt = IF_NONE;
5328 bool isLdSt = false;
5329 bool isSIMD = false;
5330 bool isAddSub = false;
5331 bool setFlags = false;
5334 /* Figure out the encoding format of the instruction */
5338 assert(insOptsNone(opt));
5339 assert(isValidGeneralDatasize(size));
5340 assert(isGeneralRegister(reg1));
5341 assert(isGeneralRegister(reg2));
5342 assert(isGeneralRegister(reg3));
5343 assert(isValidImmShift(imm, size));
5355 assert(isValidGeneralDatasize(size));
5356 assert(isGeneralRegister(reg1));
5357 assert(isGeneralRegister(reg2));
5358 assert(isGeneralRegister(reg3));
5359 assert(isValidImmShift(imm, size));
5362 assert(insOptsNone(opt)); // a zero imm, means no shift kind
5367 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
5372 case INS_fmul: // by element, imm[0..3] selects the element of reg3
5376 assert(isVectorRegister(reg1));
5377 assert(isVectorRegister(reg2));
5378 assert(isVectorRegister(reg3));
5379 if (insOptsAnyArrangement(opt))
5382 assert(isValidVectorDatasize(size));
5383 assert(isValidArrangement(size, opt));
5384 elemsize = optGetElemsize(opt);
5385 assert(isValidVectorElemsizeFloat(elemsize));
5386 assert(isValidVectorIndex(size, elemsize, imm));
5387 assert(opt != INS_OPTS_1D); // Reserved encoding
5393 assert(insOptsNone(opt));
5394 assert(isValidScalarDatasize(size));
5396 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
5401 case INS_mul: // by element, imm[0..7] selects the element of reg3
5404 assert(isVectorRegister(reg1));
5405 assert(isVectorRegister(reg2));
5406 assert(isVectorRegister(reg3));
5408 assert(insOptsAnyArrangement(opt));
5409 assert(isValidVectorDatasize(size));
5410 assert(isValidArrangement(size, opt));
5411 elemsize = optGetElemsize(opt);
5412 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
5413 // Only has encodings for H or S elemsize
5414 assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE));
5415 // Only has encodings for V0..V15
5416 if ((elemsize == EA_2BYTE) && (reg3 >= REG_V16))
5418 noway_assert(!"Invalid reg3");
5442 assert(insOptsNone(opt)); // Can't use Pre/Post index on these two instructions
5447 // Is the target a vector register?
5448 if (isVectorRegister(reg1))
5450 scale = NaturalScale_helper(size);
5455 scale = (size == EA_8BYTE) ? 3 : 2;
5464 } // end switch (ins)
5469 assert(isGeneralRegisterOrSP(reg3));
5470 assert(insOptsNone(opt) || insOptsIndexed(opt));
5474 assert(isValidVectorLSPDatasize(size));
5475 assert(isVectorRegister(reg1));
5476 assert(isVectorRegister(reg2));
5477 assert((scale >= 2) && (scale <= 4));
5481 assert(isValidGeneralDatasize(size));
5482 assert(isGeneralRegisterOrZR(reg1));
5483 assert(isGeneralRegisterOrZR(reg2));
5484 assert((scale == 2) || (scale == 3));
5487 // Load/Store Pair reserved encodings:
5488 if (emitInsIsLoad(ins))
5490 assert(reg1 != reg2);
5492 if (insOptsIndexed(opt))
5494 assert(reg1 != reg3);
5495 assert(reg2 != reg3);
5498 reg3 = encodingSPtoZR(reg3);
5500 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
5503 assert(insOptsNone(opt)); // PRE/POST Index doesn't make sense with an immediate of zero
5509 if ((imm & mask) == 0)
5511 imm >>= scale; // The immediate is scaled by the size of the ld/st
5513 if ((imm >= -64) && (imm <= 63))
5519 if (fmt != IF_LS_3C)
5521 assert(!"Instruction cannot be encoded: IF_LS_3C");
5528 bool reg2IsSP = (reg2 == REG_SP);
5530 assert(isValidGeneralDatasize(size));
5531 assert(isGeneralRegister(reg3));
5533 if (setFlags || insOptsAluShift(opt)) // Can't encode SP in reg1 with setFlags or AluShift option
5535 assert(isGeneralRegisterOrZR(reg1));
5539 assert(isGeneralRegisterOrSP(reg1));
5540 reg1 = encodingSPtoZR(reg1);
5543 if (insOptsAluShift(opt)) // Can't encode SP in reg2 with AluShift option
5545 assert(isGeneralRegister(reg2));
5549 assert(isGeneralRegisterOrSP(reg2));
5550 reg2 = encodingSPtoZR(reg2);
5553 if (insOptsAnyExtend(opt))
5555 assert((imm >= 0) && (imm <= 4));
5559 else if (insOptsAluShift(opt))
5561 // imm should be non-zero and in [1..63]
5562 assert(isValidImmShift(imm, size) && (imm != 0));
5567 assert(insOptsNone(opt));
5571 // To encode the SP register as reg2 we must use the IF_DR_3C encoding
5572 // and also specify a LSL of zero (imm == 0)
5583 assert(!"Instruction cannot be encoded: Add/Sub IF_DR_3A");
5586 assert(fmt != IF_NONE);
5588 instrDesc* id = emitNewInstrCns(attr, imm);
5598 // Record the attribute for the second register in the pair
5599 id->idGCrefReg2(GCT_NONE);
5600 if (attrReg2 != EA_UNKNOWN)
5602 // Record the attribute for the second register in the pair
5603 assert((fmt == IF_LS_3B) || (fmt == IF_LS_3C));
5604 if (EA_IS_GCREF(attrReg2))
5606 id->idGCrefReg2(GCT_GCREF);
5608 else if (EA_IS_BYREF(attrReg2))
5610 id->idGCrefReg2(GCT_BYREF);
5618 /*****************************************************************************
5620 * Add an instruction referencing three registers, with an extend option
5623 void emitter::emitIns_R_R_R_Ext(instruction ins,
5628 insOpts opt, /* = INS_OPTS_NONE */
5629 int shiftAmount) /* = -1 -- unset */
5631 emitAttr size = EA_SIZE(attr);
5632 insFormat fmt = IF_NONE;
5633 bool isSIMD = false;
5636 /* Figure out the encoding format of the instruction */
5657 // Is the target a vector register?
5658 if (isVectorRegister(reg1))
5660 assert(isValidVectorLSDatasize(size));
5661 scale = NaturalScale_helper(size);
5666 assert(isValidGeneralDatasize(size));
5667 scale = (size == EA_8BYTE) ? 3 : 2;
5676 } // end switch (ins)
5678 assert(scale != -1);
5679 assert(insOptsLSExtend(opt));
5683 assert(isValidVectorLSDatasize(size));
5684 assert(isVectorRegister(reg1));
5688 assert(isValidGeneralLSDatasize(size));
5689 assert(isGeneralRegisterOrZR(reg1));
5692 assert(isGeneralRegisterOrSP(reg2));
5693 assert(isGeneralRegister(reg3));
5695 // Load/Store reserved encodings:
5696 if (insOptsIndexed(opt))
5698 assert(reg1 != reg2);
5701 if (shiftAmount == -1)
5703 shiftAmount = insOptsLSL(opt) ? scale : 0;
5705 assert((shiftAmount == scale) || (shiftAmount == 0));
5707 reg2 = encodingSPtoZR(reg2);
5710 instrDesc* id = emitNewInstr(attr);
5719 id->idReg3Scaled(shiftAmount == scale);
5725 /*****************************************************************************
5727 * Add an instruction referencing two registers and two constants.
5730 void emitter::emitIns_R_R_I_I(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, int imm1, int imm2)
5732 emitAttr size = EA_SIZE(attr);
5733 emitAttr elemsize = EA_UNKNOWN;
5734 insFormat fmt = IF_NONE;
5735 size_t immOut = 0; // composed from imm1 and imm2 and stored in the instrDesc
5737 /* Figure out the encoding format of the instruction */
5747 assert(isGeneralRegister(reg1));
5748 assert(isGeneralRegister(reg2));
5749 assert(isValidImmShift(imm1, size));
5750 assert(isValidImmShift(imm2, size));
5752 bmi.immN = (size == EA_8BYTE);
5755 immOut = bmi.immNRS;
5762 assert(isGeneralRegister(reg1));
5763 assert(isGeneralRegister(reg2));
5764 lsb = getBitWidth(size) - imm1;
5766 assert(isValidImmShift(lsb, size));
5767 assert(isValidImmShift(width, size));
5769 bmi.immN = (size == EA_8BYTE);
5772 immOut = bmi.immNRS;
5779 assert(isGeneralRegister(reg1));
5780 assert(isGeneralRegister(reg2));
5782 width = imm2 + imm1 - 1;
5783 assert(isValidImmShift(lsb, size));
5784 assert(isValidImmShift(width, size));
5786 bmi.immN = (size == EA_8BYTE);
5788 bmi.immS = imm2 + imm1 - 1;
5789 immOut = bmi.immNRS;
5795 assert(isVectorRegister(reg1));
5796 assert(isVectorRegister(reg2));
5798 assert(isValidVectorElemsize(elemsize));
5799 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm1));
5800 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm2));
5801 immOut = (imm1 << 4) + imm2;
5809 assert(fmt != IF_NONE);
5811 instrDesc* id = emitNewInstrSC(attr, immOut);
5823 /*****************************************************************************
5825 * Add an instruction referencing four registers.
5828 void emitter::emitIns_R_R_R_R(
5829 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, regNumber reg4)
5831 emitAttr size = EA_SIZE(attr);
5832 insFormat fmt = IF_NONE;
5834 /* Figure out the encoding format of the instruction */
5843 assert(isValidGeneralDatasize(size));
5844 assert(isGeneralRegister(reg1));
5845 assert(isGeneralRegister(reg2));
5846 assert(isGeneralRegister(reg3));
5847 assert(isGeneralRegister(reg4));
5856 assert(isValidScalarDatasize(size));
5857 assert(isVectorRegister(reg1));
5858 assert(isVectorRegister(reg2));
5859 assert(isVectorRegister(reg3));
5860 assert(isVectorRegister(reg4));
5872 assert(fmt != IF_NONE);
5874 instrDesc* id = emitNewInstr(attr);
5888 /*****************************************************************************
5890 * Add an instruction referencing a register and a condition code
5893 void emitter::emitIns_R_COND(instruction ins, emitAttr attr, regNumber reg, insCond cond)
5895 emitAttr size = EA_SIZE(attr);
5896 insFormat fmt = IF_NONE;
5900 /* Figure out the encoding format of the instruction */
5905 assert(isGeneralRegister(reg));
5914 } // end switch (ins)
5916 assert(fmt != IF_NONE);
5917 assert(isValidImmCond(cfi.immCFVal));
5919 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
5923 id->idInsOpt(INS_OPTS_NONE);
5931 /*****************************************************************************
5933 * Add an instruction referencing two registers and a condition code
5936 void emitter::emitIns_R_R_COND(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insCond cond)
5938 emitAttr size = EA_SIZE(attr);
5939 insFormat fmt = IF_NONE;
5943 /* Figure out the encoding format of the instruction */
5949 assert(isGeneralRegister(reg1));
5950 assert(isGeneralRegister(reg2));
5958 } // end switch (ins)
5960 assert(fmt != IF_NONE);
5961 assert(isValidImmCond(cfi.immCFVal));
5963 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
5967 id->idInsOpt(INS_OPTS_NONE);
5976 /*****************************************************************************
5978 * Add an instruction referencing two registers and a condition code
5981 void emitter::emitIns_R_R_R_COND(
5982 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insCond cond)
5984 emitAttr size = EA_SIZE(attr);
5985 insFormat fmt = IF_NONE;
5989 /* Figure out the encoding format of the instruction */
5996 assert(isGeneralRegister(reg1));
5997 assert(isGeneralRegister(reg2));
5998 assert(isGeneralRegister(reg3));
6007 } // end switch (ins)
6009 assert(fmt != IF_NONE);
6010 assert(isValidImmCond(cfi.immCFVal));
6012 instrDesc* id = emitNewInstr(attr);
6016 id->idInsOpt(INS_OPTS_NONE);
6021 id->idSmallCns(cfi.immCFVal);
6027 /*****************************************************************************
6029 * Add an instruction referencing two registers the flags and a condition code
6032 void emitter::emitIns_R_R_FLAGS_COND(
6033 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insCflags flags, insCond cond)
6035 emitAttr size = EA_SIZE(attr);
6036 insFormat fmt = IF_NONE;
6040 /* Figure out the encoding format of the instruction */
6045 assert(isGeneralRegister(reg1));
6046 assert(isGeneralRegister(reg2));
6054 } // end switch (ins)
6056 assert(fmt != IF_NONE);
6057 assert(isValidImmCondFlags(cfi.immCFVal));
6059 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6063 id->idInsOpt(INS_OPTS_NONE);
6072 /*****************************************************************************
6074 * Add an instruction referencing a register, an immediate, the flags and a condition code
6077 void emitter::emitIns_R_I_FLAGS_COND(
6078 instruction ins, emitAttr attr, regNumber reg, int imm, insCflags flags, insCond cond)
6080 emitAttr size = EA_SIZE(attr);
6081 insFormat fmt = IF_NONE;
6085 /* Figure out the encoding format of the instruction */
6090 assert(isGeneralRegister(reg));
6093 ins = insReverse(ins);
6096 if ((imm >= 0) && (imm <= 31))
6105 assert(!"Instruction cannot be encoded: ccmp/ccmn imm5");
6111 } // end switch (ins)
6113 assert(fmt != IF_NONE);
6114 assert(isValidImmCondFlagsImm5(cfi.immCFVal));
6116 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6120 id->idInsOpt(INS_OPTS_NONE);
6128 /*****************************************************************************
6130 * Add a memory barrier instruction with a 'barrier' immediate
6133 void emitter::emitIns_BARR(instruction ins, insBarrier barrier)
6135 insFormat fmt = IF_NONE;
6138 /* Figure out the encoding format of the instruction */
6146 imm = (ssize_t)barrier;
6151 } // end switch (ins)
6153 assert(fmt != IF_NONE);
6155 instrDesc* id = emitNewInstrSC(EA_8BYTE, imm);
6159 id->idInsOpt(INS_OPTS_NONE);
6165 /*****************************************************************************
6167 * Add an instruction with a static data member operand. If 'size' is 0, the
6168 * instruction operates on the address of the static member instead of its
6169 * value (e.g. "push offset clsvar", rather than "push dword ptr [clsvar]").
6172 void emitter::emitIns_C(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, int offs)
6177 /*****************************************************************************
6179 * Add an instruction referencing stack-based local variable.
6182 void emitter::emitIns_S(instruction ins, emitAttr attr, int varx, int offs)
6187 /*****************************************************************************
6189 * Add an instruction referencing a register and a stack-based local variable.
6191 void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
6193 emitAttr size = EA_SIZE(attr);
6194 insFormat fmt = IF_NONE;
6200 // TODO-ARM64-CQ: use unscaled loads?
6201 /* Figure out the encoding format of the instruction */
6222 assert(isValidGeneralDatasize(size) || isValidVectorDatasize(size));
6223 scale = genLog2(EA_SIZE_IN_BYTES(size));
6227 assert(size == EA_8BYTE);
6232 NYI("emitIns_R_S"); // FP locals?
6235 } // end switch (ins)
6237 /* Figure out the variable's frame position */
6242 base = emitComp->lvaFrameAddress(varx, &FPbased);
6244 assert((scale >= 0) && (scale <= 4));
6246 regNumber reg2 = FPbased ? REG_FPBASE : REG_SPBASE;
6247 reg2 = encodingSPtoZR(reg2);
6264 fmt = IF_DI_2A; // add reg1,reg2,#disp
6268 regNumber rsvdReg = codeGen->rsGetRsvdReg();
6269 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6270 fmt = IF_DR_3A; // add reg1,reg2,rsvdReg
6275 bool useRegForImm = false;
6276 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6283 else if ((imm < 0) || ((imm & mask) != 0))
6285 if ((imm >= -256) && (imm <= 255))
6291 useRegForImm = true;
6296 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
6298 imm >>= scale; // The immediate is scaled by the size of the ld/st
6304 useRegForImm = true;
6310 regNumber rsvdReg = codeGen->rsGetRsvdReg();
6311 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6316 assert(fmt != IF_NONE);
6318 instrDesc* id = emitNewInstrCns(attr, imm);
6322 id->idInsOpt(INS_OPTS_NONE);
6326 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6327 id->idSetIsLclVar();
6330 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6337 /*****************************************************************************
6339 * Add an instruction referencing two register and consectutive stack-based local variable slots.
6341 void emitter::emitIns_R_R_S_S(
6342 instruction ins, emitAttr attr1, emitAttr attr2, regNumber reg1, regNumber reg2, int varx, int offs)
6344 assert((ins == INS_ldp) || (ins == INS_ldnp));
6345 assert(EA_8BYTE == EA_SIZE(attr1));
6346 assert(EA_8BYTE == EA_SIZE(attr2));
6347 assert(isGeneralRegisterOrZR(reg1));
6348 assert(isGeneralRegisterOrZR(reg2));
6351 insFormat fmt = IF_LS_3B;
6353 const unsigned scale = 3;
6355 /* Figure out the variable's frame position */
6359 base = emitComp->lvaFrameAddress(varx, &FPbased);
6362 // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6363 regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE;
6364 reg3 = encodingSPtoZR(reg3);
6366 bool useRegForAdr = true;
6368 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6371 useRegForAdr = false;
6375 if ((imm & mask) == 0)
6377 ssize_t immShift = imm >> scale; // The immediate is scaled by the size of the ld/st
6379 if ((immShift >= -64) && (immShift <= 63))
6382 useRegForAdr = false;
6390 regNumber rsvd = codeGen->rsGetRsvdReg();
6391 emitIns_R_R_Imm(INS_add, EA_PTRSIZE, rsvd, reg3, imm);
6396 assert(fmt != IF_NONE);
6398 instrDesc* id = emitNewInstrCns(attr1, imm);
6402 id->idInsOpt(INS_OPTS_NONE);
6404 // Record the attribute for the second register in the pair
6405 if (EA_IS_GCREF(attr2))
6407 id->idGCrefReg2(GCT_GCREF);
6409 else if (EA_IS_BYREF(attr2))
6411 id->idGCrefReg2(GCT_BYREF);
6415 id->idGCrefReg2(GCT_NONE);
6421 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6422 id->idSetIsLclVar();
6425 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6432 /*****************************************************************************
6434 * Add an instruction referencing a stack-based local variable and a register
6436 void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
6439 emitAttr size = EA_SIZE(attr);
6440 insFormat fmt = IF_NONE;
6443 bool isVectorStore = false;
6445 // TODO-ARM64-CQ: use unscaled loads?
6446 /* Figure out the encoding format of the instruction */
6451 assert(isGeneralRegisterOrZR(reg1));
6456 assert(isGeneralRegisterOrZR(reg1));
6460 if (isGeneralRegisterOrZR(reg1))
6462 assert(isValidGeneralDatasize(size));
6463 scale = (size == EA_8BYTE) ? 3 : 2;
6467 assert(isVectorRegister(reg1));
6468 assert(isValidVectorLSDatasize(size));
6469 scale = NaturalScale_helper(size);
6470 isVectorStore = true;
6475 NYI("emitIns_S_R"); // FP locals?
6478 } // end switch (ins)
6480 /* Figure out the variable's frame position */
6484 base = emitComp->lvaFrameAddress(varx, &FPbased);
6496 // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6497 regNumber reg2 = FPbased ? REG_FPBASE : REG_SPBASE;
6498 reg2 = encodingSPtoZR(reg2);
6500 bool useRegForImm = false;
6502 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6507 else if ((imm < 0) || ((imm & mask) != 0))
6509 if ((imm >= -256) && (imm <= 255))
6515 useRegForImm = true;
6520 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
6522 imm >>= scale; // The immediate is scaled by the size of the ld/st
6528 useRegForImm = true;
6534 // The reserved register is not stored in idReg3() since that field overlaps with iiaLclVar.
6535 // It is instead implicit when idSetIsLclVar() is set, with this encoding format.
6536 regNumber rsvdReg = codeGen->rsGetRsvdReg();
6537 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6541 assert(fmt != IF_NONE);
6543 instrDesc* id = emitNewInstrCns(attr, imm);
6547 id->idInsOpt(INS_OPTS_NONE);
6551 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6552 id->idSetIsLclVar();
6555 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6562 /*****************************************************************************
6564 * Add an instruction referencing consecutive stack-based local variable slots and two registers
6566 void emitter::emitIns_S_S_R_R(
6567 instruction ins, emitAttr attr1, emitAttr attr2, regNumber reg1, regNumber reg2, int varx, int offs)
6569 assert((ins == INS_stp) || (ins == INS_stnp));
6570 assert(EA_8BYTE == EA_SIZE(attr1));
6571 assert(EA_8BYTE == EA_SIZE(attr2));
6572 assert(isGeneralRegisterOrZR(reg1));
6573 assert(isGeneralRegisterOrZR(reg2));
6576 insFormat fmt = IF_LS_3B;
6578 const unsigned scale = 3;
6580 /* Figure out the variable's frame position */
6584 base = emitComp->lvaFrameAddress(varx, &FPbased);
6587 // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6588 regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE;
6589 reg3 = encodingSPtoZR(reg3);
6591 bool useRegForAdr = true;
6593 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6596 useRegForAdr = false;
6600 if ((imm & mask) == 0)
6602 ssize_t immShift = imm >> scale; // The immediate is scaled by the size of the ld/st
6604 if ((immShift >= -64) && (immShift <= 63))
6607 useRegForAdr = false;
6615 regNumber rsvd = codeGen->rsGetRsvdReg();
6616 emitIns_R_R_Imm(INS_add, EA_PTRSIZE, rsvd, reg3, imm);
6621 assert(fmt != IF_NONE);
6623 instrDesc* id = emitNewInstrCns(attr1, imm);
6627 id->idInsOpt(INS_OPTS_NONE);
6629 // Record the attribute for the second register in the pair
6630 if (EA_IS_GCREF(attr2))
6632 id->idGCrefReg2(GCT_GCREF);
6634 else if (EA_IS_BYREF(attr2))
6636 id->idGCrefReg2(GCT_BYREF);
6640 id->idGCrefReg2(GCT_NONE);
6646 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6647 id->idSetIsLclVar();
6650 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6657 /*****************************************************************************
6659 * Add an instruction referencing stack-based local variable and an immediate
6661 void emitter::emitIns_S_I(instruction ins, emitAttr attr, int varx, int offs, int val)
6666 /*****************************************************************************
6668 * Add an instruction with a register + static member operands.
6669 * Constant is stored into JIT data which is adjacent to code.
6670 * No relocation is needed. PC-relative offset will be encoded directly into instruction.
6673 void emitter::emitIns_R_C(
6674 instruction ins, emitAttr attr, regNumber reg, regNumber addrReg, CORINFO_FIELD_HANDLE fldHnd, int offs)
6677 assert(instrDesc::fitsInSmallCns(offs));
6679 emitAttr size = EA_SIZE(attr);
6680 insFormat fmt = IF_NONE;
6682 instrDescJmp* id = emitNewInstrJmp();
6687 // This is case to get address to the constant data.
6689 assert(isGeneralRegister(reg));
6690 assert(isValidGeneralDatasize(size));
6695 if (isVectorRegister(reg))
6697 assert(isValidScalarDatasize(size));
6698 // For vector (float/double) register, we should have an integer address reg to
6699 // compute long address which consists of page address and page offset.
6700 // For integer constant, this is not needed since the dest reg can be used to
6701 // compute address as well as contain the final contents.
6702 assert(isGeneralRegister(reg) || (addrReg != REG_NA));
6706 assert(isGeneralRegister(reg));
6707 assert(isValidGeneralDatasize(size));
6714 assert(fmt != IF_NONE);
6718 id->idInsOpt(INS_OPTS_NONE);
6719 id->idSmallCns(offs);
6721 id->idAddr()->iiaFieldHnd = fldHnd;
6722 id->idSetIsBound(); // We won't patch address since we will know the exact distance once JIT code and data are
6723 // allocated together.
6725 id->idReg1(reg); // destination register that will get the constant value.
6726 if (addrReg != REG_NA)
6728 id->idReg2(addrReg); // integer register to compute long address (used for vector dest when we end up with long
6731 id->idjShort = false; // Assume loading constant from long address
6733 // Keep it long if it's in cold code.
6734 id->idjKeepLong = emitComp->fgIsBlockCold(emitComp->compCurBB);
6737 if (emitComp->opts.compLongAddress)
6738 id->idjKeepLong = 1;
6741 // If it's possible to be shortened, then put it in jump list
6742 // to be revisited by emitJumpDistBind.
6743 if (!id->idjKeepLong)
6745 /* Record the jump's IG and offset within it */
6746 id->idjIG = emitCurIG;
6747 id->idjOffs = emitCurIGsize;
6749 /* Append this jump to this IG's jump list */
6750 id->idjNext = emitCurIGjmpList;
6751 emitCurIGjmpList = id;
6762 /*****************************************************************************
6764 * Add an instruction with a static member + constant.
6767 void emitter::emitIns_C_I(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, ssize_t offs, ssize_t val)
6772 /*****************************************************************************
6774 * Add an instruction with a static member + register operands.
6777 void emitter::emitIns_C_R(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, regNumber reg, int offs)
6779 assert(!"emitIns_C_R not supported for RyuJIT backend");
6782 void emitter::emitIns_R_AR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
6784 NYI("emitIns_R_AR");
6787 // This computes address from the immediate which is relocatable.
6788 void emitter::emitIns_R_AI(instruction ins, emitAttr attr, regNumber ireg, ssize_t addr)
6790 assert(EA_IS_RELOC(attr));
6791 emitAttr size = EA_SIZE(attr);
6792 insFormat fmt = IF_DI_1E;
6793 bool needAdd = false;
6794 instrDescJmp* id = emitNewInstrJmp();
6799 // This computes page address.
6800 // page offset is needed using add.
6811 id->idInsOpt(INS_OPTS_NONE);
6813 id->idAddr()->iiaAddr = (BYTE*)addr;
6815 id->idSetIsDspReloc();
6822 // add reg, reg, imm
6825 instrDesc* id = emitAllocInstr(attr);
6826 assert(id->idIsReloc());
6830 id->idInsOpt(INS_OPTS_NONE);
6832 id->idAddr()->iiaAddr = (BYTE*)addr;
6841 void emitter::emitIns_AR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
6843 NYI("emitIns_AR_R");
6846 void emitter::emitIns_R_ARR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
6848 NYI("emitIns_R_ARR");
6851 void emitter::emitIns_ARR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
6853 NYI("emitIns_R_ARR");
6856 void emitter::emitIns_R_ARX(
6857 instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, unsigned mul, int disp)
6859 NYI("emitIns_R_ARR");
6862 /*****************************************************************************
6864 * Record that a jump instruction uses the short encoding
6867 void emitter::emitSetShortJump(instrDescJmp* id)
6869 if (id->idjKeepLong)
6872 insFormat fmt = IF_NONE;
6873 if (emitIsCondJump(id))
6875 switch (id->idIns())
6890 else if (emitIsLoadLabel(id))
6894 else if (emitIsLoadConstant(id))
6904 id->idjShort = true;
6907 /*****************************************************************************
6909 * Add a label instruction.
6912 void emitter::emitIns_R_L(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
6914 assert(dst->bbFlags & BBF_JMP_TARGET);
6916 insFormat fmt = IF_NONE;
6927 instrDescJmp* id = emitNewInstrJmp();
6931 id->idjShort = false;
6932 id->idAddr()->iiaBBlabel = dst;
6934 id->idOpSize(EA_PTRSIZE);
6937 // Mark the catch return
6938 if (emitComp->compCurBB->bbJumpKind == BBJ_EHCATCHRET)
6940 id->idDebugOnlyInfo()->idCatchRet = true;
6944 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
6947 if (emitComp->opts.compLongAddress)
6948 id->idjKeepLong = 1;
6951 /* Record the jump's IG and offset within it */
6953 id->idjIG = emitCurIG;
6954 id->idjOffs = emitCurIGsize;
6956 /* Append this jump to this IG's jump list */
6958 id->idjNext = emitCurIGjmpList;
6959 emitCurIGjmpList = id;
6969 /*****************************************************************************
6971 * Add a data label instruction.
6974 void emitter::emitIns_R_D(instruction ins, emitAttr attr, unsigned offs, regNumber reg)
6979 void emitter::emitIns_J_R(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
6981 assert((ins == INS_cbz) || (ins == INS_cbnz));
6983 assert(dst != nullptr);
6984 assert((dst->bbFlags & BBF_JMP_TARGET) != 0);
6986 insFormat fmt = IF_LARGEJMP;
6988 instrDescJmp* id = emitNewInstrJmp();
6993 id->idjShort = false;
6994 id->idOpSize(EA_SIZE(attr));
6996 id->idAddr()->iiaBBlabel = dst;
6997 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
6999 /* Record the jump's IG and offset within it */
7001 id->idjIG = emitCurIG;
7002 id->idjOffs = emitCurIGsize;
7004 /* Append this jump to this IG's jump list */
7006 id->idjNext = emitCurIGjmpList;
7007 emitCurIGjmpList = id;
7017 void emitter::emitIns_J_R_I(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg, int imm)
7019 assert((ins == INS_tbz) || (ins == INS_tbnz));
7021 assert(dst != nullptr);
7022 assert((dst->bbFlags & BBF_JMP_TARGET) != 0);
7023 assert((EA_SIZE(attr) == EA_4BYTE) || (EA_SIZE(attr) == EA_8BYTE));
7024 assert(imm < ((EA_SIZE(attr) == EA_4BYTE) ? 32 : 64));
7026 insFormat fmt = IF_LARGEJMP;
7028 instrDescJmp* id = emitNewInstrJmp();
7033 id->idjShort = false;
7034 id->idSmallCns(imm);
7035 id->idOpSize(EA_SIZE(attr));
7037 id->idAddr()->iiaBBlabel = dst;
7038 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7040 /* Record the jump's IG and offset within it */
7042 id->idjIG = emitCurIG;
7043 id->idjOffs = emitCurIGsize;
7045 /* Append this jump to this IG's jump list */
7047 id->idjNext = emitCurIGjmpList;
7048 emitCurIGjmpList = id;
7058 void emitter::emitIns_J(instruction ins, BasicBlock* dst, int instrCount)
7060 insFormat fmt = IF_NONE;
7064 assert(dst->bbFlags & BBF_JMP_TARGET);
7068 assert(instrCount != 0);
7071 /* Figure out the encoding format of the instruction */
7073 bool idjShort = false;
7078 // Unconditional jump is a single form.
7097 // Assume conditional jump is long.
7106 instrDescJmp* id = emitNewInstrJmp();
7110 id->idjShort = idjShort;
7113 // Mark the finally call
7114 if (ins == INS_bl_local && emitComp->compCurBB->bbJumpKind == BBJ_CALLFINALLY)
7116 id->idDebugOnlyInfo()->idFinallyCall = true;
7122 id->idAddr()->iiaBBlabel = dst;
7124 // Skip unconditional jump that has a single form.
7125 // TODO-ARM64-NYI: enable hot/cold splittingNYI.
7126 // The target needs to be relocated.
7129 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7132 if (emitComp->opts.compLongAddress) // Force long branches
7133 id->idjKeepLong = 1;
7139 id->idAddr()->iiaSetInstrCount(instrCount);
7140 id->idjKeepLong = false;
7141 /* This jump must be short */
7142 emitSetShortJump(id);
7146 /* Record the jump's IG and offset within it */
7148 id->idjIG = emitCurIG;
7149 id->idjOffs = emitCurIGsize;
7151 /* Append this jump to this IG's jump list */
7153 id->idjNext = emitCurIGjmpList;
7154 emitCurIGjmpList = id;
7164 /*****************************************************************************
7166 * Add a call instruction (direct or indirect).
7167 * argSize<0 means that the caller will pop the arguments
7169 * The other arguments are interpreted depending on callType as shown:
7170 * Unless otherwise specified, ireg,xreg,xmul,disp should have default values.
7172 * EC_FUNC_TOKEN : addr is the method address
7173 * EC_FUNC_ADDR : addr is the absolute address of the function
7175 * If callType is one of these emitCallTypes, addr has to be NULL.
7176 * EC_INDIR_R : "call ireg".
7178 * For ARM xreg, xmul and disp are never used and should always be 0/REG_NA.
7180 * Please consult the "debugger team notification" comment in genFnProlog().
7183 void emitter::emitIns_Call(EmitCallType callType,
7184 CORINFO_METHOD_HANDLE methHnd,
7185 INDEBUG_LDISASM_COMMA(CORINFO_SIG_INFO* sigInfo) // used to report call sites to the EE
7189 emitAttr secondRetSize,
7190 VARSET_VALARG_TP ptrVars,
7191 regMaskTP gcrefRegs,
7192 regMaskTP byrefRegs,
7193 IL_OFFSETX ilOffset /* = BAD_IL_OFFSET */,
7194 regNumber ireg /* = REG_NA */,
7195 regNumber xreg /* = REG_NA */,
7196 unsigned xmul /* = 0 */,
7197 ssize_t disp /* = 0 */,
7198 bool isJump /* = false */,
7199 bool isNoGC /* = false */,
7200 bool isProfLeaveCB /* = false */)
7202 /* Sanity check the arguments depending on callType */
7204 assert(callType < EC_COUNT);
7205 assert((callType != EC_FUNC_TOKEN && callType != EC_FUNC_ADDR) ||
7206 (ireg == REG_NA && xreg == REG_NA && xmul == 0 && disp == 0));
7207 assert(callType < EC_INDIR_R || addr == NULL);
7208 assert(callType != EC_INDIR_R || (ireg < REG_COUNT && xreg == REG_NA && xmul == 0 && disp == 0));
7210 // ARM never uses these
7211 assert(xreg == REG_NA && xmul == 0 && disp == 0);
7213 // Our stack level should be always greater than the bytes of arguments we push. Just
7215 assert((unsigned)abs(argSize) <= codeGen->genStackLevel);
7220 /* This is the saved set of registers after a normal call */
7221 regMaskTP savedSet = RBM_CALLEE_SAVED;
7223 /* some special helper calls have a different saved set registers */
7227 assert(emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
7229 // Get the set of registers that this call kills and remove it from the saved set.
7230 savedSet = RBM_ALLINT & ~emitComp->compNoGCHelperCallKillSet(Compiler::eeGetHelperNum(methHnd));
7232 // In case of Leave profiler callback, we need to preserve liveness of REG_PROFILER_RET_SCRATCH
7235 savedSet |= RBM_PROFILER_RET_SCRATCH;
7240 assert(!emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
7243 /* Trim out any callee-trashed registers from the live set */
7245 gcrefRegs &= savedSet;
7246 byrefRegs &= savedSet;
7249 if (EMIT_GC_VERBOSE)
7251 printf("Call: GCvars=%s ", VarSetOps::ToString(emitComp, ptrVars));
7252 dumpConvertedVarSet(emitComp, ptrVars);
7253 printf(", gcrefRegs=");
7254 printRegMaskInt(gcrefRegs);
7255 emitDispRegSet(gcrefRegs);
7256 printf(", byrefRegs=");
7257 printRegMaskInt(byrefRegs);
7258 emitDispRegSet(byrefRegs);
7263 assert(argSize % REGSIZE_BYTES == 0);
7264 argCnt = (int)(argSize / (int)REGSIZE_BYTES);
7266 /* Managed RetVal: emit sequence point for the call */
7267 if (emitComp->opts.compDbgInfo && ilOffset != BAD_IL_OFFSET)
7269 codeGen->genIPmappingAdd(ilOffset, false);
7273 We need to allocate the appropriate instruction descriptor based
7274 on whether this is a direct/indirect call, and whether we need to
7275 record an updated set of live GC variables.
7278 if (callType >= EC_INDIR_R)
7280 /* Indirect call, virtual calls */
7282 assert(callType == EC_INDIR_R);
7284 id = emitNewInstrCallInd(argCnt, disp, ptrVars, gcrefRegs, byrefRegs, retSize, secondRetSize);
7288 /* Helper/static/nonvirtual/function calls (direct or through handle),
7289 and calls to an absolute addr. */
7291 assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
7293 id = emitNewInstrCallDir(argCnt, ptrVars, gcrefRegs, byrefRegs, retSize, secondRetSize);
7296 /* Update the emitter's live GC ref sets */
7298 VarSetOps::Assign(emitComp, emitThisGCrefVars, ptrVars);
7299 emitThisGCrefRegs = gcrefRegs;
7300 emitThisByrefRegs = byrefRegs;
7302 /* Set the instruction - special case jumping a function */
7304 insFormat fmt = IF_NONE;
7306 id->idSetIsNoGC(isNoGC);
7308 /* Record the address: method, indirection, or funcptr */
7310 if (callType > EC_FUNC_ADDR)
7312 /* This is an indirect call (either a virtual call or func ptr call) */
7316 case EC_INDIR_R: // the address is in a register
7318 id->idSetIsCallRegPtr();
7322 ins = INS_br_tail; // INS_br_tail Reg
7326 ins = INS_blr; // INS_blr Reg
7334 assert(xreg == REG_NA);
7338 NO_WAY("unexpected instruction");
7344 /* This is a simple direct call: "call helper/method/addr" */
7346 assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
7348 assert(addr != NULL);
7352 ins = INS_b_tail; // INS_b_tail imm28
7356 ins = INS_bl; // INS_bl imm28
7363 id->idAddr()->iiaAddr = (BYTE*)addr;
7365 if (callType == EC_FUNC_ADDR)
7367 id->idSetIsCallAddr();
7370 if (emitComp->opts.compReloc)
7372 id->idSetIsDspReloc();
7377 if (EMIT_GC_VERBOSE)
7379 if (id->idIsLargeCall())
7381 printf("[%02u] Rec call GC vars = %s\n", id->idDebugOnlyInfo()->idNum,
7382 VarSetOps::ToString(emitComp, ((instrDescCGCA*)id)->idcGCvars));
7386 id->idDebugOnlyInfo()->idMemCookie = (size_t)methHnd; // method token
7387 id->idDebugOnlyInfo()->idCallSig = sigInfo;
7391 if (addr != nullptr)
7393 codeGen->getDisAssembler().disSetMethod((size_t)addr, methHnd);
7395 #endif // LATE_DISASM
7401 /*****************************************************************************
7403 * Returns true if 'imm' is valid Cond encoding
7406 /*static*/ bool emitter::isValidImmCond(ssize_t imm)
7408 // range check the ssize_t value, to make sure it is a small unsigned value
7409 // and that only the bits in the cfi.cond are set
7410 if ((imm < 0) || (imm > 0xF))
7414 cfi.immCFVal = (unsigned)imm;
7416 return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7419 /*****************************************************************************
7421 * Returns true if 'imm' is valid Cond/Flags encoding
7424 /*static*/ bool emitter::isValidImmCondFlags(ssize_t imm)
7426 // range check the ssize_t value, to make sure it is a small unsigned value
7427 // and that only the bits in the cfi.cond or cfi.flags are set
7428 if ((imm < 0) || (imm > 0xFF))
7432 cfi.immCFVal = (unsigned)imm;
7434 return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7437 /*****************************************************************************
7439 * Returns true if 'imm' is valid Cond/Flags/Imm5 encoding
7442 /*static*/ bool emitter::isValidImmCondFlagsImm5(ssize_t imm)
7444 // range check the ssize_t value, to make sure it is a small unsigned value
7445 // and that only the bits in the cfi.cond, cfi.flags or cfi.imm5 are set
7446 if ((imm < 0) || (imm > 0x1FFF))
7450 cfi.immCFVal = (unsigned)imm;
7452 return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7455 /*****************************************************************************
7457 * Returns an encoding for the specified register used in the 'Rd' position
7460 /*static*/ emitter::code_t emitter::insEncodeReg_Rd(regNumber reg)
7462 assert(isIntegerRegister(reg));
7463 emitter::code_t ureg = (emitter::code_t)reg;
7464 assert((ureg >= 0) && (ureg <= 31));
7468 /*****************************************************************************
7470 * Returns an encoding for the specified register used in the 'Rt' position
7473 /*static*/ emitter::code_t emitter::insEncodeReg_Rt(regNumber reg)
7475 assert(isIntegerRegister(reg));
7476 emitter::code_t ureg = (emitter::code_t)reg;
7477 assert((ureg >= 0) && (ureg <= 31));
7481 /*****************************************************************************
7483 * Returns an encoding for the specified register used in the 'Rn' position
7486 /*static*/ emitter::code_t emitter::insEncodeReg_Rn(regNumber reg)
7488 assert(isIntegerRegister(reg));
7489 emitter::code_t ureg = (emitter::code_t)reg;
7490 assert((ureg >= 0) && (ureg <= 31));
7494 /*****************************************************************************
7496 * Returns an encoding for the specified register used in the 'Rm' position
7499 /*static*/ emitter::code_t emitter::insEncodeReg_Rm(regNumber reg)
7501 assert(isIntegerRegister(reg));
7502 emitter::code_t ureg = (emitter::code_t)reg;
7503 assert((ureg >= 0) && (ureg <= 31));
7507 /*****************************************************************************
7509 * Returns an encoding for the specified register used in the 'Ra' position
7512 /*static*/ emitter::code_t emitter::insEncodeReg_Ra(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 'Vd' position
7525 /*static*/ emitter::code_t emitter::insEncodeReg_Vd(regNumber reg)
7527 assert(emitter::isVectorRegister(reg));
7528 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7529 assert((ureg >= 0) && (ureg <= 31));
7533 /*****************************************************************************
7535 * Returns an encoding for the specified register used in the 'Vt' position
7538 /*static*/ emitter::code_t emitter::insEncodeReg_Vt(regNumber reg)
7540 assert(emitter::isVectorRegister(reg));
7541 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7542 assert((ureg >= 0) && (ureg <= 31));
7546 /*****************************************************************************
7548 * Returns an encoding for the specified register used in the 'Vn' position
7551 /*static*/ emitter::code_t emitter::insEncodeReg_Vn(regNumber reg)
7553 assert(emitter::isVectorRegister(reg));
7554 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7555 assert((ureg >= 0) && (ureg <= 31));
7559 /*****************************************************************************
7561 * Returns an encoding for the specified register used in the 'Vm' position
7564 /*static*/ emitter::code_t emitter::insEncodeReg_Vm(regNumber reg)
7566 assert(emitter::isVectorRegister(reg));
7567 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7568 assert((ureg >= 0) && (ureg <= 31));
7572 /*****************************************************************************
7574 * Returns an encoding for the specified register used in the 'Va' position
7577 /*static*/ emitter::code_t emitter::insEncodeReg_Va(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 condition code.
7590 /*static*/ emitter::code_t emitter::insEncodeCond(insCond cond)
7592 emitter::code_t uimm = (emitter::code_t)cond;
7596 /*****************************************************************************
7598 * Returns an encoding for the condition code with the lowest bit inverted (marked by invert(<cond>) in the
7599 * architecture manual).
7602 /*static*/ emitter::code_t emitter::insEncodeInvertedCond(insCond cond)
7604 emitter::code_t uimm = (emitter::code_t)cond;
7605 uimm ^= 1; // invert the lowest bit
7609 /*****************************************************************************
7611 * Returns an encoding for the specified flags.
7614 /*static*/ emitter::code_t emitter::insEncodeFlags(insCflags flags)
7616 emitter::code_t uimm = (emitter::code_t)flags;
7620 /*****************************************************************************
7622 * Returns the encoding for the Shift Count bits to be used for Arm64 encodings
7625 /*static*/ emitter::code_t emitter::insEncodeShiftCount(ssize_t imm, emitAttr size)
7627 assert((imm & 0x003F) == imm);
7628 assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
7630 return (emitter::code_t)imm << 10;
7633 /*****************************************************************************
7635 * Returns the encoding to select a 64-bit datasize for an Arm64 instruction
7638 /*static*/ emitter::code_t emitter::insEncodeDatasize(emitAttr size)
7640 if (size == EA_8BYTE)
7642 return 0x80000000; // set the bit at location 31
7646 assert(size == EA_4BYTE);
7651 /*****************************************************************************
7653 * Returns the encoding to select the datasize for the general load/store Arm64 instructions
7657 /*static*/ emitter::code_t emitter::insEncodeDatasizeLS(emitter::code_t code, emitAttr size)
7659 bool exclusive = ((code & 0x35000000) == 0);
7661 if ((code & 0x00800000) && !exclusive) // Is this a sign-extending opcode? (i.e. ldrsw, ldrsh, ldrsb)
7663 if ((code & 0x80000000) == 0) // Is it a ldrsh or ldrsb and not ldrsw ?
7665 if (EA_SIZE(size) != EA_8BYTE) // Do we need to encode the 32-bit Rt size bit?
7667 return 0x00400000; // set the bit at location 22
7671 else if (code & 0x80000000) // Is this a ldr/str/ldur/stur opcode?
7673 if (EA_SIZE(size) == EA_8BYTE) // Do we need to encode the 64-bit size bit?
7675 return 0x40000000; // set the bit at location 30
7681 /*****************************************************************************
7683 * Returns the encoding to select the datasize for the vector load/store Arm64 instructions
7687 /*static*/ emitter::code_t emitter::insEncodeDatasizeVLS(emitter::code_t code, emitAttr size)
7692 if ((code & 0x20000000) == 0)
7696 if (size == EA_16BYTE)
7698 // set the operation size in bit 31
7699 result = 0x80000000;
7701 else if (size == EA_8BYTE)
7703 // set the operation size in bit 30
7704 result = 0x40000000;
7708 assert(size == EA_4BYTE);
7710 result = 0x00000000;
7717 if (size == EA_16BYTE)
7719 // The operation size in bits 31 and 30 are zero
7720 // Bit 23 specifies a 128-bit Load/Store
7721 result = 0x00800000;
7723 else if (size == EA_8BYTE)
7725 // set the operation size in bits 31 and 30
7726 result = 0xC0000000;
7728 else if (size == EA_4BYTE)
7730 // set the operation size in bit 31
7731 result = 0x80000000;
7733 else if (size == EA_2BYTE)
7735 // set the operation size in bit 30
7736 result = 0x40000000;
7740 assert(size == EA_1BYTE);
7741 // The operation size in bits 31 and 30 are zero
7742 result = 0x00000000;
7746 // Or in bit 26 to indicate a Vector register is used as 'target'
7747 result |= 0x04000000;
7752 /*****************************************************************************
7754 * Returns the encoding to select the datasize for the vector load/store Arm64 instructions
7758 /*static*/ emitter::code_t emitter::insEncodeDatasizeVPLS(emitter::code_t code, emitAttr size)
7762 if (size == EA_16BYTE)
7764 // The operation size in bits 31 and 30 are zero
7765 // Bit 23 specifies a 128-bit Load/Store
7766 result = 0x80000000;
7768 else if (size == EA_8BYTE)
7770 // set the operation size in bits 31 and 30
7771 result = 0x40000000;
7773 else if (size == EA_4BYTE)
7775 // set the operation size in bit 31
7776 result = 0x00000000;
7779 // Or in bit 26 to indicate a Vector register is used as 'target'
7780 result |= 0x04000000;
7785 /*****************************************************************************
7787 * Returns the encoding to set the size bit and the N bits for a 'bitfield' instruction
7791 /*static*/ emitter::code_t emitter::insEncodeDatasizeBF(emitter::code_t code, emitAttr size)
7793 // is bit 30 equal to 0?
7794 if ((code & 0x40000000) == 0) // is the opcode one of extr, sxtb, sxth or sxtw
7796 if (size == EA_8BYTE) // Do we need to set the sf and N bits?
7798 return 0x80400000; // set the sf-bit at location 31 and the N-bit at location 22
7801 return 0; // don't set any bits
7804 /*****************************************************************************
7806 * Returns the encoding to select the 64/128-bit datasize for an Arm64 vector instruction
7809 /*static*/ emitter::code_t emitter::insEncodeVectorsize(emitAttr size)
7811 if (size == EA_16BYTE)
7813 return 0x40000000; // set the bit at location 30
7817 assert(size == EA_8BYTE);
7822 /*****************************************************************************
7824 * Returns the encoding to select 'index' for an Arm64 vector elem instruction
7826 /*static*/ emitter::code_t emitter::insEncodeVectorIndex(emitAttr elemsize, ssize_t index)
7828 code_t bits = (code_t)index;
7829 if (elemsize == EA_1BYTE)
7834 else if (elemsize == EA_2BYTE)
7839 else if (elemsize == EA_4BYTE)
7846 assert(elemsize == EA_8BYTE);
7850 assert((bits >= 1) && (bits <= 0x1f));
7852 return (bits << 16); // bits at locations [20,19,18,17,16]
7855 /*****************************************************************************
7857 * Returns the encoding to select 'index2' for an Arm64 'ins' elem instruction
7859 /*static*/ emitter::code_t emitter::insEncodeVectorIndex2(emitAttr elemsize, ssize_t index2)
7861 code_t bits = (code_t)index2;
7862 if (elemsize == EA_1BYTE)
7866 else if (elemsize == EA_2BYTE)
7870 else if (elemsize == EA_4BYTE)
7876 assert(elemsize == EA_8BYTE);
7879 assert((bits >= 0) && (bits <= 0xf));
7881 return (bits << 11); // bits at locations [14,13,12,11]
7884 /*****************************************************************************
7886 * Returns the encoding to select the 'index' for an Arm64 'mul' by elem instruction
7888 /*static*/ emitter::code_t emitter::insEncodeVectorIndexLMH(emitAttr elemsize, ssize_t index)
7892 if (elemsize == EA_2BYTE)
7894 assert((index >= 0) && (index <= 7));
7897 bits |= (1 << 11); // set bit 11 'H'
7901 bits |= (1 << 21); // set bit 21 'L'
7905 bits |= (1 << 20); // set bit 20 'M'
7908 else if (elemsize == EA_4BYTE)
7910 assert((index >= 0) && (index <= 3));
7913 bits |= (1 << 11); // set bit 11 'H'
7917 bits |= (1 << 21); // set bit 21 'L'
7922 assert(!"Invalid 'elemsize' value");
7928 /*****************************************************************************
7930 * Returns the encoding to shift by 'shift' for an Arm64 vector or scalar instruction
7933 /*static*/ emitter::code_t emitter::insEncodeVectorShift(emitAttr size, ssize_t shift)
7935 assert(shift < getBitWidth(size));
7937 code_t imm = (code_t)(getBitWidth(size) + shift);
7942 /*****************************************************************************
7944 * Returns the encoding to select the 1/2/4/8 byte elemsize for an Arm64 vector instruction
7947 /*static*/ emitter::code_t emitter::insEncodeElemsize(emitAttr size)
7949 if (size == EA_8BYTE)
7951 return 0x00C00000; // set the bit at location 23 and 22
7953 else if (size == EA_4BYTE)
7955 return 0x00800000; // set the bit at location 23
7957 else if (size == EA_2BYTE)
7959 return 0x00400000; // set the bit at location 22
7961 assert(size == EA_1BYTE);
7965 /*****************************************************************************
7967 * Returns the encoding to select the 4/8 byte elemsize for an Arm64 float vector instruction
7970 /*static*/ emitter::code_t emitter::insEncodeFloatElemsize(emitAttr size)
7972 if (size == EA_8BYTE)
7974 return 0x00400000; // set the bit at location 22
7976 assert(size == EA_4BYTE);
7980 // Returns the encoding to select the index for an Arm64 float vector by elem instruction
7981 /*static*/ emitter::code_t emitter::insEncodeFloatIndex(emitAttr elemsize, ssize_t index)
7983 code_t result = 0x00000000;
7984 if (elemsize == EA_8BYTE)
7986 assert((index >= 0) && (index <= 1));
7989 result |= 0x00000800; // 'H' - set the bit at location 11
7994 assert(elemsize == EA_4BYTE);
7995 assert((index >= 0) && (index <= 3));
7998 result |= 0x00000800; // 'H' - set the bit at location 11
8002 result |= 0x00200000; // 'L' - set the bit at location 21
8008 /*****************************************************************************
8010 * Returns the encoding to select the fcvt operation for Arm64 instructions
8012 /*static*/ emitter::code_t emitter::insEncodeConvertOpt(insFormat fmt, insOpts conversion)
8017 case INS_OPTS_S_TO_D: // Single to Double
8018 assert(fmt == IF_DV_2J);
8019 result = 0x00008000; // type=00, opc=01
8022 case INS_OPTS_D_TO_S: // Double to Single
8023 assert(fmt == IF_DV_2J);
8024 result = 0x00400000; // type=01, opc=00
8027 case INS_OPTS_H_TO_S: // Half to Single
8028 assert(fmt == IF_DV_2J);
8029 result = 0x00C00000; // type=11, opc=00
8032 case INS_OPTS_H_TO_D: // Half to Double
8033 assert(fmt == IF_DV_2J);
8034 result = 0x00C08000; // type=11, opc=01
8037 case INS_OPTS_S_TO_H: // Single to Half
8038 assert(fmt == IF_DV_2J);
8039 result = 0x00018000; // type=00, opc=11
8042 case INS_OPTS_D_TO_H: // Double to Half
8043 assert(fmt == IF_DV_2J);
8044 result = 0x00418000; // type=01, opc=11
8047 case INS_OPTS_S_TO_4BYTE: // Single to INT32
8048 assert(fmt == IF_DV_2H);
8049 result = 0x00000000; // sf=0, type=00
8052 case INS_OPTS_D_TO_4BYTE: // Double to INT32
8053 assert(fmt == IF_DV_2H);
8054 result = 0x00400000; // sf=0, type=01
8057 case INS_OPTS_S_TO_8BYTE: // Single to INT64
8058 assert(fmt == IF_DV_2H);
8059 result = 0x80000000; // sf=1, type=00
8062 case INS_OPTS_D_TO_8BYTE: // Double to INT64
8063 assert(fmt == IF_DV_2H);
8064 result = 0x80400000; // sf=1, type=01
8067 case INS_OPTS_4BYTE_TO_S: // INT32 to Single
8068 assert(fmt == IF_DV_2I);
8069 result = 0x00000000; // sf=0, type=00
8072 case INS_OPTS_4BYTE_TO_D: // INT32 to Double
8073 assert(fmt == IF_DV_2I);
8074 result = 0x00400000; // sf=0, type=01
8077 case INS_OPTS_8BYTE_TO_S: // INT64 to Single
8078 assert(fmt == IF_DV_2I);
8079 result = 0x80000000; // sf=1, type=00
8082 case INS_OPTS_8BYTE_TO_D: // INT64 to Double
8083 assert(fmt == IF_DV_2I);
8084 result = 0x80400000; // sf=1, type=01
8088 assert(!"Invalid 'conversion' value");
8094 /*****************************************************************************
8096 * Returns the encoding to have the Rn register be updated Pre/Post indexed
8100 /*static*/ emitter::code_t emitter::insEncodeIndexedOpt(insOpts opt)
8102 assert(emitter::insOptsNone(opt) || emitter::insOptsIndexed(opt));
8104 if (emitter::insOptsIndexed(opt))
8106 if (emitter::insOptsPostIndex(opt))
8108 return 0x00000400; // set the bit at location 10
8112 assert(emitter::insOptsPreIndex(opt));
8113 return 0x00000C00; // set the bit at location 10 and 11
8118 assert(emitter::insOptsNone(opt));
8119 return 0; // bits 10 and 11 are zero
8123 /*****************************************************************************
8125 * Returns the encoding for a ldp/stp instruction to have the Rn register
8126 * be updated Pre/Post indexed or not updated
8129 /*static*/ emitter::code_t emitter::insEncodePairIndexedOpt(instruction ins, insOpts opt)
8131 assert(emitter::insOptsNone(opt) || emitter::insOptsIndexed(opt));
8133 if ((ins == INS_ldnp) || (ins == INS_stnp))
8135 assert(emitter::insOptsNone(opt));
8136 return 0; // bits 23 and 24 are zero
8140 if (emitter::insOptsIndexed(opt))
8142 if (emitter::insOptsPostIndex(opt))
8144 return 0x00800000; // set the bit at location 23
8148 assert(emitter::insOptsPreIndex(opt));
8149 return 0x01800000; // set the bit at location 24 and 23
8154 assert(emitter::insOptsNone(opt));
8155 return 0x01000000; // set the bit at location 24
8160 /*****************************************************************************
8162 * Returns the encoding to apply a Shift Type on the Rm register
8165 /*static*/ emitter::code_t emitter::insEncodeShiftType(insOpts opt)
8167 if (emitter::insOptsNone(opt))
8169 // None implies the we encode LSL (with a zero immediate)
8172 assert(emitter::insOptsAnyShift(opt));
8174 emitter::code_t option = (emitter::code_t)opt - (emitter::code_t)INS_OPTS_LSL;
8175 assert(option <= 3);
8177 return option << 22; // bits 23, 22
8180 /*****************************************************************************
8182 * Returns the encoding to apply a 12 bit left shift to the immediate
8185 /*static*/ emitter::code_t emitter::insEncodeShiftImm12(insOpts opt)
8187 if (emitter::insOptsLSL12(opt))
8189 return 0x00400000; // set the bit at location 22
8194 /*****************************************************************************
8196 * Returns the encoding to have the Rm register use an extend operation
8199 /*static*/ emitter::code_t emitter::insEncodeExtend(insOpts opt)
8201 if (emitter::insOptsNone(opt) || (opt == INS_OPTS_LSL))
8203 // None or LSL implies the we encode UXTX
8204 opt = INS_OPTS_UXTX;
8206 assert(emitter::insOptsAnyExtend(opt));
8208 emitter::code_t option = (emitter::code_t)opt - (emitter::code_t)INS_OPTS_UXTB;
8209 assert(option <= 7);
8211 return option << 13; // bits 15,14,13
8214 /*****************************************************************************
8216 * Returns the encoding to scale the Rm register by {0,1,2,3,4}
8217 * when using an extend operation
8220 /*static*/ emitter::code_t emitter::insEncodeExtendScale(ssize_t imm)
8222 assert((imm >= 0) && (imm <= 4));
8224 return (emitter::code_t)imm << 10; // bits 12,11,10
8227 /*****************************************************************************
8229 * Returns the encoding to have the Rm register be auto scaled by the ld/st size
8232 /*static*/ emitter::code_t emitter::insEncodeReg3Scale(bool isScaled)
8236 return 0x00001000; // set the bit at location 12
8244 BYTE* emitter::emitOutputLoadLabel(BYTE* dst, BYTE* srcAddr, BYTE* dstAddr, instrDescJmp* id)
8246 instruction ins = id->idIns();
8247 insFormat fmt = id->idInsFmt();
8248 regNumber dstReg = id->idReg1();
8251 // adr x, [rel addr] -- compute address: current addr(ip) + rel addr.
8252 assert(ins == INS_adr);
8253 assert(fmt == IF_DI_1E);
8254 ssize_t distVal = (ssize_t)(dstAddr - srcAddr);
8255 dst = emitOutputShortAddress(dst, ins, fmt, distVal, dstReg);
8259 // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8260 assert(fmt == IF_LARGEADR);
8261 ssize_t relPageAddr =
8262 (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8263 dst = emitOutputShortAddress(dst, INS_adrp, IF_DI_1E, relPageAddr, dstReg);
8265 // add x, x, page offs -- compute address = page addr + page offs
8266 ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8267 assert(isValidUimm12(imm12));
8269 emitInsCode(INS_add, IF_DI_2A); // DI_2A X0010001shiiiiii iiiiiinnnnnddddd 1100 0000 imm(i12, sh)
8270 code |= insEncodeDatasize(EA_8BYTE); // X
8271 code |= ((code_t)imm12 << 10); // iiiiiiiiiiii
8272 code |= insEncodeReg_Rd(dstReg); // ddddd
8273 code |= insEncodeReg_Rn(dstReg); // nnnnn
8274 dst += emitOutput_Instr(dst, code);
8279 /*****************************************************************************
8281 * Output a local jump or other instruction with a pc-relative immediate.
8282 * Note that this may be invoked to overwrite an existing jump instruction at 'dst'
8283 * to handle forward branch patching.
8286 BYTE* emitter::emitOutputLJ(insGroup* ig, BYTE* dst, instrDesc* i)
8288 instrDescJmp* id = (instrDescJmp*)i;
8297 // Set default ins/fmt from id.
8298 instruction ins = id->idIns();
8299 insFormat fmt = id->idInsFmt();
8301 bool loadLabel = false;
8302 bool isJump = false;
8303 bool loadConstant = false;
8320 loadConstant = true;
8329 /* Figure out the distance to the target */
8331 srcOffs = emitCurCodeOffs(dst);
8332 srcAddr = emitOffsetToPtr(srcOffs);
8334 if (id->idAddr()->iiaIsJitDataOffset())
8336 assert(loadConstant || loadLabel);
8337 int doff = id->idAddr()->iiaGetJitDataOffset();
8339 ssize_t imm = emitGetInsSC(id);
8340 assert((imm >= 0) && (imm < 0x1000)); // 0x1000 is arbitrary, currently 'imm' is always 0
8342 unsigned dataOffs = (unsigned)(doff + imm);
8343 assert(dataOffs < emitDataSize());
8344 dstAddr = emitDataOffsetToPtr(dataOffs);
8346 regNumber dstReg = id->idReg1();
8347 regNumber addrReg = dstReg; // an integer register to compute long address.
8348 emitAttr opSize = id->idOpSize();
8354 // ldr x/v, [rel addr] -- load constant from current addr(ip) + rel addr.
8355 assert(ins == INS_ldr);
8356 assert(fmt == IF_LS_1A);
8357 distVal = (ssize_t)(dstAddr - srcAddr);
8358 dst = emitOutputShortConstant(dst, ins, fmt, distVal, dstReg, opSize);
8362 // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8363 assert(fmt == IF_LARGELDC);
8364 ssize_t relPageAddr =
8365 (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8366 if (isVectorRegister(dstReg))
8368 // Update addrReg with the reserved integer register
8369 // since we cannot use dstReg (vector) to load constant directly from memory.
8370 addrReg = id->idReg2();
8371 assert(isGeneralRegister(addrReg));
8375 dst = emitOutputShortAddress(dst, ins, fmt, relPageAddr, addrReg);
8377 // ldr x, [x, page offs] -- load constant from page address + page offset into integer register.
8378 ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8379 assert(isValidUimm12(imm12));
8382 dst = emitOutputShortConstant(dst, ins, fmt, imm12, addrReg, opSize);
8384 // fmov v, d -- copy constant in integer register to vector register.
8385 // This is needed only for vector constant.
8386 if (addrReg != dstReg)
8388 // fmov Vd,Rn DV_2I X00111100X100111 000000nnnnnddddd 1E27 0000 Vd,Rn
8389 // (scalar, from general)
8390 assert(isVectorRegister(dstReg) && isGeneralRegister(addrReg));
8393 code_t code = emitInsCode(ins, fmt);
8395 code |= insEncodeReg_Vd(dstReg); // ddddd
8396 code |= insEncodeReg_Rn(addrReg); // nnnnn
8397 if (id->idOpSize() == EA_8BYTE)
8399 code |= 0x80400000; // X ... X
8401 dst += emitOutput_Instr(dst, code);
8408 dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8414 assert(loadLabel || isJump);
8416 if (id->idAddr()->iiaHasInstrCount())
8419 int instrCount = id->idAddr()->iiaGetInstrCount();
8420 unsigned insNum = emitFindInsNum(ig, id);
8423 // Backward branches using instruction count must be within the same instruction group.
8424 assert(insNum + 1 >= (unsigned)(-instrCount));
8426 dstOffs = ig->igOffs + emitFindOffset(ig, (insNum + 1 + instrCount));
8427 dstAddr = emitOffsetToPtr(dstOffs);
8431 dstOffs = id->idAddr()->iiaIGlabel->igOffs;
8432 dstAddr = emitOffsetToPtr(dstOffs);
8435 distVal = (ssize_t)(dstAddr - srcAddr);
8437 if (dstOffs <= srcOffs)
8440 /* This is a backward jump - distance is known at this point */
8442 if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8444 size_t blkOffs = id->idjIG->igOffs;
8446 if (INTERESTING_JUMP_NUM == 0)
8447 printf("[3] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8448 printf("[3] Jump block is at %08X - %02X = %08X\n", blkOffs, emitOffsAdj, blkOffs - emitOffsAdj);
8449 printf("[3] Jump is at %08X - %02X = %08X\n", srcOffs, emitOffsAdj, srcOffs - emitOffsAdj);
8450 printf("[3] Label block is at %08X - %02X = %08X\n", dstOffs, emitOffsAdj, dstOffs - emitOffsAdj);
8456 /* This is a forward jump - distance will be an upper limit */
8458 emitFwdJumps = true;
8460 /* The target offset will be closer by at least 'emitOffsAdj', but only if this
8461 jump doesn't cross the hot-cold boundary. */
8463 if (!emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8465 dstOffs -= emitOffsAdj;
8466 distVal -= emitOffsAdj;
8469 /* Record the location of the jump for later patching */
8471 id->idjOffs = dstOffs;
8473 /* Are we overflowing the id->idjOffs bitfield? */
8474 if (id->idjOffs != dstOffs)
8475 IMPL_LIMITATION("Method is too large");
8478 if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8480 size_t blkOffs = id->idjIG->igOffs;
8482 if (INTERESTING_JUMP_NUM == 0)
8483 printf("[4] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8484 printf("[4] Jump block is at %08X\n", blkOffs);
8485 printf("[4] Jump is at %08X\n", srcOffs);
8486 printf("[4] Label block is at %08X - %02X = %08X\n", dstOffs + emitOffsAdj, emitOffsAdj, dstOffs);
8492 if (0 && emitComp->verbose)
8495 int distValSize = id->idjShort ? 4 : 8;
8496 printf("; %s jump [%08X/%03u] from %0*X to %0*X: dist = %08XH\n", (dstOffs <= srcOffs) ? "Fwd" : "Bwd",
8497 dspPtr(id), id->idDebugOnlyInfo()->idNum, distValSize, srcOffs + sz, distValSize, dstOffs, distVal);
8501 /* For forward jumps, record the address of the distance value */
8502 id->idjTemp.idjAddr = (distVal > 0) ? dst : NULL;
8504 if (emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8506 assert(!id->idjShort);
8507 NYI_ARM64("Relocation Support for long address");
8510 assert(insOptsNone(id->idInsOpt()));
8516 // Short conditional/unconditional jump
8517 assert(!id->idjKeepLong);
8518 assert(emitJumpCrossHotColdBoundary(srcOffs, dstOffs) == false);
8519 assert((fmt == IF_BI_0A) || (fmt == IF_BI_0B) || (fmt == IF_BI_1A) || (fmt == IF_BI_1B));
8523 // Long conditional jump
8524 assert(fmt == IF_LARGEJMP);
8525 // This is a pseudo-instruction format representing a large conditional branch, to allow
8526 // us to get a greater branch target range than we can get by using a straightforward conditional
8527 // branch. It is encoded as a short conditional branch that branches around a long unconditional
8530 // Conceptually, we have:
8534 // The code we emit is:
8536 // b<!cond> L_not // 4 bytes. Note that we reverse the condition.
8537 // b L_target // 4 bytes
8540 // Note that we don't actually insert any blocks: we simply encode "b <!cond> L_not" as a branch with
8541 // the correct offset. Note also that this works for both integer and floating-point conditions, because
8542 // the condition inversion takes ordered/unordered into account, preserving NaN behavior. For example,
8543 // "GT" (greater than) is inverted to "LE" (less than, equal, or unordered).
8545 instruction reverseIns;
8546 insFormat reverseFmt;
8551 reverseIns = INS_cbnz;
8552 reverseFmt = IF_BI_1A;
8555 reverseIns = INS_cbz;
8556 reverseFmt = IF_BI_1A;
8559 reverseIns = INS_tbnz;
8560 reverseFmt = IF_BI_1B;
8563 reverseIns = INS_tbz;
8564 reverseFmt = IF_BI_1B;
8567 reverseIns = emitJumpKindToIns(emitReverseJumpKind(emitInsToJumpKind(ins)));
8568 reverseFmt = IF_BI_0B;
8572 emitOutputShortBranch(dst,
8573 reverseIns, // reverse the conditional instruction
8575 8, /* 8 bytes from start of this large conditional pseudo-instruction to L_not. */
8578 // Now, pretend we've got a normal unconditional branch, and fall through to the code to emit that.
8582 // The distVal was computed based on the beginning of the pseudo-instruction,
8583 // So subtract the size of the conditional branch so that it is relative to the
8584 // unconditional branch.
8588 dst = emitOutputShortBranch(dst, ins, fmt, distVal, id);
8592 dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8598 /*****************************************************************************
8600 * Output a short branch instruction.
8602 BYTE* emitter::emitOutputShortBranch(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, instrDescJmp* id)
8604 code_t code = emitInsCode(ins, fmt);
8606 ssize_t loBits = (distVal & 3);
8607 noway_assert(loBits == 0);
8608 distVal >>= 2; // branch offset encodings are scaled by 4.
8610 if (fmt == IF_BI_0A)
8612 // INS_b or INS_bl_local
8613 noway_assert(isValidSimm26(distVal));
8614 distVal &= 0x3FFFFFFLL;
8617 else if (fmt == IF_BI_0B) // BI_0B 01010100iiiiiiii iiiiiiiiiiiXXXXX simm19:00
8619 // INS_beq, INS_bne, etc...
8620 noway_assert(isValidSimm19(distVal));
8621 distVal &= 0x7FFFFLL;
8622 code |= distVal << 5;
8624 else if (fmt == IF_BI_1A) // BI_1A X.......iiiiiiii iiiiiiiiiiittttt Rt simm19:00
8626 // INS_cbz or INS_cbnz
8627 assert(id != nullptr);
8628 code |= insEncodeDatasize(id->idOpSize()); // X
8629 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
8631 noway_assert(isValidSimm19(distVal));
8632 distVal &= 0x7FFFFLL; // 19 bits
8633 code |= distVal << 5;
8635 else if (fmt == IF_BI_1B) // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
8637 // INS_tbz or INS_tbnz
8638 assert(id != nullptr);
8639 ssize_t imm = emitGetInsSC(id);
8640 assert(isValidImmShift(imm, id->idOpSize()));
8642 if (imm & 0x20) // test bit 32-63 ?
8644 code |= 0x80000000; // B
8646 code |= ((imm & 0x1F) << 19); // bbbbb
8647 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
8649 noway_assert(isValidSimm14(distVal));
8650 distVal &= 0x3FFFLL; // 14 bits
8651 code |= distVal << 5;
8655 assert(!"Unknown fmt for emitOutputShortBranch");
8658 dst += emitOutput_Instr(dst, code);
8663 /*****************************************************************************
8665 * Output a short address instruction.
8667 BYTE* emitter::emitOutputShortAddress(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, regNumber reg)
8669 ssize_t loBits = (distVal & 3);
8672 code_t code = emitInsCode(ins, fmt);
8673 if (fmt == IF_DI_1E) // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
8675 // INS_adr or INS_adrp
8676 code |= insEncodeReg_Rd(reg); // ddddd
8678 noway_assert(isValidSimm19(distVal));
8679 distVal &= 0x7FFFFLL; // 19 bits
8680 code |= distVal << 5;
8681 code |= loBits << 29; // 2 bits
8685 assert(!"Unknown fmt for emitOutputShortAddress");
8688 dst += emitOutput_Instr(dst, code);
8693 /*****************************************************************************
8695 * Output a short constant instruction.
8697 BYTE* emitter::emitOutputShortConstant(
8698 BYTE* dst, instruction ins, insFormat fmt, ssize_t imm, regNumber reg, emitAttr opSize)
8700 code_t code = emitInsCode(ins, fmt);
8702 if (fmt == IF_LS_1A)
8704 // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt simm21
8705 // INS_ldr or INS_ldrsw (PC-Relative)
8707 ssize_t loBits = (imm & 3);
8708 noway_assert(loBits == 0);
8709 ssize_t distVal = imm >>= 2; // load offset encodings are scaled by 4.
8711 noway_assert(isValidSimm19(distVal));
8713 // Is the target a vector register?
8714 if (isVectorRegister(reg))
8716 code |= insEncodeDatasizeVLS(code, opSize); // XX V
8717 code |= insEncodeReg_Vt(reg); // ttttt
8721 assert(isGeneralRegister(reg));
8722 // insEncodeDatasizeLS is not quite right for this case.
8723 // So just specialize it.
8724 if ((ins == INS_ldr) && (opSize == EA_8BYTE))
8726 // set the operation size in bit 30
8730 code |= insEncodeReg_Rt(reg); // ttttt
8733 distVal &= 0x7FFFFLL; // 19 bits
8734 code |= distVal << 5;
8736 else if (fmt == IF_LS_2B)
8738 // ldr Rt,[Xn+pimm12] LS_2B 1X11100101iiiiii iiiiiinnnnnttttt B940 0000 imm(0-4095<<{2,3})
8739 // INS_ldr or INS_ldrsw (PC-Relative)
8740 noway_assert(isValidUimm12(imm));
8741 assert(isGeneralRegister(reg));
8743 if (opSize == EA_8BYTE)
8745 // insEncodeDatasizeLS is not quite right for this case.
8746 // So just specialize it.
8749 // set the operation size in bit 30
8752 // Low 3 bits should be 0 -- 8 byte JIT data should be aligned on 8 byte.
8753 assert((imm & 7) == 0);
8758 assert(opSize == EA_4BYTE);
8759 // Low 2 bits should be 0 -- 4 byte aligned data.
8760 assert((imm & 3) == 0);
8764 code |= insEncodeReg_Rt(reg); // ttttt
8765 code |= insEncodeReg_Rn(reg); // nnnnn
8770 assert(!"Unknown fmt for emitOutputShortConstant");
8773 dst += emitOutput_Instr(dst, code);
8777 /*****************************************************************************
8779 * Output a call instruction.
8782 unsigned emitter::emitOutputCall(insGroup* ig, BYTE* dst, instrDesc* id, code_t code)
8784 const unsigned char callInstrSize = sizeof(code_t); // 4 bytes
8785 regMaskTP gcrefRegs;
8786 regMaskTP byrefRegs;
8788 VARSET_TP GCvars(VarSetOps::UninitVal());
8790 // Is this a "fat" call descriptor?
8791 if (id->idIsLargeCall())
8793 instrDescCGCA* idCall = (instrDescCGCA*)id;
8794 gcrefRegs = idCall->idcGcrefRegs;
8795 byrefRegs = idCall->idcByrefRegs;
8796 VarSetOps::Assign(emitComp, GCvars, idCall->idcGCvars);
8800 assert(!id->idIsLargeDsp());
8801 assert(!id->idIsLargeCns());
8803 gcrefRegs = emitDecodeCallGCregs(id);
8805 VarSetOps::AssignNoCopy(emitComp, GCvars, VarSetOps::MakeEmpty(emitComp));
8808 /* We update the GC info before the call as the variables cannot be
8809 used by the call. Killing variables before the call helps with
8810 boundary conditions if the call is CORINFO_HELP_THROW - see bug 50029.
8811 If we ever track aliased variables (which could be used by the
8812 call), we would have to keep them alive past the call. */
8814 emitUpdateLiveGCvars(GCvars, dst);
8816 // Now output the call instruction and update the 'dst' pointer
8818 unsigned outputInstrSize = emitOutput_Instr(dst, code);
8819 dst += outputInstrSize;
8821 // All call instructions are 4-byte in size on ARM64
8823 assert(outputInstrSize == callInstrSize);
8825 // If the method returns a GC ref, mark INTRET (R0) appropriately.
8826 if (id->idGCref() == GCT_GCREF)
8828 gcrefRegs |= RBM_INTRET;
8830 else if (id->idGCref() == GCT_BYREF)
8832 byrefRegs |= RBM_INTRET;
8835 // If is a multi-register return method is called, mark INTRET_1 (X1) appropriately
8836 if (id->idIsLargeCall())
8838 instrDescCGCA* idCall = (instrDescCGCA*)id;
8839 if (idCall->idSecondGCref() == GCT_GCREF)
8841 gcrefRegs |= RBM_INTRET_1;
8843 else if (idCall->idSecondGCref() == GCT_BYREF)
8845 byrefRegs |= RBM_INTRET_1;
8849 // If the GC register set has changed, report the new set.
8850 if (gcrefRegs != emitThisGCrefRegs)
8852 emitUpdateLiveGCregs(GCT_GCREF, gcrefRegs, dst);
8854 // If the Byref register set has changed, report the new set.
8855 if (byrefRegs != emitThisByrefRegs)
8857 emitUpdateLiveGCregs(GCT_BYREF, byrefRegs, dst);
8860 // Some helper calls may be marked as not requiring GC info to be recorded.
8861 if ((!id->idIsNoGC()))
8863 // On ARM64, as on AMD64, we don't change the stack pointer to push/pop args.
8864 // So we're not really doing a "stack pop" here (note that "args" is 0), but we use this mechanism
8865 // to record the call for GC info purposes. (It might be best to use an alternate call,
8866 // and protect "emitStackPop" under the EMIT_TRACK_STACK_DEPTH preprocessor variable.)
8867 emitStackPop(dst, /*isCall*/ true, callInstrSize, /*args*/ 0);
8869 // Do we need to record a call location for GC purposes?
8871 if (!emitFullGCinfo)
8873 emitRecordGCcall(dst, callInstrSize);
8876 return callInstrSize;
8879 /*****************************************************************************
8881 * Emit a 32-bit Arm64 instruction
8884 /*static*/ unsigned emitter::emitOutput_Instr(BYTE* dst, code_t code)
8886 assert(sizeof(code_t) == 4);
8887 *((code_t*)dst) = code;
8889 return sizeof(code_t);
8892 /*****************************************************************************
8894 * Append the machine code corresponding to the given instruction descriptor
8895 * to the code block at '*dp'; the base of the code block is 'bp', and 'ig'
8896 * is the instruction group that contains the instruction. Updates '*dp' to
8897 * point past the generated code, and returns the size of the instruction
8898 * descriptor in bytes.
8901 size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
8906 size_t sz = emitGetInstrDescSize(id); // TODO-ARM64-Cleanup: on ARM, this is set in each case. why?
8907 instruction ins = id->idIns();
8908 insFormat fmt = id->idInsFmt();
8909 emitAttr size = id->idOpSize();
8910 unsigned char callInstrSize = 0;
8915 bool dspOffs = emitComp->opts.dspGCtbls;
8917 bool dspOffs = !emitComp->opts.disDiffable;
8921 assert(REG_NA == (int)REG_NA);
8923 VARSET_TP GCvars(VarSetOps::UninitVal());
8925 /* What instruction format have we got? */
8940 case IF_BI_0A: // BI_0A ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
8941 case IF_BI_0B: // BI_0B ......iiiiiiiiii iiiiiiiiiii..... simm19:00
8943 assert(id->idGCref() == GCT_NONE);
8944 assert(id->idIsBound());
8945 dst = emitOutputLJ(ig, dst, id);
8946 sz = sizeof(instrDescJmp);
8949 case IF_BI_0C: // BI_0C ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
8950 code = emitInsCode(ins, fmt);
8951 sz = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
8952 dst += emitOutputCall(ig, dst, id, code);
8953 // Always call RecordRelocation so that we wire in a JumpStub when we don't reach
8954 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_BRANCH26);
8957 case IF_BI_1A: // BI_1A ......iiiiiiiiii iiiiiiiiiiittttt Rt simm19:00
8958 assert(insOptsNone(id->idInsOpt()));
8959 assert(id->idIsBound());
8961 dst = emitOutputLJ(ig, dst, id);
8962 sz = sizeof(instrDescJmp);
8965 case IF_BI_1B: // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
8966 assert(insOptsNone(id->idInsOpt()));
8967 assert(id->idIsBound());
8969 dst = emitOutputLJ(ig, dst, id);
8970 sz = sizeof(instrDescJmp);
8973 case IF_BR_1A: // BR_1A ................ ......nnnnn..... Rn
8974 assert(insOptsNone(id->idInsOpt()));
8975 assert((ins == INS_ret) || (ins == INS_br));
8976 code = emitInsCode(ins, fmt);
8977 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
8979 dst += emitOutput_Instr(dst, code);
8982 case IF_BR_1B: // BR_1B ................ ......nnnnn..... Rn
8983 assert(insOptsNone(id->idInsOpt()));
8984 assert((ins == INS_br_tail) || (ins == INS_blr));
8985 code = emitInsCode(ins, fmt);
8986 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
8988 sz = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
8989 dst += emitOutputCall(ig, dst, id, code);
8992 case IF_LS_1A: // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB)
8994 assert(insOptsNone(id->idInsOpt()));
8995 assert(id->idIsBound());
8997 dst = emitOutputLJ(ig, dst, id);
8998 sz = sizeof(instrDescJmp);
9001 case IF_LS_2A: // LS_2A .X.......X...... ......nnnnnttttt Rt Rn
9002 assert(insOptsNone(id->idInsOpt()));
9003 code = emitInsCode(ins, fmt);
9004 // Is the target a vector register?
9005 if (isVectorRegister(id->idReg1()))
9007 code &= 0x3FFFFFFF; // clear the size bits
9008 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9009 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9013 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9014 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9016 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9017 dst += emitOutput_Instr(dst, code);
9020 case IF_LS_2B: // LS_2B .X.......Xiiiiii iiiiiinnnnnttttt Rt Rn imm(0-4095)
9021 assert(insOptsNone(id->idInsOpt()));
9022 imm = emitGetInsSC(id);
9023 assert(isValidUimm12(imm));
9024 code = emitInsCode(ins, fmt);
9025 // Is the target a vector register?
9026 if (isVectorRegister(id->idReg1()))
9028 code &= 0x3FFFFFFF; // clear the size bits
9029 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9030 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9034 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9035 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9037 code |= ((code_t)imm << 10); // iiiiiiiiiiii
9038 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9039 dst += emitOutput_Instr(dst, code);
9042 case IF_LS_2C: // LS_2C .X.......X.iiiii iiiiPPnnnnnttttt Rt Rn imm(-256..+255) no/pre/post inc
9043 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9044 imm = emitGetInsSC(id);
9045 assert((imm >= -256) && (imm <= 255)); // signed 9 bits
9046 imm &= 0x1ff; // force into unsigned 9 bit representation
9047 code = emitInsCode(ins, fmt);
9048 // Is the target a vector register?
9049 if (isVectorRegister(id->idReg1()))
9051 code &= 0x3FFFFFFF; // clear the size bits
9052 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9053 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9057 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9058 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9060 code |= insEncodeIndexedOpt(id->idInsOpt()); // PP
9061 code |= ((code_t)imm << 12); // iiiiiiiii
9062 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9063 dst += emitOutput_Instr(dst, code);
9066 case IF_LS_3A: // LS_3A .X.......X.mmmmm oooS..nnnnnttttt Rt Rn Rm ext(Rm) LSL {}
9067 assert(insOptsLSExtend(id->idInsOpt()));
9068 code = emitInsCode(ins, fmt);
9069 // Is the target a vector register?
9070 if (isVectorRegister(id->idReg1()))
9072 code &= 0x3FFFFFFF; // clear the size bits
9073 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9074 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9078 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9079 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9081 code |= insEncodeExtend(id->idInsOpt()); // ooo
9082 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9083 if (id->idIsLclVar())
9085 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9089 code |= insEncodeReg3Scale(id->idReg3Scaled()); // S
9090 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9092 dst += emitOutput_Instr(dst, code);
9095 case IF_LS_3B: // LS_3B X............... .aaaaannnnnddddd Rd Ra Rn
9096 assert(insOptsNone(id->idInsOpt()));
9097 code = emitInsCode(ins, fmt);
9098 // Is the target a vector register?
9099 if (isVectorRegister(id->idReg1()))
9101 code &= 0x3FFFFFFF; // clear the size bits
9102 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9103 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9104 code |= insEncodeReg_Va(id->idReg2()); // aaaaa
9108 code |= insEncodeDatasize(id->idOpSize()); // X
9109 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9110 code |= insEncodeReg_Ra(id->idReg2()); // aaaaa
9112 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9113 dst += emitOutput_Instr(dst, code);
9116 case IF_LS_3C: // LS_3C X......PP.iiiiii iaaaaannnnnddddd Rd Ra Rn imm(im7,sh)
9117 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9118 imm = emitGetInsSC(id);
9119 assert((imm >= -64) && (imm <= 63)); // signed 7 bits
9120 imm &= 0x7f; // force into unsigned 7 bit representation
9121 code = emitInsCode(ins, fmt);
9122 // Is the target a vector register?
9123 if (isVectorRegister(id->idReg1()))
9125 code &= 0x3FFFFFFF; // clear the size bits
9126 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9127 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9128 code |= insEncodeReg_Va(id->idReg2()); // aaaaa
9132 code |= insEncodeDatasize(id->idOpSize()); // X
9133 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9134 code |= insEncodeReg_Ra(id->idReg2()); // aaaaa
9136 code |= insEncodePairIndexedOpt(ins, id->idInsOpt()); // PP
9137 code |= ((code_t)imm << 15); // iiiiiiiii
9138 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9139 dst += emitOutput_Instr(dst, code);
9142 case IF_LS_3D: // LS_3D .X.......X.mmmmm ......nnnnnttttt Wm Rt Rn
9143 code = emitInsCode(ins, fmt);
9144 // Arm64 store exclusive unpredictable cases
9145 assert(id->idReg1() != id->idReg2());
9146 assert(id->idReg1() != id->idReg3());
9147 code |= insEncodeDatasizeLS(code, id->idOpSize()); // X
9148 code |= insEncodeReg_Rm(id->idReg1()); // mmmmm
9149 code |= insEncodeReg_Rt(id->idReg2()); // ttttt
9150 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9151 dst += emitOutput_Instr(dst, code);
9154 case IF_DI_1A: // DI_1A X.......shiiiiii iiiiiinnnnn..... Rn imm(i12,sh)
9155 assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9156 imm = emitGetInsSC(id);
9157 assert(isValidUimm12(imm));
9158 code = emitInsCode(ins, fmt);
9159 code |= insEncodeDatasize(id->idOpSize()); // X
9160 code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9161 code |= ((code_t)imm << 10); // iiiiiiiiiiii
9162 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9163 dst += emitOutput_Instr(dst, code);
9166 case IF_DI_1B: // DI_1B X........hwiiiii iiiiiiiiiiiddddd Rd imm(i16,hw)
9167 imm = emitGetInsSC(id);
9168 assert(isValidImmHWVal(imm, id->idOpSize()));
9169 code = emitInsCode(ins, fmt);
9170 code |= insEncodeDatasize(id->idOpSize()); // X
9171 code |= ((code_t)imm << 5); // hwiiiii iiiiiiiiiii
9172 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9173 dst += emitOutput_Instr(dst, code);
9176 case IF_DI_1C: // DI_1C X........Nrrrrrr ssssssnnnnn..... Rn imm(N,r,s)
9177 imm = emitGetInsSC(id);
9178 assert(isValidImmNRS(imm, id->idOpSize()));
9179 code = emitInsCode(ins, fmt);
9180 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9181 code |= insEncodeDatasize(id->idOpSize()); // X
9182 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9183 dst += emitOutput_Instr(dst, code);
9186 case IF_DI_1D: // DI_1D X........Nrrrrrr ssssss.....ddddd Rd imm(N,r,s)
9187 imm = emitGetInsSC(id);
9188 assert(isValidImmNRS(imm, id->idOpSize()));
9189 code = emitInsCode(ins, fmt);
9190 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9191 code |= insEncodeDatasize(id->idOpSize()); // X
9192 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9193 dst += emitOutput_Instr(dst, code);
9196 case IF_DI_1E: // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
9198 assert(insOptsNone(id->idInsOpt()));
9199 if (id->idIsReloc())
9201 code = emitInsCode(ins, fmt);
9202 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9203 dst += emitOutput_Instr(dst, code);
9204 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEBASE_REL21);
9208 // Local jmp/load case which does not need a relocation.
9209 assert(id->idIsBound());
9210 dst = emitOutputLJ(ig, dst, id);
9212 sz = sizeof(instrDescJmp);
9215 case IF_DI_1F: // DI_1F X..........iiiii cccc..nnnnn.nzcv Rn imm5 nzcv cond
9216 imm = emitGetInsSC(id);
9217 assert(isValidImmCondFlagsImm5(imm));
9220 cfi.immCFVal = (unsigned)imm;
9221 code = emitInsCode(ins, fmt);
9222 code |= insEncodeDatasize(id->idOpSize()); // X
9223 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9224 code |= ((code_t)cfi.imm5 << 16); // iiiii
9225 code |= insEncodeFlags(cfi.flags); // nzcv
9226 code |= insEncodeCond(cfi.cond); // cccc
9227 dst += emitOutput_Instr(dst, code);
9231 case IF_DI_2A: // DI_2A X.......shiiiiii iiiiiinnnnnddddd Rd Rn imm(i12,sh)
9232 assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9233 imm = emitGetInsSC(id);
9234 assert(isValidUimm12(imm));
9235 code = emitInsCode(ins, fmt);
9236 code |= insEncodeDatasize(id->idOpSize()); // X
9237 code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9238 code |= ((code_t)imm << 10); // iiiiiiiiiiii
9239 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9240 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9241 dst += emitOutput_Instr(dst, code);
9243 if (id->idIsReloc())
9245 assert(sz == sizeof(instrDesc));
9246 assert(id->idAddr()->iiaAddr != nullptr);
9247 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEOFFSET_12A);
9251 case IF_DI_2B: // DI_2B X.........Xnnnnn ssssssnnnnnddddd Rd Rn imm(0-63)
9252 code = emitInsCode(ins, fmt);
9253 imm = emitGetInsSC(id);
9254 assert(isValidImmShift(imm, id->idOpSize()));
9255 code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9256 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9257 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9258 code |= insEncodeReg_Rm(id->idReg2()); // Reg2 also in mmmmm
9259 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9260 dst += emitOutput_Instr(dst, code);
9263 case IF_DI_2C: // DI_2C X........Nrrrrrr ssssssnnnnnddddd Rd Rn imm(N,r,s)
9264 imm = emitGetInsSC(id);
9265 assert(isValidImmNRS(imm, id->idOpSize()));
9266 code = emitInsCode(ins, fmt);
9267 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9268 code |= insEncodeDatasize(id->idOpSize()); // X
9269 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9270 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9271 dst += emitOutput_Instr(dst, code);
9274 case IF_DI_2D: // DI_2D X........Nrrrrrr ssssssnnnnnddddd Rd Rn imr, imms (N,r,s)
9275 if (ins == INS_asr || ins == INS_lsl || ins == INS_lsr)
9277 imm = emitGetInsSC(id);
9278 assert(isValidImmShift(imm, id->idOpSize()));
9280 // Shift immediates are aliases of the SBFM/UBFM instructions
9281 // that actually take 2 registers and 2 constants,
9282 // Since we stored the shift immediate value
9283 // we need to calculate the N,R and S values here.
9288 bmi.immN = (size == EA_8BYTE) ? 1 : 0;
9290 bmi.immS = (size == EA_8BYTE) ? 0x3f : 0x1f;
9292 // immR and immS are now set correctly for INS_asr and INS_lsr
9293 // but for INS_lsl we have to adjust the values for immR and immS
9297 bmi.immR = -imm & bmi.immS;
9298 bmi.immS = bmi.immS - imm;
9301 // setup imm with the proper 13 bit value N:R:S
9307 // The other instructions have already have encoded N,R and S values
9308 imm = emitGetInsSC(id);
9310 assert(isValidImmNRS(imm, id->idOpSize()));
9312 code = emitInsCode(ins, fmt);
9313 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9314 code |= insEncodeDatasize(id->idOpSize()); // X
9315 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9316 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9317 dst += emitOutput_Instr(dst, code);
9320 case IF_DR_1D: // DR_1D X............... cccc.......ddddd Rd cond
9321 imm = emitGetInsSC(id);
9322 assert(isValidImmCond(imm));
9325 cfi.immCFVal = (unsigned)imm;
9326 code = emitInsCode(ins, fmt);
9327 code |= insEncodeDatasize(id->idOpSize()); // X
9328 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9329 code |= insEncodeInvertedCond(cfi.cond); // cccc
9330 dst += emitOutput_Instr(dst, code);
9334 case IF_DR_2A: // DR_2A X..........mmmmm ......nnnnn..... Rn Rm
9335 assert(insOptsNone(id->idInsOpt()));
9336 code = emitInsCode(ins, fmt);
9337 code |= insEncodeDatasize(id->idOpSize()); // X
9338 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9339 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9340 dst += emitOutput_Instr(dst, code);
9343 case IF_DR_2B: // DR_2B X.......sh.mmmmm ssssssnnnnn..... Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
9344 code = emitInsCode(ins, fmt);
9345 imm = emitGetInsSC(id);
9346 assert(isValidImmShift(imm, id->idOpSize()));
9347 code |= insEncodeDatasize(id->idOpSize()); // X
9348 code |= insEncodeShiftType(id->idInsOpt()); // sh
9349 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9350 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9351 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9352 dst += emitOutput_Instr(dst, code);
9355 case IF_DR_2C: // DR_2C X..........mmmmm ooosssnnnnn..... Rn Rm ext(Rm) LSL imm(0-4)
9356 code = emitInsCode(ins, fmt);
9357 imm = emitGetInsSC(id);
9358 assert((imm >= 0) && (imm <= 4)); // imm [0..4]
9359 code |= insEncodeDatasize(id->idOpSize()); // X
9360 code |= insEncodeExtend(id->idInsOpt()); // ooo
9361 code |= insEncodeExtendScale(imm); // sss
9362 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9363 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9364 dst += emitOutput_Instr(dst, code);
9367 case IF_DR_2D: // DR_2D X..........nnnnn cccc..nnnnnddddd Rd Rn cond
9368 imm = emitGetInsSC(id);
9369 assert(isValidImmCond(imm));
9372 cfi.immCFVal = (unsigned)imm;
9373 code = emitInsCode(ins, fmt);
9374 code |= insEncodeDatasize(id->idOpSize()); // X
9375 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9376 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9377 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9378 code |= insEncodeInvertedCond(cfi.cond); // cccc
9379 dst += emitOutput_Instr(dst, code);
9383 case IF_DR_2E: // DR_2E X..........mmmmm ...........ddddd Rd Rm
9384 code = emitInsCode(ins, fmt);
9385 code |= insEncodeDatasize(id->idOpSize()); // X
9386 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9387 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9388 dst += emitOutput_Instr(dst, code);
9391 case IF_DR_2F: // DR_2F X.......sh.mmmmm ssssss.....ddddd Rd Rm {LSL,LSR,ASR} imm(0-63)
9392 code = emitInsCode(ins, fmt);
9393 imm = emitGetInsSC(id);
9394 assert(isValidImmShift(imm, id->idOpSize()));
9395 code |= insEncodeDatasize(id->idOpSize()); // X
9396 code |= insEncodeShiftType(id->idInsOpt()); // sh
9397 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9398 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9399 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9400 dst += emitOutput_Instr(dst, code);
9403 case IF_DR_2G: // DR_2G X............... .....xnnnnnddddd Rd Rn
9404 code = emitInsCode(ins, fmt);
9405 code |= insEncodeDatasize(id->idOpSize()); // X
9408 if (size == EA_8BYTE)
9410 code |= 0x00000400; // x - bit at location 10
9413 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9414 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9415 dst += emitOutput_Instr(dst, code);
9418 case IF_DR_2H: // DR_2H X........X...... ......nnnnnddddd Rd Rn
9419 code = emitInsCode(ins, fmt);
9420 code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9421 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9422 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9423 dst += emitOutput_Instr(dst, code);
9426 case IF_DR_2I: // DR_2I X..........mmmmm cccc..nnnnn.nzcv Rn Rm nzcv cond
9427 imm = emitGetInsSC(id);
9428 assert(isValidImmCondFlags(imm));
9431 cfi.immCFVal = (unsigned)imm;
9432 code = emitInsCode(ins, fmt);
9433 code |= insEncodeDatasize(id->idOpSize()); // X
9434 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9435 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9436 code |= insEncodeFlags(cfi.flags); // nzcv
9437 code |= insEncodeCond(cfi.cond); // cccc
9438 dst += emitOutput_Instr(dst, code);
9442 case IF_DR_3A: // DR_3A X..........mmmmm ......nnnnnmmmmm Rd Rn Rm
9443 code = emitInsCode(ins, fmt);
9444 code |= insEncodeDatasize(id->idOpSize()); // X
9445 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9446 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9447 if (id->idIsLclVar())
9449 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9453 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9455 dst += emitOutput_Instr(dst, code);
9458 case IF_DR_3B: // DR_3B X.......sh.mmmmm ssssssnnnnnddddd Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
9459 code = emitInsCode(ins, fmt);
9460 imm = emitGetInsSC(id);
9461 assert(isValidImmShift(imm, id->idOpSize()));
9462 code |= insEncodeDatasize(id->idOpSize()); // X
9463 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9464 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9465 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9466 code |= insEncodeShiftType(id->idInsOpt()); // sh
9467 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9468 dst += emitOutput_Instr(dst, code);
9471 case IF_DR_3C: // DR_3C X..........mmmmm ooosssnnnnnddddd Rd Rn Rm ext(Rm) LSL imm(0-4)
9472 code = emitInsCode(ins, fmt);
9473 imm = emitGetInsSC(id);
9474 assert((imm >= 0) && (imm <= 4)); // imm [0..4]
9475 code |= insEncodeDatasize(id->idOpSize()); // X
9476 code |= insEncodeExtend(id->idInsOpt()); // ooo
9477 code |= insEncodeExtendScale(imm); // sss
9478 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9479 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9480 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9481 dst += emitOutput_Instr(dst, code);
9484 case IF_DR_3D: // DR_3D X..........mmmmm cccc..nnnnnddddd Rd Rn Rm cond
9485 imm = emitGetInsSC(id);
9486 assert(isValidImmCond(imm));
9489 cfi.immCFVal = (unsigned)imm;
9490 code = emitInsCode(ins, fmt);
9491 code |= insEncodeDatasize(id->idOpSize()); // X
9492 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9493 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9494 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9495 code |= insEncodeCond(cfi.cond); // cccc
9496 dst += emitOutput_Instr(dst, code);
9500 case IF_DR_3E: // DR_3E X........X.mmmmm ssssssnnnnnddddd Rd Rn Rm imm(0-63)
9501 code = emitInsCode(ins, fmt);
9502 imm = emitGetInsSC(id);
9503 assert(isValidImmShift(imm, id->idOpSize()));
9504 code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9505 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9506 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9507 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9508 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9509 dst += emitOutput_Instr(dst, code);
9512 case IF_DR_4A: // DR_4A X..........mmmmm .aaaaannnnnmmmmm Rd Rn Rm Ra
9513 code = emitInsCode(ins, fmt);
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 |= insEncodeReg_Ra(id->idReg4()); // aaaaa
9519 dst += emitOutput_Instr(dst, code);
9522 case IF_DV_1A: // DV_1A .........X.iiiii iii........ddddd Vd imm8 (fmov - immediate scalar)
9523 imm = emitGetInsSC(id);
9524 elemsize = id->idOpSize();
9525 code = emitInsCode(ins, fmt);
9526 code |= insEncodeFloatElemsize(elemsize); // X
9527 code |= ((code_t)imm << 13); // iiiii iii
9528 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9529 dst += emitOutput_Instr(dst, code);
9532 case IF_DV_1B: // DV_1B .QX..........iii cmod..iiiiiddddd Vd imm8 (immediate vector)
9533 imm = emitGetInsSC(id) & 0x0ff;
9534 immShift = (emitGetInsSC(id) & 0x700) >> 8;
9535 elemsize = optGetElemsize(id->idInsOpt());
9540 cmode = 0xE; // 1110
9544 cmode |= (immShift << 1); // 10x0
9550 cmode |= (immShift << 1); // 0xx0
9560 cmode = 0xE; // 1110
9567 code = emitInsCode(ins, fmt);
9568 code |= insEncodeVectorsize(id->idOpSize()); // Q
9569 if ((ins == INS_fmov) || (ins == INS_movi))
9571 if (elemsize == EA_8BYTE)
9573 code |= 0x20000000; // X
9576 if (ins != INS_fmov)
9578 assert((cmode >= 0) && (cmode <= 0xF));
9579 code |= (cmode << 12); // cmod
9581 code |= (((code_t)imm >> 5) << 16); // iii
9582 code |= (((code_t)imm & 0x1f) << 5); // iiiii
9583 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9584 dst += emitOutput_Instr(dst, code);
9587 case IF_DV_1C: // DV_1C .........X...... ......nnnnn..... Vn #0.0 (fcmp - with zero)
9588 elemsize = id->idOpSize();
9589 code = emitInsCode(ins, fmt);
9590 code |= insEncodeFloatElemsize(elemsize); // X
9591 code |= insEncodeReg_Vn(id->idReg1()); // nnnnn
9592 dst += emitOutput_Instr(dst, code);
9595 case IF_DV_2A: // DV_2A .Q.......X...... ......nnnnnddddd Vd Vn (fabs, fcvt - vector)
9596 elemsize = optGetElemsize(id->idInsOpt());
9597 code = emitInsCode(ins, fmt);
9598 code |= insEncodeVectorsize(id->idOpSize()); // Q
9599 code |= insEncodeFloatElemsize(elemsize); // X
9600 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9601 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9602 dst += emitOutput_Instr(dst, code);
9605 case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov/smov - to general)
9606 elemsize = id->idOpSize();
9607 index = emitGetInsSC(id);
9608 datasize = (elemsize == EA_8BYTE) ? EA_16BYTE : EA_8BYTE;
9609 if (ins == INS_smov)
9611 datasize = EA_16BYTE;
9613 code = emitInsCode(ins, fmt);
9614 code |= insEncodeVectorsize(datasize); // Q
9615 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9616 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9617 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9618 dst += emitOutput_Instr(dst, code);
9621 case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
9624 datasize = id->idOpSize();
9625 elemsize = optGetElemsize(id->idInsOpt());
9630 datasize = EA_16BYTE;
9631 elemsize = id->idOpSize();
9632 index = emitGetInsSC(id);
9634 code = emitInsCode(ins, fmt);
9635 code |= insEncodeVectorsize(datasize); // Q
9636 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9637 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9638 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9639 dst += emitOutput_Instr(dst, code);
9642 case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
9643 index = emitGetInsSC(id);
9644 elemsize = optGetElemsize(id->idInsOpt());
9645 code = emitInsCode(ins, fmt);
9646 code |= insEncodeVectorsize(id->idOpSize()); // Q
9647 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9648 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9649 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9650 dst += emitOutput_Instr(dst, code);
9653 case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
9654 index = emitGetInsSC(id);
9655 elemsize = id->idOpSize();
9656 code = emitInsCode(ins, fmt);
9657 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9658 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9659 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9660 dst += emitOutput_Instr(dst, code);
9663 case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
9664 elemsize = id->idOpSize();
9665 imm = emitGetInsSC(id);
9666 index = (imm >> 4) & 0xf;
9668 code = emitInsCode(ins, fmt);
9669 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9670 code |= insEncodeVectorIndex2(elemsize, index2); // jjjj
9671 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9672 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9673 dst += emitOutput_Instr(dst, code);
9676 case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov,fcvtXX - register)
9677 elemsize = id->idOpSize();
9678 code = emitInsCode(ins, fmt);
9679 code |= insEncodeFloatElemsize(elemsize); // X
9680 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9681 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9682 dst += emitOutput_Instr(dst, code);
9685 case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov - to general)
9686 elemsize = id->idOpSize();
9687 code = emitInsCode(ins, fmt);
9688 code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X X
9689 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9690 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9691 dst += emitOutput_Instr(dst, code);
9694 case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov - from general)
9695 elemsize = id->idOpSize();
9696 code = emitInsCode(ins, fmt);
9697 code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X X
9698 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9699 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9700 dst += emitOutput_Instr(dst, code);
9703 case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
9704 code = emitInsCode(ins, fmt);
9705 code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // SS DD
9706 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9707 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9708 dst += emitOutput_Instr(dst, code);
9711 case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
9712 elemsize = id->idOpSize();
9713 code = emitInsCode(ins, fmt);
9714 code |= insEncodeFloatElemsize(elemsize); // X
9715 code |= insEncodeReg_Vn(id->idReg1()); // nnnnn
9716 code |= insEncodeReg_Vm(id->idReg2()); // mmmmm
9717 dst += emitOutput_Instr(dst, code);
9720 case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
9721 elemsize = id->idOpSize();
9722 code = emitInsCode(ins, fmt);
9723 code |= insEncodeElemsize(elemsize); // XX
9724 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9725 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9726 dst += emitOutput_Instr(dst, code);
9729 case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
9730 elemsize = optGetElemsize(id->idInsOpt());
9731 code = emitInsCode(ins, fmt);
9732 code |= insEncodeVectorsize(id->idOpSize()); // Q
9733 code |= insEncodeElemsize(elemsize); // XX
9734 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9735 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9736 dst += emitOutput_Instr(dst, code);
9739 case IF_DV_2N: // DV_2N .........iiiiiii ......nnnnnddddd Vd Vn imm (shift - scalar)
9740 imm = emitGetInsSC(id);
9741 code = emitInsCode(ins, fmt);
9742 code |= insEncodeVectorShift(EA_8BYTE, imm); // iiiiiii
9743 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9744 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9745 dst += emitOutput_Instr(dst, code);
9748 case IF_DV_2O: // DV_2O .Q.......iiiiiii ......nnnnnddddd Vd Vn imm (shift - vector)
9749 imm = emitGetInsSC(id);
9750 elemsize = optGetElemsize(id->idInsOpt());
9751 code = emitInsCode(ins, fmt);
9752 code |= insEncodeVectorsize(id->idOpSize()); // Q
9753 code |= insEncodeVectorShift(elemsize, imm); // iiiiiii
9754 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9755 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9756 dst += emitOutput_Instr(dst, code);
9759 case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
9760 code = emitInsCode(ins, fmt);
9761 elemsize = optGetElemsize(id->idInsOpt());
9762 code |= insEncodeVectorsize(id->idOpSize()); // Q
9763 code |= insEncodeElemsize(elemsize); // XX
9764 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9765 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9766 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9767 dst += emitOutput_Instr(dst, code);
9770 case IF_DV_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector)
9771 code = emitInsCode(ins, fmt);
9772 imm = emitGetInsSC(id);
9773 elemsize = optGetElemsize(id->idInsOpt());
9774 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
9775 code |= insEncodeVectorsize(id->idOpSize()); // Q
9776 code |= insEncodeElemsize(elemsize); // XX
9777 code |= insEncodeVectorIndexLMH(elemsize, imm); // LM H
9778 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9779 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9780 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9781 dst += emitOutput_Instr(dst, code);
9784 case IF_DV_3B: // DV_3B .Q.......X.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
9785 code = emitInsCode(ins, fmt);
9786 elemsize = optGetElemsize(id->idInsOpt());
9787 code |= insEncodeVectorsize(id->idOpSize()); // Q
9788 code |= insEncodeFloatElemsize(elemsize); // X
9789 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9790 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9791 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9792 dst += emitOutput_Instr(dst, code);
9795 case IF_DV_3BI: // DV_3BI .Q.......XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
9796 code = emitInsCode(ins, fmt);
9797 imm = emitGetInsSC(id);
9798 elemsize = optGetElemsize(id->idInsOpt());
9799 assert(isValidVectorIndex(id->idOpSize(), elemsize, imm));
9800 code |= insEncodeVectorsize(id->idOpSize()); // Q
9801 code |= insEncodeFloatElemsize(elemsize); // X
9802 code |= insEncodeFloatIndex(elemsize, imm); // L H
9803 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9804 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9805 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9806 dst += emitOutput_Instr(dst, code);
9809 case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
9810 code = emitInsCode(ins, fmt);
9811 code |= insEncodeVectorsize(id->idOpSize()); // Q
9812 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9813 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9814 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9815 dst += emitOutput_Instr(dst, code);
9818 case IF_DV_3D: // DV_3D .........X.mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
9819 code = emitInsCode(ins, fmt);
9820 code |= insEncodeFloatElemsize(id->idOpSize()); // X
9821 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9822 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9823 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9824 dst += emitOutput_Instr(dst, code);
9827 case IF_DV_3DI: // DV_3DI .........XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (scalar by elem)
9828 code = emitInsCode(ins, fmt);
9829 imm = emitGetInsSC(id);
9830 elemsize = id->idOpSize();
9831 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
9832 code |= insEncodeFloatElemsize(elemsize); // X
9833 code |= insEncodeFloatIndex(elemsize, imm); // L H
9834 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9835 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9836 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9837 dst += emitOutput_Instr(dst, code);
9840 case IF_DV_3E: // DV_3E ...........mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
9841 code = emitInsCode(ins, fmt);
9842 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9843 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9844 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9845 dst += emitOutput_Instr(dst, code);
9848 case IF_DV_4A: // DV_4A .........X.mmmmm .aaaaannnnnddddd Vd Va Vn Vm (scalar)
9849 code = emitInsCode(ins, fmt);
9850 elemsize = id->idOpSize();
9851 code |= insEncodeFloatElemsize(elemsize); // X
9852 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9853 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9854 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9855 code |= insEncodeReg_Va(id->idReg4()); // aaaaa
9856 dst += emitOutput_Instr(dst, code);
9859 case IF_SN_0A: // SN_0A ................ ................
9860 code = emitInsCode(ins, fmt);
9861 dst += emitOutput_Instr(dst, code);
9864 case IF_SI_0A: // SI_0A ...........iiiii iiiiiiiiiii..... imm16
9865 imm = emitGetInsSC(id);
9866 assert(isValidUimm16(imm));
9867 code = emitInsCode(ins, fmt);
9868 code |= ((code_t)imm << 5); // iiiii iiiiiiiiiii
9869 dst += emitOutput_Instr(dst, code);
9872 case IF_SI_0B: // SI_0B ................ ....bbbb........ imm4 - barrier
9873 imm = emitGetInsSC(id);
9874 assert((imm >= 0) && (imm <= 15));
9875 code = emitInsCode(ins, fmt);
9876 code |= ((code_t)imm << 8); // bbbb
9877 dst += emitOutput_Instr(dst, code);
9881 assert(!"Unexpected format");
9885 // Determine if any registers now hold GC refs, or whether a register that was overwritten held a GC ref.
9886 // We assume here that "id->idGCref()" is not GC_NONE only if the instruction described by "id" writes a
9887 // GC ref to register "id->idReg1()". (It may, apparently, also not be GC_NONE in other cases, such as
9888 // for stores, but we ignore those cases here.)
9889 if (emitInsMayWriteToGCReg(id)) // True if "id->idIns()" writes to a register than can hold GC ref.
9891 // We assume that "idReg1" is the primary destination register for all instructions
9892 if (id->idGCref() != GCT_NONE)
9894 emitGCregLiveUpd(id->idGCref(), id->idReg1(), dst);
9898 emitGCregDeadUpd(id->idReg1(), dst);
9901 if (emitInsMayWriteMultipleRegs(id))
9904 // "idReg2" is the secondary destination register
9905 if (id->idGCrefReg2() != GCT_NONE)
9907 emitGCregLiveUpd(id->idGCrefReg2(), id->idReg2(), dst);
9911 emitGCregDeadUpd(id->idReg2(), dst);
9916 // Now we determine if the instruction has written to a (local variable) stack location, and either written a GC
9917 // ref or overwritten one.
9918 if (emitInsWritesToLclVarStackLoc(id) || emitInsWritesToLclVarStackLocPair(id))
9920 int varNum = id->idAddr()->iiaLclVar.lvaVarNum();
9921 unsigned ofs = AlignDown(id->idAddr()->iiaLclVar.lvaOffset(), TARGET_POINTER_SIZE);
9923 int adr = emitComp->lvaFrameAddress(varNum, &FPbased);
9924 if (id->idGCref() != GCT_NONE)
9926 emitGCvarLiveUpd(adr + ofs, varNum, id->idGCref(), dst);
9930 // If the type of the local is a gc ref type, update the liveness.
9934 // "Regular" (non-spill-temp) local.
9935 vt = var_types(emitComp->lvaTable[varNum].lvType);
9939 TempDsc* tmpDsc = emitComp->tmpFindNum(varNum);
9940 vt = tmpDsc->tdTempType();
9942 if (vt == TYP_REF || vt == TYP_BYREF)
9943 emitGCvarDeadUpd(adr + ofs, dst);
9945 if (emitInsWritesToLclVarStackLocPair(id))
9947 unsigned ofs2 = ofs + TARGET_POINTER_SIZE;
9948 if (id->idGCrefReg2() != GCT_NONE)
9950 emitGCvarLiveUpd(adr + ofs2, varNum, id->idGCrefReg2(), dst);
9954 // If the type of the local is a gc ref type, update the liveness.
9958 // "Regular" (non-spill-temp) local.
9959 vt = var_types(emitComp->lvaTable[varNum].lvType);
9963 TempDsc* tmpDsc = emitComp->tmpFindNum(varNum);
9964 vt = tmpDsc->tdTempType();
9966 if (vt == TYP_REF || vt == TYP_BYREF)
9967 emitGCvarDeadUpd(adr + ofs2, dst);
9973 /* Make sure we set the instruction descriptor size correctly */
9975 size_t expected = emitSizeOfInsDsc(id);
9976 assert(sz == expected);
9978 if (emitComp->opts.disAsm || emitComp->opts.dspEmit || emitComp->verbose)
9980 emitDispIns(id, false, dspOffs, true, emitCurCodeOffs(odst), *dp, (dst - *dp), ig);
9983 if (emitComp->compDebugBreak)
9985 // For example, set JitBreakEmitOutputInstr=a6 will break when this method is called for
9986 // emitting instruction a6, (i.e. IN00a6 in jitdump).
9987 if ((unsigned)JitConfig.JitBreakEmitOutputInstr() == id->idDebugOnlyInfo()->idNum)
9989 assert(!"JitBreakEmitOutputInstr reached");
9994 /* All instructions are expected to generate code */
10003 /*****************************************************************************/
10004 /*****************************************************************************/
10008 /*****************************************************************************
10010 * Display the instruction name
10012 void emitter::emitDispInst(instruction ins)
10014 const char* insstr = codeGen->genInsName(ins);
10015 size_t len = strlen(insstr);
10017 /* Display the instruction name */
10019 printf("%s", insstr);
10022 // Add at least one space after the instruction name
10023 // and add spaces until we have reach the normal size of 8
10031 /*****************************************************************************
10033 * Display an reloc value
10034 * If we are formatting for an assembly listing don't print the hex value
10035 * since it will prevent us from doing assembly diffs
10037 void emitter::emitDispReloc(int value, bool addComma)
10039 if (emitComp->opts.disAsm)
10045 printf("(reloc 0x%x)", dspPtr(value));
10052 /*****************************************************************************
10054 * Display an immediate value
10056 void emitter::emitDispImm(ssize_t imm, bool addComma, bool alwaysHex /* =false */)
10063 // Munge any pointers if we want diff-able disassembly.
10064 // Since some may be emitted as partial words, print as diffable anything that has
10065 // significant bits beyond the lowest 8-bits.
10066 if (emitComp->opts.disDiffable)
10068 ssize_t top56bits = (imm >> 8);
10069 if ((top56bits != 0) && (top56bits != -1))
10073 if (!alwaysHex && (imm > -1000) && (imm < 1000))
10079 if ((imm < 0) && ((imm & 0xFFFFFFFF00000000LL) == 0xFFFFFFFF00000000LL))
10085 if ((imm & 0xFFFFFFFF00000000LL) != 0)
10087 printf("0x%llx", imm);
10091 printf("0x%02x", imm);
10099 /*****************************************************************************
10101 * Display a float zero constant
10103 void emitter::emitDispFloatZero()
10112 /*****************************************************************************
10114 * Display an encoded float constant value
10116 void emitter::emitDispFloatImm(ssize_t imm8)
10118 assert((0 <= imm8) && (imm8 <= 0x0ff));
10125 fpImm.immFPIVal = (unsigned)imm8;
10126 double result = emitDecodeFloatImm8(fpImm);
10128 printf("%.4f", result);
10131 /*****************************************************************************
10133 * Display an immediate that is optionally LSL12.
10135 void emitter::emitDispImmOptsLSL12(ssize_t imm, insOpts opt)
10137 if (!strictArmAsm && insOptsLSL12(opt))
10141 emitDispImm(imm, false);
10142 if (strictArmAsm && insOptsLSL12(opt))
10144 printf(", LSL #12");
10148 /*****************************************************************************
10150 * Display an ARM64 condition code for the conditional instructions
10152 void emitter::emitDispCond(insCond cond)
10154 const static char* armCond[16] = {"eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc",
10155 "hi", "ls", "ge", "lt", "gt", "le", "AL", "NV"}; // The last two are invalid
10156 unsigned imm = (unsigned)cond;
10157 assert((0 <= imm) && (imm < ArrLen(armCond)));
10158 printf(armCond[imm]);
10161 /*****************************************************************************
10163 * Display an ARM64 flags for the conditional instructions
10165 void emitter::emitDispFlags(insCflags flags)
10167 const static char* armFlags[16] = {"0", "v", "c", "cv", "z", "zv", "zc", "zcv",
10168 "n", "nv", "nc", "ncv", "nz", "nzv", "nzc", "nzcv"};
10169 unsigned imm = (unsigned)flags;
10170 assert((0 <= imm) && (imm < ArrLen(armFlags)));
10171 printf(armFlags[imm]);
10174 /*****************************************************************************
10176 * Display an ARM64 'barrier' for the memory barrier instructions
10178 void emitter::emitDispBarrier(insBarrier barrier)
10180 const static char* armBarriers[16] = {"#0", "oshld", "oshst", "osh", "#4", "nshld", "nshst", "nsh",
10181 "#8", "ishld", "ishst", "ish", "#12", "ld", "st", "sy"};
10182 unsigned imm = (unsigned)barrier;
10183 assert((0 <= imm) && (imm < ArrLen(armBarriers)));
10184 printf(armBarriers[imm]);
10187 /*****************************************************************************
10189 * Prints the encoding for the Shift Type encoding
10192 void emitter::emitDispShiftOpts(insOpts opt)
10194 if (opt == INS_OPTS_LSL)
10196 else if (opt == INS_OPTS_LSR)
10198 else if (opt == INS_OPTS_ASR)
10200 else if (opt == INS_OPTS_ROR)
10202 else if (opt == INS_OPTS_MSL)
10205 assert(!"Bad value");
10208 /*****************************************************************************
10210 * Prints the encoding for the Extend Type encoding
10213 void emitter::emitDispExtendOpts(insOpts opt)
10215 if (opt == INS_OPTS_UXTB)
10217 else if (opt == INS_OPTS_UXTH)
10219 else if (opt == INS_OPTS_UXTW)
10221 else if (opt == INS_OPTS_UXTX)
10223 else if (opt == INS_OPTS_SXTB)
10225 else if (opt == INS_OPTS_SXTH)
10227 else if (opt == INS_OPTS_SXTW)
10229 else if (opt == INS_OPTS_SXTX)
10232 assert(!"Bad value");
10235 /*****************************************************************************
10237 * Prints the encoding for the Extend Type encoding in loads/stores
10240 void emitter::emitDispLSExtendOpts(insOpts opt)
10242 if (opt == INS_OPTS_LSL)
10244 else if (opt == INS_OPTS_UXTW)
10246 else if (opt == INS_OPTS_UXTX)
10248 else if (opt == INS_OPTS_SXTW)
10250 else if (opt == INS_OPTS_SXTX)
10253 assert(!"Bad value");
10256 /*****************************************************************************
10258 * Display a register
10260 void emitter::emitDispReg(regNumber reg, emitAttr attr, bool addComma)
10262 emitAttr size = EA_SIZE(attr);
10263 printf(emitRegName(reg, size));
10269 /*****************************************************************************
10271 * Display a vector register with an arrangement suffix
10273 void emitter::emitDispVectorReg(regNumber reg, insOpts opt, bool addComma)
10275 assert(isVectorRegister(reg));
10276 printf(emitVectorRegName(reg));
10277 emitDispArrangement(opt);
10283 /*****************************************************************************
10285 * Display an vector register index suffix
10287 void emitter::emitDispVectorRegIndex(regNumber reg, emitAttr elemsize, ssize_t index, bool addComma)
10289 assert(isVectorRegister(reg));
10290 printf(emitVectorRegName(reg));
10307 assert(!"invalid elemsize");
10311 printf("[%d]", index);
10317 /*****************************************************************************
10319 * Display an arrangement suffix
10321 void emitter::emitDispArrangement(insOpts opt)
10323 const char* str = "???";
10353 assert(!"Invalid insOpt for vector register");
10359 /*****************************************************************************
10361 * Display a register with an optional shift operation
10363 void emitter::emitDispShiftedReg(regNumber reg, insOpts opt, ssize_t imm, emitAttr attr)
10365 emitAttr size = EA_SIZE(attr);
10366 assert((imm & 0x003F) == imm);
10367 assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
10369 printf(emitRegName(reg, size));
10377 emitDispShiftOpts(opt);
10378 emitDispImm(imm, false);
10382 /*****************************************************************************
10384 * Display a register with an optional extend and scale operations
10386 void emitter::emitDispExtendReg(regNumber reg, insOpts opt, ssize_t imm)
10388 assert((imm >= 0) && (imm <= 4));
10389 assert(insOptsNone(opt) || insOptsAnyExtend(opt) || (opt == INS_OPTS_LSL));
10391 // size is based on the extend option, not the instr size.
10392 emitAttr size = insOpts32BitExtend(opt) ? EA_4BYTE : EA_8BYTE;
10396 if (insOptsNone(opt))
10398 emitDispReg(reg, size, false);
10402 emitDispReg(reg, size, true);
10403 if (opt == INS_OPTS_LSL)
10406 emitDispExtendOpts(opt);
10407 if ((imm > 0) || (opt == INS_OPTS_LSL))
10410 emitDispImm(imm, false);
10414 else // !strictArmAsm
10416 if (insOptsNone(opt))
10418 emitDispReg(reg, size, false);
10422 if (opt != INS_OPTS_LSL)
10424 emitDispExtendOpts(opt);
10426 emitDispReg(reg, size, false);
10433 emitDispImm(1 << imm, false);
10438 /*****************************************************************************
10440 * Display an addressing operand [reg + imm]
10442 void emitter::emitDispAddrRI(regNumber reg, insOpts opt, ssize_t imm)
10444 reg = encodingZRtoSP(reg); // ZR (R31) encodes the SP register
10450 emitDispReg(reg, EA_8BYTE, false);
10452 if (!insOptsPostIndex(opt) && (imm != 0))
10455 emitDispImm(imm, false);
10459 if (insOptsPreIndex(opt))
10463 else if (insOptsPostIndex(opt))
10466 emitDispImm(imm, false);
10469 else // !strictArmAsm
10473 const char* operStr = "++";
10480 if (insOptsPreIndex(opt))
10485 emitDispReg(reg, EA_8BYTE, false);
10487 if (insOptsPostIndex(opt))
10492 if (insOptsIndexed(opt))
10498 printf("%c", operStr[1]);
10500 emitDispImm(imm, false);
10505 /*****************************************************************************
10507 * Display an addressing operand [reg + extended reg]
10509 void emitter::emitDispAddrRRExt(regNumber reg1, regNumber reg2, insOpts opt, bool isScaled, emitAttr size)
10511 reg1 = encodingZRtoSP(reg1); // ZR (R31) encodes the SP register
10513 unsigned scale = 0;
10516 scale = NaturalScale_helper(size);
10523 emitDispReg(reg1, EA_8BYTE, true);
10524 emitDispExtendReg(reg2, opt, scale);
10526 else // !strictArmAsm
10528 emitDispReg(reg1, EA_8BYTE, false);
10530 emitDispExtendReg(reg2, opt, scale);
10536 /*****************************************************************************
10538 * Display (optionally) the instruction encoding in hex
10541 void emitter::emitDispInsHex(BYTE* code, size_t sz)
10543 // We do not display the instruction hex if we want diff-able disassembly
10544 if (!emitComp->opts.disDiffable)
10548 printf(" %08X ", (*((code_t*)code)));
10557 /****************************************************************************
10559 * Display the given instruction.
10562 void emitter::emitDispIns(
10563 instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* pCode, size_t sz, insGroup* ig)
10568 id->idDebugOnlyInfo()->idNum; // Do not remove this! It is needed for VisualStudio conditional breakpoints
10570 printf("IN%04x: ", idNum);
10576 if (!emitComp->opts.dspEmit && !isNew && !asmfm && sz)
10579 /* Display the instruction offset */
10581 emitDispInsOffs(offset, doffs);
10583 /* Display the instruction hex code */
10585 emitDispInsHex(pCode, sz);
10589 /* Get the instruction and format */
10591 instruction ins = id->idIns();
10592 insFormat fmt = id->idInsFmt();
10596 /* If this instruction has just been added, check its size */
10598 assert(isNew == false || (int)emitSizeOfInsDsc(id) == emitCurIGfreeNext - (BYTE*)id);
10600 /* Figure out the operand size */
10601 emitAttr size = id->idOpSize();
10602 emitAttr attr = size;
10603 if (id->idGCref() == GCT_GCREF)
10605 else if (id->idGCref() == GCT_BYREF)
10613 bool isExtendAlias;
10622 const char* methodName;
10630 case IF_BI_0A: // BI_0A ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
10631 case IF_BI_0B: // BI_0B ......iiiiiiiiii iiiiiiiiiii..... simm19:00
10634 if (fmt == IF_LARGEJMP)
10636 printf("(LARGEJMP)");
10638 if (id->idAddr()->iiaHasInstrCount())
10640 int instrCount = id->idAddr()->iiaGetInstrCount();
10644 printf("pc%s%d instructions", (instrCount >= 0) ? "+" : "", instrCount);
10648 unsigned insNum = emitFindInsNum(ig, id);
10649 UNATIVE_OFFSET srcOffs = ig->igOffs + emitFindOffset(ig, insNum + 1);
10650 UNATIVE_OFFSET dstOffs = ig->igOffs + emitFindOffset(ig, insNum + 1 + instrCount);
10651 ssize_t relOffs = (ssize_t)(emitOffsetToPtr(dstOffs) - emitOffsetToPtr(srcOffs));
10652 printf("pc%s%d (%d instructions)", (relOffs >= 0) ? "+" : "", relOffs, instrCount);
10655 else if (id->idIsBound())
10657 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10661 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10666 case IF_BI_0C: // BI_0C ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
10667 if (id->idIsCallAddr())
10669 offs = (ssize_t)id->idAddr()->iiaAddr;
10675 methodName = emitComp->eeGetMethodFullName((CORINFO_METHOD_HANDLE)id->idDebugOnlyInfo()->idMemCookie);
10680 if (id->idIsDspReloc())
10682 printf("%08X", offs);
10686 printf("%s", methodName);
10690 case IF_BI_1A: // BI_1A ......iiiiiiiiii iiiiiiiiiiittttt Rt simm19:00
10691 assert(insOptsNone(id->idInsOpt()));
10692 emitDispReg(id->idReg1(), size, true);
10693 if (id->idIsBound())
10695 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10699 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10703 case IF_BI_1B: // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
10704 assert(insOptsNone(id->idInsOpt()));
10705 emitDispReg(id->idReg1(), size, true);
10706 emitDispImm(emitGetInsSC(id), true);
10707 if (id->idIsBound())
10709 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10713 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10717 case IF_BR_1A: // BR_1A ................ ......nnnnn..... Rn
10718 assert(insOptsNone(id->idInsOpt()));
10719 emitDispReg(id->idReg1(), size, false);
10722 case IF_BR_1B: // BR_1B ................ ......nnnnn..... Rn
10723 assert(insOptsNone(id->idInsOpt()));
10724 emitDispReg(id->idReg3(), size, false);
10727 case IF_LS_1A: // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB)
10728 case IF_DI_1E: // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
10731 assert(insOptsNone(id->idInsOpt()));
10732 emitDispReg(id->idReg1(), size, true);
10733 imm = emitGetInsSC(id);
10735 /* Is this actually a reference to a data section? */
10736 if (fmt == IF_LARGEADR)
10738 printf("(LARGEADR)");
10740 else if (fmt == IF_LARGELDC)
10742 printf("(LARGELDC)");
10746 if (id->idAddr()->iiaIsJitDataOffset())
10748 doffs = Compiler::eeGetJitDataOffs(id->idAddr()->iiaFieldHnd);
10749 /* Display a data section reference */
10752 printf("@CNS%02u", doffs - 1);
10754 printf("@RWD%02u", doffs);
10757 printf("%+Id", imm);
10762 if (id->idIsReloc())
10765 emitDispImm((ssize_t)id->idAddr()->iiaAddr, false);
10767 else if (id->idIsBound())
10769 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10773 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10779 case IF_LS_2A: // LS_2A .X.......X...... ......nnnnnttttt Rt Rn
10780 assert(insOptsNone(id->idInsOpt()));
10781 assert(emitGetInsSC(id) == 0);
10782 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10783 emitDispAddrRI(id->idReg2(), id->idInsOpt(), 0);
10786 case IF_LS_2B: // LS_2B .X.......Xiiiiii iiiiiinnnnnttttt Rt Rn imm(0-4095)
10787 assert(insOptsNone(id->idInsOpt()));
10788 imm = emitGetInsSC(id);
10789 scale = NaturalScale_helper(emitInsLoadStoreSize(id));
10790 imm <<= scale; // The immediate is scaled by the size of the ld/st
10791 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10792 emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
10795 case IF_LS_2C: // LS_2C .X.......X.iiiii iiiiPPnnnnnttttt Rt Rn imm(-256..+255) no/pre/post inc
10796 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
10797 imm = emitGetInsSC(id);
10798 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10799 emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
10802 case IF_LS_3A: // LS_3A .X.......X.mmmmm oooS..nnnnnttttt Rt Rn Rm ext(Rm) LSL {}
10803 assert(insOptsLSExtend(id->idInsOpt()));
10804 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10805 if (id->idIsLclVar())
10807 emitDispAddrRRExt(id->idReg2(), codeGen->rsGetRsvdReg(), id->idInsOpt(), false, size);
10811 emitDispAddrRRExt(id->idReg2(), id->idReg3(), id->idInsOpt(), id->idReg3Scaled(), size);
10815 case IF_LS_3B: // LS_3B X............... .aaaaannnnnddddd Rt Ra Rn
10816 assert(insOptsNone(id->idInsOpt()));
10817 assert(emitGetInsSC(id) == 0);
10818 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10819 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10820 emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
10823 case IF_LS_3C: // LS_3C X.........iiiiii iaaaaannnnnddddd Rt Ra Rn imm(im7,sh)
10824 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
10825 imm = emitGetInsSC(id);
10826 scale = NaturalScale_helper(emitInsLoadStoreSize(id));
10828 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10829 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10830 emitDispAddrRI(id->idReg3(), id->idInsOpt(), imm);
10833 case IF_LS_3D: // LS_3D .X.......X.mmmmm ......nnnnnttttt Wm Rt Rn
10834 assert(insOptsNone(id->idInsOpt()));
10835 emitDispReg(id->idReg1(), EA_4BYTE, true);
10836 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10837 emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
10840 case IF_DI_1A: // DI_1A X.......shiiiiii iiiiiinnnnn..... Rn imm(i12,sh)
10841 emitDispReg(id->idReg1(), size, true);
10842 emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
10845 case IF_DI_1B: // DI_1B X........hwiiiii iiiiiiiiiiiddddd Rd imm(i16,hw)
10846 emitDispReg(id->idReg1(), size, true);
10847 hwi.immHWVal = (unsigned)emitGetInsSC(id);
10848 if (ins == INS_mov)
10850 emitDispImm(emitDecodeHalfwordImm(hwi, size), false);
10852 else // movz, movn, movk
10854 emitDispImm(hwi.immVal, false);
10855 if (hwi.immHW != 0)
10857 emitDispShiftOpts(INS_OPTS_LSL);
10858 emitDispImm(hwi.immHW * 16, false);
10863 case IF_DI_1C: // DI_1C X........Nrrrrrr ssssssnnnnn..... Rn imm(N,r,s)
10864 emitDispReg(id->idReg1(), size, true);
10865 bmi.immNRS = (unsigned)emitGetInsSC(id);
10866 emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
10869 case IF_DI_1D: // DI_1D X........Nrrrrrr ssssss.....ddddd Rd imm(N,r,s)
10870 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
10871 bmi.immNRS = (unsigned)emitGetInsSC(id);
10872 emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
10875 case IF_DI_2A: // DI_2A X.......shiiiiii iiiiiinnnnnddddd Rd Rn imm(i12,sh)
10876 if ((ins == INS_add) || (ins == INS_sub))
10878 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
10879 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
10883 emitDispReg(id->idReg1(), size, true);
10884 emitDispReg(id->idReg2(), size, true);
10886 emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
10889 case IF_DI_2B: // DI_2B X........X.nnnnn ssssssnnnnnddddd Rd Rn imm(0-63)
10890 emitDispReg(id->idReg1(), size, true);
10891 emitDispReg(id->idReg2(), size, true);
10892 emitDispImm(emitGetInsSC(id), false);
10895 case IF_DI_2C: // DI_2C X........Nrrrrrr ssssssnnnnnddddd Rd Rn imm(N,r,s)
10896 if (ins == INS_ands)
10898 emitDispReg(id->idReg1(), size, true);
10902 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
10904 emitDispReg(id->idReg2(), size, true);
10905 bmi.immNRS = (unsigned)emitGetInsSC(id);
10906 emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
10909 case IF_DI_2D: // DI_2D X........Nrrrrrr ssssssnnnnnddddd Rd Rn imr, ims (N,r,s)
10910 emitDispReg(id->idReg1(), size, true);
10911 emitDispReg(id->idReg2(), size, true);
10913 imm = emitGetInsSC(id);
10914 bmi.immNRS = (unsigned)imm;
10921 emitDispImm(bmi.immR, true);
10922 emitDispImm(bmi.immS, false);
10928 emitDispImm(getBitWidth(size) - bmi.immR, true);
10929 emitDispImm(bmi.immS + 1, false);
10935 emitDispImm(bmi.immR, true);
10936 emitDispImm(bmi.immS - bmi.immR + 1, false);
10942 emitDispImm(imm, false);
10946 assert(!"Unexpected instruction in IF_DI_2D");
10951 case IF_DI_1F: // DI_1F X..........iiiii cccc..nnnnn.nzcv Rn imm5 nzcv cond
10952 emitDispReg(id->idReg1(), size, true);
10953 cfi.immCFVal = (unsigned)emitGetInsSC(id);
10954 emitDispImm(cfi.imm5, true);
10955 emitDispFlags(cfi.flags);
10957 emitDispCond(cfi.cond);
10960 case IF_DR_1D: // DR_1D X............... cccc.......mmmmm Rd cond
10961 emitDispReg(id->idReg1(), size, true);
10962 cfi.immCFVal = (unsigned)emitGetInsSC(id);
10963 emitDispCond(cfi.cond);
10966 case IF_DR_2A: // DR_2A X..........mmmmm ......nnnnn..... Rn Rm
10967 emitDispReg(id->idReg1(), size, true);
10968 emitDispReg(id->idReg2(), size, false);
10971 case IF_DR_2B: // DR_2B X.......sh.mmmmm ssssssnnnnn..... Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
10972 emitDispReg(id->idReg1(), size, true);
10973 emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
10976 case IF_DR_2C: // DR_2C X..........mmmmm ooosssnnnnn..... Rn Rm ext(Rm) LSL imm(0-4)
10977 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
10978 imm = emitGetInsSC(id);
10979 emitDispExtendReg(id->idReg2(), id->idInsOpt(), imm);
10982 case IF_DR_2D: // DR_2D X..........nnnnn cccc..nnnnnddddd Rd Rn cond
10983 emitDispReg(id->idReg1(), size, true);
10984 emitDispReg(id->idReg2(), size, true);
10985 cfi.immCFVal = (unsigned)emitGetInsSC(id);
10986 emitDispCond(cfi.cond);
10989 case IF_DR_2E: // DR_2E X..........mmmmm ...........ddddd Rd Rm
10990 emitDispReg(id->idReg1(), size, true);
10991 emitDispReg(id->idReg2(), size, false);
10994 case IF_DR_2F: // DR_2F X.......sh.mmmmm ssssss.....ddddd Rd Rm {LSL,LSR,ASR} imm(0-63)
10995 emitDispReg(id->idReg1(), size, true);
10996 emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
10999 case IF_DR_2G: // DR_2G X............... ......nnnnnddddd Rd Rn
11000 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11001 emitDispReg(encodingZRtoSP(id->idReg2()), size, false);
11004 case IF_DR_2H: // DR_2H X........X...... ......nnnnnddddd Rd Rn
11005 emitDispReg(id->idReg1(), size, true);
11006 emitDispReg(id->idReg2(), size, false);
11009 case IF_DR_2I: // DR_2I X..........mmmmm cccc..nnnnn.nzcv Rn Rm nzcv cond
11010 emitDispReg(id->idReg1(), size, true);
11011 emitDispReg(id->idReg2(), size, true);
11012 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11013 emitDispFlags(cfi.flags);
11015 emitDispCond(cfi.cond);
11018 case IF_DR_3A: // DR_3A X..........mmmmm ......nnnnnmmmmm Rd Rn Rm
11019 if ((ins == INS_add) || (ins == INS_sub))
11021 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11022 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11024 else if ((ins == INS_smull) || (ins == INS_smulh))
11026 // Rd is always 8 bytes
11027 emitDispReg(id->idReg1(), EA_8BYTE, true);
11029 // Rn, Rm effective size depends on instruction type
11030 size = (ins == INS_smulh) ? EA_8BYTE : EA_4BYTE;
11031 emitDispReg(id->idReg2(), size, true);
11035 emitDispReg(id->idReg1(), size, true);
11036 emitDispReg(id->idReg2(), size, true);
11038 if (id->idIsLclVar())
11040 emitDispReg(codeGen->rsGetRsvdReg(), size, false);
11044 emitDispReg(id->idReg3(), size, false);
11049 case IF_DR_3B: // DR_3B X.......sh.mmmmm ssssssnnnnnddddd Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
11050 emitDispReg(id->idReg1(), size, true);
11051 emitDispReg(id->idReg2(), size, true);
11052 emitDispShiftedReg(id->idReg3(), id->idInsOpt(), emitGetInsSC(id), size);
11055 case IF_DR_3C: // DR_3C X..........mmmmm ooosssnnnnnddddd Rd Rn Rm ext(Rm) LSL imm(0-4)
11056 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11057 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11058 imm = emitGetInsSC(id);
11059 emitDispExtendReg(id->idReg3(), id->idInsOpt(), imm);
11062 case IF_DR_3D: // DR_3D X..........mmmmm cccc..nnnnnmmmmm Rd Rn Rm cond
11063 emitDispReg(id->idReg1(), size, true);
11064 emitDispReg(id->idReg2(), size, true);
11065 emitDispReg(id->idReg3(), size, true);
11066 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11067 emitDispCond(cfi.cond);
11070 case IF_DR_3E: // DR_3E X........X.mmmmm ssssssnnnnnddddd Rd Rn Rm imm(0-63)
11071 emitDispReg(id->idReg1(), size, true);
11072 emitDispReg(id->idReg2(), size, true);
11073 emitDispReg(id->idReg3(), size, true);
11074 emitDispImm(emitGetInsSC(id), false);
11077 case IF_DR_4A: // DR_4A X..........mmmmm .aaaaannnnnmmmmm Rd Rn Rm Ra
11078 emitDispReg(id->idReg1(), size, true);
11079 emitDispReg(id->idReg2(), size, true);
11080 emitDispReg(id->idReg3(), size, true);
11081 emitDispReg(id->idReg4(), size, false);
11084 case IF_DV_1A: // DV_1A .........X.iiiii iii........ddddd Vd imm8 (fmov - immediate scalar)
11085 elemsize = id->idOpSize();
11086 emitDispReg(id->idReg1(), elemsize, true);
11087 emitDispFloatImm(emitGetInsSC(id));
11090 case IF_DV_1B: // DV_1B .QX..........iii cmod..iiiiiddddd Vd imm8 (immediate vector)
11091 imm = emitGetInsSC(id) & 0x0ff;
11092 immShift = (emitGetInsSC(id) & 0x700) >> 8;
11093 hasShift = (immShift != 0);
11094 elemsize = optGetElemsize(id->idInsOpt());
11095 if (id->idInsOpt() == INS_OPTS_1D)
11097 assert(elemsize == size);
11098 emitDispReg(id->idReg1(), size, true);
11102 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11104 if (ins == INS_fmov)
11106 emitDispFloatImm(imm);
11107 assert(hasShift == false);
11111 if (elemsize == EA_8BYTE)
11113 assert(ins == INS_movi);
11115 const ssize_t mask8 = 0xFF;
11116 for (unsigned b = 0; b < 8; b++)
11118 if (imm & (1 << b))
11120 imm64 |= (mask8 << (b * 8));
11123 emitDispImm(imm64, hasShift, true);
11127 emitDispImm(imm, hasShift, true);
11131 insOpts opt = (immShift & 0x4) ? INS_OPTS_MSL : INS_OPTS_LSL;
11132 unsigned shift = (immShift & 0x3) * 8;
11133 emitDispShiftOpts(opt);
11134 emitDispImm(shift, false);
11139 case IF_DV_1C: // DV_1C .........X...... ......nnnnn..... Vn #0.0 (fcmp - with zero)
11140 elemsize = id->idOpSize();
11141 emitDispReg(id->idReg1(), elemsize, true);
11142 emitDispFloatZero();
11145 case IF_DV_2A: // DV_2A .Q.......X...... ......nnnnnddddd Vd Vn (fabs, fcvt - vector)
11146 case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
11147 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11148 emitDispVectorReg(id->idReg2(), id->idInsOpt(), false);
11151 case IF_DV_2N: // DV_2N .........iiiiiii ......nnnnnddddd Vd Vn imm (shift - scalar)
11152 elemsize = id->idOpSize();
11153 emitDispReg(id->idReg1(), elemsize, true);
11154 emitDispReg(id->idReg2(), elemsize, true);
11155 emitDispImm(emitGetInsSC(id), false);
11158 case IF_DV_2O: // DV_2O .Q.......iiiiiii ......nnnnnddddd Vd Vn imm (shift - vector)
11159 imm = emitGetInsSC(id);
11160 // Do we have a sxtl or uxtl instruction?
11161 isExtendAlias = ((ins == INS_sxtl) || (ins == INS_sxtl2) || (ins == INS_uxtl) || (ins == INS_uxtl2));
11162 code = emitInsCode(ins, fmt);
11163 if (code & 0x00008000) // widen/narrow opcodes
11165 if (code & 0x00002000) // SHL opcodes
11167 emitDispVectorReg(id->idReg1(), optWidenElemsize(id->idInsOpt()), true);
11168 emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11170 else // SHR opcodes
11172 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11173 emitDispVectorReg(id->idReg2(), optWidenElemsize(id->idInsOpt()), !isExtendAlias);
11178 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11179 emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11181 // Print the immediate unless we have a sxtl or uxtl instruction
11182 if (!isExtendAlias)
11184 emitDispImm(imm, false);
11188 case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov/smov - to general)
11189 srcsize = id->idOpSize();
11190 index = emitGetInsSC(id);
11191 if (ins == INS_smov)
11193 dstsize = EA_8BYTE;
11195 else // INS_umov or INS_mov
11197 dstsize = (srcsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE;
11199 emitDispReg(id->idReg1(), dstsize, true);
11200 emitDispVectorRegIndex(id->idReg2(), srcsize, index, false);
11203 case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
11204 if (ins == INS_dup)
11206 datasize = id->idOpSize();
11207 assert(isValidVectorDatasize(datasize));
11208 assert(isValidArrangement(datasize, id->idInsOpt()));
11209 elemsize = optGetElemsize(id->idInsOpt());
11210 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11214 elemsize = id->idOpSize();
11215 index = emitGetInsSC(id);
11216 assert(isValidVectorElemsize(elemsize));
11217 emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11219 emitDispReg(id->idReg2(), (elemsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE, false);
11222 case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
11223 datasize = id->idOpSize();
11224 assert(isValidVectorDatasize(datasize));
11225 assert(isValidArrangement(datasize, id->idInsOpt()));
11226 elemsize = optGetElemsize(id->idInsOpt());
11227 index = emitGetInsSC(id);
11228 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11229 emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11232 case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
11233 elemsize = id->idOpSize();
11234 index = emitGetInsSC(id);
11235 emitDispReg(id->idReg1(), elemsize, true);
11236 emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11239 case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
11240 imm = emitGetInsSC(id);
11241 index = (imm >> 4) & 0xf;
11242 index2 = imm & 0xf;
11243 elemsize = id->idOpSize();
11244 emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11245 emitDispVectorRegIndex(id->idReg2(), elemsize, index2, false);
11248 case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov, fcvtXX - register)
11249 case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
11250 case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
11251 elemsize = id->idOpSize();
11252 emitDispReg(id->idReg1(), elemsize, true);
11253 emitDispReg(id->idReg2(), elemsize, false);
11256 case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov, fcvtXX - to general)
11257 case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov, Xcvtf - from general)
11258 case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
11259 dstsize = optGetDstsize(id->idInsOpt());
11260 srcsize = optGetSrcsize(id->idInsOpt());
11262 emitDispReg(id->idReg1(), dstsize, true);
11263 emitDispReg(id->idReg2(), srcsize, false);
11266 case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11267 case IF_DV_3B: // DV_3B .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11268 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11269 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11270 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11273 case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11274 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11275 if (ins != INS_mov)
11277 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11279 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11282 case IF_DV_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
11283 case IF_DV_3BI: // DV_3BI .Q........Lmmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
11284 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11285 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11286 elemsize = optGetElemsize(id->idInsOpt());
11287 emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11290 case IF_DV_3D: // DV_3D .........X.mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
11291 case IF_DV_3E: // DV_3E ...........mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
11292 emitDispReg(id->idReg1(), size, true);
11293 emitDispReg(id->idReg2(), size, true);
11294 emitDispReg(id->idReg3(), size, false);
11297 case IF_DV_3DI: // DV_3DI .........XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (scalar by elem)
11298 emitDispReg(id->idReg1(), size, true);
11299 emitDispReg(id->idReg2(), size, true);
11301 emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11304 case IF_DV_4A: // DV_4A .........X.mmmmm .aaaaannnnnddddd Vd Va Vn Vm (scalar)
11305 emitDispReg(id->idReg1(), size, true);
11306 emitDispReg(id->idReg2(), size, true);
11307 emitDispReg(id->idReg3(), size, true);
11308 emitDispReg(id->idReg4(), size, false);
11311 case IF_SN_0A: // SN_0A ................ ................
11314 case IF_SI_0A: // SI_0A ...........iiiii iiiiiiiiiii..... imm16
11315 emitDispImm(emitGetInsSC(id), false);
11318 case IF_SI_0B: // SI_0B ................ ....bbbb........ imm4 - barrier
11319 emitDispBarrier((insBarrier)emitGetInsSC(id));
11323 printf("unexpected format %s", emitIfName(id->idInsFmt()));
11324 assert(!"unexpectedFormat");
11328 if (id->idDebugOnlyInfo()->idVarRefOffs)
11331 emitDispFrameRef(id->idAddr()->iiaLclVar.lvaVarNum(), id->idAddr()->iiaLclVar.lvaOffset(),
11332 id->idDebugOnlyInfo()->idVarRefOffs, asmfm);
11338 /*****************************************************************************
11340 * Display a stack frame reference.
11343 void emitter::emitDispFrameRef(int varx, int disp, int offs, bool asmfm)
11348 printf("TEMP_%02u", -varx);
11350 emitComp->gtDispLclVar(+varx, false);
11353 printf("-0x%02x", -disp);
11355 printf("+0x%02x", +disp);
11359 if (varx >= 0 && emitComp->opts.varNames)
11362 const char* varName;
11364 assert((unsigned)varx < emitComp->lvaCount);
11365 varDsc = emitComp->lvaTable + varx;
11366 varName = emitComp->compLocalVarName(varx, offs);
11370 printf("'%s", varName);
11373 printf("-%d", -disp);
11375 printf("+%d", +disp);
11384 // Generate code for a load or store operation with a potentially complex addressing mode
11385 // This method handles the case of a GT_IND with contained GT_LEA op1 of the x86 form [base + index*sccale + offset]
11386 // Since Arm64 does not directly support this complex of an addressing mode
11387 // we may generates up to three instructions for this for Arm64
11389 void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataReg, GenTreeIndir* indir)
11391 emitAttr ldstAttr = isVectorRegister(dataReg) ? attr : emitInsAdjustLoadStoreAttr(ins, attr);
11393 GenTree* addr = indir->Addr();
11395 if (addr->isContained())
11397 assert(addr->OperGet() == GT_LCL_VAR_ADDR || addr->OperGet() == GT_LEA);
11402 if (addr->OperGet() == GT_LEA)
11404 offset = addr->AsAddrMode()->Offset();
11405 if (addr->AsAddrMode()->gtScale > 0)
11407 assert(isPow2(addr->AsAddrMode()->gtScale));
11408 BitScanForward(&lsl, addr->AsAddrMode()->gtScale);
11412 GenTree* memBase = indir->Base();
11414 if (indir->HasIndex())
11416 GenTree* index = indir->Index();
11420 regNumber tmpReg = indir->GetSingleTempReg();
11422 emitAttr addType = varTypeIsGC(memBase) ? EA_BYREF : EA_PTRSIZE;
11424 if (emitIns_valid_imm_for_add(offset, EA_8BYTE))
11428 // Generate code to set tmpReg = base + index*scale
11429 emitIns_R_R_R_I(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum, lsl,
11434 // Generate code to set tmpReg = base + index
11435 emitIns_R_R_R(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum);
11438 noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11440 // Then load/store dataReg from/to [tmpReg + offset]
11441 emitIns_R_R_I(ins, ldstAttr, dataReg, tmpReg, offset);
11443 else // large offset
11445 // First load/store tmpReg with the large offset constant
11446 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11447 // Then add the base register
11449 emitIns_R_R_R(INS_add, addType, tmpReg, tmpReg, memBase->gtRegNum);
11451 noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11452 noway_assert(tmpReg != index->gtRegNum);
11454 // Then load/store dataReg from/to [tmpReg + index*scale]
11455 emitIns_R_R_R_I(ins, ldstAttr, dataReg, tmpReg, index->gtRegNum, lsl, INS_OPTS_LSL);
11458 else // (offset == 0)
11462 // Then load/store dataReg from/to [memBase + index*scale]
11463 emitIns_R_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum, lsl, INS_OPTS_LSL);
11467 // Then load/store dataReg from/to [memBase + index]
11468 emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum);
11472 else // no Index register
11474 if (emitIns_valid_imm_for_ldst_offset(offset, EA_SIZE(attr)))
11476 // Then load/store dataReg from/to [memBase + offset]
11477 emitIns_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, offset);
11481 // We require a tmpReg to hold the offset
11482 regNumber tmpReg = indir->GetSingleTempReg();
11484 // First load/store tmpReg with the large offset constant
11485 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11487 // Then load/store dataReg from/to [memBase + tmpReg]
11488 emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, tmpReg);
11492 else // addr is not contained, so we evaluate it into a register
11494 // Then load/store dataReg from/to [addrReg]
11495 emitIns_R_R(ins, ldstAttr, dataReg, addr->gtRegNum);
11499 // The callee must call genConsumeReg() for any non-contained srcs
11500 // and genProduceReg() for any non-contained dsts.
11502 regNumber emitter::emitInsBinary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src)
11504 regNumber result = REG_NA;
11506 // dst can only be a reg
11507 assert(!dst->isContained());
11509 // src can be immed or reg
11510 assert(!src->isContained() || src->isContainedIntOrIImmed());
11512 // find immed (if any) - it cannot be a dst
11513 GenTreeIntConCommon* intConst = nullptr;
11514 if (src->isContainedIntOrIImmed())
11516 intConst = src->AsIntConCommon();
11521 emitIns_R_I(ins, attr, dst->gtRegNum, intConst->IconValue());
11522 return dst->gtRegNum;
11526 emitIns_R_R(ins, attr, dst->gtRegNum, src->gtRegNum);
11527 return dst->gtRegNum;
11531 // The callee must call genConsumeReg() for any non-contained srcs
11532 // and genProduceReg() for any non-contained dsts.
11534 regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src1, GenTree* src2)
11536 regNumber result = REG_NA;
11538 // dst can only be a reg
11539 assert(!dst->isContained());
11541 // find immed (if any) - it cannot be a dst
11542 // Only one src can be an int.
11543 GenTreeIntConCommon* intConst = nullptr;
11544 GenTree* nonIntReg = nullptr;
11546 if (varTypeIsFloating(dst))
11548 // src1 can only be a reg
11549 assert(!src1->isContained());
11550 // src2 can only be a reg
11551 assert(!src2->isContained());
11553 else // not floating point
11555 // src2 can be immed or reg
11556 assert(!src2->isContained() || src2->isContainedIntOrIImmed());
11558 // Check src2 first as we can always allow it to be a contained immediate
11559 if (src2->isContainedIntOrIImmed())
11561 intConst = src2->AsIntConCommon();
11564 // Only for commutative operations do we check src1 and allow it to be a contained immediate
11565 else if (dst->OperIsCommutative())
11567 // src1 can be immed or reg
11568 assert(!src1->isContained() || src1->isContainedIntOrIImmed());
11570 // Check src1 and allow it to be a contained immediate
11571 if (src1->isContainedIntOrIImmed())
11573 assert(!src2->isContainedIntOrIImmed());
11574 intConst = src1->AsIntConCommon();
11580 // src1 can only be a reg
11581 assert(!src1->isContained());
11585 bool isMulOverflow = false;
11586 if (dst->gtOverflowEx())
11588 if ((ins == INS_add) || (ins == INS_adds))
11592 else if ((ins == INS_sub) || (ins == INS_subs))
11596 else if (ins == INS_mul)
11598 isMulOverflow = true;
11599 assert(intConst == nullptr); // overflow format doesn't support an int constant operand
11603 assert(!"Invalid ins for overflow check");
11606 if (intConst != nullptr)
11608 emitIns_R_R_I(ins, attr, dst->gtRegNum, nonIntReg->gtRegNum, intConst->IconValue());
11614 regNumber extraReg = dst->GetSingleTempReg();
11615 assert(extraReg != dst->gtRegNum);
11617 if ((dst->gtFlags & GTF_UNSIGNED) != 0)
11619 if (attr == EA_4BYTE)
11621 // Compute 8 byte results from 4 byte by 4 byte multiplication.
11622 emitIns_R_R_R(INS_umull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11624 // Get the high result by shifting dst.
11625 emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11629 assert(attr == EA_8BYTE);
11630 // Compute the high result.
11631 emitIns_R_R_R(INS_umulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11633 // Now multiply without skewing the high result.
11634 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11637 // zero-sign bit comparison to detect overflow.
11638 emitIns_R_I(INS_cmp, attr, extraReg, 0);
11643 if (attr == EA_4BYTE)
11645 // Compute 8 byte results from 4 byte by 4 byte multiplication.
11646 emitIns_R_R_R(INS_smull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11648 // Get the high result by shifting dst.
11649 emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11655 assert(attr == EA_8BYTE);
11656 // Save the high result in a temporary register.
11657 emitIns_R_R_R(INS_smulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11659 // Now multiply without skewing the high result.
11660 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11665 // Sign bit comparison to detect overflow.
11666 emitIns_R_R_I(INS_cmp, attr, extraReg, dst->gtRegNum, bitShift, INS_OPTS_ASR);
11671 // We can just multiply.
11672 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11676 if (dst->gtOverflowEx())
11678 assert(!varTypeIsFloating(dst));
11679 codeGen->genCheckOverflow(dst);
11682 return dst->gtRegNum;
11685 #endif // defined(_TARGET_ARM64_)