1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
5 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
6 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
10 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
11 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
19 #if defined(_TARGET_ARM64_)
21 /*****************************************************************************/
22 /*****************************************************************************/
28 /* static */ bool emitter::strictArmAsm = true;
30 /*****************************************************************************/
32 const instruction emitJumpKindInstructions[] = {
35 #define JMP_SMALL(en, rev, ins) INS_##ins,
39 const emitJumpKind emitReverseJumpKinds[] = {
42 #define JMP_SMALL(en, rev, ins) EJ_##rev,
46 /*****************************************************************************
47 * Look up the instruction for a jump kind
50 /*static*/ instruction emitter::emitJumpKindToIns(emitJumpKind jumpKind)
52 assert((unsigned)jumpKind < ArrLen(emitJumpKindInstructions));
53 return emitJumpKindInstructions[jumpKind];
56 /*****************************************************************************
57 * Look up the jump kind for an instruction. It better be a conditional
58 * branch instruction with a jump kind!
61 /*static*/ emitJumpKind emitter::emitInsToJumpKind(instruction ins)
63 for (unsigned i = 0; i < ArrLen(emitJumpKindInstructions); i++)
65 if (ins == emitJumpKindInstructions[i])
67 emitJumpKind ret = (emitJumpKind)i;
68 assert(EJ_NONE < ret && ret < EJ_COUNT);
75 /*****************************************************************************
76 * Reverse the conditional jump
79 /*static*/ emitJumpKind emitter::emitReverseJumpKind(emitJumpKind jumpKind)
81 assert(jumpKind < EJ_COUNT);
82 return emitReverseJumpKinds[jumpKind];
85 /*****************************************************************************
87 * Return the allocated size (in bytes) of the given instruction descriptor.
90 size_t emitter::emitSizeOfInsDsc(instrDesc* id)
92 assert(!emitIsTinyInsDsc(id));
94 if (emitIsScnsInsDsc(id))
95 return SMALL_IDSC_SIZE;
97 assert((unsigned)id->idInsFmt() < emitFmtCount);
99 ID_OPS idOp = (ID_OPS)emitFmtToOps[id->idInsFmt()];
100 bool isCallIns = (id->idIns() == INS_bl) || (id->idIns() == INS_blr) || (id->idIns() == INS_b_tail) ||
101 (id->idIns() == INS_br_tail);
102 bool maybeCallIns = (id->idIns() == INS_b) || (id->idIns() == INS_br);
110 return sizeof(instrDescJmp);
113 assert(isCallIns || maybeCallIns);
114 if (id->idIsLargeCall())
116 /* Must be a "fat" call descriptor */
117 return sizeof(instrDescCGCA);
121 assert(!id->idIsLargeDsp());
122 assert(!id->idIsLargeCns());
123 return sizeof(instrDesc);
128 NO_WAY("unexpected instruction descriptor format");
132 if (id->idIsLargeCns())
134 if (id->idIsLargeDsp())
135 return sizeof(instrDescCnsDsp);
137 return sizeof(instrDescCns);
141 if (id->idIsLargeDsp())
142 return sizeof(instrDescDsp);
144 return sizeof(instrDesc);
149 /*****************************************************************************
151 * The following called for each recorded instruction -- use for debugging.
153 void emitter::emitInsSanityCheck(instrDesc* id)
155 /* What instruction format have we got? */
157 switch (id->idInsFmt())
169 case IF_BI_0A: // BI_0A ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
172 case IF_BI_0B: // BI_0B ......iiiiiiiiii iiiiiiiiiiii.... simm19:00
180 case IF_BI_0C: // BI_0C ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
183 case IF_BI_1A: // BI_1A ......iiiiiiiiii iiiiiiiiiiittttt Rt simm19:00
184 assert(isValidGeneralDatasize(id->idOpSize()));
185 assert(isGeneralRegister(id->idReg1()));
188 case IF_BI_1B: // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
189 assert(isValidGeneralDatasize(id->idOpSize()));
190 assert(isGeneralRegister(id->idReg1()));
191 assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
194 case IF_BR_1A: // BR_1A ................ ......nnnnn..... Rn
195 assert(isGeneralRegister(id->idReg1()));
198 case IF_BR_1B: // BR_1B ................ ......nnnnn..... Rn
199 assert(isGeneralRegister(id->idReg3()));
202 case IF_LS_1A: // LS_1A .X......iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB)
203 assert(isGeneralRegister(id->idReg1()) || isVectorRegister(id->idReg1()));
204 assert(insOptsNone(id->idInsOpt()));
207 case IF_LS_2A: // LS_2A .X.......X...... ......nnnnnttttt Rt Rn
208 assert(isIntegerRegister(id->idReg1()) || // ZR
209 isVectorRegister(id->idReg1()));
210 assert(isIntegerRegister(id->idReg2())); // SP
211 assert(emitGetInsSC(id) == 0);
212 assert(insOptsNone(id->idInsOpt()));
215 case IF_LS_2B: // LS_2B .X.......Xiiiiii iiiiiinnnnnttttt Rt Rn imm(0-4095)
216 assert(isIntegerRegister(id->idReg1()) || // ZR
217 isVectorRegister(id->idReg1()));
218 assert(isIntegerRegister(id->idReg2())); // SP
219 assert(isValidUimm12(emitGetInsSC(id)));
220 assert(insOptsNone(id->idInsOpt()));
223 case IF_LS_2C: // LS_2C .X.......X.iiiii iiiiPPnnnnnttttt Rt Rn imm(-256..+255) no/pre/post inc
224 assert(isIntegerRegister(id->idReg1()) || // ZR
225 isVectorRegister(id->idReg1()));
226 assert(isIntegerRegister(id->idReg2())); // SP
227 assert(emitGetInsSC(id) >= -0x100);
228 assert(emitGetInsSC(id) < 0x100);
229 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
232 case IF_LS_3A: // LS_3A .X.......X.mmmmm oooS..nnnnnttttt Rt Rn Rm ext(Rm) LSL {}
233 assert(isIntegerRegister(id->idReg1()) || // ZR
234 isVectorRegister(id->idReg1()));
235 assert(isIntegerRegister(id->idReg2())); // SP
236 if (id->idIsLclVar())
238 assert(isGeneralRegister(codeGen->rsGetRsvdReg()));
242 assert(isGeneralRegister(id->idReg3()));
244 assert(insOptsLSExtend(id->idInsOpt()));
247 case IF_LS_3B: // LS_3B X............... .aaaaannnnnttttt Rt Ra Rn
248 assert((isValidGeneralDatasize(id->idOpSize()) && isIntegerRegister(id->idReg1())) ||
249 (isValidVectorLSPDatasize(id->idOpSize()) && isVectorRegister(id->idReg1())));
250 assert(isIntegerRegister(id->idReg1()) || // ZR
251 isVectorRegister(id->idReg1()));
252 assert(isIntegerRegister(id->idReg2()) || // ZR
253 isVectorRegister(id->idReg2()));
254 assert(isIntegerRegister(id->idReg3())); // SP
255 assert(emitGetInsSC(id) == 0);
256 assert(insOptsNone(id->idInsOpt()));
259 case IF_LS_3C: // LS_3C X.........iiiiii iaaaaannnnnttttt Rt Ra Rn imm(im7,sh)
260 assert((isValidGeneralDatasize(id->idOpSize()) && isIntegerRegister(id->idReg1())) ||
261 (isValidVectorLSPDatasize(id->idOpSize()) && isVectorRegister(id->idReg1())));
262 assert(isIntegerRegister(id->idReg1()) || // ZR
263 isVectorRegister(id->idReg1()));
264 assert(isIntegerRegister(id->idReg2()) || // ZR
265 isVectorRegister(id->idReg2()));
266 assert(isIntegerRegister(id->idReg3())); // SP
267 assert(emitGetInsSC(id) >= -0x40);
268 assert(emitGetInsSC(id) < 0x40);
269 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
272 case IF_LS_3D: // LS_3D .X.......X.mmmmm ......nnnnnttttt Wm Rt Rn
273 assert(isIntegerRegister(id->idReg1()));
274 assert(isIntegerRegister(id->idReg2()));
275 assert(isIntegerRegister(id->idReg3()));
276 assert(emitGetInsSC(id) == 0);
277 assert(!id->idIsLclVar());
278 assert(insOptsNone(id->idInsOpt()));
281 case IF_DI_1A: // DI_1A X.......shiiiiii iiiiiinnnnn..... Rn imm(i12,sh)
282 assert(isValidGeneralDatasize(id->idOpSize()));
283 assert(isGeneralRegister(id->idReg1()));
284 assert(isValidUimm12(emitGetInsSC(id)));
285 assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
288 case IF_DI_1B: // DI_1B X........hwiiiii iiiiiiiiiiiddddd Rd imm(i16,hw)
289 assert(isValidGeneralDatasize(id->idOpSize()));
290 assert(isGeneralRegister(id->idReg1()));
291 assert(isValidImmHWVal(emitGetInsSC(id), id->idOpSize()));
294 case IF_DI_1C: // DI_1C X........Nrrrrrr ssssssnnnnn..... Rn imm(N,r,s)
295 assert(isValidGeneralDatasize(id->idOpSize()));
296 assert(isGeneralRegister(id->idReg1()));
297 assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
300 case IF_DI_1D: // DI_1D X........Nrrrrrr ssssss.....ddddd Rd imm(N,r,s)
301 assert(isValidGeneralDatasize(id->idOpSize()));
302 assert(isIntegerRegister(id->idReg1())); // SP
303 assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
306 case IF_DI_1E: // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
307 assert(isGeneralRegister(id->idReg1()));
310 case IF_DI_1F: // DI_1F X..........iiiii cccc..nnnnn.nzcv Rn imm5 nzcv cond
311 assert(isValidGeneralDatasize(id->idOpSize()));
312 assert(isGeneralRegister(id->idReg1()));
313 assert(isValidImmCondFlagsImm5(emitGetInsSC(id)));
316 case IF_DI_2A: // DI_2A X.......shiiiiii iiiiiinnnnnddddd Rd Rn imm(i12,sh)
317 assert(isValidGeneralDatasize(id->idOpSize()));
318 assert(isIntegerRegister(id->idReg1())); // SP
319 assert(isIntegerRegister(id->idReg2())); // SP
320 assert(isValidUimm12(emitGetInsSC(id)));
321 assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
324 case IF_DI_2B: // DI_2B X.........Xnnnnn ssssssnnnnnddddd Rd Rn imm(0-63)
325 assert(isValidGeneralDatasize(id->idOpSize()));
326 assert(isGeneralRegister(id->idReg1()));
327 assert(isGeneralRegister(id->idReg2()));
328 assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
331 case IF_DI_2C: // DI_2C X........Nrrrrrr ssssssnnnnnddddd Rd Rn imm(N,r,s)
332 assert(isValidGeneralDatasize(id->idOpSize()));
333 assert(isIntegerRegister(id->idReg1())); // SP
334 assert(isGeneralRegister(id->idReg2()));
335 assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
338 case IF_DI_2D: // DI_2D X........Nrrrrrr ssssssnnnnnddddd Rd Rn imr, imms (N,r,s)
339 assert(isValidGeneralDatasize(id->idOpSize()));
340 assert(isGeneralRegister(id->idReg1()));
341 assert(isGeneralRegister(id->idReg2()));
342 assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
345 case IF_DR_1D: // DR_1D X............... cccc.......ddddd Rd cond
346 assert(isValidGeneralDatasize(id->idOpSize()));
347 assert(isGeneralRegister(id->idReg1()));
348 assert(isValidImmCond(emitGetInsSC(id)));
351 case IF_DR_2A: // DR_2A X..........mmmmm ......nnnnn..... Rn Rm
352 assert(isValidGeneralDatasize(id->idOpSize()));
353 assert(isGeneralRegister(id->idReg1()));
354 assert(isGeneralRegister(id->idReg2()));
357 case IF_DR_2B: // DR_2B X.......sh.mmmmm ssssssnnnnn..... Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
358 assert(isValidGeneralDatasize(id->idOpSize()));
359 assert(isIntegerRegister(id->idReg1())); // ZR
360 assert(isGeneralRegister(id->idReg2()));
361 assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
362 if (!insOptsNone(id->idInsOpt()))
364 if (id->idIns() == INS_tst) // tst allows ROR, cmp/cmn don't
366 assert(insOptsAnyShift(id->idInsOpt()));
370 assert(insOptsAluShift(id->idInsOpt()));
373 assert(insOptsNone(id->idInsOpt()) || (emitGetInsSC(id) > 0));
376 case IF_DR_2C: // DR_2C X..........mmmmm ooosssnnnnn..... Rn Rm ext(Rm) LSL imm(0-4)
377 assert(isValidGeneralDatasize(id->idOpSize()));
378 assert(isIntegerRegister(id->idReg1())); // SP
379 assert(isGeneralRegister(id->idReg2()));
380 assert(insOptsNone(id->idInsOpt()) || insOptsLSL(id->idInsOpt()) || insOptsAnyExtend(id->idInsOpt()));
381 assert(emitGetInsSC(id) >= 0);
382 assert(emitGetInsSC(id) <= 4);
383 if (insOptsLSL(id->idInsOpt()))
385 assert(emitGetInsSC(id) > 0);
389 case IF_DR_2D: // DR_2D X..........nnnnn cccc..nnnnnmmmmm Rd Rn cond
390 assert(isValidGeneralDatasize(id->idOpSize()));
391 assert(isGeneralRegister(id->idReg1()));
392 assert(isGeneralRegister(id->idReg2()));
393 assert(isValidImmCond(emitGetInsSC(id)));
396 case IF_DR_2E: // DR_2E X..........mmmmm ...........ddddd Rd Rm
397 assert(isValidGeneralDatasize(id->idOpSize()));
398 assert(isGeneralRegister(id->idReg1()));
399 assert(isIntegerRegister(id->idReg2())); // ZR
402 case IF_DR_2F: // DR_2F X.......sh.mmmmm ssssss.....ddddd Rd Rm {LSL,LSR,ASR} imm(0-63)
403 assert(isValidGeneralDatasize(id->idOpSize()));
404 assert(isGeneralRegister(id->idReg1()));
405 assert(isGeneralRegister(id->idReg2()));
406 assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
407 assert(insOptsNone(id->idInsOpt()) || insOptsAluShift(id->idInsOpt()));
408 assert(insOptsNone(id->idInsOpt()) || (emitGetInsSC(id) > 0));
411 case IF_DR_2G: // DR_2G X............... ......nnnnnddddd Rd Rm
412 assert(isValidGeneralDatasize(id->idOpSize()));
413 assert(isIntegerRegister(id->idReg1())); // SP
414 assert(isIntegerRegister(id->idReg2())); // SP
417 case IF_DR_2H: // DR_2H X........X...... ......nnnnnddddd Rd Rn
418 assert(isValidGeneralDatasize(id->idOpSize()));
419 assert(isGeneralRegister(id->idReg1()));
420 assert(isGeneralRegister(id->idReg2()));
423 case IF_DR_2I: // DR_2I X..........mmmmm cccc..nnnnn.nzcv Rn Rm nzcv cond
424 assert(isValidGeneralDatasize(id->idOpSize()));
425 assert(isGeneralRegister(id->idReg1()));
426 assert(isGeneralRegister(id->idReg2()));
427 assert(isValidImmCondFlags(emitGetInsSC(id)));
430 case IF_DR_3A: // DR_3A X..........mmmmm ......nnnnnmmmmm Rd Rn Rm
431 assert(isValidGeneralDatasize(id->idOpSize()));
432 assert(isIntegerRegister(id->idReg1())); // SP
433 assert(isIntegerRegister(id->idReg2())); // SP
434 if (id->idIsLclVar())
436 assert(isGeneralRegister(codeGen->rsGetRsvdReg()));
440 assert(isGeneralRegister(id->idReg3()));
442 assert(insOptsNone(id->idInsOpt()));
445 case IF_DR_3B: // DR_3B X.......sh.mmmmm ssssssnnnnnddddd Rd Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
446 assert(isValidGeneralDatasize(id->idOpSize()));
447 assert(isGeneralRegister(id->idReg1()));
448 assert(isGeneralRegister(id->idReg2()));
449 assert(isGeneralRegister(id->idReg3()));
450 assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
451 assert(insOptsNone(id->idInsOpt()) || insOptsAnyShift(id->idInsOpt()));
452 assert(insOptsNone(id->idInsOpt()) || (emitGetInsSC(id) > 0));
455 case IF_DR_3C: // DR_3C X..........mmmmm ooosssnnnnnddddd Rd Rn Rm ext(Rm) LSL imm(0-4)
456 assert(isValidGeneralDatasize(id->idOpSize()));
457 assert(isIntegerRegister(id->idReg1())); // SP
458 assert(isIntegerRegister(id->idReg2())); // SP
459 assert(isGeneralRegister(id->idReg3()));
460 assert(insOptsNone(id->idInsOpt()) || insOptsLSL(id->idInsOpt()) || insOptsAnyExtend(id->idInsOpt()));
461 assert(emitGetInsSC(id) >= 0);
462 assert(emitGetInsSC(id) <= 4);
463 if (insOptsLSL(id->idInsOpt()))
465 assert((emitGetInsSC(id) > 0) ||
466 (id->idReg2() == REG_ZR)); // REG_ZR encodes SP and we allow a shift of zero
470 case IF_DR_3D: // DR_3D X..........mmmmm cccc..nnnnnmmmmm Rd Rn Rm cond
471 assert(isValidGeneralDatasize(id->idOpSize()));
472 assert(isGeneralRegister(id->idReg1()));
473 assert(isGeneralRegister(id->idReg2()));
474 assert(isGeneralRegister(id->idReg3()));
475 assert(isValidImmCond(emitGetInsSC(id)));
478 case IF_DR_3E: // DR_3E X........X.mmmmm ssssssnnnnnddddd Rd Rn Rm imm(0-63)
479 assert(isValidGeneralDatasize(id->idOpSize()));
480 assert(isGeneralRegister(id->idReg1()));
481 assert(isGeneralRegister(id->idReg2()));
482 assert(isGeneralRegister(id->idReg3()));
483 assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
484 assert(insOptsNone(id->idInsOpt()));
487 case IF_DR_4A: // DR_4A X..........mmmmm .aaaaannnnnddddd Rd Rn Rm Ra
488 assert(isValidGeneralDatasize(id->idOpSize()));
489 assert(isGeneralRegister(id->idReg1()));
490 assert(isGeneralRegister(id->idReg2()));
491 assert(isGeneralRegister(id->idReg3()));
492 assert(isGeneralRegister(id->idReg4()));
495 case IF_DV_1A: // DV_1A .........X.iiiii iii........ddddd Vd imm8 (fmov - immediate scalar)
496 assert(insOptsNone(id->idInsOpt()));
497 elemsize = id->idOpSize();
498 assert(isValidVectorElemsizeFloat(elemsize));
499 assert(isVectorRegister(id->idReg1()));
500 assert(isValidUimm8(emitGetInsSC(id)));
503 case IF_DV_1B: // DV_1B .QX..........iii cmod..iiiiiddddd Vd imm8 (immediate vector)
505 imm = emitGetInsSC(id) & 0x0ff;
506 immShift = (emitGetInsSC(id) & 0x700) >> 8;
507 assert(immShift >= 0);
508 datasize = id->idOpSize();
509 assert(isValidVectorDatasize(datasize));
510 assert(isValidArrangement(datasize, id->idInsOpt()));
511 elemsize = optGetElemsize(id->idInsOpt());
514 assert(isValidVectorElemsizeFloat(elemsize));
515 assert(id->idInsOpt() != INS_OPTS_1D); // Reserved encoding
516 assert(immShift == 0);
520 assert(isValidVectorElemsize(elemsize));
521 assert((immShift != 4) && (immShift != 7)); // always invalid values
522 if (ins != INS_movi) // INS_mvni, INS_orr, INS_bic
524 assert((elemsize != EA_1BYTE) && (elemsize != EA_8BYTE)); // only H or S
525 if (elemsize == EA_2BYTE)
527 assert(immShift < 2);
529 else // (elemsize == EA_4BYTE)
533 assert(immShift < 4);
538 assert(isVectorRegister(id->idReg1()));
539 assert(isValidUimm8(imm));
542 case IF_DV_1C: // DV_1C .........X...... ......nnnnn..... Vn #0.0 (fcmp - with zero)
543 assert(insOptsNone(id->idInsOpt()));
544 elemsize = id->idOpSize();
545 assert(isValidVectorElemsizeFloat(elemsize));
546 assert(isVectorRegister(id->idReg1()));
549 case IF_DV_2A: // DV_2A .Q.......X...... ......nnnnnddddd Vd Vn (fabs, fcvt - vector)
550 case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
551 assert(isValidVectorDatasize(id->idOpSize()));
552 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
553 assert(isVectorRegister(id->idReg1()));
554 assert(isVectorRegister(id->idReg2()));
557 case IF_DV_2N: // DV_2N .........iiiiiii ......nnnnnddddd Vd Vn imm (shift - scalar)
558 assert(id->idOpSize() == EA_8BYTE);
559 assert(insOptsNone(id->idInsOpt()));
560 assert(isVectorRegister(id->idReg1()));
561 assert(isVectorRegister(id->idReg2()));
562 assert(isValidImmShift(emitGetInsSC(id), EA_8BYTE));
565 case IF_DV_2O: // DV_2O .Q.......iiiiiii ......nnnnnddddd Vd Vn imm (shift - vector)
566 assert(isValidVectorDatasize(id->idOpSize()));
567 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
568 assert(isVectorRegister(id->idReg1()));
569 assert(isVectorRegister(id->idReg2()));
570 elemsize = optGetElemsize(id->idInsOpt());
571 assert(isValidImmShift(emitGetInsSC(id), elemsize));
574 case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov/smov - to general)
575 elemsize = id->idOpSize();
576 index = emitGetInsSC(id);
577 assert(insOptsNone(id->idInsOpt()));
578 assert(isValidVectorIndex(EA_16BYTE, elemsize, index));
579 assert(isValidVectorElemsize(elemsize));
580 assert(isGeneralRegister(id->idReg1()));
581 assert(isVectorRegister(id->idReg2()));
584 case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
585 if (id->idIns() == INS_dup)
587 datasize = id->idOpSize();
588 assert(isValidVectorDatasize(datasize));
589 assert(isValidArrangement(datasize, id->idInsOpt()));
590 elemsize = optGetElemsize(id->idInsOpt());
594 datasize = EA_16BYTE;
595 elemsize = id->idOpSize();
596 assert(isValidVectorElemsize(elemsize));
598 assert(isVectorRegister(id->idReg1()));
599 assert(isGeneralRegisterOrZR(id->idReg2()));
602 case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
603 datasize = id->idOpSize();
604 assert(isValidVectorDatasize(datasize));
605 assert(isValidArrangement(datasize, id->idInsOpt()));
606 elemsize = optGetElemsize(id->idInsOpt());
607 index = emitGetInsSC(id);
608 assert(isValidVectorIndex(datasize, elemsize, index));
609 assert(isVectorRegister(id->idReg1()));
610 assert(isVectorRegister(id->idReg2()));
613 case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
614 elemsize = id->idOpSize();
615 index = emitGetInsSC(id);
616 assert(isValidVectorIndex(EA_16BYTE, elemsize, index));
617 assert(isValidVectorElemsize(elemsize));
618 assert(isVectorRegister(id->idReg1()));
619 assert(isVectorRegister(id->idReg2()));
622 case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
623 imm = emitGetInsSC(id);
624 index = (imm >> 4) & 0xf;
626 elemsize = id->idOpSize();
627 assert(isValidVectorElemsize(elemsize));
628 assert(isValidVectorIndex(EA_16BYTE, elemsize, index));
629 assert(isValidVectorIndex(EA_16BYTE, elemsize, index2));
630 assert(isVectorRegister(id->idReg1()));
631 assert(isVectorRegister(id->idReg2()));
634 case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
635 assert(id->idOpSize() == EA_8BYTE); // only type D is supported
638 case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov, fcvtXX - register)
639 case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
640 assert(insOptsNone(id->idInsOpt()));
641 assert(isValidVectorElemsizeFloat(id->idOpSize()));
642 assert(isVectorRegister(id->idReg1()));
643 assert(isVectorRegister(id->idReg2()));
646 case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov/fcvtXX - to general)
647 assert(insOptsConvertFloatToInt(id->idInsOpt()));
648 dstsize = optGetDstsize(id->idInsOpt());
649 srcsize = optGetSrcsize(id->idInsOpt());
650 assert(isValidGeneralDatasize(dstsize));
651 assert(isValidVectorElemsizeFloat(srcsize));
652 assert(dstsize == id->idOpSize());
653 assert(isGeneralRegister(id->idReg1()));
654 assert(isVectorRegister(id->idReg2()));
657 case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov/Xcvtf - from general)
658 assert(insOptsConvertIntToFloat(id->idInsOpt()));
659 dstsize = optGetDstsize(id->idInsOpt());
660 srcsize = optGetSrcsize(id->idInsOpt());
661 assert(isValidGeneralDatasize(srcsize));
662 assert(isValidVectorElemsizeFloat(dstsize));
663 assert(dstsize == id->idOpSize());
664 assert(isVectorRegister(id->idReg1()));
665 assert(isGeneralRegister(id->idReg2()));
668 case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
669 assert(insOptsConvertFloatToFloat(id->idInsOpt()));
670 dstsize = optGetDstsize(id->idInsOpt());
671 srcsize = optGetSrcsize(id->idInsOpt());
672 assert(isValidVectorFcvtsize(srcsize));
673 assert(isValidVectorFcvtsize(dstsize));
674 assert(dstsize == id->idOpSize());
675 assert(isVectorRegister(id->idReg1()));
676 assert(isVectorRegister(id->idReg2()));
679 case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
680 assert(isValidVectorDatasize(id->idOpSize()));
681 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
682 assert(isVectorRegister(id->idReg1()));
683 assert(isVectorRegister(id->idReg2()));
684 assert(isVectorRegister(id->idReg3()));
685 elemsize = optGetElemsize(id->idInsOpt());
689 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
691 else if (ins == INS_pmul)
693 assert(elemsize == EA_1BYTE); // only supports 8B or 16B
697 case IF_DV_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
698 assert(isValidVectorDatasize(id->idOpSize()));
699 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
700 assert(isVectorRegister(id->idReg1()));
701 assert(isVectorRegister(id->idReg2()));
702 assert(isVectorRegister(id->idReg3()));
703 elemsize = optGetElemsize(id->idInsOpt());
704 assert(isValidVectorIndex(EA_16BYTE, elemsize, emitGetInsSC(id)));
705 // Only has encodings for H or S elemsize
706 assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE));
709 case IF_DV_3B: // DV_3B .Q.......X.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
710 assert(isValidVectorDatasize(id->idOpSize()));
711 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
712 assert(isVectorRegister(id->idReg1()));
713 assert(isVectorRegister(id->idReg2()));
714 assert(isVectorRegister(id->idReg3()));
717 case IF_DV_3BI: // DV_3BI .Q.......XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
718 assert(isValidVectorDatasize(id->idOpSize()));
719 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
720 assert(isVectorRegister(id->idReg1()));
721 assert(isVectorRegister(id->idReg2()));
722 assert(isVectorRegister(id->idReg3()));
723 elemsize = optGetElemsize(id->idInsOpt());
724 assert(isValidVectorIndex(id->idOpSize(), elemsize, emitGetInsSC(id)));
727 case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
728 assert(isValidVectorDatasize(id->idOpSize()));
729 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
730 assert(isVectorRegister(id->idReg1()));
731 assert(isVectorRegister(id->idReg2()));
732 assert(isVectorRegister(id->idReg3()));
735 case IF_DV_3D: // DV_3D .........X.mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
736 assert(isValidScalarDatasize(id->idOpSize()));
737 assert(insOptsNone(id->idInsOpt()));
738 assert(isVectorRegister(id->idReg1()));
739 assert(isVectorRegister(id->idReg2()));
740 assert(isVectorRegister(id->idReg3()));
743 case IF_DV_3DI: // DV_3DI .........XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (scalar by elem)
744 assert(isValidScalarDatasize(id->idOpSize()));
745 assert(insOptsNone(id->idInsOpt()));
746 assert(isVectorRegister(id->idReg1()));
747 assert(isVectorRegister(id->idReg2()));
748 assert(isVectorRegister(id->idReg3()));
749 elemsize = id->idOpSize();
750 assert(isValidVectorIndex(EA_16BYTE, elemsize, emitGetInsSC(id)));
753 case IF_DV_3E: // DV_3E ...........mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
754 assert(insOptsNone(id->idInsOpt()));
755 assert(id->idOpSize() == EA_8BYTE);
756 assert(isVectorRegister(id->idReg1()));
757 assert(isVectorRegister(id->idReg2()));
758 assert(isVectorRegister(id->idReg3()));
761 case IF_DV_4A: // DR_4A .........X.mmmmm .aaaaannnnnddddd Rd Rn Rm Ra (scalar)
762 assert(isValidGeneralDatasize(id->idOpSize()));
763 assert(isVectorRegister(id->idReg1()));
764 assert(isVectorRegister(id->idReg2()));
765 assert(isVectorRegister(id->idReg3()));
766 assert(isVectorRegister(id->idReg4()));
769 case IF_SN_0A: // SN_0A ................ ................
770 case IF_SI_0A: // SI_0A ...........iiiii iiiiiiiiiii..... imm16
771 case IF_SI_0B: // SI_0B ................ ....bbbb........ imm4 - barrier
775 printf("unexpected format %s\n", emitIfName(id->idInsFmt()));
776 assert(!"Unexpected format");
782 bool emitter::emitInsMayWriteToGCReg(instrDesc* id)
784 instruction ins = id->idIns();
785 insFormat fmt = id->idInsFmt();
790 // These are the formats with "destination" registers:
792 case IF_DI_1B: // DI_1B X........hwiiiii iiiiiiiiiiiddddd Rd imm(i16,hw)
793 case IF_DI_1D: // DI_1D X........Nrrrrrr ssssss.....ddddd Rd imm(N,r,s)
794 case IF_DI_1E: // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
796 case IF_DI_2A: // DI_2A X.......shiiiiii iiiiiinnnnnddddd Rd Rn imm(i12,sh)
797 case IF_DI_2B: // DI_2B X.........Xnnnnn ssssssnnnnnddddd Rd Rn imm(0-63)
798 case IF_DI_2C: // DI_2C X........Nrrrrrr ssssssnnnnnddddd Rd Rn imm(N,r,s)
799 case IF_DI_2D: // DI_2D X........Nrrrrrr ssssssnnnnnddddd Rd Rn imr, imms (N,r,s)
801 case IF_DR_1D: // DR_1D X............... cccc.......ddddd Rd cond
803 case IF_DR_2D: // DR_2D X..........nnnnn cccc..nnnnnddddd Rd Rn cond
804 case IF_DR_2E: // DR_2E X..........mmmmm ...........ddddd Rd Rm
805 case IF_DR_2F: // DR_2F X.......sh.mmmmm ssssss.....ddddd Rd Rm {LSL,LSR,ASR} imm(0-63)
806 case IF_DR_2G: // DR_2G X............... ......nnnnnddddd Rd Rn
807 case IF_DR_2H: // DR_2H X........X...... ......nnnnnddddd Rd Rn
809 case IF_DR_3A: // DR_3A X..........mmmmm ......nnnnnddddd Rd Rn Rm
810 case IF_DR_3B: // DR_3B X.......sh.mmmmm ssssssnnnnnddddd Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
811 case IF_DR_3C: // DR_3C X..........mmmmm xxxsssnnnnnddddd Rd Rn Rm ext(Rm) LSL imm(0-4)
812 case IF_DR_3D: // DR_3D X..........mmmmm cccc..nnnnnddddd Rd Rn Rm cond
813 case IF_DR_3E: // DR_3E X........X.mmmmm ssssssnnnnnddddd Rd Rn Rm imm(0-63)
815 case IF_DR_4A: // DR_4A X..........mmmmm .aaaaannnnnddddd Rd Rn Rm Ra
817 case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov - to general)
818 case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov - to general)
822 case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
823 case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
824 case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
825 case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
826 case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov, fcvtXX - register)
827 case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov - from general)
828 case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
829 case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
830 case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
831 case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
832 case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
833 case IF_DV_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector)
834 case IF_DV_3B: // DV_3B .Q.......X.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
835 case IF_DV_3BI: // DV_3BI .Q.......XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
836 case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
837 case IF_DV_3D: // DV_3D .........X.mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
838 case IF_DV_3DI: // DV_3DI .........XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (scalar by elem)
839 case IF_DV_3E: // DV_3E ...........mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
840 case IF_DV_4A: // DV_4A .........X.mmmmm .aaaaannnnnddddd Vd Va Vn Vm (scalar)
841 // Tracked GC pointers cannot be placed into the SIMD registers.
844 // These are the load/store formats with "target" registers:
846 case IF_LS_1A: // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB)
847 case IF_LS_2A: // LS_2A .X.......X...... ......nnnnnttttt Rt Rn
848 case IF_LS_2B: // LS_2B .X.......Xiiiiii iiiiiinnnnnttttt Rt Rn imm(0-4095)
849 case IF_LS_2C: // LS_2C .X.......X.iiiii iiiiP.nnnnnttttt Rt Rn imm(-256..+255) pre/post inc
850 case IF_LS_3A: // LS_3A .X.......X.mmmmm xxxS..nnnnnttttt Rt Rn Rm ext(Rm) LSL {}
851 case IF_LS_3B: // LS_3B X............... .aaaaannnnnttttt Rt Ra Rn
852 case IF_LS_3C: // LS_3C X.........iiiiii iaaaaannnnnttttt Rt Ra Rn imm(im7,sh)
853 case IF_LS_3D: // LS_3D .X.......X.mmmmm ......nnnnnttttt Wm Rt Rn
855 // For the Store instructions the "target" register is actually a "source" value
857 if (emitInsIsStore(ins))
863 assert(emitInsIsLoad(ins));
872 bool emitter::emitInsWritesToLclVarStackLoc(instrDesc* id)
874 if (!id->idIsLclVar())
877 instruction ins = id->idIns();
879 // This list is related to the list of instructions used to store local vars in emitIns_S_R().
880 // We don't accept writing to float local vars.
896 bool emitter::emitInsWritesToLclVarStackLocPair(instrDesc* id)
898 if (!id->idIsLclVar())
901 instruction ins = id->idIns();
903 // This list is related to the list of instructions used to store local vars in emitIns_S_S_R_R().
904 // We don't accept writing to float local vars.
916 bool emitter::emitInsMayWriteMultipleRegs(instrDesc* id)
918 instruction ins = id->idIns();
931 // For the small loads/store instruction we adjust the size 'attr'
932 // depending upon whether we have a load or a store
934 emitAttr emitter::emitInsAdjustLoadStoreAttr(instruction ins, emitAttr attr)
936 if (EA_SIZE(attr) <= EA_4BYTE)
938 if (emitInsIsLoad(ins))
940 // The value of 'ins' encodes the size to load
941 // we use EA_8BYTE here because it is the size we will write (into dataReg)
942 // it is also required when ins is INS_ldrsw
948 assert(emitInsIsStore(ins));
950 // The value of 'ins' encodes the size to store
951 // we use EA_4BYTE here because it is the size of the register
952 // that we want to display when storing small values
960 // Takes an instrDesc 'id' and uses the instruction 'ins' to determine the
961 // size of the target register that is written or read by the instruction.
962 // Note that even if EA_4BYTE is returned a load instruction will still
963 // always zero the upper 4 bytes of the target register.
964 // This method is required so that we can distinguish between loads that are
965 // sign-extending as they can have two different sizes for their target register.
966 // Additionally for instructions like 'ldr' and 'str' these can load/store
967 // either 4 byte or 8 bytes to/from the target register.
968 // By convention the small unsigned load instructions are considered to write
969 // a 4 byte sized target register, though since these also zero the upper 4 bytes
970 // they could equally be considered to write the unsigned value to full 8 byte register.
972 emitAttr emitter::emitInsTargetRegSize(instrDesc* id)
974 instruction ins = id->idIns();
975 emitAttr result = EA_UNKNOWN;
977 // This is used to determine the size of the target registers for a load/store instruction
1011 if (id->idOpSize() == EA_8BYTE)
1027 result = id->idOpSize();
1040 result = id->idOpSize();
1044 NO_WAY("unexpected instruction");
1050 // Takes an instrDesc and uses the instruction to determine the 'size' of the
1051 // data that is loaded from memory.
1053 emitAttr emitter::emitInsLoadStoreSize(instrDesc* id)
1055 instruction ins = id->idIns();
1056 emitAttr result = EA_UNKNOWN;
1058 // The 'result' returned is the 'size' of the data that is loaded from memory.
1094 result = id->idOpSize();
1103 result = id->idOpSize();
1107 NO_WAY("unexpected instruction");
1113 /*****************************************************************************/
1117 static const char * const xRegNames[] =
1119 #define REGDEF(name, rnum, mask, xname, wname) xname,
1120 #include "register.h"
1123 static const char * const wRegNames[] =
1125 #define REGDEF(name, rnum, mask, xname, wname) wname,
1126 #include "register.h"
1129 static const char * const vRegNames[] =
1131 "v0", "v1", "v2", "v3", "v4",
1132 "v5", "v6", "v7", "v8", "v9",
1133 "v10", "v11", "v12", "v13", "v14",
1134 "v15", "v16", "v17", "v18", "v19",
1135 "v20", "v21", "v22", "v23", "v24",
1136 "v25", "v26", "v27", "v28", "v29",
1140 static const char * const qRegNames[] =
1142 "q0", "q1", "q2", "q3", "q4",
1143 "q5", "q6", "q7", "q8", "q9",
1144 "q10", "q11", "q12", "q13", "q14",
1145 "q15", "q16", "q17", "q18", "q19",
1146 "q20", "q21", "q22", "q23", "q24",
1147 "q25", "q26", "q27", "q28", "q29",
1151 static const char * const hRegNames[] =
1153 "h0", "h1", "h2", "h3", "h4",
1154 "h5", "h6", "h7", "h8", "h9",
1155 "h10", "h11", "h12", "h13", "h14",
1156 "h15", "h16", "h17", "h18", "h19",
1157 "h20", "h21", "h22", "h23", "h24",
1158 "h25", "h26", "h27", "h28", "h29",
1161 static const char * const bRegNames[] =
1163 "b0", "b1", "b2", "b3", "b4",
1164 "b5", "b6", "b7", "b8", "b9",
1165 "b10", "b11", "b12", "b13", "b14",
1166 "b15", "b16", "b17", "b18", "b19",
1167 "b20", "b21", "b22", "b23", "b24",
1168 "b25", "b26", "b27", "b28", "b29",
1173 /*****************************************************************************
1175 * Return a string that represents the given register.
1178 const char* emitter::emitRegName(regNumber reg, emitAttr size, bool varName)
1180 assert(reg < REG_COUNT);
1182 const char* rn = nullptr;
1184 if (size == EA_8BYTE)
1186 rn = xRegNames[reg];
1188 else if (size == EA_4BYTE)
1190 rn = wRegNames[reg];
1192 else if (isVectorRegister(reg))
1194 if (size == EA_16BYTE)
1196 rn = qRegNames[reg - REG_V0];
1198 else if (size == EA_2BYTE)
1200 rn = hRegNames[reg - REG_V0];
1202 else if (size == EA_1BYTE)
1204 rn = bRegNames[reg - REG_V0];
1208 assert(rn != nullptr);
1213 /*****************************************************************************
1215 * Return a string that represents the given register.
1218 const char* emitter::emitVectorRegName(regNumber reg)
1220 assert((reg >= REG_V0) && (reg <= REG_V31));
1222 int index = (int)reg - (int)REG_V0;
1224 return vRegNames[index];
1228 /*****************************************************************************
1230 * Returns the base encoding of the given CPU instruction.
1233 emitter::insFormat emitter::emitInsFormat(instruction ins)
1236 const static insFormat insFormats[] =
1238 #define INST1(id, nm, fp, ldst, fmt, e1 ) fmt,
1239 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) fmt,
1240 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) fmt,
1241 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) fmt,
1242 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) fmt,
1243 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) fmt,
1244 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) fmt,
1249 assert(ins < ArrLen(insFormats));
1250 assert((insFormats[ins] != IF_NONE));
1252 return insFormats[ins];
1261 /*static*/ const BYTE CodeGenInterface::instInfo[] =
1263 #define INST1(id, nm, fp, ldst, fmt, e1 ) ldst | INST_FP*fp,
1264 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) ldst | INST_FP*fp,
1265 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) ldst | INST_FP*fp,
1266 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) ldst | INST_FP*fp,
1267 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) ldst | INST_FP*fp,
1268 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) ldst | INST_FP*fp,
1269 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) ldst | INST_FP*fp,
1274 /*****************************************************************************
1276 * Returns true if the instruction is some kind of compare or test instruction
1279 bool emitter::emitInsIsCompare(instruction ins)
1281 // We have pseudo ins like lea which are not included in emitInsLdStTab.
1282 if (ins < ArrLen(CodeGenInterface::instInfo))
1283 return (CodeGenInterface::instInfo[ins] & CMP) ? true : false;
1288 /*****************************************************************************
1290 * Returns true if the instruction is some kind of load instruction
1293 bool emitter::emitInsIsLoad(instruction ins)
1295 // We have pseudo ins like lea which are not included in emitInsLdStTab.
1296 if (ins < ArrLen(CodeGenInterface::instInfo))
1297 return (CodeGenInterface::instInfo[ins] & LD) ? true : false;
1301 /*****************************************************************************
1303 * Returns true if the instruction is some kind of store instruction
1306 bool emitter::emitInsIsStore(instruction ins)
1308 // We have pseudo ins like lea which are not included in emitInsLdStTab.
1309 if (ins < ArrLen(CodeGenInterface::instInfo))
1310 return (CodeGenInterface::instInfo[ins] & ST) ? true : false;
1315 /*****************************************************************************
1317 * Returns true if the instruction is some kind of load/store instruction
1320 bool emitter::emitInsIsLoadOrStore(instruction ins)
1322 // We have pseudo ins like lea which are not included in emitInsLdStTab.
1323 if (ins < ArrLen(CodeGenInterface::instInfo))
1324 return (CodeGenInterface::instInfo[ins] & (LD | ST)) ? true : false;
1333 /*****************************************************************************
1335 * Returns the specific encoding of the given CPU instruction and format
1338 emitter::code_t emitter::emitInsCode(instruction ins, insFormat fmt)
1341 const static code_t insCodes1[] =
1343 #define INST1(id, nm, fp, ldst, fmt, e1 ) e1,
1344 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) e1,
1345 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) e1,
1346 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e1,
1347 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e1,
1348 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e1,
1349 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e1,
1352 const static code_t insCodes2[] =
1354 #define INST1(id, nm, fp, ldst, fmt, e1 )
1355 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) e2,
1356 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) e2,
1357 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e2,
1358 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e2,
1359 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e2,
1360 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e2,
1363 const static code_t insCodes3[] =
1365 #define INST1(id, nm, fp, ldst, fmt, e1 )
1366 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1367 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) e3,
1368 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e3,
1369 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e3,
1370 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e3,
1371 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e3,
1374 const static code_t insCodes4[] =
1376 #define INST1(id, nm, fp, ldst, fmt, e1 )
1377 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1378 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
1379 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e4,
1380 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e4,
1381 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e4,
1382 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e4,
1385 const static code_t insCodes5[] =
1387 #define INST1(id, nm, fp, ldst, fmt, e1 )
1388 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1389 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
1390 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
1391 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e5,
1392 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e5,
1393 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e5,
1396 const static code_t insCodes6[] =
1398 #define INST1(id, nm, fp, ldst, fmt, e1 )
1399 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1400 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
1401 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
1402 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
1403 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e6,
1404 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e6,
1407 const static code_t insCodes7[] =
1409 #define INST1(id, nm, fp, ldst, fmt, e1 )
1410 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1411 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
1412 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
1413 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
1414 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 )
1415 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e7,
1418 const static code_t insCodes8[] =
1420 #define INST1(id, nm, fp, ldst, fmt, e1 )
1421 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1422 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
1423 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
1424 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
1425 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 )
1426 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e8,
1429 const static code_t insCodes9[] =
1431 #define INST1(id, nm, fp, ldst, fmt, e1 )
1432 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1433 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
1434 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
1435 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
1436 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 )
1437 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e9,
1442 const static insFormat formatEncode9[9] = {IF_DR_2E, IF_DR_2G, IF_DI_1B, IF_DI_1D, IF_DV_3C,
1443 IF_DV_2B, IF_DV_2C, IF_DV_2E, IF_DV_2F};
1444 const static insFormat formatEncode6A[6] = {IF_DR_3A, IF_DR_3B, IF_DR_3C, IF_DI_2A, IF_DV_3A, IF_DV_3E};
1445 const static insFormat formatEncode5A[5] = {IF_LS_2A, IF_LS_2B, IF_LS_2C, IF_LS_3A, IF_LS_1A};
1446 const static insFormat formatEncode5B[5] = {IF_DV_2G, IF_DV_2H, IF_DV_2I, IF_DV_1A, IF_DV_1B};
1447 const static insFormat formatEncode5C[5] = {IF_DR_3A, IF_DR_3B, IF_DI_2C, IF_DV_3C, IF_DV_1B};
1448 const static insFormat formatEncode4A[4] = {IF_LS_2A, IF_LS_2B, IF_LS_2C, IF_LS_3A};
1449 const static insFormat formatEncode4B[4] = {IF_DR_3A, IF_DR_3B, IF_DR_3C, IF_DI_2A};
1450 const static insFormat formatEncode4C[4] = {IF_DR_2A, IF_DR_2B, IF_DR_2C, IF_DI_1A};
1451 const static insFormat formatEncode4D[4] = {IF_DV_3B, IF_DV_3D, IF_DV_3BI, IF_DV_3DI};
1452 const static insFormat formatEncode4E[4] = {IF_DR_3A, IF_DR_3B, IF_DI_2C, IF_DV_3C};
1453 const static insFormat formatEncode4F[4] = {IF_DR_3A, IF_DR_3B, IF_DV_3C, IF_DV_1B};
1454 const static insFormat formatEncode4G[4] = {IF_DR_2E, IF_DR_2F, IF_DV_2M, IF_DV_2L};
1455 const static insFormat formatEncode4H[4] = {IF_DV_3E, IF_DV_3A, IF_DV_2L, IF_DV_2M};
1456 const static insFormat formatEncode4I[4] = {IF_DV_3D, IF_DV_3B, IF_DV_2G, IF_DV_2A};
1457 const static insFormat formatEncode3A[3] = {IF_DR_3A, IF_DR_3B, IF_DI_2C};
1458 const static insFormat formatEncode3B[3] = {IF_DR_2A, IF_DR_2B, IF_DI_1C};
1459 const static insFormat formatEncode3C[3] = {IF_DR_3A, IF_DR_3B, IF_DV_3C};
1460 const static insFormat formatEncode3D[3] = {IF_DV_2C, IF_DV_2D, IF_DV_2E};
1461 const static insFormat formatEncode3E[3] = {IF_DV_3B, IF_DV_3BI, IF_DV_3DI};
1462 const static insFormat formatEncode3F[3] = {IF_DV_2A, IF_DV_2G, IF_DV_2H};
1463 const static insFormat formatEncode3G[3] = {IF_DV_2A, IF_DV_2G, IF_DV_2I};
1464 const static insFormat formatEncode3H[3] = {IF_DR_3A, IF_DV_3A, IF_DV_3AI};
1465 const static insFormat formatEncode3I[3] = {IF_DR_2E, IF_DR_2F, IF_DV_2M};
1466 const static insFormat formatEncode2A[2] = {IF_DR_2E, IF_DR_2F};
1467 const static insFormat formatEncode2B[2] = {IF_DR_3A, IF_DR_3B};
1468 const static insFormat formatEncode2C[2] = {IF_DR_3A, IF_DI_2D};
1469 const static insFormat formatEncode2D[2] = {IF_DR_3A, IF_DI_2B};
1470 const static insFormat formatEncode2E[2] = {IF_LS_3B, IF_LS_3C};
1471 const static insFormat formatEncode2F[2] = {IF_DR_2I, IF_DI_1F};
1472 const static insFormat formatEncode2G[2] = {IF_DV_3B, IF_DV_3D};
1473 const static insFormat formatEncode2H[2] = {IF_DV_2C, IF_DV_2F};
1474 const static insFormat formatEncode2I[2] = {IF_DV_2K, IF_DV_1C};
1475 const static insFormat formatEncode2J[2] = {IF_DV_2A, IF_DV_2G};
1476 const static insFormat formatEncode2K[2] = {IF_DV_2M, IF_DV_2L};
1477 const static insFormat formatEncode2L[2] = {IF_DV_2G, IF_DV_2M};
1478 const static insFormat formatEncode2M[2] = {IF_DV_3A, IF_DV_3AI};
1479 const static insFormat formatEncode2N[2] = {IF_DV_2N, IF_DV_2O};
1480 const static insFormat formatEncode2O[2] = {IF_DV_3E, IF_DV_3A};
1481 const static insFormat formatEncode2P[2] = {IF_DV_2G, IF_DV_3B};
1483 code_t code = BAD_CODE;
1484 insFormat insFmt = emitInsFormat(ins);
1485 bool encoding_found = false;
1491 for (index = 0; index < 9; index++)
1493 if (fmt == formatEncode9[index])
1495 encoding_found = true;
1502 for (index = 0; index < 6; index++)
1504 if (fmt == formatEncode6A[index])
1506 encoding_found = true;
1513 for (index = 0; index < 5; index++)
1515 if (fmt == formatEncode5A[index])
1517 encoding_found = true;
1524 for (index = 0; index < 5; index++)
1526 if (fmt == formatEncode5B[index])
1528 encoding_found = true;
1535 for (index = 0; index < 5; index++)
1537 if (fmt == formatEncode5C[index])
1539 encoding_found = true;
1546 for (index = 0; index < 4; index++)
1548 if (fmt == formatEncode4A[index])
1550 encoding_found = true;
1557 for (index = 0; index < 4; index++)
1559 if (fmt == formatEncode4B[index])
1561 encoding_found = true;
1568 for (index = 0; index < 4; index++)
1570 if (fmt == formatEncode4C[index])
1572 encoding_found = true;
1579 for (index = 0; index < 4; index++)
1581 if (fmt == formatEncode4D[index])
1583 encoding_found = true;
1590 for (index = 0; index < 4; index++)
1592 if (fmt == formatEncode4E[index])
1594 encoding_found = true;
1601 for (index = 0; index < 4; index++)
1603 if (fmt == formatEncode4F[index])
1605 encoding_found = true;
1612 for (index = 0; index < 4; index++)
1614 if (fmt == formatEncode4G[index])
1616 encoding_found = true;
1623 for (index = 0; index < 4; index++)
1625 if (fmt == formatEncode4H[index])
1627 encoding_found = true;
1634 for (index = 0; index < 4; index++)
1636 if (fmt == formatEncode4I[index])
1638 encoding_found = true;
1645 for (index = 0; index < 3; index++)
1647 if (fmt == formatEncode3A[index])
1649 encoding_found = true;
1656 for (index = 0; index < 3; index++)
1658 if (fmt == formatEncode3B[index])
1660 encoding_found = true;
1667 for (index = 0; index < 3; index++)
1669 if (fmt == formatEncode3C[index])
1671 encoding_found = true;
1678 for (index = 0; index < 3; index++)
1680 if (fmt == formatEncode3D[index])
1682 encoding_found = true;
1689 for (index = 0; index < 3; index++)
1691 if (fmt == formatEncode3E[index])
1693 encoding_found = true;
1700 for (index = 0; index < 3; index++)
1702 if (fmt == formatEncode3F[index])
1704 encoding_found = true;
1711 for (index = 0; index < 3; index++)
1713 if (fmt == formatEncode3G[index])
1715 encoding_found = true;
1722 for (index = 0; index < 3; index++)
1724 if (fmt == formatEncode3H[index])
1726 encoding_found = true;
1733 for (index = 0; index < 3; index++)
1735 if (fmt == formatEncode3I[index])
1737 encoding_found = true;
1744 for (index = 0; index < 2; index++)
1746 if (fmt == formatEncode2A[index])
1748 encoding_found = true;
1755 for (index = 0; index < 2; index++)
1757 if (fmt == formatEncode2B[index])
1759 encoding_found = true;
1766 for (index = 0; index < 2; index++)
1768 if (fmt == formatEncode2C[index])
1770 encoding_found = true;
1777 for (index = 0; index < 2; index++)
1779 if (fmt == formatEncode2D[index])
1781 encoding_found = true;
1788 for (index = 0; index < 2; index++)
1790 if (fmt == formatEncode2E[index])
1792 encoding_found = true;
1799 for (index = 0; index < 2; index++)
1801 if (fmt == formatEncode2F[index])
1803 encoding_found = true;
1810 for (index = 0; index < 2; index++)
1812 if (fmt == formatEncode2G[index])
1814 encoding_found = true;
1821 for (index = 0; index < 2; index++)
1823 if (fmt == formatEncode2H[index])
1825 encoding_found = true;
1832 for (index = 0; index < 2; index++)
1834 if (fmt == formatEncode2I[index])
1836 encoding_found = true;
1843 for (index = 0; index < 2; index++)
1845 if (fmt == formatEncode2J[index])
1847 encoding_found = true;
1854 for (index = 0; index < 2; index++)
1856 if (fmt == formatEncode2K[index])
1858 encoding_found = true;
1865 for (index = 0; index < 2; index++)
1867 if (fmt == formatEncode2L[index])
1869 encoding_found = true;
1876 for (index = 0; index < 2; index++)
1878 if (fmt == formatEncode2M[index])
1880 encoding_found = true;
1887 for (index = 0; index < 2; index++)
1889 if (fmt == formatEncode2N[index])
1891 encoding_found = true;
1898 for (index = 0; index < 2; index++)
1900 if (fmt == formatEncode2O[index])
1902 encoding_found = true;
1909 for (index = 0; index < 2; index++)
1911 if (fmt == formatEncode2P[index])
1913 encoding_found = true;
1992 encoding_found = true;
1997 encoding_found = false;
2001 assert(encoding_found);
2006 assert(ins < ArrLen(insCodes1));
2007 code = insCodes1[ins];
2010 assert(ins < ArrLen(insCodes2));
2011 code = insCodes2[ins];
2014 assert(ins < ArrLen(insCodes3));
2015 code = insCodes3[ins];
2018 assert(ins < ArrLen(insCodes4));
2019 code = insCodes4[ins];
2022 assert(ins < ArrLen(insCodes5));
2023 code = insCodes5[ins];
2026 assert(ins < ArrLen(insCodes6));
2027 code = insCodes6[ins];
2030 assert(ins < ArrLen(insCodes7));
2031 code = insCodes7[ins];
2034 assert(ins < ArrLen(insCodes8));
2035 code = insCodes8[ins];
2038 assert(ins < ArrLen(insCodes9));
2039 code = insCodes9[ins];
2043 assert((code != BAD_CODE));
2048 // true if this 'imm' can be encoded as a input operand to a mov instruction
2049 /*static*/ bool emitter::emitIns_valid_imm_for_mov(INT64 imm, emitAttr size)
2051 // Check for "MOV (wide immediate)".
2052 if (canEncodeHalfwordImm(imm, size))
2055 // Next try the ones-complement form of 'halfword immediate' imm(i16,hw),
2056 // namely "MOV (inverted wide immediate)".
2057 ssize_t notOfImm = NOT_helper(imm, getBitWidth(size));
2058 if (canEncodeHalfwordImm(notOfImm, size))
2061 // Finally try "MOV (bitmask immediate)" imm(N,r,s)
2062 if (canEncodeBitMaskImm(imm, size))
2068 // true if this 'imm' can be encoded as a input operand to a vector movi instruction
2069 /*static*/ bool emitter::emitIns_valid_imm_for_movi(INT64 imm, emitAttr elemsize)
2071 if (elemsize == EA_8BYTE)
2076 INT64 loByte = uimm & 0xFF;
2077 if ((loByte == 0) || (loByte == 0xFF))
2091 // First try the standard 'byteShifted immediate' imm(i8,bySh)
2092 if (canEncodeByteShiftedImm(imm, elemsize, true))
2095 // Next try the ones-complement form of the 'immediate' imm(i8,bySh)
2096 ssize_t notOfImm = NOT_helper(imm, getBitWidth(elemsize));
2097 if (canEncodeByteShiftedImm(notOfImm, elemsize, true))
2103 // true if this 'imm' can be encoded as a input operand to a fmov instruction
2104 /*static*/ bool emitter::emitIns_valid_imm_for_fmov(double immDbl)
2106 if (canEncodeFloatImm8(immDbl))
2112 // true if this 'imm' can be encoded as a input operand to an add instruction
2113 /*static*/ bool emitter::emitIns_valid_imm_for_add(INT64 imm, emitAttr size)
2115 if (unsigned_abs(imm) <= 0x0fff)
2117 else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
2123 // true if this 'imm' can be encoded as a input operand to an non-add/sub alu instruction
2124 /*static*/ bool emitter::emitIns_valid_imm_for_cmp(INT64 imm, emitAttr size)
2126 return emitIns_valid_imm_for_add(imm, size);
2129 // true if this 'imm' can be encoded as a input operand to an non-add/sub alu instruction
2130 /*static*/ bool emitter::emitIns_valid_imm_for_alu(INT64 imm, emitAttr size)
2132 if (canEncodeBitMaskImm(imm, size))
2138 // true if this 'imm' can be encoded as the offset in a ldr/str instruction
2139 /*static*/ bool emitter::emitIns_valid_imm_for_ldst_offset(INT64 imm, emitAttr attr)
2142 return true; // Encodable using IF_LS_2A
2144 if ((imm >= -256) && (imm <= 255))
2145 return true; // Encodable using IF_LS_2C (or possibly IF_LS_2B)
2148 return false; // not encodable
2150 emitAttr size = EA_SIZE(attr);
2151 unsigned scale = NaturalScale_helper(size);
2152 ssize_t mask = size - 1; // the mask of low bits that must be zero to encode the immediate
2154 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
2155 return true; // Encodable using IF_LS_2B
2157 return false; // not encodable
2160 /************************************************************************
2162 * A helper method to return the natural scale for an EA 'size'
2165 /*static*/ unsigned emitter::NaturalScale_helper(emitAttr size)
2167 assert(size == EA_1BYTE || size == EA_2BYTE || size == EA_4BYTE || size == EA_8BYTE || size == EA_16BYTE);
2169 unsigned result = 0;
2170 unsigned utemp = (unsigned)size;
2172 // Compute log base 2 of utemp (aka 'size')
2182 /************************************************************************
2184 * A helper method to perform a Rotate-Right shift operation
2185 * the source is 'value' and it is rotated right by 'sh' bits
2186 * 'value' is considered to be a fixed size 'width' set of bits.
2189 * value is '00001111', sh is 2 and width is 8
2190 * result is '11000011'
2193 /*static*/ UINT64 emitter::ROR_helper(UINT64 value, unsigned sh, unsigned width)
2195 assert(width <= 64);
2196 // Check that 'value' fits in 'width' bits
2197 assert((width == 64) || (value < (1ULL << width)));
2198 // We don't support shifts >= width
2204 unsigned lsh = width - rsh;
2206 result = (value >> rsh);
2207 result |= (value << lsh);
2211 // mask off any extra bits that we got from the left shift
2212 result &= ((1ULL << width) - 1);
2216 /************************************************************************
2218 * A helper method to perform a 'NOT' bitwise complement operation.
2219 * 'value' is considered to be a fixed size 'width' set of bits.
2222 * value is '01001011', and width is 8
2223 * result is '10110100'
2226 /*static*/ UINT64 emitter::NOT_helper(UINT64 value, unsigned width)
2228 assert(width <= 64);
2230 UINT64 result = ~value;
2234 // Check that 'value' fits in 'width' bits. Don't consider "sign" bits above width.
2235 UINT64 maxVal = 1ULL << width;
2236 UINT64 lowBitsMask = maxVal - 1;
2237 UINT64 signBitsMask = ~lowBitsMask | (1ULL << (width - 1)); // The high bits must be set, and the top bit
2238 // (sign bit) must be set.
2239 assert((value < maxVal) || ((value & signBitsMask) == signBitsMask));
2241 // mask off any extra bits that we got from the complement operation
2242 result &= lowBitsMask;
2248 /************************************************************************
2250 * A helper method to perform a bit Replicate operation
2251 * the source is 'value' with a fixed size 'width' set of bits.
2252 * value is replicated to fill out 32 or 64 bits as determined by 'size'.
2255 * value is '11000011' (0xE3), width is 8 and size is EA_8BYTE
2256 * result is '11000011 11000011 11000011 11000011 11000011 11000011 11000011 11000011'
2257 * 0xE3E3E3E3E3E3E3E3
2260 /*static*/ UINT64 emitter::Replicate_helper(UINT64 value, unsigned width, emitAttr size)
2262 assert(emitter::isValidGeneralDatasize(size));
2264 unsigned immWidth = (size == EA_8BYTE) ? 64 : 32;
2265 assert(width <= immWidth);
2267 UINT64 result = value;
2268 unsigned filledBits = width;
2270 while (filledBits < immWidth)
2274 filledBits += width;
2279 /************************************************************************
2281 * Convert an imm(N,r,s) into a 64-bit immediate
2282 * inputs 'bmImm' a bitMaskImm struct
2283 * 'size' specifies the size of the result (64 or 32 bits)
2286 /*static*/ INT64 emitter::emitDecodeBitMaskImm(const emitter::bitMaskImm bmImm, emitAttr size)
2288 assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2290 unsigned N = bmImm.immN; // read the N,R and S values from the 'bitMaskImm' encoding
2291 unsigned R = bmImm.immR;
2292 unsigned S = bmImm.immS;
2294 unsigned elemWidth = 64; // used when immN == 1
2296 if (bmImm.immN == 0) // find the smaller elemWidth when immN == 0
2298 // Scan S for the highest bit not set
2300 for (unsigned bitNum = 5; bitNum > 0; bitNum--)
2302 unsigned oneBit = elemWidth;
2303 if ((S & oneBit) == 0)
2310 assert(size == EA_8BYTE);
2313 unsigned maskSR = elemWidth - 1;
2318 // encoding for S is one less than the number of consecutive one bits
2319 S++; // Number of consecutive ones to generate in 'welem'
2323 // 'elemWidth' is the number of bits that we will use for the ROR and Replicate operations
2324 // 'S' is the number of consecutive 1 bits for the immediate
2325 // 'R' is the number of bits that we will Rotate Right the immediate
2326 // 'size' selects the final size of the immedate that we return (64 or 32 bits)
2328 assert(S < elemWidth); // 'elemWidth' consecutive one's is a reserved encoding
2333 welem = (1ULL << S) - 1;
2335 wmask = ROR_helper(welem, R, elemWidth);
2336 wmask = Replicate_helper(wmask, elemWidth, size);
2341 /*****************************************************************************
2343 * Check if an immediate can use the left shifted by 12 bits encoding
2346 /*static*/ bool emitter::canEncodeWithShiftImmBy12(INT64 imm)
2350 imm = -imm; // convert to unsigned
2355 return false; // Must be MIN_INT64
2358 if ((imm & 0xfff) != 0) // Now the low 12 bits all have to be zero
2363 imm >>= 12; // shift right by 12 bits
2365 return (imm <= 0x0fff); // Does it fit in 12 bits
2368 /*****************************************************************************
2370 * Normalize the 'imm' so that the upper bits, as defined by 'size' are zero
2373 /*static*/ INT64 emitter::normalizeImm64(INT64 imm, emitAttr size)
2375 unsigned immWidth = getBitWidth(size);
2380 // Check that 'imm' fits in 'immWidth' bits. Don't consider "sign" bits above width.
2381 INT64 maxVal = 1LL << immWidth;
2382 INT64 lowBitsMask = maxVal - 1;
2383 INT64 hiBitsMask = ~lowBitsMask;
2384 INT64 signBitsMask =
2385 hiBitsMask | (1LL << (immWidth - 1)); // The high bits must be set, and the top bit (sign bit) must be set.
2386 assert((imm < maxVal) || ((imm & signBitsMask) == signBitsMask));
2388 // mask off the hiBits
2389 result &= lowBitsMask;
2394 /*****************************************************************************
2396 * Normalize the 'imm' so that the upper bits, as defined by 'size' are zero
2399 /*static*/ INT32 emitter::normalizeImm32(INT32 imm, emitAttr size)
2401 unsigned immWidth = getBitWidth(size);
2406 // Check that 'imm' fits in 'immWidth' bits. Don't consider "sign" bits above width.
2407 INT32 maxVal = 1 << immWidth;
2408 INT32 lowBitsMask = maxVal - 1;
2409 INT32 hiBitsMask = ~lowBitsMask;
2410 INT32 signBitsMask = hiBitsMask | (1 << (immWidth - 1)); // The high bits must be set, and the top bit
2411 // (sign bit) must be set.
2412 assert((imm < maxVal) || ((imm & signBitsMask) == signBitsMask));
2414 // mask off the hiBits
2415 result &= lowBitsMask;
2420 /************************************************************************
2422 * returns true if 'imm' of 'size bits (32/64) can be encoded
2423 * using the ARM64 'bitmask immediate' form.
2424 * When a non-null value is passed for 'wbBMI' then this method
2425 * writes back the 'N','S' and 'R' values use to encode this immediate
2429 /*static*/ bool emitter::canEncodeBitMaskImm(INT64 imm, emitAttr size, emitter::bitMaskImm* wbBMI)
2431 assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2433 unsigned immWidth = (size == EA_8BYTE) ? 64 : 32;
2434 unsigned maxLen = (size == EA_8BYTE) ? 6 : 5;
2436 imm = normalizeImm64(imm, size);
2438 // Starting with len=1, elemWidth is 2 bits
2439 // len=2, elemWidth is 4 bits
2440 // len=3, elemWidth is 8 bits
2441 // len=4, elemWidth is 16 bits
2442 // len=5, elemWidth is 32 bits
2443 // (optionally) len=6, elemWidth is 64 bits
2445 for (unsigned len = 1; (len <= maxLen); len++)
2447 unsigned elemWidth = 1 << len;
2448 UINT64 elemMask = ((UINT64)-1) >> (64 - elemWidth);
2449 UINT64 tempImm = (UINT64)imm; // A working copy of 'imm' that we can mutate
2450 UINT64 elemVal = tempImm & elemMask; // The low 'elemWidth' bits of 'imm'
2452 // Check for all 1's or 0's as these can't be encoded
2453 if ((elemVal == 0) || (elemVal == elemMask))
2456 // 'checkedBits' is the count of bits that are known to match 'elemVal' when replicated
2457 unsigned checkedBits = elemWidth; // by definition the first 'elemWidth' bits match
2459 // Now check to see if each of the next bits match...
2461 while (checkedBits < immWidth)
2463 tempImm >>= elemWidth;
2465 UINT64 nextElem = tempImm & elemMask;
2466 if (nextElem != elemVal)
2468 // Not matching, exit this loop and checkedBits will not be equal to immWidth
2472 // The 'nextElem' is matching, so increment 'checkedBits'
2473 checkedBits += elemWidth;
2476 // Did the full immediate contain bits that can be formed by repeating 'elemVal'?
2477 if (checkedBits == immWidth)
2479 // We are not quite done, since the only values that we can encode as a
2480 // 'bitmask immediate' are those that can be formed by starting with a
2481 // bit string of 0*1* that is rotated by some number of bits.
2483 // We check to see if 'elemVal' can be formed using these restrictions.
2486 // Rotating by one bit any value that passes these restrictions
2487 // can be xor-ed with the original value and will result it a string
2488 // of bits that have exactly two 1 bits: 'elemRorXor'
2489 // Further the distance between the two one bits tells us the value
2490 // of S and the location of the 1 bits tells us the value of R
2492 // Some examples: (immWidth is 8)
2494 // S=4,R=0 S=5,R=3 S=3,R=6
2495 // elemVal: 00001111 11100011 00011100
2496 // elemRor: 10000111 11110001 00001110
2497 // elemRorXor: 10001000 00010010 00010010
2498 // compute S 45678--- ---5678- ---3210-
2499 // compute R 01234567 ---34567 ------67
2501 UINT64 elemRor = ROR_helper(elemVal, 1, elemWidth); // Rotate 'elemVal' Right by one bit
2502 UINT64 elemRorXor = elemVal ^ elemRor; // Xor elemVal and elemRor
2504 // If we only have a two-bit change in elemROR then we can form a mask for this value
2505 unsigned bitCount = 0;
2506 UINT64 oneBit = 0x1;
2507 unsigned R = elemWidth; // R is shift count for ROR (rotate right shift)
2508 unsigned S = 0; // S is number of consecutive one bits
2511 // Loop over the 'elemWidth' bits in 'elemRorXor'
2513 for (unsigned bitNum = 0; bitNum < elemWidth; bitNum++)
2517 R--; // We decrement R by one whenever incr is -1
2521 S += incr; // We incr/decr S, after we find the first one bit in 'elemRorXor'
2524 // Is this bit position a 1 bit in 'elemRorXor'?
2526 if (oneBit & elemRorXor)
2529 // Is this the first 1 bit that we found in 'elemRorXor'?
2532 // Does this 1 bit represent a transition to zero bits?
2533 bool toZeros = ((oneBit & elemVal) != 0);
2536 // S :: Count down from elemWidth
2540 else // this 1 bit represent a transition to one bits.
2542 // S :: Count up from zero
2547 else // bitCount > 1
2549 // We found the second (or third...) 1 bit in 'elemRorXor'
2550 incr = 0; // stop decrementing 'R'
2554 // More than 2 transitions from 0/1 in 'elemVal'
2555 // This means that 'elemVal' can't be encoded
2556 // using a 'bitmask immediate'.
2558 // Furthermore, it will continue to fail
2559 // with any larger 'len' that we try.
2560 // so just return false.
2567 // shift oneBit left by one bit to test the next position
2571 // We expect that bitCount will always be two at this point
2572 // but just in case return false for any bad cases.
2574 assert(bitCount == 2);
2578 // Perform some sanity checks on the values of 'S' and 'R'
2580 assert(S < elemWidth);
2581 assert(R < elemWidth);
2583 // Does the caller want us to return the N,R,S encoding values?
2585 if (wbBMI != nullptr)
2588 // The encoding used for S is one less than the
2589 // number of consecutive one bits
2599 // The encoding used for 'S' here is a bit peculiar.
2601 // The upper bits need to be complemented, followed by a zero bit
2602 // then the value of 'S-1'
2604 unsigned upperBitsOfS = 64 - (1 << (len + 1));
2610 // Verify that what we are returning is correct.
2611 assert(imm == emitDecodeBitMaskImm(*wbBMI, size));
2613 // Tell the caller that we can successfully encode this immediate
2614 // using a 'bitmask immediate'.
2622 /************************************************************************
2624 * Convert a 64-bit immediate into its 'bitmask immediate' representation imm(N,r,s)
2627 /*static*/ emitter::bitMaskImm emitter::emitEncodeBitMaskImm(INT64 imm, emitAttr size)
2629 emitter::bitMaskImm result;
2632 bool canEncode = canEncodeBitMaskImm(imm, size, &result);
2638 /************************************************************************
2640 * Convert an imm(i16,hw) into a 32/64-bit immediate
2641 * inputs 'hwImm' a halfwordImm struct
2642 * 'size' specifies the size of the result (64 or 32 bits)
2645 /*static*/ INT64 emitter::emitDecodeHalfwordImm(const emitter::halfwordImm hwImm, emitAttr size)
2647 assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2649 unsigned hw = hwImm.immHW;
2650 INT64 val = (INT64)hwImm.immVal;
2652 assert((hw <= 1) || (size == EA_8BYTE));
2654 INT64 result = val << (16 * hw);
2658 /************************************************************************
2660 * returns true if 'imm' of 'size' bits (32/64) can be encoded
2661 * using the ARM64 'halfword immediate' form.
2662 * When a non-null value is passed for 'wbHWI' then this method
2663 * writes back the 'immHW' and 'immVal' values use to encode this immediate
2667 /*static*/ bool emitter::canEncodeHalfwordImm(INT64 imm, emitAttr size, emitter::halfwordImm* wbHWI)
2669 assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2671 unsigned immWidth = (size == EA_8BYTE) ? 64 : 32;
2672 unsigned maxHW = (size == EA_8BYTE) ? 4 : 2;
2674 // setup immMask to a (EA_4BYTE) 0x00000000_FFFFFFFF or (EA_8BYTE) 0xFFFFFFFF_FFFFFFFF
2675 const UINT64 immMask = ((UINT64)-1) >> (64 - immWidth);
2676 const INT64 mask16 = (INT64)0xFFFF;
2678 imm = normalizeImm64(imm, size);
2680 // Try each of the valid hw shift sizes
2681 for (unsigned hw = 0; (hw < maxHW); hw++)
2683 INT64 curMask = mask16 << (hw * 16); // Represents the mask of the bits in the current halfword
2684 INT64 checkBits = immMask & ~curMask;
2686 // Excluding the current halfword (using ~curMask)
2687 // does the immediate have zero bits in every other bit that we care about?
2688 // note we care about all 64-bits for EA_8BYTE
2689 // and we care about the lowest 32 bits for EA_4BYTE
2691 if ((imm & checkBits) == 0)
2693 // Does the caller want us to return the imm(i16,hw) encoding values?
2695 if (wbHWI != nullptr)
2697 INT64 val = ((imm & curMask) >> (hw * 16)) & mask16;
2699 wbHWI->immVal = val;
2701 // Verify that what we are returning is correct.
2702 assert(imm == emitDecodeHalfwordImm(*wbHWI, size));
2704 // Tell the caller that we can successfully encode this immediate
2705 // using a 'halfword immediate'.
2713 /************************************************************************
2715 * Convert a 64-bit immediate into its 'halfword immediate' representation imm(i16,hw)
2718 /*static*/ emitter::halfwordImm emitter::emitEncodeHalfwordImm(INT64 imm, emitAttr size)
2720 emitter::halfwordImm result;
2721 result.immHWVal = 0;
2723 bool canEncode = canEncodeHalfwordImm(imm, size, &result);
2729 /************************************************************************
2731 * Convert an imm(i8,sh) into a 16/32-bit immediate
2732 * inputs 'bsImm' a byteShiftedImm struct
2733 * 'size' specifies the size of the result (16 or 32 bits)
2736 /*static*/ INT32 emitter::emitDecodeByteShiftedImm(const emitter::byteShiftedImm bsImm, emitAttr size)
2738 bool onesShift = (bsImm.immOnes == 1);
2739 unsigned bySh = bsImm.immBY; // Num Bytes to shift 0,1,2,3
2740 INT32 val = (INT32)bsImm.immVal; // 8-bit immediate
2745 assert((size == EA_2BYTE) || (size == EA_4BYTE)); // Only EA_2BYTE or EA_4BYTE forms
2746 if (size == EA_2BYTE)
2755 result <<= (8 * bySh);
2759 result |= ((1 << (8 * bySh)) - 1);
2765 /************************************************************************
2767 * returns true if 'imm' of 'size' bits (16/32) can be encoded
2768 * using the ARM64 'byteShifted immediate' form.
2769 * When a non-null value is passed for 'wbBSI' then this method
2770 * writes back the 'immBY' and 'immVal' values use to encode this immediate
2774 /*static*/ bool emitter::canEncodeByteShiftedImm(INT64 imm,
2777 emitter::byteShiftedImm* wbBSI)
2779 bool canEncode = false;
2780 bool onesShift = false; // true if we use the shifting ones variant
2781 unsigned bySh = 0; // number of bytes to shift: 0, 1, 2, 3
2782 unsigned imm8 = 0; // immediate to use in the encoding
2784 imm = normalizeImm64(imm, size);
2786 if (size == EA_1BYTE)
2788 imm8 = (unsigned)imm;
2789 assert(imm8 < 0x100);
2792 else if (size == EA_8BYTE)
2794 imm8 = (unsigned)imm;
2795 assert(imm8 < 0x100);
2800 assert((size == EA_2BYTE) || (size == EA_4BYTE)); // Only EA_2BYTE or EA_4BYTE forms
2802 unsigned immWidth = (size == EA_4BYTE) ? 32 : 16;
2803 unsigned maxBY = (size == EA_4BYTE) ? 4 : 2;
2805 // setup immMask to a (EA_2BYTE) 0x0000FFFF or (EA_4BYTE) 0xFFFFFFFF
2806 const UINT32 immMask = ((UINT32)-1) >> (32 - immWidth);
2807 const INT32 mask8 = (INT32)0xFF;
2809 // Try each of the valid by shift sizes
2810 for (bySh = 0; (bySh < maxBY); bySh++)
2812 INT32 curMask = mask8 << (bySh * 8); // Represents the mask of the bits in the current byteShifted
2813 INT32 checkBits = immMask & ~curMask;
2814 INT32 immCheck = (imm & checkBits);
2816 // Excluding the current byte (using ~curMask)
2817 // does the immediate have zero bits in every other bit that we care about?
2818 // or can be use the shifted one variant?
2819 // note we care about all 32-bits for EA_4BYTE
2820 // and we care about the lowest 16 bits for EA_2BYTE
2828 if ((bySh == 1) && (immCheck == 0xFF))
2833 else if ((bySh == 2) && (immCheck == 0xFFFF))
2841 imm8 = (unsigned)(((imm & curMask) >> (bySh * 8)) & mask8);
2849 // Does the caller want us to return the imm(i8,bySh) encoding values?
2851 if (wbBSI != nullptr)
2853 wbBSI->immOnes = onesShift;
2854 wbBSI->immBY = bySh;
2855 wbBSI->immVal = imm8;
2857 // Verify that what we are returning is correct.
2858 assert(imm == emitDecodeByteShiftedImm(*wbBSI, size));
2860 // Tell the caller that we can successfully encode this immediate
2861 // using a 'byteShifted immediate'.
2868 /************************************************************************
2870 * Convert a 32-bit immediate into its 'byteShifted immediate' representation imm(i8,by)
2873 /*static*/ emitter::byteShiftedImm emitter::emitEncodeByteShiftedImm(INT64 imm, emitAttr size, bool allow_MSL)
2875 emitter::byteShiftedImm result;
2876 result.immBSVal = 0;
2878 bool canEncode = canEncodeByteShiftedImm(imm, size, allow_MSL, &result);
2884 /************************************************************************
2886 * Convert a 'float 8-bit immediate' into a double.
2887 * inputs 'fpImm' a floatImm8 struct
2890 /*static*/ double emitter::emitDecodeFloatImm8(const emitter::floatImm8 fpImm)
2892 unsigned sign = fpImm.immSign;
2893 unsigned exp = fpImm.immExp ^ 0x4;
2894 unsigned mant = fpImm.immMant + 16;
2895 unsigned scale = 16 * 8;
2903 double result = ((double)mant) / ((double)scale);
2912 /************************************************************************
2914 * returns true if the 'immDbl' can be encoded using the 'float 8-bit immediate' form.
2915 * also returns the encoding if wbFPI is non-null
2919 /*static*/ bool emitter::canEncodeFloatImm8(double immDbl, emitter::floatImm8* wbFPI)
2921 bool canEncode = false;
2922 double val = immDbl;
2932 while ((val < 1.0) && (exp >= -4))
2937 while ((val >= 2.0) && (exp <= 5))
2944 int ival = (int)val;
2946 if ((exp >= 0) && (exp <= 7))
2948 if (val == (double)ival)
2952 if (wbFPI != nullptr)
2955 assert((ival >= 0) && (ival <= 15));
2957 wbFPI->immSign = sign;
2958 wbFPI->immExp = exp ^ 0x4;
2959 wbFPI->immMant = ival;
2960 unsigned imm8 = wbFPI->immFPIVal;
2961 assert((imm8 >= 0) && (imm8 <= 0xff));
2969 /************************************************************************
2971 * Convert a double into its 'float 8-bit immediate' representation
2974 /*static*/ emitter::floatImm8 emitter::emitEncodeFloatImm8(double immDbl)
2976 emitter::floatImm8 result;
2977 result.immFPIVal = 0;
2979 bool canEncode = canEncodeFloatImm8(immDbl, &result);
2985 /*****************************************************************************
2987 * For the given 'ins' returns the reverse instruction
2988 * if one exists, otherwise returns INS_INVALID
2991 /*static*/ instruction emitter::insReverse(instruction ins)
3020 /*****************************************************************************
3022 * For the given 'datasize' and 'elemsize', make the proper arrangement option
3023 * returns the insOpts that specifies the vector register arrangement
3024 * if one does not exist returns INS_OPTS_NONE
3027 /*static*/ insOpts emitter::optMakeArrangement(emitAttr datasize, emitAttr elemsize)
3029 insOpts result = INS_OPTS_NONE;
3031 if (datasize == EA_8BYTE)
3036 result = INS_OPTS_8B;
3039 result = INS_OPTS_4H;
3042 result = INS_OPTS_2S;
3045 result = INS_OPTS_1D;
3052 else if (datasize == EA_16BYTE)
3057 result = INS_OPTS_16B;
3060 result = INS_OPTS_8H;
3063 result = INS_OPTS_4S;
3066 result = INS_OPTS_2D;
3076 /*****************************************************************************
3078 * For the given 'datasize' and arrangement 'opts'
3079 * returns true is the pair spcifies a valid arrangement
3081 /*static*/ bool emitter::isValidArrangement(emitAttr datasize, insOpts opt)
3083 if (datasize == EA_8BYTE)
3085 if ((opt == INS_OPTS_8B) || (opt == INS_OPTS_4H) || (opt == INS_OPTS_2S) || (opt == INS_OPTS_1D))
3090 else if (datasize == EA_16BYTE)
3092 if ((opt == INS_OPTS_16B) || (opt == INS_OPTS_8H) || (opt == INS_OPTS_4S) || (opt == INS_OPTS_2D))
3100 // For the given 'arrangement' returns the 'datasize' specified by the vector register arrangement
3101 // asserts and returns EA_UNKNOWN if an invalid 'arrangement' value is passed
3103 /*static*/ emitAttr emitter::optGetDatasize(insOpts arrangement)
3105 if ((arrangement == INS_OPTS_8B) || (arrangement == INS_OPTS_4H) || (arrangement == INS_OPTS_2S) ||
3106 (arrangement == INS_OPTS_1D))
3110 else if ((arrangement == INS_OPTS_16B) || (arrangement == INS_OPTS_8H) || (arrangement == INS_OPTS_4S) ||
3111 (arrangement == INS_OPTS_2D))
3117 assert(!" invalid 'arrangement' value");
3122 // For the given 'arrangement' returns the 'elemsize' specified by the vector register arrangement
3123 // asserts and returns EA_UNKNOWN if an invalid 'arrangement' value is passed
3125 /*static*/ emitAttr emitter::optGetElemsize(insOpts arrangement)
3127 if ((arrangement == INS_OPTS_8B) || (arrangement == INS_OPTS_16B))
3131 else if ((arrangement == INS_OPTS_4H) || (arrangement == INS_OPTS_8H))
3135 else if ((arrangement == INS_OPTS_2S) || (arrangement == INS_OPTS_4S))
3139 else if ((arrangement == INS_OPTS_1D) || (arrangement == INS_OPTS_2D))
3145 assert(!" invalid 'arrangement' value");
3150 // For the given 'arrangement' returns the 'widen-arrangement' specified by the vector register arrangement
3151 // asserts and returns INS_OPTS_NONE if an invalid 'arrangement' value is passed
3153 /*static*/ insOpts emitter::optWidenElemsize(insOpts arrangement)
3155 if ((arrangement == INS_OPTS_8B) || (arrangement == INS_OPTS_16B))
3159 else if ((arrangement == INS_OPTS_4H) || (arrangement == INS_OPTS_8H))
3163 else if ((arrangement == INS_OPTS_2S) || (arrangement == INS_OPTS_4S))
3169 assert(!" invalid 'arrangement' value");
3170 return INS_OPTS_NONE;
3174 // For the given 'conversion' returns the 'dstsize' specified by the conversion option
3175 /*static*/ emitAttr emitter::optGetDstsize(insOpts conversion)
3179 case INS_OPTS_S_TO_8BYTE:
3180 case INS_OPTS_D_TO_8BYTE:
3181 case INS_OPTS_4BYTE_TO_D:
3182 case INS_OPTS_8BYTE_TO_D:
3183 case INS_OPTS_S_TO_D:
3184 case INS_OPTS_H_TO_D:
3188 case INS_OPTS_S_TO_4BYTE:
3189 case INS_OPTS_D_TO_4BYTE:
3190 case INS_OPTS_4BYTE_TO_S:
3191 case INS_OPTS_8BYTE_TO_S:
3192 case INS_OPTS_D_TO_S:
3193 case INS_OPTS_H_TO_S:
3197 case INS_OPTS_S_TO_H:
3198 case INS_OPTS_D_TO_H:
3203 assert(!" invalid 'conversion' value");
3208 // For the given 'conversion' returns the 'srcsize' specified by the conversion option
3209 /*static*/ emitAttr emitter::optGetSrcsize(insOpts conversion)
3213 case INS_OPTS_D_TO_8BYTE:
3214 case INS_OPTS_D_TO_4BYTE:
3215 case INS_OPTS_8BYTE_TO_D:
3216 case INS_OPTS_8BYTE_TO_S:
3217 case INS_OPTS_D_TO_S:
3218 case INS_OPTS_D_TO_H:
3222 case INS_OPTS_S_TO_8BYTE:
3223 case INS_OPTS_S_TO_4BYTE:
3224 case INS_OPTS_4BYTE_TO_S:
3225 case INS_OPTS_4BYTE_TO_D:
3226 case INS_OPTS_S_TO_D:
3227 case INS_OPTS_S_TO_H:
3231 case INS_OPTS_H_TO_S:
3232 case INS_OPTS_H_TO_D:
3237 assert(!" invalid 'conversion' value");
3242 // For the given 'size' and 'index' returns true if it specifies a valid index for a vector register of 'size'
3243 /*static*/ bool emitter::isValidVectorIndex(emitAttr datasize, emitAttr elemsize, ssize_t index)
3245 assert(isValidVectorDatasize(datasize));
3246 assert(isValidVectorElemsize(elemsize));
3248 bool result = false;
3251 if (datasize == EA_8BYTE)
3256 result = (index < 8);
3259 result = (index < 4);
3262 result = (index < 2);
3265 result = (index < 1);
3272 else if (datasize == EA_16BYTE)
3277 result = (index < 16);
3280 result = (index < 8);
3283 result = (index < 4);
3286 result = (index < 2);
3297 /*****************************************************************************
3299 * Add an instruction with no operands.
3302 void emitter::emitIns(instruction ins)
3304 instrDesc* id = emitNewInstrSmall(EA_8BYTE);
3305 insFormat fmt = emitInsFormat(ins);
3307 assert(fmt == IF_SN_0A);
3316 /*****************************************************************************
3318 * Add an instruction with a single immediate value.
3321 void emitter::emitIns_I(instruction ins, emitAttr attr, ssize_t imm)
3323 insFormat fmt = IF_NONE;
3325 /* Figure out the encoding format of the instruction */
3329 if ((imm & 0x0000ffff) == imm)
3335 assert(!"Instruction cannot be encoded: IF_SI_0A");
3342 assert(fmt != IF_NONE);
3344 instrDesc* id = emitNewInstrSC(attr, imm);
3353 /*****************************************************************************
3355 * Add an instruction referencing a single register.
3358 void emitter::emitIns_R(instruction ins, emitAttr attr, regNumber reg)
3360 emitAttr size = EA_SIZE(attr);
3361 insFormat fmt = IF_NONE;
3362 instrDesc* id = nullptr;
3364 /* Figure out the encoding format of the instruction */
3369 assert(isGeneralRegister(reg));
3370 id = emitNewInstrSmall(attr);
3379 assert(fmt != IF_NONE);
3388 /*****************************************************************************
3390 * Add an instruction referencing a register and a constant.
3393 void emitter::emitIns_R_I(instruction ins, emitAttr attr, regNumber reg, ssize_t imm, insOpts opt /* = INS_OPTS_NONE */)
3395 emitAttr size = EA_SIZE(attr);
3396 emitAttr elemsize = EA_UNKNOWN;
3397 insFormat fmt = IF_NONE;
3398 bool canEncode = false;
3400 /* Figure out the encoding format of the instruction */
3409 assert(insOptsNone(opt));
3410 assert(isGeneralRegister(reg));
3412 canEncode = canEncodeBitMaskImm(imm, size, &bmi);
3416 assert(isValidImmNRS(imm, size));
3424 assert(isValidGeneralDatasize(size));
3425 assert(insOptsNone(opt)); // No LSL here (you must use emitIns_R_I_I if a shift is needed)
3426 assert(isGeneralRegister(reg));
3427 assert(isValidUimm16(imm));
3431 assert(imm == emitDecodeHalfwordImm(hwi, size));
3439 assert(isValidGeneralDatasize(size));
3440 assert(insOptsNone(opt)); // No explicit LSL here
3441 // We will automatically determine the shift based upon the imm
3443 // First try the standard 'halfword immediate' imm(i16,hw)
3445 canEncode = canEncodeHalfwordImm(imm, size, &hwi);
3448 // uses a movz encoding
3449 assert(isGeneralRegister(reg));
3451 assert(isValidImmHWVal(imm, size));
3456 // Next try the ones-complement form of 'halfword immediate' imm(i16,hw)
3457 notOfImm = NOT_helper(imm, getBitWidth(size));
3458 canEncode = canEncodeHalfwordImm(notOfImm, size, &hwi);
3461 assert(isGeneralRegister(reg));
3463 ins = INS_movn; // uses a movn encoding
3464 assert(isValidImmHWVal(imm, size));
3469 // Finally try the 'bitmask immediate' imm(N,r,s)
3471 canEncode = canEncodeBitMaskImm(imm, size, &bmi);
3474 assert(isGeneralRegisterOrSP(reg));
3475 reg = encodingSPtoZR(reg);
3477 assert(isValidImmNRS(imm, size));
3483 assert(!"Instruction cannot be encoded: mov imm");
3489 assert(isValidVectorDatasize(size));
3490 assert(isVectorRegister(reg));
3491 if (insOptsNone(opt) && (size == EA_8BYTE))
3495 assert(isValidArrangement(size, opt));
3496 elemsize = optGetElemsize(opt);
3498 if (elemsize == EA_8BYTE)
3504 bool failed = false;
3507 INT64 loByte = uimm & 0xFF;
3508 if (((loByte == 0) || (loByte == 0xFF)) && (pos < 8))
3524 assert(isValidUimm8(imm));
3532 // No explicit LSL/MSL is used for the immediate
3533 // We will automatically determine the shift based upon the value of imm
3535 // First try the standard 'byteShifted immediate' imm(i8,bySh)
3537 canEncode = canEncodeByteShiftedImm(imm, elemsize, true, &bsi);
3541 assert(isValidImmBSVal(imm, size));
3546 // Next try the ones-complement form of the 'immediate' imm(i8,bySh)
3547 if ((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE)) // Only EA_2BYTE or EA_4BYTE forms
3549 notOfImm = NOT_helper(imm, getBitWidth(elemsize));
3550 canEncode = canEncodeByteShiftedImm(notOfImm, elemsize, true, &bsi);
3554 ins = INS_mvni; // uses a mvni encoding
3555 assert(isValidImmBSVal(imm, size));
3566 assert(isValidVectorDatasize(size));
3567 assert(isVectorRegister(reg));
3568 assert(isValidArrangement(size, opt));
3569 elemsize = optGetElemsize(opt);
3570 assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE)); // Only EA_2BYTE or EA_4BYTE forms
3574 // No explicit LSL/MSL is used for the immediate
3575 // We will automatically determine the shift based upon the value of imm
3577 // First try the standard 'byteShifted immediate' imm(i8,bySh)
3579 canEncode = canEncodeByteShiftedImm(imm, elemsize,
3580 (ins == INS_mvni), // mvni supports the ones shifting variant (aka MSL)
3585 assert(isValidImmBSVal(imm, size));
3593 assert(insOptsNone(opt));
3594 assert(isGeneralRegister(reg));
3596 if (unsigned_abs(imm) <= 0x0fff)
3600 ins = insReverse(ins);
3603 assert(isValidUimm12(imm));
3607 else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
3609 // Encoding will use a 12-bit left shift of the immediate
3610 opt = INS_OPTS_LSL12;
3613 ins = insReverse(ins);
3616 assert((imm & 0xfff) == 0);
3618 assert(isValidUimm12(imm));
3624 assert(!"Instruction cannot be encoded: IF_DI_1A");
3632 } // end switch (ins)
3635 assert(fmt != IF_NONE);
3637 instrDesc* id = emitNewInstrSC(attr, imm);
3649 /*****************************************************************************
3651 * Add an instruction referencing a register and a floating point constant.
3654 void emitter::emitIns_R_F(
3655 instruction ins, emitAttr attr, regNumber reg, double immDbl, insOpts opt /* = INS_OPTS_NONE */)
3658 emitAttr size = EA_SIZE(attr);
3659 emitAttr elemsize = EA_UNKNOWN;
3660 insFormat fmt = IF_NONE;
3662 bool canEncode = false;
3664 /* Figure out the encoding format of the instruction */
3671 assert(insOptsNone(opt));
3672 assert(isValidVectorElemsizeFloat(size));
3673 assert(isVectorRegister(reg));
3682 assert(isVectorRegister(reg));
3684 canEncode = canEncodeFloatImm8(immDbl, &fpi);
3686 if (insOptsAnyArrangement(opt))
3689 assert(isValidVectorDatasize(size));
3690 assert(isValidArrangement(size, opt));
3691 elemsize = optGetElemsize(opt);
3692 assert(isValidVectorElemsizeFloat(elemsize));
3693 assert(opt != INS_OPTS_1D); // Reserved encoding
3697 imm = fpi.immFPIVal;
3698 assert((imm >= 0) && (imm <= 0xff));
3705 assert(insOptsNone(opt));
3706 assert(isValidVectorElemsizeFloat(size));
3710 imm = fpi.immFPIVal;
3711 assert((imm >= 0) && (imm <= 0xff));
3721 } // end switch (ins)
3724 assert(fmt != IF_NONE);
3726 instrDesc* id = emitNewInstrSC(attr, imm);
3738 /*****************************************************************************
3740 * Add an instruction referencing two registers
3743 void emitter::emitIns_R_R(
3744 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insOpts opt /* = INS_OPTS_NONE */)
3746 emitAttr size = EA_SIZE(attr);
3747 emitAttr elemsize = EA_UNKNOWN;
3748 insFormat fmt = IF_NONE;
3750 /* Figure out the encoding format of the instruction */
3754 assert(insOptsNone(opt));
3755 // Is the mov even necessary?
3758 // A mov with a EA_4BYTE has the side-effect of clearing the upper bits
3759 // So only eliminate mov instructions that are not clearing the upper bits
3761 if (isGeneralRegisterOrSP(reg1) && (size == EA_8BYTE))
3765 else if (isVectorRegister(reg1) && (size == EA_16BYTE))
3771 // Check for the 'mov' aliases for the vector registers
3772 if (isVectorRegister(reg1))
3774 if (isVectorRegister(reg2) && isValidVectorDatasize(size))
3776 return emitIns_R_R_R(INS_mov, size, reg1, reg2, reg2);
3780 return emitIns_R_R_I(INS_mov, size, reg1, reg2, 0);
3785 if (isVectorRegister(reg2))
3787 assert(isGeneralRegister(reg1));
3788 return emitIns_R_R_I(INS_mov, size, reg1, reg2, 0);
3792 // Is this a MOV to/from SP instruction?
3793 if ((reg1 == REG_SP) || (reg2 == REG_SP))
3795 assert(isGeneralRegisterOrSP(reg1));
3796 assert(isGeneralRegisterOrSP(reg2));
3797 reg1 = encodingSPtoZR(reg1);
3798 reg2 = encodingSPtoZR(reg2);
3803 assert(insOptsNone(opt));
3804 assert(isGeneralRegister(reg1));
3805 assert(isGeneralRegisterOrZR(reg2));
3812 assert(insOptsAnyArrangement(opt));
3813 assert(isVectorRegister(reg1));
3814 assert(isGeneralRegisterOrZR(reg2));
3815 assert(isValidVectorDatasize(size));
3816 assert(isValidArrangement(size, opt));
3822 assert(isVectorRegister(reg1));
3823 assert(isVectorRegister(reg2));
3824 // for 'NOT' we can construct the arrangement: 8B or 16B
3825 if ((ins == INS_not) && insOptsNone(opt))
3827 assert(isValidVectorDatasize(size));
3828 elemsize = EA_1BYTE;
3829 opt = optMakeArrangement(size, elemsize);
3831 if (insOptsNone(opt))
3834 assert(size == EA_8BYTE); // Only type D is supported
3840 assert(insOptsAnyArrangement(opt));
3841 assert(isValidVectorDatasize(size));
3842 assert(isValidArrangement(size, opt));
3843 elemsize = optGetElemsize(opt);
3846 assert(elemsize == EA_1BYTE);
3854 if (isVectorRegister(reg1))
3856 assert(isVectorRegister(reg2));
3857 // for 'mvn' we can construct the arrangement: 8B or 16b
3858 if ((ins == INS_mvn) && insOptsNone(opt))
3860 assert(isValidVectorDatasize(size));
3861 elemsize = EA_1BYTE;
3862 opt = optMakeArrangement(size, elemsize);
3864 if (insOptsNone(opt))
3867 assert(size == EA_8BYTE); // Only type D is supported
3873 assert(isValidVectorDatasize(size));
3874 assert(isValidArrangement(size, opt));
3875 elemsize = optGetElemsize(opt);
3878 assert(elemsize == EA_1BYTE); // Only supports 8B or 16B
3887 assert(insOptsNone(opt));
3888 assert(isGeneralRegister(reg1));
3889 assert(isGeneralRegisterOrZR(reg2));
3894 assert(size == EA_8BYTE);
3901 assert(insOptsNone(opt));
3902 assert(isValidGeneralDatasize(size));
3903 assert(isGeneralRegister(reg1));
3904 assert(isGeneralRegister(reg2));
3912 return emitIns_R_R_I(ins, size, reg1, reg2, 0, opt);
3920 if (isVectorRegister(reg1))
3922 assert(isVectorRegister(reg2));
3923 assert(isValidVectorDatasize(size));
3924 assert(isValidArrangement(size, opt));
3925 elemsize = optGetElemsize(opt);
3926 if ((ins == INS_cls) || (ins == INS_clz))
3928 assert(elemsize != EA_8BYTE); // No encoding for type D
3930 else if (ins == INS_rev32)
3932 assert((elemsize == EA_2BYTE) || (elemsize == EA_1BYTE));
3936 assert(elemsize == EA_1BYTE); // Only supports 8B or 16B
3943 // Doesn't have general register version(s)
3950 assert(insOptsNone(opt));
3951 assert(isGeneralRegister(reg1));
3952 assert(isGeneralRegister(reg2));
3953 if (ins == INS_rev32)
3955 assert(size == EA_8BYTE);
3959 assert(isValidGeneralDatasize(size));
3972 assert(isVectorRegister(reg1));
3973 assert(isVectorRegister(reg2));
3974 assert(isValidVectorDatasize(size));
3975 assert(isValidArrangement(size, opt));
3976 elemsize = optGetElemsize(opt);
3977 assert(elemsize != EA_8BYTE); // No encoding for type D
3983 assert(isVectorRegister(reg1));
3984 assert(isVectorRegister(reg2));
3985 assert(isValidVectorDatasize(size));
3986 assert(isValidArrangement(size, opt));
3987 elemsize = optGetElemsize(opt);
3988 assert(size == (ins == INS_xtn) ? EA_8BYTE : EA_16BYTE); // Size is determined by instruction
3989 assert(elemsize != EA_8BYTE); // Narrowing must not end with 8 byte data
3997 assert(isValidGeneralDatasize(size));
4009 assert(isValidGeneralLSDatasize(size));
4010 assert(isGeneralRegisterOrZR(reg1));
4011 assert(isGeneralRegisterOrSP(reg2));
4012 assert(insOptsNone(opt));
4014 reg2 = encodingSPtoZR(reg2);
4032 assert(insOptsNone(opt));
4033 emitIns_R_R_I(ins, attr, reg1, reg2, 0, INS_OPTS_NONE);
4037 assert(isValidVectorElemsizeFloat(size));
4039 // Is the mov even necessary?
4045 if (isVectorRegister(reg1))
4047 if (isVectorRegister(reg2))
4049 assert(insOptsNone(opt));
4054 assert(isGeneralRegister(reg2));
4056 // if the optional conversion specifier is not present we calculate it
4057 if (opt == INS_OPTS_NONE)
4059 opt = (size == EA_4BYTE) ? INS_OPTS_4BYTE_TO_S : INS_OPTS_8BYTE_TO_D;
4061 assert(insOptsConvertIntToFloat(opt));
4068 assert(isGeneralRegister(reg1));
4069 assert(isVectorRegister(reg2));
4071 // if the optional conversion specifier is not present we calculate it
4072 if (opt == INS_OPTS_NONE)
4074 opt = (size == EA_4BYTE) ? INS_OPTS_S_TO_4BYTE : INS_OPTS_D_TO_8BYTE;
4076 assert(insOptsConvertFloatToInt(opt));
4084 assert(insOptsNone(opt));
4085 assert(isValidVectorElemsizeFloat(size));
4086 assert(isVectorRegister(reg1));
4087 assert(isVectorRegister(reg2));
4101 if (insOptsAnyArrangement(opt))
4104 assert(isVectorRegister(reg1));
4105 assert(isVectorRegister(reg2));
4106 assert(isValidVectorDatasize(size));
4107 assert(isValidArrangement(size, opt));
4108 elemsize = optGetElemsize(opt);
4109 assert(isValidVectorElemsizeFloat(elemsize));
4110 assert(opt != INS_OPTS_1D); // Reserved encoding
4116 assert(isVectorRegister(reg2));
4117 if (isVectorRegister(reg1))
4119 assert(insOptsNone(opt));
4120 assert(isValidVectorElemsizeFloat(size));
4125 assert(isGeneralRegister(reg1));
4126 assert(insOptsConvertFloatToInt(opt));
4127 assert(isValidVectorElemsizeFloat(size));
4137 assert(isVectorRegister(reg1));
4138 assert(isVectorRegister(reg2));
4139 assert(isValidVectorDatasize(size));
4140 assert(insOptsNone(opt));
4141 assert(size == EA_8BYTE); // Narrowing from Double or Widening to Double (Half not supported)
4147 if (insOptsAnyArrangement(opt))
4150 assert(isVectorRegister(reg1));
4151 assert(isVectorRegister(reg2));
4152 assert(isValidVectorDatasize(size));
4153 assert(isValidArrangement(size, opt));
4154 elemsize = optGetElemsize(opt);
4155 assert(isValidVectorElemsizeFloat(elemsize));
4156 assert(opt != INS_OPTS_1D); // Reserved encoding
4162 assert(isVectorRegister(reg1));
4163 if (isVectorRegister(reg2))
4165 assert(insOptsNone(opt));
4166 assert(isValidVectorElemsizeFloat(size));
4171 assert(isGeneralRegister(reg2));
4172 assert(insOptsConvertIntToFloat(opt));
4173 assert(isValidVectorElemsizeFloat(size));
4189 if (insOptsAnyArrangement(opt))
4192 assert(isVectorRegister(reg1));
4193 assert(isVectorRegister(reg2));
4194 assert(isValidVectorDatasize(size));
4195 assert(isValidArrangement(size, opt));
4196 elemsize = optGetElemsize(opt);
4197 assert(isValidVectorElemsizeFloat(elemsize));
4198 assert(opt != INS_OPTS_1D); // Reserved encoding
4204 assert(insOptsNone(opt));
4205 assert(isValidVectorElemsizeFloat(size));
4206 assert(isVectorRegister(reg1));
4207 assert(isVectorRegister(reg2));
4214 assert(insOptsNone(opt));
4215 assert(isValidVectorElemsizeFloat(size));
4216 assert(isVectorRegister(reg1));
4217 assert(isVectorRegister(reg2));
4222 assert(insOptsConvertFloatToFloat(opt));
4223 assert(isValidVectorFcvtsize(size));
4224 assert(isVectorRegister(reg1));
4225 assert(isVectorRegister(reg2));
4233 } // end switch (ins)
4235 assert(fmt != IF_NONE);
4237 instrDesc* id = emitNewInstrSmall(attr);
4250 /*****************************************************************************
4252 * Add an instruction referencing a register and two constants.
4255 void emitter::emitIns_R_I_I(
4256 instruction ins, emitAttr attr, regNumber reg, ssize_t imm1, ssize_t imm2, insOpts opt /* = INS_OPTS_NONE */)
4258 emitAttr size = EA_SIZE(attr);
4259 insFormat fmt = IF_NONE;
4260 size_t immOut = 0; // composed from imm1 and imm2 and stored in the instrDesc
4262 /* Figure out the encoding format of the instruction */
4269 ins = INS_movz; // INS_mov with LSL is an alias for INS_movz LSL
4275 assert(isValidGeneralDatasize(size));
4276 assert(isGeneralRegister(reg));
4277 assert(isValidUimm16(imm1));
4278 assert(insOptsLSL(opt)); // Must be INS_OPTS_LSL
4280 if (size == EA_8BYTE)
4282 assert((imm2 == 0) || (imm2 == 16) || // shift amount: 0, 16, 32 or 48
4283 (imm2 == 32) || (imm2 == 48));
4287 assert((imm2 == 0) || (imm2 == 16)); // shift amount: 0 or 16
4322 immOut = hwi.immHWVal;
4323 assert(isValidImmHWVal(immOut, size));
4332 } // end switch (ins)
4334 assert(fmt != IF_NONE);
4336 instrDesc* id = emitNewInstrSC(attr, immOut);
4347 /*****************************************************************************
4349 * Add an instruction referencing two registers and a constant.
4352 void emitter::emitIns_R_R_I(
4353 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm, insOpts opt /* = INS_OPTS_NONE */)
4355 emitAttr size = EA_SIZE(attr);
4356 emitAttr elemsize = EA_UNKNOWN;
4357 insFormat fmt = IF_NONE;
4358 bool isLdSt = false;
4359 bool isSIMD = false;
4360 bool isAddSub = false;
4361 bool setFlags = false;
4363 bool unscaledOp = false;
4365 /* Figure out the encoding format of the instruction */
4372 // Check for the 'mov' aliases for the vector registers
4373 assert(insOptsNone(opt));
4374 assert(isValidVectorElemsize(size));
4376 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4378 if (isVectorRegister(reg1))
4380 if (isGeneralRegisterOrZR(reg2))
4382 fmt = IF_DV_2C; // Alias for 'ins'
4385 else if (isVectorRegister(reg2))
4387 fmt = IF_DV_2E; // Alias for 'dup'
4391 else // isGeneralRegister(reg1)
4393 assert(isGeneralRegister(reg1));
4394 if (isVectorRegister(reg2))
4396 fmt = IF_DV_2B; // Alias for 'umov'
4400 assert(!" invalid INS_mov operands");
4406 assert(insOptsNone(opt));
4407 assert(isValidGeneralDatasize(size));
4408 assert(isGeneralRegister(reg1));
4409 assert(isGeneralRegister(reg2));
4410 assert(isValidImmShift(imm, size));
4415 assert(insOptsNone(opt));
4416 assert(isValidGeneralDatasize(size));
4417 assert(isGeneralRegister(reg1));
4418 assert(isGeneralRegister(reg2));
4419 assert(isValidImmShift(imm, size));
4434 assert(isVectorRegister(reg1));
4435 assert(isVectorRegister(reg2));
4436 if (insOptsAnyArrangement(opt))
4439 assert(isValidVectorDatasize(size));
4440 assert(isValidArrangement(size, opt));
4441 elemsize = optGetElemsize(opt);
4442 assert(isValidVectorElemsize(elemsize));
4443 assert(isValidImmShift(imm, elemsize));
4444 assert(opt != INS_OPTS_1D); // Reserved encoding
4451 assert(insOptsNone(opt));
4452 assert(size == EA_8BYTE); // only supported size
4453 assert(isValidImmShift(imm, size));
4467 assert(isVectorRegister(reg1));
4468 assert(isVectorRegister(reg2));
4470 assert(size == EA_8BYTE);
4471 assert(isValidArrangement(size, opt));
4472 elemsize = optGetElemsize(opt);
4473 assert(elemsize != EA_8BYTE); // Reserved encodings
4474 assert(isValidVectorElemsize(elemsize));
4475 assert(isValidImmShift(imm, elemsize));
4488 assert(isVectorRegister(reg1));
4489 assert(isVectorRegister(reg2));
4491 assert(size == EA_16BYTE);
4492 assert(isValidArrangement(size, opt));
4493 elemsize = optGetElemsize(opt);
4494 assert(elemsize != EA_8BYTE); // Reserved encodings
4495 assert(isValidVectorElemsize(elemsize));
4496 assert(isValidImmShift(imm, elemsize));
4503 assert(isValidGeneralDatasize(size));
4504 assert(isGeneralRegister(reg1));
4505 assert(isGeneralRegisterOrZR(reg2));
4509 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4517 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
4521 assert(insOptsAluShift(opt)); // a non-zero imm, must select shift kind, can't use ROR
4523 assert(isValidImmShift(imm, size));
4529 assert(isValidGeneralDatasize(size));
4530 assert(isGeneralRegisterOrZR(reg1));
4531 assert(isGeneralRegister(reg2));
4533 if (insOptsAnyShift(opt))
4535 assert(isValidImmShift(imm, size) && (imm != 0));
4540 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4548 assert(isValidGeneralDatasize(size));
4549 assert(isGeneralRegisterOrSP(reg1));
4550 assert(isGeneralRegister(reg2));
4552 reg1 = encodingSPtoZR(reg1);
4553 if (insOptsAnyExtend(opt))
4555 assert((imm >= 0) && (imm <= 4));
4561 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4567 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
4568 assert(isValidImmShift(imm, size));
4577 assert(insOptsNone(opt));
4578 assert(isGeneralRegister(reg2));
4579 if (ins == INS_ands)
4581 assert(isGeneralRegister(reg1));
4585 assert(isGeneralRegisterOrSP(reg1));
4586 reg1 = encodingSPtoZR(reg1);
4590 canEncode = canEncodeBitMaskImm(imm, size, &bmi);
4594 assert(isValidImmNRS(imm, size));
4599 case INS_dup: // by element, imm selects the element of reg2
4600 assert(isVectorRegister(reg1));
4601 if (isVectorRegister(reg2))
4603 if (insOptsAnyArrangement(opt))
4606 assert(isValidVectorDatasize(size));
4607 assert(isValidArrangement(size, opt));
4608 elemsize = optGetElemsize(opt);
4609 assert(isValidVectorElemsize(elemsize));
4610 assert(isValidVectorIndex(size, elemsize, imm));
4611 assert(opt != INS_OPTS_1D); // Reserved encoding
4618 assert(insOptsNone(opt));
4620 assert(isValidVectorElemsize(elemsize));
4621 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4628 case INS_ins: // (MOV from general)
4629 assert(insOptsNone(opt));
4630 assert(isValidVectorElemsize(size));
4631 assert(isVectorRegister(reg1));
4632 assert(isGeneralRegisterOrZR(reg2));
4634 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4638 case INS_umov: // (MOV to general)
4639 assert(insOptsNone(opt));
4640 assert(isValidVectorElemsize(size));
4641 assert(isGeneralRegister(reg1));
4642 assert(isVectorRegister(reg2));
4644 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4649 assert(insOptsNone(opt));
4650 assert(isValidVectorElemsize(size));
4651 assert(size != EA_8BYTE); // no encoding, use INS_umov
4652 assert(isGeneralRegister(reg1));
4653 assert(isVectorRegister(reg2));
4655 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4673 // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4674 assert(isValidGeneralDatasize(size));
4675 unscaledOp = (ins == INS_ldursb);
4682 // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4683 assert(isValidGeneralDatasize(size));
4684 unscaledOp = (ins == INS_ldursh);
4691 // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4692 assert(size == EA_8BYTE);
4693 unscaledOp = (ins == INS_ldursw);
4732 // Is the target a vector register?
4733 if (isVectorRegister(reg1))
4735 assert(isValidVectorLSDatasize(size));
4736 assert(isGeneralRegisterOrSP(reg2));
4741 assert(isValidGeneralDatasize(size));
4744 scale = NaturalScale_helper(size);
4750 // Is the target a vector register?
4751 if (isVectorRegister(reg1))
4753 assert(isValidVectorLSDatasize(size));
4754 assert(isGeneralRegisterOrSP(reg2));
4759 assert(isValidGeneralDatasize(size));
4770 } // end switch (ins)
4778 assert(isValidVectorLSDatasize(size));
4779 assert(isVectorRegister(reg1));
4780 assert((scale >= 0) && (scale <= 4));
4784 assert(isValidGeneralLSDatasize(size));
4785 assert(isGeneralRegisterOrZR(reg1));
4786 assert((scale >= 0) && (scale <= 3));
4789 assert(isGeneralRegisterOrSP(reg2));
4791 // Load/Store reserved encodings:
4792 if (insOptsIndexed(opt))
4794 assert(reg1 != reg2);
4797 reg2 = encodingSPtoZR(reg2);
4799 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
4802 assert(insOptsNone(opt)); // PRE/POST Index doesn't make sense with an immediate of zero
4806 else if (insOptsIndexed(opt) || unscaledOp || (imm < 0) || ((imm & mask) != 0))
4808 if ((imm >= -256) && (imm <= 255))
4814 assert(!"Instruction cannot be encoded: IF_LS_2C");
4819 assert(insOptsNone(opt));
4820 assert(!unscaledOp);
4822 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
4824 imm >>= scale; // The immediate is scaled by the size of the ld/st
4830 assert(!"Instruction cannot be encoded: IF_LS_2B");
4837 assert(insOptsNone(opt));
4839 if (setFlags) // Can't encode SP with setFlags
4841 assert(isGeneralRegister(reg1));
4842 assert(isGeneralRegister(reg2));
4846 assert(isGeneralRegisterOrSP(reg1));
4847 assert(isGeneralRegisterOrSP(reg2));
4849 // Is it just a mov?
4852 // Is the mov even necessary?
4855 emitIns_R_R(INS_mov, attr, reg1, reg2);
4860 reg1 = encodingSPtoZR(reg1);
4861 reg2 = encodingSPtoZR(reg2);
4864 if (unsigned_abs(imm) <= 0x0fff)
4868 ins = insReverse(ins);
4871 assert(isValidUimm12(imm));
4874 else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
4876 // Encoding will use a 12-bit left shift of the immediate
4877 opt = INS_OPTS_LSL12;
4880 ins = insReverse(ins);
4883 assert((imm & 0xfff) == 0);
4885 assert(isValidUimm12(imm));
4890 assert(!"Instruction cannot be encoded: IF_DI_2A");
4894 assert(fmt != IF_NONE);
4896 instrDesc* id = emitNewInstrSC(attr, imm);
4909 /*****************************************************************************
4911 * Add an instruction referencing two registers and a constant.
4912 * Also checks for a large immediate that needs a second instruction
4913 * and will load it in reg1
4915 * - Supports instructions: add, adds, sub, subs, and, ands, eor and orr
4916 * - Requires that reg1 is a general register and not SP or ZR
4917 * - Requires that reg1 != reg2
4919 void emitter::emitIns_R_R_Imm(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm)
4921 assert(isGeneralRegister(reg1));
4922 assert(reg1 != reg2);
4924 bool immFits = true;
4932 immFits = emitter::emitIns_valid_imm_for_add(imm, attr);
4939 immFits = emitter::emitIns_valid_imm_for_alu(imm, attr);
4943 assert(!"Unsupported instruction in emitIns_R_R_Imm");
4948 emitIns_R_R_I(ins, attr, reg1, reg2, imm);
4952 // Load 'imm' into the reg1 register
4953 // then issue: 'ins' reg1, reg2, reg1
4955 codeGen->instGen_Set_Reg_To_Imm(attr, reg1, imm);
4956 emitIns_R_R_R(ins, attr, reg1, reg2, reg1);
4960 /*****************************************************************************
4962 * Add an instruction referencing three registers.
4965 void emitter::emitIns_R_R_R(
4966 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insOpts opt) /* = INS_OPTS_NONE */
4968 emitAttr size = EA_SIZE(attr);
4969 emitAttr elemsize = EA_UNKNOWN;
4970 insFormat fmt = IF_NONE;
4972 /* Figure out the encoding format of the instruction */
4996 assert(insOptsNone(opt));
4997 assert(isValidGeneralDatasize(size));
4998 assert(isGeneralRegister(reg1));
4999 assert(isGeneralRegister(reg2));
5000 assert(isGeneralRegister(reg3));
5005 if (insOptsNone(opt))
5008 assert(isValidGeneralDatasize(size));
5009 assert(isGeneralRegister(reg1));
5010 assert(isGeneralRegister(reg2));
5011 assert(isGeneralRegister(reg3));
5020 assert(insOptsAnyArrangement(opt));
5021 assert(isVectorRegister(reg1));
5022 assert(isVectorRegister(reg2));
5023 assert(isVectorRegister(reg3));
5024 assert(isValidVectorDatasize(size));
5025 assert(isValidArrangement(size, opt));
5026 elemsize = optGetElemsize(opt);
5027 if (ins == INS_pmul)
5029 assert(elemsize == EA_1BYTE); // only supports 8B or 16B
5031 else // INS_mul, INS_mla, INS_mls
5033 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
5040 if (isVectorRegister(reg1))
5042 assert(isVectorRegister(reg2));
5043 assert(isVectorRegister(reg3));
5045 if (insOptsAnyArrangement(opt))
5048 assert(opt != INS_OPTS_1D); // Reserved encoding
5049 assert(isValidVectorDatasize(size));
5050 assert(isValidArrangement(size, opt));
5056 assert(insOptsNone(opt));
5057 assert(size == EA_8BYTE);
5066 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, INS_OPTS_NONE);
5075 assert(isVectorRegister(reg1));
5076 assert(isVectorRegister(reg2));
5077 assert(isVectorRegister(reg3));
5079 if (isValidVectorDatasize(size))
5082 assert(insOptsAnyArrangement(opt));
5083 assert(isValidArrangement(size, opt));
5084 elemsize = optGetElemsize(opt);
5091 assert(size == EA_8BYTE); // Only Double supported
5099 assert(isVectorRegister(reg1));
5100 assert(isVectorRegister(reg2));
5101 assert(isVectorRegister(reg3));
5103 if (isValidVectorDatasize(size))
5106 assert(insOptsAnyArrangement(opt));
5107 assert(isValidArrangement(size, opt));
5108 elemsize = optGetElemsize(opt);
5109 assert((elemsize == EA_8BYTE) || (elemsize == EA_4BYTE)); // Only Double/Float supported
5110 assert(opt != INS_OPTS_1D); // Reserved encoding
5117 assert((size == EA_8BYTE) || (size == EA_4BYTE)); // Only Double/Float supported
5130 assert(isVectorRegister(reg1));
5131 assert(isVectorRegister(reg2));
5132 assert(isVectorRegister(reg3));
5133 assert(insOptsAnyArrangement(opt));
5136 assert(isValidVectorDatasize(size));
5137 assert(isValidArrangement(size, opt));
5138 elemsize = optGetElemsize(opt);
5139 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
5145 assert(isVectorRegister(reg1));
5146 assert(isVectorRegister(reg2));
5147 assert(reg2 == reg3);
5148 assert(isValidVectorDatasize(size));
5149 // INS_mov is an alias for INS_orr (vector register)
5150 if (opt == INS_OPTS_NONE)
5152 elemsize = EA_1BYTE;
5153 opt = optMakeArrangement(size, elemsize);
5155 assert(isValidArrangement(size, opt));
5164 if (isVectorRegister(reg1))
5166 assert(isValidVectorDatasize(size));
5167 assert(isVectorRegister(reg2));
5168 assert(isVectorRegister(reg3));
5169 if (opt == INS_OPTS_NONE)
5171 elemsize = EA_1BYTE;
5172 opt = optMakeArrangement(size, elemsize);
5174 assert(isValidArrangement(size, opt));
5183 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, INS_OPTS_NONE);
5189 assert(isValidVectorDatasize(size));
5190 assert(isVectorRegister(reg1));
5191 assert(isVectorRegister(reg2));
5192 assert(isVectorRegister(reg3));
5193 if (opt == INS_OPTS_NONE)
5195 elemsize = EA_1BYTE;
5196 opt = optMakeArrangement(size, elemsize);
5198 assert(isValidArrangement(size, opt));
5210 assert(isVectorRegister(reg1));
5211 assert(isVectorRegister(reg2));
5212 assert(isVectorRegister(reg3));
5213 if (insOptsAnyArrangement(opt))
5216 assert(isValidVectorDatasize(size));
5217 assert(isValidArrangement(size, opt));
5218 elemsize = optGetElemsize(opt);
5219 assert(isValidVectorElemsizeFloat(elemsize));
5220 assert(opt != INS_OPTS_1D); // Reserved encoding
5226 assert(insOptsNone(opt));
5227 assert(isValidScalarDatasize(size));
5234 assert(insOptsNone(opt));
5235 assert(isVectorRegister(reg1));
5236 assert(isVectorRegister(reg2));
5237 assert(isVectorRegister(reg3));
5238 assert(isValidScalarDatasize(size));
5245 assert(isVectorRegister(reg1));
5246 assert(isVectorRegister(reg2));
5247 assert(isVectorRegister(reg3));
5248 assert(insOptsAnyArrangement(opt)); // no scalar encoding, use 4-operand 'fmadd' or 'fmsub'
5251 assert(isValidVectorDatasize(size));
5252 assert(isValidArrangement(size, opt));
5253 elemsize = optGetElemsize(opt);
5254 assert(isValidVectorElemsizeFloat(elemsize));
5255 assert(opt != INS_OPTS_1D); // Reserved encoding
5268 emitIns_R_R_R_Ext(ins, attr, reg1, reg2, reg3, opt);
5276 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0);
5285 assert(isGeneralRegisterOrZR(reg1));
5286 assert(isGeneralRegisterOrZR(reg2));
5287 assert(isGeneralRegisterOrSP(reg3));
5295 } // end switch (ins)
5297 assert(fmt != IF_NONE);
5299 instrDesc* id = emitNewInstr(attr);
5313 /*****************************************************************************
5315 * Add an instruction referencing three registers and a constant.
5318 void emitter::emitIns_R_R_R_I(instruction ins,
5324 insOpts opt /* = INS_OPTS_NONE */,
5325 emitAttr attrReg2 /* = EA_UNKNOWN */)
5327 emitAttr size = EA_SIZE(attr);
5328 emitAttr elemsize = EA_UNKNOWN;
5329 insFormat fmt = IF_NONE;
5330 bool isLdSt = false;
5331 bool isSIMD = false;
5332 bool isAddSub = false;
5333 bool setFlags = false;
5336 /* Figure out the encoding format of the instruction */
5340 assert(insOptsNone(opt));
5341 assert(isValidGeneralDatasize(size));
5342 assert(isGeneralRegister(reg1));
5343 assert(isGeneralRegister(reg2));
5344 assert(isGeneralRegister(reg3));
5345 assert(isValidImmShift(imm, size));
5357 assert(isValidGeneralDatasize(size));
5358 assert(isGeneralRegister(reg1));
5359 assert(isGeneralRegister(reg2));
5360 assert(isGeneralRegister(reg3));
5361 assert(isValidImmShift(imm, size));
5364 assert(insOptsNone(opt)); // a zero imm, means no shift kind
5369 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
5374 case INS_fmul: // by element, imm[0..3] selects the element of reg3
5378 assert(isVectorRegister(reg1));
5379 assert(isVectorRegister(reg2));
5380 assert(isVectorRegister(reg3));
5381 if (insOptsAnyArrangement(opt))
5384 assert(isValidVectorDatasize(size));
5385 assert(isValidArrangement(size, opt));
5386 elemsize = optGetElemsize(opt);
5387 assert(isValidVectorElemsizeFloat(elemsize));
5388 assert(isValidVectorIndex(size, elemsize, imm));
5389 assert(opt != INS_OPTS_1D); // Reserved encoding
5395 assert(insOptsNone(opt));
5396 assert(isValidScalarDatasize(size));
5398 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
5403 case INS_mul: // by element, imm[0..7] selects the element of reg3
5406 assert(isVectorRegister(reg1));
5407 assert(isVectorRegister(reg2));
5408 assert(isVectorRegister(reg3));
5410 assert(insOptsAnyArrangement(opt));
5411 assert(isValidVectorDatasize(size));
5412 assert(isValidArrangement(size, opt));
5413 elemsize = optGetElemsize(opt);
5414 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
5415 // Only has encodings for H or S elemsize
5416 assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE));
5417 // Only has encodings for V0..V15
5418 if ((elemsize == EA_2BYTE) && (reg3 >= REG_V16))
5420 noway_assert(!"Invalid reg3");
5444 assert(insOptsNone(opt)); // Can't use Pre/Post index on these two instructions
5449 // Is the target a vector register?
5450 if (isVectorRegister(reg1))
5452 scale = NaturalScale_helper(size);
5457 scale = (size == EA_8BYTE) ? 3 : 2;
5466 } // end switch (ins)
5471 assert(isGeneralRegisterOrSP(reg3));
5472 assert(insOptsNone(opt) || insOptsIndexed(opt));
5476 assert(isValidVectorLSPDatasize(size));
5477 assert(isVectorRegister(reg1));
5478 assert(isVectorRegister(reg2));
5479 assert((scale >= 2) && (scale <= 4));
5483 assert(isValidGeneralDatasize(size));
5484 assert(isGeneralRegisterOrZR(reg1));
5485 assert(isGeneralRegisterOrZR(reg2));
5486 assert((scale == 2) || (scale == 3));
5489 // Load/Store Pair reserved encodings:
5490 if (emitInsIsLoad(ins))
5492 assert(reg1 != reg2);
5494 if (insOptsIndexed(opt))
5496 assert(reg1 != reg3);
5497 assert(reg2 != reg3);
5500 reg3 = encodingSPtoZR(reg3);
5502 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
5505 assert(insOptsNone(opt)); // PRE/POST Index doesn't make sense with an immediate of zero
5511 if ((imm & mask) == 0)
5513 imm >>= scale; // The immediate is scaled by the size of the ld/st
5515 if ((imm >= -64) && (imm <= 63))
5521 if (fmt != IF_LS_3C)
5523 assert(!"Instruction cannot be encoded: IF_LS_3C");
5530 bool reg2IsSP = (reg2 == REG_SP);
5532 assert(isValidGeneralDatasize(size));
5533 assert(isGeneralRegister(reg3));
5535 if (setFlags || insOptsAluShift(opt)) // Can't encode SP in reg1 with setFlags or AluShift option
5537 assert(isGeneralRegisterOrZR(reg1));
5541 assert(isGeneralRegisterOrSP(reg1));
5542 reg1 = encodingSPtoZR(reg1);
5545 if (insOptsAluShift(opt)) // Can't encode SP in reg2 with AluShift option
5547 assert(isGeneralRegister(reg2));
5551 assert(isGeneralRegisterOrSP(reg2));
5552 reg2 = encodingSPtoZR(reg2);
5555 if (insOptsAnyExtend(opt))
5557 assert((imm >= 0) && (imm <= 4));
5561 else if (insOptsAluShift(opt))
5563 // imm should be non-zero and in [1..63]
5564 assert(isValidImmShift(imm, size) && (imm != 0));
5569 assert(insOptsNone(opt));
5573 // To encode the SP register as reg2 we must use the IF_DR_3C encoding
5574 // and also specify a LSL of zero (imm == 0)
5585 assert(!"Instruction cannot be encoded: Add/Sub IF_DR_3A");
5588 assert(fmt != IF_NONE);
5590 instrDesc* id = emitNewInstrCns(attr, imm);
5600 // Record the attribute for the second register in the pair
5601 id->idGCrefReg2(GCT_NONE);
5602 if (attrReg2 != EA_UNKNOWN)
5604 // Record the attribute for the second register in the pair
5605 assert((fmt == IF_LS_3B) || (fmt == IF_LS_3C));
5606 if (EA_IS_GCREF(attrReg2))
5608 id->idGCrefReg2(GCT_GCREF);
5610 else if (EA_IS_BYREF(attrReg2))
5612 id->idGCrefReg2(GCT_BYREF);
5620 /*****************************************************************************
5622 * Add an instruction referencing three registers, with an extend option
5625 void emitter::emitIns_R_R_R_Ext(instruction ins,
5630 insOpts opt, /* = INS_OPTS_NONE */
5631 int shiftAmount) /* = -1 -- unset */
5633 emitAttr size = EA_SIZE(attr);
5634 insFormat fmt = IF_NONE;
5635 bool isSIMD = false;
5638 /* Figure out the encoding format of the instruction */
5659 // Is the target a vector register?
5660 if (isVectorRegister(reg1))
5662 assert(isValidVectorLSDatasize(size));
5663 scale = NaturalScale_helper(size);
5668 assert(isValidGeneralDatasize(size));
5669 scale = (size == EA_8BYTE) ? 3 : 2;
5678 } // end switch (ins)
5680 assert(scale != -1);
5681 assert(insOptsLSExtend(opt));
5685 assert(isValidVectorLSDatasize(size));
5686 assert(isVectorRegister(reg1));
5690 assert(isValidGeneralLSDatasize(size));
5691 assert(isGeneralRegisterOrZR(reg1));
5694 assert(isGeneralRegisterOrSP(reg2));
5695 assert(isGeneralRegister(reg3));
5697 // Load/Store reserved encodings:
5698 if (insOptsIndexed(opt))
5700 assert(reg1 != reg2);
5703 if (shiftAmount == -1)
5705 shiftAmount = insOptsLSL(opt) ? scale : 0;
5707 assert((shiftAmount == scale) || (shiftAmount == 0));
5709 reg2 = encodingSPtoZR(reg2);
5712 instrDesc* id = emitNewInstr(attr);
5721 id->idReg3Scaled(shiftAmount == scale);
5727 /*****************************************************************************
5729 * Add an instruction referencing two registers and two constants.
5732 void emitter::emitIns_R_R_I_I(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, int imm1, int imm2)
5734 emitAttr size = EA_SIZE(attr);
5735 emitAttr elemsize = EA_UNKNOWN;
5736 insFormat fmt = IF_NONE;
5737 size_t immOut = 0; // composed from imm1 and imm2 and stored in the instrDesc
5739 /* Figure out the encoding format of the instruction */
5749 assert(isGeneralRegister(reg1));
5750 assert(isGeneralRegister(reg2));
5751 assert(isValidImmShift(imm1, size));
5752 assert(isValidImmShift(imm2, size));
5754 bmi.immN = (size == EA_8BYTE);
5757 immOut = bmi.immNRS;
5764 assert(isGeneralRegister(reg1));
5765 assert(isGeneralRegister(reg2));
5766 lsb = getBitWidth(size) - imm1;
5768 assert(isValidImmShift(lsb, size));
5769 assert(isValidImmShift(width, size));
5771 bmi.immN = (size == EA_8BYTE);
5774 immOut = bmi.immNRS;
5781 assert(isGeneralRegister(reg1));
5782 assert(isGeneralRegister(reg2));
5784 width = imm2 + imm1 - 1;
5785 assert(isValidImmShift(lsb, size));
5786 assert(isValidImmShift(width, size));
5788 bmi.immN = (size == EA_8BYTE);
5790 bmi.immS = imm2 + imm1 - 1;
5791 immOut = bmi.immNRS;
5797 assert(isVectorRegister(reg1));
5798 assert(isVectorRegister(reg2));
5800 assert(isValidVectorElemsize(elemsize));
5801 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm1));
5802 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm2));
5803 immOut = (imm1 << 4) + imm2;
5811 assert(fmt != IF_NONE);
5813 instrDesc* id = emitNewInstrSC(attr, immOut);
5825 /*****************************************************************************
5827 * Add an instruction referencing four registers.
5830 void emitter::emitIns_R_R_R_R(
5831 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, regNumber reg4)
5833 emitAttr size = EA_SIZE(attr);
5834 insFormat fmt = IF_NONE;
5836 /* Figure out the encoding format of the instruction */
5845 assert(isValidGeneralDatasize(size));
5846 assert(isGeneralRegister(reg1));
5847 assert(isGeneralRegister(reg2));
5848 assert(isGeneralRegister(reg3));
5849 assert(isGeneralRegister(reg4));
5858 assert(isValidScalarDatasize(size));
5859 assert(isVectorRegister(reg1));
5860 assert(isVectorRegister(reg2));
5861 assert(isVectorRegister(reg3));
5862 assert(isVectorRegister(reg4));
5874 assert(fmt != IF_NONE);
5876 instrDesc* id = emitNewInstr(attr);
5890 /*****************************************************************************
5892 * Add an instruction referencing a register and a condition code
5895 void emitter::emitIns_R_COND(instruction ins, emitAttr attr, regNumber reg, insCond cond)
5897 emitAttr size = EA_SIZE(attr);
5898 insFormat fmt = IF_NONE;
5902 /* Figure out the encoding format of the instruction */
5907 assert(isGeneralRegister(reg));
5916 } // end switch (ins)
5918 assert(fmt != IF_NONE);
5919 assert(isValidImmCond(cfi.immCFVal));
5921 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
5925 id->idInsOpt(INS_OPTS_NONE);
5933 /*****************************************************************************
5935 * Add an instruction referencing two registers and a condition code
5938 void emitter::emitIns_R_R_COND(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insCond cond)
5940 emitAttr size = EA_SIZE(attr);
5941 insFormat fmt = IF_NONE;
5945 /* Figure out the encoding format of the instruction */
5951 assert(isGeneralRegister(reg1));
5952 assert(isGeneralRegister(reg2));
5960 } // end switch (ins)
5962 assert(fmt != IF_NONE);
5963 assert(isValidImmCond(cfi.immCFVal));
5965 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
5969 id->idInsOpt(INS_OPTS_NONE);
5978 /*****************************************************************************
5980 * Add an instruction referencing two registers and a condition code
5983 void emitter::emitIns_R_R_R_COND(
5984 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insCond cond)
5986 emitAttr size = EA_SIZE(attr);
5987 insFormat fmt = IF_NONE;
5991 /* Figure out the encoding format of the instruction */
5998 assert(isGeneralRegister(reg1));
5999 assert(isGeneralRegister(reg2));
6000 assert(isGeneralRegister(reg3));
6009 } // end switch (ins)
6011 assert(fmt != IF_NONE);
6012 assert(isValidImmCond(cfi.immCFVal));
6014 instrDesc* id = emitNewInstr(attr);
6018 id->idInsOpt(INS_OPTS_NONE);
6023 id->idSmallCns(cfi.immCFVal);
6029 /*****************************************************************************
6031 * Add an instruction referencing two registers the flags and a condition code
6034 void emitter::emitIns_R_R_FLAGS_COND(
6035 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insCflags flags, insCond cond)
6037 emitAttr size = EA_SIZE(attr);
6038 insFormat fmt = IF_NONE;
6042 /* Figure out the encoding format of the instruction */
6047 assert(isGeneralRegister(reg1));
6048 assert(isGeneralRegister(reg2));
6056 } // end switch (ins)
6058 assert(fmt != IF_NONE);
6059 assert(isValidImmCondFlags(cfi.immCFVal));
6061 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6065 id->idInsOpt(INS_OPTS_NONE);
6074 /*****************************************************************************
6076 * Add an instruction referencing a register, an immediate, the flags and a condition code
6079 void emitter::emitIns_R_I_FLAGS_COND(
6080 instruction ins, emitAttr attr, regNumber reg, int imm, insCflags flags, insCond cond)
6082 emitAttr size = EA_SIZE(attr);
6083 insFormat fmt = IF_NONE;
6087 /* Figure out the encoding format of the instruction */
6092 assert(isGeneralRegister(reg));
6095 ins = insReverse(ins);
6098 if ((imm >= 0) && (imm <= 31))
6107 assert(!"Instruction cannot be encoded: ccmp/ccmn imm5");
6113 } // end switch (ins)
6115 assert(fmt != IF_NONE);
6116 assert(isValidImmCondFlagsImm5(cfi.immCFVal));
6118 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6122 id->idInsOpt(INS_OPTS_NONE);
6130 /*****************************************************************************
6132 * Add a memory barrier instruction with a 'barrier' immediate
6135 void emitter::emitIns_BARR(instruction ins, insBarrier barrier)
6137 insFormat fmt = IF_NONE;
6140 /* Figure out the encoding format of the instruction */
6148 imm = (ssize_t)barrier;
6153 } // end switch (ins)
6155 assert(fmt != IF_NONE);
6157 instrDesc* id = emitNewInstrSC(EA_8BYTE, imm);
6161 id->idInsOpt(INS_OPTS_NONE);
6167 /*****************************************************************************
6169 * Add an instruction with a static data member operand. If 'size' is 0, the
6170 * instruction operates on the address of the static member instead of its
6171 * value (e.g. "push offset clsvar", rather than "push dword ptr [clsvar]").
6174 void emitter::emitIns_C(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, int offs)
6179 /*****************************************************************************
6181 * Add an instruction referencing stack-based local variable.
6184 void emitter::emitIns_S(instruction ins, emitAttr attr, int varx, int offs)
6189 /*****************************************************************************
6191 * Add an instruction referencing a register and a stack-based local variable.
6193 void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
6195 emitAttr size = EA_SIZE(attr);
6196 insFormat fmt = IF_NONE;
6202 // TODO-ARM64-CQ: use unscaled loads?
6203 /* Figure out the encoding format of the instruction */
6224 assert(isValidGeneralDatasize(size) || isValidVectorDatasize(size));
6225 scale = genLog2(EA_SIZE_IN_BYTES(size));
6229 assert(size == EA_8BYTE);
6234 NYI("emitIns_R_S"); // FP locals?
6237 } // end switch (ins)
6239 /* Figure out the variable's frame position */
6244 base = emitComp->lvaFrameAddress(varx, &FPbased);
6246 assert((scale >= 0) && (scale <= 4));
6248 regNumber reg2 = FPbased ? REG_FPBASE : REG_SPBASE;
6249 reg2 = encodingSPtoZR(reg2);
6266 fmt = IF_DI_2A; // add reg1,reg2,#disp
6270 regNumber rsvdReg = codeGen->rsGetRsvdReg();
6271 codeGen->instGen_Set_Reg_To_Imm(size, rsvdReg, imm);
6272 fmt = IF_DR_3A; // add reg1,reg2,rsvdReg
6277 bool useRegForImm = false;
6278 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6285 else if ((imm < 0) || ((imm & mask) != 0))
6287 if ((imm >= -256) && (imm <= 255))
6293 useRegForImm = true;
6298 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
6300 imm >>= scale; // The immediate is scaled by the size of the ld/st
6306 useRegForImm = true;
6312 regNumber rsvdReg = codeGen->rsGetRsvdReg();
6313 codeGen->instGen_Set_Reg_To_Imm(size, rsvdReg, imm);
6318 assert(fmt != IF_NONE);
6320 instrDesc* id = emitNewInstrCns(attr, imm);
6324 id->idInsOpt(INS_OPTS_NONE);
6328 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6329 id->idSetIsLclVar();
6332 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6339 /*****************************************************************************
6341 * Add an instruction referencing two register and consectutive stack-based local variable slots.
6343 void emitter::emitIns_R_R_S_S(
6344 instruction ins, emitAttr attr1, emitAttr attr2, regNumber reg1, regNumber reg2, int varx, int offs)
6346 assert((ins == INS_ldp) || (ins == INS_ldnp));
6347 assert(EA_8BYTE == EA_SIZE(attr1));
6348 assert(EA_8BYTE == EA_SIZE(attr2));
6349 assert(isGeneralRegisterOrZR(reg1));
6350 assert(isGeneralRegisterOrZR(reg2));
6353 emitAttr size = EA_SIZE(attr1);
6354 insFormat fmt = IF_LS_3B;
6356 const unsigned scale = 3;
6358 /* Figure out the variable's frame position */
6362 base = emitComp->lvaFrameAddress(varx, &FPbased);
6365 // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6366 regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE;
6367 reg3 = encodingSPtoZR(reg3);
6369 bool useRegForAdr = true;
6371 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6374 useRegForAdr = false;
6378 if ((imm & mask) == 0)
6380 ssize_t immShift = imm >> scale; // The immediate is scaled by the size of the ld/st
6382 if ((immShift >= -64) && (immShift <= 63))
6385 useRegForAdr = false;
6393 regNumber rsvd = codeGen->rsGetRsvdReg();
6394 emitIns_R_R_Imm(INS_add, EA_8BYTE, rsvd, reg3, imm);
6399 assert(fmt != IF_NONE);
6401 instrDesc* id = emitNewInstrCns(attr1, imm);
6405 id->idInsOpt(INS_OPTS_NONE);
6407 // Record the attribute for the second register in the pair
6408 if (EA_IS_GCREF(attr2))
6410 id->idGCrefReg2(GCT_GCREF);
6412 else if (EA_IS_BYREF(attr2))
6414 id->idGCrefReg2(GCT_BYREF);
6418 id->idGCrefReg2(GCT_NONE);
6424 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6425 id->idSetIsLclVar();
6428 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6435 /*****************************************************************************
6437 * Add an instruction referencing a stack-based local variable and a register
6439 void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
6442 emitAttr size = EA_SIZE(attr);
6443 insFormat fmt = IF_NONE;
6446 bool isVectorStore = false;
6448 // TODO-ARM64-CQ: use unscaled loads?
6449 /* Figure out the encoding format of the instruction */
6454 assert(isGeneralRegisterOrZR(reg1));
6459 assert(isGeneralRegisterOrZR(reg1));
6463 if (isGeneralRegisterOrZR(reg1))
6465 assert(isValidGeneralDatasize(size));
6466 scale = (size == EA_8BYTE) ? 3 : 2;
6470 assert(isVectorRegister(reg1));
6471 assert(isValidVectorLSDatasize(size));
6472 scale = NaturalScale_helper(size);
6473 isVectorStore = true;
6478 NYI("emitIns_S_R"); // FP locals?
6481 } // end switch (ins)
6483 /* Figure out the variable's frame position */
6487 base = emitComp->lvaFrameAddress(varx, &FPbased);
6499 // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6500 regNumber reg2 = FPbased ? REG_FPBASE : REG_SPBASE;
6501 reg2 = encodingSPtoZR(reg2);
6503 bool useRegForImm = false;
6505 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6510 else if ((imm < 0) || ((imm & mask) != 0))
6512 if ((imm >= -256) && (imm <= 255))
6518 useRegForImm = true;
6523 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
6525 imm >>= scale; // The immediate is scaled by the size of the ld/st
6531 useRegForImm = true;
6537 // The reserved register is not stored in idReg3() since that field overlaps with iiaLclVar.
6538 // It is instead implicit when idSetIsLclVar() is set, with this encoding format.
6539 regNumber rsvdReg = codeGen->rsGetRsvdReg();
6540 codeGen->instGen_Set_Reg_To_Imm(size, rsvdReg, imm);
6544 assert(fmt != IF_NONE);
6546 instrDesc* id = emitNewInstrCns(attr, imm);
6550 id->idInsOpt(INS_OPTS_NONE);
6554 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6555 id->idSetIsLclVar();
6558 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6565 /*****************************************************************************
6567 * Add an instruction referencing consecutive stack-based local variable slots and two registers
6569 void emitter::emitIns_S_S_R_R(
6570 instruction ins, emitAttr attr1, emitAttr attr2, regNumber reg1, regNumber reg2, int varx, int offs)
6572 assert((ins == INS_stp) || (ins == INS_stnp));
6573 assert(EA_8BYTE == EA_SIZE(attr1));
6574 assert(EA_8BYTE == EA_SIZE(attr2));
6575 assert(isGeneralRegisterOrZR(reg1));
6576 assert(isGeneralRegisterOrZR(reg2));
6579 emitAttr size = EA_SIZE(attr1);
6580 insFormat fmt = IF_LS_3B;
6582 const unsigned scale = 3;
6584 /* Figure out the variable's frame position */
6588 base = emitComp->lvaFrameAddress(varx, &FPbased);
6591 // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6592 regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE;
6593 reg3 = encodingSPtoZR(reg3);
6595 bool useRegForAdr = true;
6597 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6600 useRegForAdr = false;
6604 if ((imm & mask) == 0)
6606 ssize_t immShift = imm >> scale; // The immediate is scaled by the size of the ld/st
6608 if ((immShift >= -64) && (immShift <= 63))
6611 useRegForAdr = false;
6619 regNumber rsvd = codeGen->rsGetRsvdReg();
6620 emitIns_R_R_Imm(INS_add, EA_8BYTE, rsvd, reg3, imm);
6625 assert(fmt != IF_NONE);
6627 instrDesc* id = emitNewInstrCns(attr1, imm);
6631 id->idInsOpt(INS_OPTS_NONE);
6633 // Record the attribute for the second register in the pair
6634 if (EA_IS_GCREF(attr2))
6636 id->idGCrefReg2(GCT_GCREF);
6638 else if (EA_IS_BYREF(attr2))
6640 id->idGCrefReg2(GCT_BYREF);
6644 id->idGCrefReg2(GCT_NONE);
6650 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6651 id->idSetIsLclVar();
6654 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6661 /*****************************************************************************
6663 * Add an instruction referencing stack-based local variable and an immediate
6665 void emitter::emitIns_S_I(instruction ins, emitAttr attr, int varx, int offs, int val)
6670 /*****************************************************************************
6672 * Add an instruction with a register + static member operands.
6673 * Constant is stored into JIT data which is adjacent to code.
6674 * No relocation is needed. PC-relative offset will be encoded directly into instruction.
6677 void emitter::emitIns_R_C(
6678 instruction ins, emitAttr attr, regNumber reg, regNumber addrReg, CORINFO_FIELD_HANDLE fldHnd, int offs)
6681 assert(instrDesc::fitsInSmallCns(offs));
6683 emitAttr size = EA_SIZE(attr);
6684 insFormat fmt = IF_NONE;
6686 instrDescJmp* id = emitNewInstrJmp();
6691 // This is case to get address to the constant data.
6693 assert(isGeneralRegister(reg));
6694 assert(isValidGeneralDatasize(size));
6699 if (isVectorRegister(reg))
6701 assert(isValidScalarDatasize(size));
6702 // For vector (float/double) register, we should have an integer address reg to
6703 // compute long address which consists of page address and page offset.
6704 // For integer constant, this is not needed since the dest reg can be used to
6705 // compute address as well as contain the final contents.
6706 assert(isGeneralRegister(reg) || (addrReg != REG_NA));
6710 assert(isGeneralRegister(reg));
6711 assert(isValidGeneralDatasize(size));
6718 assert(fmt != IF_NONE);
6722 id->idInsOpt(INS_OPTS_NONE);
6723 id->idSmallCns(offs);
6725 id->idAddr()->iiaFieldHnd = fldHnd;
6726 id->idSetIsBound(); // We won't patch address since we will know the exact distance once JIT code and data are
6727 // allocated together.
6729 id->idReg1(reg); // destination register that will get the constant value.
6730 if (addrReg != REG_NA)
6732 id->idReg2(addrReg); // integer register to compute long address (used for vector dest when we end up with long
6735 id->idjShort = false; // Assume loading constant from long address
6737 // Keep it long if it's in cold code.
6738 id->idjKeepLong = emitComp->fgIsBlockCold(emitComp->compCurBB);
6741 if (emitComp->opts.compLongAddress)
6742 id->idjKeepLong = 1;
6745 // If it's possible to be shortened, then put it in jump list
6746 // to be revisited by emitJumpDistBind.
6747 if (!id->idjKeepLong)
6749 /* Record the jump's IG and offset within it */
6750 id->idjIG = emitCurIG;
6751 id->idjOffs = emitCurIGsize;
6753 /* Append this jump to this IG's jump list */
6754 id->idjNext = emitCurIGjmpList;
6755 emitCurIGjmpList = id;
6766 /*****************************************************************************
6768 * Add an instruction with a static member + constant.
6771 void emitter::emitIns_C_I(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, ssize_t offs, ssize_t val)
6776 /*****************************************************************************
6778 * Add an instruction with a static member + register operands.
6781 void emitter::emitIns_C_R(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, regNumber reg, int offs)
6783 assert(!"emitIns_C_R not supported for RyuJIT backend");
6786 void emitter::emitIns_R_AR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
6788 NYI("emitIns_R_AR");
6791 // This computes address from the immediate which is relocatable.
6792 void emitter::emitIns_R_AI(instruction ins, emitAttr attr, regNumber ireg, ssize_t addr)
6794 assert(EA_IS_RELOC(attr));
6795 emitAttr size = EA_SIZE(attr);
6796 insFormat fmt = IF_DI_1E;
6797 bool needAdd = false;
6798 instrDescJmp* id = emitNewInstrJmp();
6803 // This computes page address.
6804 // page offset is needed using add.
6815 id->idInsOpt(INS_OPTS_NONE);
6817 id->idAddr()->iiaAddr = (BYTE*)addr;
6819 id->idSetIsDspReloc();
6826 // add reg, reg, imm
6829 instrDesc* id = emitAllocInstr(attr);
6830 assert(id->idIsReloc());
6834 id->idInsOpt(INS_OPTS_NONE);
6836 id->idAddr()->iiaAddr = (BYTE*)addr;
6845 void emitter::emitIns_AR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
6847 NYI("emitIns_AR_R");
6850 void emitter::emitIns_R_ARR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
6852 NYI("emitIns_R_ARR");
6855 void emitter::emitIns_ARR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
6857 NYI("emitIns_R_ARR");
6860 void emitter::emitIns_R_ARX(
6861 instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, unsigned mul, int disp)
6863 NYI("emitIns_R_ARR");
6866 /*****************************************************************************
6868 * Record that a jump instruction uses the short encoding
6871 void emitter::emitSetShortJump(instrDescJmp* id)
6873 if (id->idjKeepLong)
6876 insFormat fmt = IF_NONE;
6877 if (emitIsCondJump(id))
6879 switch (id->idIns())
6894 else if (emitIsLoadLabel(id))
6898 else if (emitIsLoadConstant(id))
6908 id->idjShort = true;
6911 /*****************************************************************************
6913 * Add a label instruction.
6916 void emitter::emitIns_R_L(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
6918 assert(dst->bbFlags & BBF_JMP_TARGET);
6920 insFormat fmt = IF_NONE;
6931 instrDescJmp* id = emitNewInstrJmp();
6935 id->idjShort = false;
6936 id->idAddr()->iiaBBlabel = dst;
6938 id->idOpSize(EA_PTRSIZE);
6941 // Mark the catch return
6942 if (emitComp->compCurBB->bbJumpKind == BBJ_EHCATCHRET)
6944 id->idDebugOnlyInfo()->idCatchRet = true;
6948 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
6951 if (emitComp->opts.compLongAddress)
6952 id->idjKeepLong = 1;
6955 /* Record the jump's IG and offset within it */
6957 id->idjIG = emitCurIG;
6958 id->idjOffs = emitCurIGsize;
6960 /* Append this jump to this IG's jump list */
6962 id->idjNext = emitCurIGjmpList;
6963 emitCurIGjmpList = id;
6973 /*****************************************************************************
6975 * Add a data label instruction.
6978 void emitter::emitIns_R_D(instruction ins, emitAttr attr, unsigned offs, regNumber reg)
6983 void emitter::emitIns_J_R(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
6985 assert((ins == INS_cbz) || (ins == INS_cbnz));
6987 assert(dst != nullptr);
6988 assert((dst->bbFlags & BBF_JMP_TARGET) != 0);
6990 insFormat fmt = IF_LARGEJMP;
6992 instrDescJmp* id = emitNewInstrJmp();
6997 id->idjShort = false;
6998 id->idOpSize(EA_SIZE(attr));
7000 id->idAddr()->iiaBBlabel = dst;
7001 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7003 /* Record the jump's IG and offset within it */
7005 id->idjIG = emitCurIG;
7006 id->idjOffs = emitCurIGsize;
7008 /* Append this jump to this IG's jump list */
7010 id->idjNext = emitCurIGjmpList;
7011 emitCurIGjmpList = id;
7021 void emitter::emitIns_J_R_I(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg, int imm)
7023 assert((ins == INS_tbz) || (ins == INS_tbnz));
7025 assert(dst != nullptr);
7026 assert((dst->bbFlags & BBF_JMP_TARGET) != 0);
7027 assert((EA_SIZE(attr) == EA_4BYTE) || (EA_SIZE(attr) == EA_8BYTE));
7028 assert(imm < ((EA_SIZE(attr) == EA_4BYTE) ? 32 : 64));
7030 insFormat fmt = IF_LARGEJMP;
7032 instrDescJmp* id = emitNewInstrJmp();
7037 id->idjShort = false;
7038 id->idSmallCns(imm);
7039 id->idOpSize(EA_SIZE(attr));
7041 id->idAddr()->iiaBBlabel = dst;
7042 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7044 /* Record the jump's IG and offset within it */
7046 id->idjIG = emitCurIG;
7047 id->idjOffs = emitCurIGsize;
7049 /* Append this jump to this IG's jump list */
7051 id->idjNext = emitCurIGjmpList;
7052 emitCurIGjmpList = id;
7062 void emitter::emitIns_J(instruction ins, BasicBlock* dst, int instrCount)
7064 insFormat fmt = IF_NONE;
7068 assert(dst->bbFlags & BBF_JMP_TARGET);
7072 assert(instrCount != 0);
7075 /* Figure out the encoding format of the instruction */
7077 bool idjShort = false;
7082 // Unconditional jump is a single form.
7101 // Assume conditional jump is long.
7110 instrDescJmp* id = emitNewInstrJmp();
7114 id->idjShort = idjShort;
7117 // Mark the finally call
7118 if (ins == INS_bl_local && emitComp->compCurBB->bbJumpKind == BBJ_CALLFINALLY)
7120 id->idDebugOnlyInfo()->idFinallyCall = true;
7126 id->idAddr()->iiaBBlabel = dst;
7128 // Skip unconditional jump that has a single form.
7129 // TODO-ARM64-NYI: enable hot/cold splittingNYI.
7130 // The target needs to be relocated.
7133 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7136 if (emitComp->opts.compLongAddress) // Force long branches
7137 id->idjKeepLong = 1;
7143 id->idAddr()->iiaSetInstrCount(instrCount);
7144 id->idjKeepLong = false;
7145 /* This jump must be short */
7146 emitSetShortJump(id);
7150 /* Record the jump's IG and offset within it */
7152 id->idjIG = emitCurIG;
7153 id->idjOffs = emitCurIGsize;
7155 /* Append this jump to this IG's jump list */
7157 id->idjNext = emitCurIGjmpList;
7158 emitCurIGjmpList = id;
7168 /*****************************************************************************
7170 * Add a call instruction (direct or indirect).
7171 * argSize<0 means that the caller will pop the arguments
7173 * The other arguments are interpreted depending on callType as shown:
7174 * Unless otherwise specified, ireg,xreg,xmul,disp should have default values.
7176 * EC_FUNC_TOKEN : addr is the method address
7177 * EC_FUNC_ADDR : addr is the absolute address of the function
7179 * If callType is one of these emitCallTypes, addr has to be NULL.
7180 * EC_INDIR_R : "call ireg".
7182 * For ARM xreg, xmul and disp are never used and should always be 0/REG_NA.
7184 * Please consult the "debugger team notification" comment in genFnProlog().
7187 void emitter::emitIns_Call(EmitCallType callType,
7188 CORINFO_METHOD_HANDLE methHnd,
7189 INDEBUG_LDISASM_COMMA(CORINFO_SIG_INFO* sigInfo) // used to report call sites to the EE
7193 emitAttr secondRetSize,
7194 VARSET_VALARG_TP ptrVars,
7195 regMaskTP gcrefRegs,
7196 regMaskTP byrefRegs,
7197 IL_OFFSETX ilOffset /* = BAD_IL_OFFSET */,
7198 regNumber ireg /* = REG_NA */,
7199 regNumber xreg /* = REG_NA */,
7200 unsigned xmul /* = 0 */,
7201 ssize_t disp /* = 0 */,
7202 bool isJump /* = false */,
7203 bool isNoGC /* = false */,
7204 bool isProfLeaveCB /* = false */)
7206 /* Sanity check the arguments depending on callType */
7208 assert(callType < EC_COUNT);
7209 assert((callType != EC_FUNC_TOKEN && callType != EC_FUNC_ADDR) ||
7210 (ireg == REG_NA && xreg == REG_NA && xmul == 0 && disp == 0));
7211 assert(callType < EC_INDIR_R || addr == NULL);
7212 assert(callType != EC_INDIR_R || (ireg < REG_COUNT && xreg == REG_NA && xmul == 0 && disp == 0));
7214 // ARM never uses these
7215 assert(xreg == REG_NA && xmul == 0 && disp == 0);
7217 // Our stack level should be always greater than the bytes of arguments we push. Just
7219 assert((unsigned)abs(argSize) <= codeGen->genStackLevel);
7224 /* This is the saved set of registers after a normal call */
7225 regMaskTP savedSet = RBM_CALLEE_SAVED;
7227 /* some special helper calls have a different saved set registers */
7231 assert(emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
7233 // Get the set of registers that this call kills and remove it from the saved set.
7234 savedSet = RBM_ALLINT & ~emitComp->compNoGCHelperCallKillSet(Compiler::eeGetHelperNum(methHnd));
7236 // In case of Leave profiler callback, we need to preserve liveness of REG_PROFILER_RET_SCRATCH
7239 savedSet |= RBM_PROFILER_RET_SCRATCH;
7244 assert(!emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
7247 /* Trim out any callee-trashed registers from the live set */
7249 gcrefRegs &= savedSet;
7250 byrefRegs &= savedSet;
7253 if (EMIT_GC_VERBOSE)
7255 printf("Call: GCvars=%s ", VarSetOps::ToString(emitComp, ptrVars));
7256 dumpConvertedVarSet(emitComp, ptrVars);
7257 printf(", gcrefRegs=");
7258 printRegMaskInt(gcrefRegs);
7259 emitDispRegSet(gcrefRegs);
7260 printf(", byrefRegs=");
7261 printRegMaskInt(byrefRegs);
7262 emitDispRegSet(byrefRegs);
7267 assert(argSize % REGSIZE_BYTES == 0);
7268 argCnt = (int)(argSize / (int)sizeof(void*));
7270 /* Managed RetVal: emit sequence point for the call */
7271 if (emitComp->opts.compDbgInfo && ilOffset != BAD_IL_OFFSET)
7273 codeGen->genIPmappingAdd(ilOffset, false);
7277 We need to allocate the appropriate instruction descriptor based
7278 on whether this is a direct/indirect call, and whether we need to
7279 record an updated set of live GC variables.
7282 if (callType >= EC_INDIR_R)
7284 /* Indirect call, virtual calls */
7286 assert(callType == EC_INDIR_R);
7288 id = emitNewInstrCallInd(argCnt, disp, ptrVars, gcrefRegs, byrefRegs, retSize, secondRetSize);
7292 /* Helper/static/nonvirtual/function calls (direct or through handle),
7293 and calls to an absolute addr. */
7295 assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
7297 id = emitNewInstrCallDir(argCnt, ptrVars, gcrefRegs, byrefRegs, retSize, secondRetSize);
7300 /* Update the emitter's live GC ref sets */
7302 VarSetOps::Assign(emitComp, emitThisGCrefVars, ptrVars);
7303 emitThisGCrefRegs = gcrefRegs;
7304 emitThisByrefRegs = byrefRegs;
7306 /* Set the instruction - special case jumping a function */
7308 insFormat fmt = IF_NONE;
7310 id->idSetIsNoGC(isNoGC);
7312 /* Record the address: method, indirection, or funcptr */
7314 if (callType > EC_FUNC_ADDR)
7316 /* This is an indirect call (either a virtual call or func ptr call) */
7320 case EC_INDIR_R: // the address is in a register
7322 id->idSetIsCallRegPtr();
7326 ins = INS_br_tail; // INS_br_tail Reg
7330 ins = INS_blr; // INS_blr Reg
7338 assert(xreg == REG_NA);
7342 NO_WAY("unexpected instruction");
7348 /* This is a simple direct call: "call helper/method/addr" */
7350 assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
7352 assert(addr != NULL);
7356 ins = INS_b_tail; // INS_b_tail imm28
7360 ins = INS_bl; // INS_bl imm28
7367 id->idAddr()->iiaAddr = (BYTE*)addr;
7369 if (callType == EC_FUNC_ADDR)
7371 id->idSetIsCallAddr();
7374 if (emitComp->opts.compReloc)
7376 id->idSetIsDspReloc();
7381 if (EMIT_GC_VERBOSE)
7383 if (id->idIsLargeCall())
7385 printf("[%02u] Rec call GC vars = %s\n", id->idDebugOnlyInfo()->idNum,
7386 VarSetOps::ToString(emitComp, ((instrDescCGCA*)id)->idcGCvars));
7390 id->idDebugOnlyInfo()->idMemCookie = (size_t)methHnd; // method token
7391 id->idDebugOnlyInfo()->idCallSig = sigInfo;
7395 if (addr != nullptr)
7397 codeGen->getDisAssembler().disSetMethod((size_t)addr, methHnd);
7399 #endif // LATE_DISASM
7405 /*****************************************************************************
7407 * Returns true if 'imm' is valid Cond encoding
7410 /*static*/ bool emitter::isValidImmCond(ssize_t imm)
7412 // range check the ssize_t value, to make sure it is a small unsigned value
7413 // and that only the bits in the cfi.cond are set
7414 if ((imm < 0) || (imm > 0xF))
7418 cfi.immCFVal = (unsigned)imm;
7420 return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7423 /*****************************************************************************
7425 * Returns true if 'imm' is valid Cond/Flags encoding
7428 /*static*/ bool emitter::isValidImmCondFlags(ssize_t imm)
7430 // range check the ssize_t value, to make sure it is a small unsigned value
7431 // and that only the bits in the cfi.cond or cfi.flags are set
7432 if ((imm < 0) || (imm > 0xFF))
7436 cfi.immCFVal = (unsigned)imm;
7438 return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7441 /*****************************************************************************
7443 * Returns true if 'imm' is valid Cond/Flags/Imm5 encoding
7446 /*static*/ bool emitter::isValidImmCondFlagsImm5(ssize_t imm)
7448 // range check the ssize_t value, to make sure it is a small unsigned value
7449 // and that only the bits in the cfi.cond, cfi.flags or cfi.imm5 are set
7450 if ((imm < 0) || (imm > 0x1FFF))
7454 cfi.immCFVal = (unsigned)imm;
7456 return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7459 /*****************************************************************************
7461 * Returns an encoding for the specified register used in the 'Rd' position
7464 /*static*/ emitter::code_t emitter::insEncodeReg_Rd(regNumber reg)
7466 assert(isIntegerRegister(reg));
7467 emitter::code_t ureg = (emitter::code_t)reg;
7468 assert((ureg >= 0) && (ureg <= 31));
7472 /*****************************************************************************
7474 * Returns an encoding for the specified register used in the 'Rt' position
7477 /*static*/ emitter::code_t emitter::insEncodeReg_Rt(regNumber reg)
7479 assert(isIntegerRegister(reg));
7480 emitter::code_t ureg = (emitter::code_t)reg;
7481 assert((ureg >= 0) && (ureg <= 31));
7485 /*****************************************************************************
7487 * Returns an encoding for the specified register used in the 'Rn' position
7490 /*static*/ emitter::code_t emitter::insEncodeReg_Rn(regNumber reg)
7492 assert(isIntegerRegister(reg));
7493 emitter::code_t ureg = (emitter::code_t)reg;
7494 assert((ureg >= 0) && (ureg <= 31));
7498 /*****************************************************************************
7500 * Returns an encoding for the specified register used in the 'Rm' position
7503 /*static*/ emitter::code_t emitter::insEncodeReg_Rm(regNumber reg)
7505 assert(isIntegerRegister(reg));
7506 emitter::code_t ureg = (emitter::code_t)reg;
7507 assert((ureg >= 0) && (ureg <= 31));
7511 /*****************************************************************************
7513 * Returns an encoding for the specified register used in the 'Ra' position
7516 /*static*/ emitter::code_t emitter::insEncodeReg_Ra(regNumber reg)
7518 assert(isIntegerRegister(reg));
7519 emitter::code_t ureg = (emitter::code_t)reg;
7520 assert((ureg >= 0) && (ureg <= 31));
7524 /*****************************************************************************
7526 * Returns an encoding for the specified register used in the 'Vd' position
7529 /*static*/ emitter::code_t emitter::insEncodeReg_Vd(regNumber reg)
7531 assert(emitter::isVectorRegister(reg));
7532 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7533 assert((ureg >= 0) && (ureg <= 31));
7537 /*****************************************************************************
7539 * Returns an encoding for the specified register used in the 'Vt' position
7542 /*static*/ emitter::code_t emitter::insEncodeReg_Vt(regNumber reg)
7544 assert(emitter::isVectorRegister(reg));
7545 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7546 assert((ureg >= 0) && (ureg <= 31));
7550 /*****************************************************************************
7552 * Returns an encoding for the specified register used in the 'Vn' position
7555 /*static*/ emitter::code_t emitter::insEncodeReg_Vn(regNumber reg)
7557 assert(emitter::isVectorRegister(reg));
7558 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7559 assert((ureg >= 0) && (ureg <= 31));
7563 /*****************************************************************************
7565 * Returns an encoding for the specified register used in the 'Vm' position
7568 /*static*/ emitter::code_t emitter::insEncodeReg_Vm(regNumber reg)
7570 assert(emitter::isVectorRegister(reg));
7571 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7572 assert((ureg >= 0) && (ureg <= 31));
7576 /*****************************************************************************
7578 * Returns an encoding for the specified register used in the 'Va' position
7581 /*static*/ emitter::code_t emitter::insEncodeReg_Va(regNumber reg)
7583 assert(emitter::isVectorRegister(reg));
7584 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7585 assert((ureg >= 0) && (ureg <= 31));
7589 /*****************************************************************************
7591 * Returns an encoding for the specified condition code.
7594 /*static*/ emitter::code_t emitter::insEncodeCond(insCond cond)
7596 emitter::code_t uimm = (emitter::code_t)cond;
7600 /*****************************************************************************
7602 * Returns an encoding for the condition code with the lowest bit inverted (marked by invert(<cond>) in the
7603 * architecture manual).
7606 /*static*/ emitter::code_t emitter::insEncodeInvertedCond(insCond cond)
7608 emitter::code_t uimm = (emitter::code_t)cond;
7609 uimm ^= 1; // invert the lowest bit
7613 /*****************************************************************************
7615 * Returns an encoding for the specified flags.
7618 /*static*/ emitter::code_t emitter::insEncodeFlags(insCflags flags)
7620 emitter::code_t uimm = (emitter::code_t)flags;
7624 /*****************************************************************************
7626 * Returns the encoding for the Shift Count bits to be used for Arm64 encodings
7629 /*static*/ emitter::code_t emitter::insEncodeShiftCount(ssize_t imm, emitAttr size)
7631 assert((imm & 0x003F) == imm);
7632 assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
7634 return (emitter::code_t)imm << 10;
7637 /*****************************************************************************
7639 * Returns the encoding to select a 64-bit datasize for an Arm64 instruction
7642 /*static*/ emitter::code_t emitter::insEncodeDatasize(emitAttr size)
7644 if (size == EA_8BYTE)
7646 return 0x80000000; // set the bit at location 31
7650 assert(size == EA_4BYTE);
7655 /*****************************************************************************
7657 * Returns the encoding to select the datasize for the general load/store Arm64 instructions
7661 /*static*/ emitter::code_t emitter::insEncodeDatasizeLS(emitter::code_t code, emitAttr size)
7663 bool exclusive = ((code & 0x35000000) == 0);
7665 if ((code & 0x00800000) && !exclusive) // Is this a sign-extending opcode? (i.e. ldrsw, ldrsh, ldrsb)
7667 if ((code & 0x80000000) == 0) // Is it a ldrsh or ldrsb and not ldrsw ?
7669 if (EA_SIZE(size) != EA_8BYTE) // Do we need to encode the 32-bit Rt size bit?
7671 return 0x00400000; // set the bit at location 22
7675 else if (code & 0x80000000) // Is this a ldr/str/ldur/stur opcode?
7677 if (EA_SIZE(size) == EA_8BYTE) // Do we need to encode the 64-bit size bit?
7679 return 0x40000000; // set the bit at location 30
7685 /*****************************************************************************
7687 * Returns the encoding to select the datasize for the vector load/store Arm64 instructions
7691 /*static*/ emitter::code_t emitter::insEncodeDatasizeVLS(emitter::code_t code, emitAttr size)
7696 if ((code & 0x20000000) == 0)
7700 if (size == EA_16BYTE)
7702 // set the operation size in bit 31
7703 result = 0x80000000;
7705 else if (size == EA_8BYTE)
7707 // set the operation size in bit 30
7708 result = 0x40000000;
7712 assert(size == EA_4BYTE);
7714 result = 0x00000000;
7721 if (size == EA_16BYTE)
7723 // The operation size in bits 31 and 30 are zero
7724 // Bit 23 specifies a 128-bit Load/Store
7725 result = 0x00800000;
7727 else if (size == EA_8BYTE)
7729 // set the operation size in bits 31 and 30
7730 result = 0xC0000000;
7732 else if (size == EA_4BYTE)
7734 // set the operation size in bit 31
7735 result = 0x80000000;
7737 else if (size == EA_2BYTE)
7739 // set the operation size in bit 30
7740 result = 0x40000000;
7744 assert(size == EA_1BYTE);
7745 // The operation size in bits 31 and 30 are zero
7746 result = 0x00000000;
7750 // Or in bit 26 to indicate a Vector register is used as 'target'
7751 result |= 0x04000000;
7756 /*****************************************************************************
7758 * Returns the encoding to select the datasize for the vector load/store Arm64 instructions
7762 /*static*/ emitter::code_t emitter::insEncodeDatasizeVPLS(emitter::code_t code, emitAttr size)
7766 if (size == EA_16BYTE)
7768 // The operation size in bits 31 and 30 are zero
7769 // Bit 23 specifies a 128-bit Load/Store
7770 result = 0x80000000;
7772 else if (size == EA_8BYTE)
7774 // set the operation size in bits 31 and 30
7775 result = 0x40000000;
7777 else if (size == EA_4BYTE)
7779 // set the operation size in bit 31
7780 result = 0x00000000;
7783 // Or in bit 26 to indicate a Vector register is used as 'target'
7784 result |= 0x04000000;
7789 /*****************************************************************************
7791 * Returns the encoding to set the size bit and the N bits for a 'bitfield' instruction
7795 /*static*/ emitter::code_t emitter::insEncodeDatasizeBF(emitter::code_t code, emitAttr size)
7797 // is bit 30 equal to 0?
7798 if ((code & 0x40000000) == 0) // is the opcode one of extr, sxtb, sxth or sxtw
7800 if (size == EA_8BYTE) // Do we need to set the sf and N bits?
7802 return 0x80400000; // set the sf-bit at location 31 and the N-bit at location 22
7805 return 0; // don't set any bits
7808 /*****************************************************************************
7810 * Returns the encoding to select the 64/128-bit datasize for an Arm64 vector instruction
7813 /*static*/ emitter::code_t emitter::insEncodeVectorsize(emitAttr size)
7815 if (size == EA_16BYTE)
7817 return 0x40000000; // set the bit at location 30
7821 assert(size == EA_8BYTE);
7826 /*****************************************************************************
7828 * Returns the encoding to select 'index' for an Arm64 vector elem instruction
7830 /*static*/ emitter::code_t emitter::insEncodeVectorIndex(emitAttr elemsize, ssize_t index)
7832 code_t bits = (code_t)index;
7833 if (elemsize == EA_1BYTE)
7838 else if (elemsize == EA_2BYTE)
7843 else if (elemsize == EA_4BYTE)
7850 assert(elemsize == EA_8BYTE);
7854 assert((bits >= 1) && (bits <= 0x1f));
7856 return (bits << 16); // bits at locations [20,19,18,17,16]
7859 /*****************************************************************************
7861 * Returns the encoding to select 'index2' for an Arm64 'ins' elem instruction
7863 /*static*/ emitter::code_t emitter::insEncodeVectorIndex2(emitAttr elemsize, ssize_t index2)
7865 code_t bits = (code_t)index2;
7866 if (elemsize == EA_1BYTE)
7870 else if (elemsize == EA_2BYTE)
7874 else if (elemsize == EA_4BYTE)
7880 assert(elemsize == EA_8BYTE);
7883 assert((bits >= 0) && (bits <= 0xf));
7885 return (bits << 11); // bits at locations [14,13,12,11]
7888 /*****************************************************************************
7890 * Returns the encoding to select the 'index' for an Arm64 'mul' by elem instruction
7892 /*static*/ emitter::code_t emitter::insEncodeVectorIndexLMH(emitAttr elemsize, ssize_t index)
7896 if (elemsize == EA_2BYTE)
7898 assert((index >= 0) && (index <= 7));
7901 bits |= (1 << 11); // set bit 11 'H'
7905 bits |= (1 << 21); // set bit 21 'L'
7909 bits |= (1 << 20); // set bit 20 'M'
7912 else if (elemsize == EA_4BYTE)
7914 assert((index >= 0) && (index <= 3));
7917 bits |= (1 << 11); // set bit 11 'H'
7921 bits |= (1 << 21); // set bit 21 'L'
7926 assert(!"Invalid 'elemsize' value");
7932 /*****************************************************************************
7934 * Returns the encoding to shift by 'shift' for an Arm64 vector or scalar instruction
7937 /*static*/ emitter::code_t emitter::insEncodeVectorShift(emitAttr size, ssize_t shift)
7939 assert(shift < getBitWidth(size));
7941 code_t imm = (code_t)(getBitWidth(size) + shift);
7946 /*****************************************************************************
7948 * Returns the encoding to select the 1/2/4/8 byte elemsize for an Arm64 vector instruction
7951 /*static*/ emitter::code_t emitter::insEncodeElemsize(emitAttr size)
7953 if (size == EA_8BYTE)
7955 return 0x00C00000; // set the bit at location 23 and 22
7957 else if (size == EA_4BYTE)
7959 return 0x00800000; // set the bit at location 23
7961 else if (size == EA_2BYTE)
7963 return 0x00400000; // set the bit at location 22
7965 assert(size == EA_1BYTE);
7969 /*****************************************************************************
7971 * Returns the encoding to select the 4/8 byte elemsize for an Arm64 float vector instruction
7974 /*static*/ emitter::code_t emitter::insEncodeFloatElemsize(emitAttr size)
7976 if (size == EA_8BYTE)
7978 return 0x00400000; // set the bit at location 22
7980 assert(size == EA_4BYTE);
7984 // Returns the encoding to select the index for an Arm64 float vector by elem instruction
7985 /*static*/ emitter::code_t emitter::insEncodeFloatIndex(emitAttr elemsize, ssize_t index)
7987 code_t result = 0x00000000;
7988 if (elemsize == EA_8BYTE)
7990 assert((index >= 0) && (index <= 1));
7993 result |= 0x00000800; // 'H' - set the bit at location 11
7998 assert(elemsize == EA_4BYTE);
7999 assert((index >= 0) && (index <= 3));
8002 result |= 0x00000800; // 'H' - set the bit at location 11
8006 result |= 0x00200000; // 'L' - set the bit at location 21
8012 /*****************************************************************************
8014 * Returns the encoding to select the fcvt operation for Arm64 instructions
8016 /*static*/ emitter::code_t emitter::insEncodeConvertOpt(insFormat fmt, insOpts conversion)
8021 case INS_OPTS_S_TO_D: // Single to Double
8022 assert(fmt == IF_DV_2J);
8023 result = 0x00008000; // type=00, opc=01
8026 case INS_OPTS_D_TO_S: // Double to Single
8027 assert(fmt == IF_DV_2J);
8028 result = 0x00400000; // type=01, opc=00
8031 case INS_OPTS_H_TO_S: // Half to Single
8032 assert(fmt == IF_DV_2J);
8033 result = 0x00C00000; // type=11, opc=00
8036 case INS_OPTS_H_TO_D: // Half to Double
8037 assert(fmt == IF_DV_2J);
8038 result = 0x00C08000; // type=11, opc=01
8041 case INS_OPTS_S_TO_H: // Single to Half
8042 assert(fmt == IF_DV_2J);
8043 result = 0x00018000; // type=00, opc=11
8046 case INS_OPTS_D_TO_H: // Double to Half
8047 assert(fmt == IF_DV_2J);
8048 result = 0x00418000; // type=01, opc=11
8051 case INS_OPTS_S_TO_4BYTE: // Single to INT32
8052 assert(fmt == IF_DV_2H);
8053 result = 0x00000000; // sf=0, type=00
8056 case INS_OPTS_D_TO_4BYTE: // Double to INT32
8057 assert(fmt == IF_DV_2H);
8058 result = 0x00400000; // sf=0, type=01
8061 case INS_OPTS_S_TO_8BYTE: // Single to INT64
8062 assert(fmt == IF_DV_2H);
8063 result = 0x80000000; // sf=1, type=00
8066 case INS_OPTS_D_TO_8BYTE: // Double to INT64
8067 assert(fmt == IF_DV_2H);
8068 result = 0x80400000; // sf=1, type=01
8071 case INS_OPTS_4BYTE_TO_S: // INT32 to Single
8072 assert(fmt == IF_DV_2I);
8073 result = 0x00000000; // sf=0, type=00
8076 case INS_OPTS_4BYTE_TO_D: // INT32 to Double
8077 assert(fmt == IF_DV_2I);
8078 result = 0x00400000; // sf=0, type=01
8081 case INS_OPTS_8BYTE_TO_S: // INT64 to Single
8082 assert(fmt == IF_DV_2I);
8083 result = 0x80000000; // sf=1, type=00
8086 case INS_OPTS_8BYTE_TO_D: // INT64 to Double
8087 assert(fmt == IF_DV_2I);
8088 result = 0x80400000; // sf=1, type=01
8092 assert(!"Invalid 'conversion' value");
8098 /*****************************************************************************
8100 * Returns the encoding to have the Rn register be updated Pre/Post indexed
8104 /*static*/ emitter::code_t emitter::insEncodeIndexedOpt(insOpts opt)
8106 assert(emitter::insOptsNone(opt) || emitter::insOptsIndexed(opt));
8108 if (emitter::insOptsIndexed(opt))
8110 if (emitter::insOptsPostIndex(opt))
8112 return 0x00000400; // set the bit at location 10
8116 assert(emitter::insOptsPreIndex(opt));
8117 return 0x00000C00; // set the bit at location 10 and 11
8122 assert(emitter::insOptsNone(opt));
8123 return 0; // bits 10 and 11 are zero
8127 /*****************************************************************************
8129 * Returns the encoding for a ldp/stp instruction to have the Rn register
8130 * be updated Pre/Post indexed or not updated
8133 /*static*/ emitter::code_t emitter::insEncodePairIndexedOpt(instruction ins, insOpts opt)
8135 assert(emitter::insOptsNone(opt) || emitter::insOptsIndexed(opt));
8137 if ((ins == INS_ldnp) || (ins == INS_stnp))
8139 assert(emitter::insOptsNone(opt));
8140 return 0; // bits 23 and 24 are zero
8144 if (emitter::insOptsIndexed(opt))
8146 if (emitter::insOptsPostIndex(opt))
8148 return 0x00800000; // set the bit at location 23
8152 assert(emitter::insOptsPreIndex(opt));
8153 return 0x01800000; // set the bit at location 24 and 23
8158 assert(emitter::insOptsNone(opt));
8159 return 0x01000000; // set the bit at location 24
8164 /*****************************************************************************
8166 * Returns the encoding to apply a Shift Type on the Rm register
8169 /*static*/ emitter::code_t emitter::insEncodeShiftType(insOpts opt)
8171 if (emitter::insOptsNone(opt))
8173 // None implies the we encode LSL (with a zero immediate)
8176 assert(emitter::insOptsAnyShift(opt));
8178 emitter::code_t option = (emitter::code_t)opt - (emitter::code_t)INS_OPTS_LSL;
8179 assert(option <= 3);
8181 return option << 22; // bits 23, 22
8184 /*****************************************************************************
8186 * Returns the encoding to apply a 12 bit left shift to the immediate
8189 /*static*/ emitter::code_t emitter::insEncodeShiftImm12(insOpts opt)
8191 if (emitter::insOptsLSL12(opt))
8193 return 0x00400000; // set the bit at location 22
8198 /*****************************************************************************
8200 * Returns the encoding to have the Rm register use an extend operation
8203 /*static*/ emitter::code_t emitter::insEncodeExtend(insOpts opt)
8205 if (emitter::insOptsNone(opt) || (opt == INS_OPTS_LSL))
8207 // None or LSL implies the we encode UXTX
8208 opt = INS_OPTS_UXTX;
8210 assert(emitter::insOptsAnyExtend(opt));
8212 emitter::code_t option = (emitter::code_t)opt - (emitter::code_t)INS_OPTS_UXTB;
8213 assert(option <= 7);
8215 return option << 13; // bits 15,14,13
8218 /*****************************************************************************
8220 * Returns the encoding to scale the Rm register by {0,1,2,3,4}
8221 * when using an extend operation
8224 /*static*/ emitter::code_t emitter::insEncodeExtendScale(ssize_t imm)
8226 assert((imm >= 0) && (imm <= 4));
8228 return (emitter::code_t)imm << 10; // bits 12,11,10
8231 /*****************************************************************************
8233 * Returns the encoding to have the Rm register be auto scaled by the ld/st size
8236 /*static*/ emitter::code_t emitter::insEncodeReg3Scale(bool isScaled)
8240 return 0x00001000; // set the bit at location 12
8248 BYTE* emitter::emitOutputLoadLabel(BYTE* dst, BYTE* srcAddr, BYTE* dstAddr, instrDescJmp* id)
8250 instruction ins = id->idIns();
8251 insFormat fmt = id->idInsFmt();
8252 regNumber dstReg = id->idReg1();
8255 // adr x, [rel addr] -- compute address: current addr(ip) + rel addr.
8256 assert(ins == INS_adr);
8257 assert(fmt == IF_DI_1E);
8258 ssize_t distVal = (ssize_t)(dstAddr - srcAddr);
8259 dst = emitOutputShortAddress(dst, ins, fmt, distVal, dstReg);
8263 // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8264 assert(fmt == IF_LARGEADR);
8265 ssize_t relPageAddr =
8266 (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8267 dst = emitOutputShortAddress(dst, INS_adrp, IF_DI_1E, relPageAddr, dstReg);
8269 // add x, x, page offs -- compute address = page addr + page offs
8270 ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8271 assert(isValidUimm12(imm12));
8273 emitInsCode(INS_add, IF_DI_2A); // DI_2A X0010001shiiiiii iiiiiinnnnnddddd 1100 0000 imm(i12, sh)
8274 code |= insEncodeDatasize(EA_8BYTE); // X
8275 code |= ((code_t)imm12 << 10); // iiiiiiiiiiii
8276 code |= insEncodeReg_Rd(dstReg); // ddddd
8277 code |= insEncodeReg_Rn(dstReg); // nnnnn
8278 dst += emitOutput_Instr(dst, code);
8283 /*****************************************************************************
8285 * Output a local jump or other instruction with a pc-relative immediate.
8286 * Note that this may be invoked to overwrite an existing jump instruction at 'dst'
8287 * to handle forward branch patching.
8290 BYTE* emitter::emitOutputLJ(insGroup* ig, BYTE* dst, instrDesc* i)
8292 instrDescJmp* id = (instrDescJmp*)i;
8301 // Set default ins/fmt from id.
8302 instruction ins = id->idIns();
8303 insFormat fmt = id->idInsFmt();
8305 bool loadLabel = false;
8306 bool isJump = false;
8307 bool loadConstant = false;
8324 loadConstant = true;
8333 /* Figure out the distance to the target */
8335 srcOffs = emitCurCodeOffs(dst);
8336 srcAddr = emitOffsetToPtr(srcOffs);
8338 if (id->idAddr()->iiaIsJitDataOffset())
8340 assert(loadConstant || loadLabel);
8341 int doff = id->idAddr()->iiaGetJitDataOffset();
8343 ssize_t imm = emitGetInsSC(id);
8344 assert((imm >= 0) && (imm < 0x1000)); // 0x1000 is arbitrary, currently 'imm' is always 0
8346 unsigned dataOffs = (unsigned)(doff + imm);
8347 assert(dataOffs < emitDataSize());
8348 dstAddr = emitDataOffsetToPtr(dataOffs);
8350 regNumber dstReg = id->idReg1();
8351 regNumber addrReg = dstReg; // an integer register to compute long address.
8352 emitAttr opSize = id->idOpSize();
8358 // ldr x/v, [rel addr] -- load constant from current addr(ip) + rel addr.
8359 assert(ins == INS_ldr);
8360 assert(fmt == IF_LS_1A);
8361 distVal = (ssize_t)(dstAddr - srcAddr);
8362 dst = emitOutputShortConstant(dst, ins, fmt, distVal, dstReg, opSize);
8366 // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8367 assert(fmt == IF_LARGELDC);
8368 ssize_t relPageAddr =
8369 (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8370 if (isVectorRegister(dstReg))
8372 // Update addrReg with the reserved integer register
8373 // since we cannot use dstReg (vector) to load constant directly from memory.
8374 addrReg = id->idReg2();
8375 assert(isGeneralRegister(addrReg));
8379 dst = emitOutputShortAddress(dst, ins, fmt, relPageAddr, addrReg);
8381 // ldr x, [x, page offs] -- load constant from page address + page offset into integer register.
8382 ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8383 assert(isValidUimm12(imm12));
8386 dst = emitOutputShortConstant(dst, ins, fmt, imm12, addrReg, opSize);
8388 // fmov v, d -- copy constant in integer register to vector register.
8389 // This is needed only for vector constant.
8390 if (addrReg != dstReg)
8392 // fmov Vd,Rn DV_2I X00111100X100111 000000nnnnnddddd 1E27 0000 Vd,Rn
8393 // (scalar, from general)
8394 assert(isVectorRegister(dstReg) && isGeneralRegister(addrReg));
8397 code_t code = emitInsCode(ins, fmt);
8399 code |= insEncodeReg_Vd(dstReg); // ddddd
8400 code |= insEncodeReg_Rn(addrReg); // nnnnn
8401 if (id->idOpSize() == EA_8BYTE)
8403 code |= 0x80400000; // X ... X
8405 dst += emitOutput_Instr(dst, code);
8412 dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8418 assert(loadLabel || isJump);
8420 if (id->idAddr()->iiaHasInstrCount())
8423 int instrCount = id->idAddr()->iiaGetInstrCount();
8424 unsigned insNum = emitFindInsNum(ig, id);
8427 // Backward branches using instruction count must be within the same instruction group.
8428 assert(insNum + 1 >= (unsigned)(-instrCount));
8430 dstOffs = ig->igOffs + emitFindOffset(ig, (insNum + 1 + instrCount));
8431 dstAddr = emitOffsetToPtr(dstOffs);
8435 dstOffs = id->idAddr()->iiaIGlabel->igOffs;
8436 dstAddr = emitOffsetToPtr(dstOffs);
8439 distVal = (ssize_t)(dstAddr - srcAddr);
8441 if (dstOffs <= srcOffs)
8444 /* This is a backward jump - distance is known at this point */
8446 if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8448 size_t blkOffs = id->idjIG->igOffs;
8450 if (INTERESTING_JUMP_NUM == 0)
8451 printf("[3] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8452 printf("[3] Jump block is at %08X - %02X = %08X\n", blkOffs, emitOffsAdj, blkOffs - emitOffsAdj);
8453 printf("[3] Jump is at %08X - %02X = %08X\n", srcOffs, emitOffsAdj, srcOffs - emitOffsAdj);
8454 printf("[3] Label block is at %08X - %02X = %08X\n", dstOffs, emitOffsAdj, dstOffs - emitOffsAdj);
8460 /* This is a forward jump - distance will be an upper limit */
8462 emitFwdJumps = true;
8464 /* The target offset will be closer by at least 'emitOffsAdj', but only if this
8465 jump doesn't cross the hot-cold boundary. */
8467 if (!emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8469 dstOffs -= emitOffsAdj;
8470 distVal -= emitOffsAdj;
8473 /* Record the location of the jump for later patching */
8475 id->idjOffs = dstOffs;
8477 /* Are we overflowing the id->idjOffs bitfield? */
8478 if (id->idjOffs != dstOffs)
8479 IMPL_LIMITATION("Method is too large");
8482 if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8484 size_t blkOffs = id->idjIG->igOffs;
8486 if (INTERESTING_JUMP_NUM == 0)
8487 printf("[4] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8488 printf("[4] Jump block is at %08X\n", blkOffs);
8489 printf("[4] Jump is at %08X\n", srcOffs);
8490 printf("[4] Label block is at %08X - %02X = %08X\n", dstOffs + emitOffsAdj, emitOffsAdj, dstOffs);
8496 if (0 && emitComp->verbose)
8499 int distValSize = id->idjShort ? 4 : 8;
8500 printf("; %s jump [%08X/%03u] from %0*X to %0*X: dist = %08XH\n", (dstOffs <= srcOffs) ? "Fwd" : "Bwd",
8501 dspPtr(id), id->idDebugOnlyInfo()->idNum, distValSize, srcOffs + sz, distValSize, dstOffs, distVal);
8505 /* For forward jumps, record the address of the distance value */
8506 id->idjTemp.idjAddr = (distVal > 0) ? dst : NULL;
8508 if (emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8510 assert(!id->idjShort);
8511 NYI_ARM64("Relocation Support for long address");
8514 assert(insOptsNone(id->idInsOpt()));
8520 // Short conditional/unconditional jump
8521 assert(!id->idjKeepLong);
8522 assert(emitJumpCrossHotColdBoundary(srcOffs, dstOffs) == false);
8523 assert((fmt == IF_BI_0A) || (fmt == IF_BI_0B) || (fmt == IF_BI_1A) || (fmt == IF_BI_1B));
8527 // Long conditional jump
8528 assert(fmt == IF_LARGEJMP);
8529 // This is a pseudo-instruction format representing a large conditional branch, to allow
8530 // us to get a greater branch target range than we can get by using a straightforward conditional
8531 // branch. It is encoded as a short conditional branch that branches around a long unconditional
8534 // Conceptually, we have:
8538 // The code we emit is:
8540 // b<!cond> L_not // 4 bytes. Note that we reverse the condition.
8541 // b L_target // 4 bytes
8544 // Note that we don't actually insert any blocks: we simply encode "b <!cond> L_not" as a branch with
8545 // the correct offset. Note also that this works for both integer and floating-point conditions, because
8546 // the condition inversion takes ordered/unordered into account, preserving NaN behavior. For example,
8547 // "GT" (greater than) is inverted to "LE" (less than, equal, or unordered).
8549 instruction reverseIns;
8550 insFormat reverseFmt;
8555 reverseIns = INS_cbnz;
8556 reverseFmt = IF_BI_1A;
8559 reverseIns = INS_cbz;
8560 reverseFmt = IF_BI_1A;
8563 reverseIns = INS_tbnz;
8564 reverseFmt = IF_BI_1B;
8567 reverseIns = INS_tbz;
8568 reverseFmt = IF_BI_1B;
8571 reverseIns = emitJumpKindToIns(emitReverseJumpKind(emitInsToJumpKind(ins)));
8572 reverseFmt = IF_BI_0B;
8576 emitOutputShortBranch(dst,
8577 reverseIns, // reverse the conditional instruction
8579 8, /* 8 bytes from start of this large conditional pseudo-instruction to L_not. */
8582 // Now, pretend we've got a normal unconditional branch, and fall through to the code to emit that.
8586 // The distVal was computed based on the beginning of the pseudo-instruction,
8587 // So subtract the size of the conditional branch so that it is relative to the
8588 // unconditional branch.
8592 dst = emitOutputShortBranch(dst, ins, fmt, distVal, id);
8596 dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8602 /*****************************************************************************
8604 * Output a short branch instruction.
8606 BYTE* emitter::emitOutputShortBranch(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, instrDescJmp* id)
8608 code_t code = emitInsCode(ins, fmt);
8610 ssize_t loBits = (distVal & 3);
8611 noway_assert(loBits == 0);
8612 distVal >>= 2; // branch offset encodings are scaled by 4.
8614 if (fmt == IF_BI_0A)
8616 // INS_b or INS_bl_local
8617 noway_assert(isValidSimm26(distVal));
8618 distVal &= 0x3FFFFFFLL;
8621 else if (fmt == IF_BI_0B) // BI_0B 01010100iiiiiiii iiiiiiiiiiiXXXXX simm19:00
8623 // INS_beq, INS_bne, etc...
8624 noway_assert(isValidSimm19(distVal));
8625 distVal &= 0x7FFFFLL;
8626 code |= distVal << 5;
8628 else if (fmt == IF_BI_1A) // BI_1A X.......iiiiiiii iiiiiiiiiiittttt Rt simm19:00
8630 // INS_cbz or INS_cbnz
8631 assert(id != nullptr);
8632 code |= insEncodeDatasize(id->idOpSize()); // X
8633 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
8635 noway_assert(isValidSimm19(distVal));
8636 distVal &= 0x7FFFFLL; // 19 bits
8637 code |= distVal << 5;
8639 else if (fmt == IF_BI_1B) // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
8641 // INS_tbz or INS_tbnz
8642 assert(id != nullptr);
8643 ssize_t imm = emitGetInsSC(id);
8644 assert(isValidImmShift(imm, id->idOpSize()));
8646 if (imm & 0x20) // test bit 32-63 ?
8648 code |= 0x80000000; // B
8650 code |= ((imm & 0x1F) << 19); // bbbbb
8651 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
8653 noway_assert(isValidSimm14(distVal));
8654 distVal &= 0x3FFFLL; // 14 bits
8655 code |= distVal << 5;
8659 assert(!"Unknown fmt for emitOutputShortBranch");
8662 dst += emitOutput_Instr(dst, code);
8667 /*****************************************************************************
8669 * Output a short address instruction.
8671 BYTE* emitter::emitOutputShortAddress(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, regNumber reg)
8673 ssize_t loBits = (distVal & 3);
8676 code_t code = emitInsCode(ins, fmt);
8677 if (fmt == IF_DI_1E) // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
8679 // INS_adr or INS_adrp
8680 code |= insEncodeReg_Rd(reg); // ddddd
8682 noway_assert(isValidSimm19(distVal));
8683 distVal &= 0x7FFFFLL; // 19 bits
8684 code |= distVal << 5;
8685 code |= loBits << 29; // 2 bits
8689 assert(!"Unknown fmt for emitOutputShortAddress");
8692 dst += emitOutput_Instr(dst, code);
8697 /*****************************************************************************
8699 * Output a short constant instruction.
8701 BYTE* emitter::emitOutputShortConstant(
8702 BYTE* dst, instruction ins, insFormat fmt, ssize_t imm, regNumber reg, emitAttr opSize)
8704 code_t code = emitInsCode(ins, fmt);
8706 if (fmt == IF_LS_1A)
8708 // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt simm21
8709 // INS_ldr or INS_ldrsw (PC-Relative)
8711 ssize_t loBits = (imm & 3);
8712 noway_assert(loBits == 0);
8713 ssize_t distVal = imm >>= 2; // load offset encodings are scaled by 4.
8715 noway_assert(isValidSimm19(distVal));
8717 // Is the target a vector register?
8718 if (isVectorRegister(reg))
8720 code |= insEncodeDatasizeVLS(code, opSize); // XX V
8721 code |= insEncodeReg_Vt(reg); // ttttt
8725 assert(isGeneralRegister(reg));
8726 // insEncodeDatasizeLS is not quite right for this case.
8727 // So just specialize it.
8728 if ((ins == INS_ldr) && (opSize == EA_8BYTE))
8730 // set the operation size in bit 30
8734 code |= insEncodeReg_Rt(reg); // ttttt
8737 distVal &= 0x7FFFFLL; // 19 bits
8738 code |= distVal << 5;
8740 else if (fmt == IF_LS_2B)
8742 // ldr Rt,[Xn+pimm12] LS_2B 1X11100101iiiiii iiiiiinnnnnttttt B940 0000 imm(0-4095<<{2,3})
8743 // INS_ldr or INS_ldrsw (PC-Relative)
8744 noway_assert(isValidUimm12(imm));
8745 assert(isGeneralRegister(reg));
8747 if (opSize == EA_8BYTE)
8749 // insEncodeDatasizeLS is not quite right for this case.
8750 // So just specialize it.
8753 // set the operation size in bit 30
8756 // Low 3 bits should be 0 -- 8 byte JIT data should be aligned on 8 byte.
8757 assert((imm & 7) == 0);
8762 assert(opSize == EA_4BYTE);
8763 // Low 2 bits should be 0 -- 4 byte aligned data.
8764 assert((imm & 3) == 0);
8768 code |= insEncodeReg_Rt(reg); // ttttt
8769 code |= insEncodeReg_Rn(reg); // nnnnn
8774 assert(!"Unknown fmt for emitOutputShortConstant");
8777 dst += emitOutput_Instr(dst, code);
8781 /*****************************************************************************
8783 * Output a call instruction.
8786 unsigned emitter::emitOutputCall(insGroup* ig, BYTE* dst, instrDesc* id, code_t code)
8788 const unsigned char callInstrSize = sizeof(code_t); // 4 bytes
8789 regMaskTP gcrefRegs;
8790 regMaskTP byrefRegs;
8792 VARSET_TP GCvars(VarSetOps::UninitVal());
8794 // Is this a "fat" call descriptor?
8795 if (id->idIsLargeCall())
8797 instrDescCGCA* idCall = (instrDescCGCA*)id;
8798 gcrefRegs = idCall->idcGcrefRegs;
8799 byrefRegs = idCall->idcByrefRegs;
8800 VarSetOps::Assign(emitComp, GCvars, idCall->idcGCvars);
8804 assert(!id->idIsLargeDsp());
8805 assert(!id->idIsLargeCns());
8807 gcrefRegs = emitDecodeCallGCregs(id);
8809 VarSetOps::AssignNoCopy(emitComp, GCvars, VarSetOps::MakeEmpty(emitComp));
8812 /* We update the GC info before the call as the variables cannot be
8813 used by the call. Killing variables before the call helps with
8814 boundary conditions if the call is CORINFO_HELP_THROW - see bug 50029.
8815 If we ever track aliased variables (which could be used by the
8816 call), we would have to keep them alive past the call. */
8818 emitUpdateLiveGCvars(GCvars, dst);
8820 // Now output the call instruction and update the 'dst' pointer
8822 unsigned outputInstrSize = emitOutput_Instr(dst, code);
8823 dst += outputInstrSize;
8825 // All call instructions are 4-byte in size on ARM64
8827 assert(outputInstrSize == callInstrSize);
8829 // If the method returns a GC ref, mark INTRET (R0) appropriately.
8830 if (id->idGCref() == GCT_GCREF)
8832 gcrefRegs |= RBM_INTRET;
8834 else if (id->idGCref() == GCT_BYREF)
8836 byrefRegs |= RBM_INTRET;
8839 // If is a multi-register return method is called, mark INTRET_1 (X1) appropriately
8840 if (id->idIsLargeCall())
8842 instrDescCGCA* idCall = (instrDescCGCA*)id;
8843 if (idCall->idSecondGCref() == GCT_GCREF)
8845 gcrefRegs |= RBM_INTRET_1;
8847 else if (idCall->idSecondGCref() == GCT_BYREF)
8849 byrefRegs |= RBM_INTRET_1;
8853 // If the GC register set has changed, report the new set.
8854 if (gcrefRegs != emitThisGCrefRegs)
8856 emitUpdateLiveGCregs(GCT_GCREF, gcrefRegs, dst);
8858 // If the Byref register set has changed, report the new set.
8859 if (byrefRegs != emitThisByrefRegs)
8861 emitUpdateLiveGCregs(GCT_BYREF, byrefRegs, dst);
8864 // Some helper calls may be marked as not requiring GC info to be recorded.
8865 if ((!id->idIsNoGC()))
8867 // On ARM64, as on AMD64, we don't change the stack pointer to push/pop args.
8868 // So we're not really doing a "stack pop" here (note that "args" is 0), but we use this mechanism
8869 // to record the call for GC info purposes. (It might be best to use an alternate call,
8870 // and protect "emitStackPop" under the EMIT_TRACK_STACK_DEPTH preprocessor variable.)
8871 emitStackPop(dst, /*isCall*/ true, callInstrSize, /*args*/ 0);
8873 // Do we need to record a call location for GC purposes?
8875 if (!emitFullGCinfo)
8877 emitRecordGCcall(dst, callInstrSize);
8880 return callInstrSize;
8883 /*****************************************************************************
8885 * Emit a 32-bit Arm64 instruction
8888 /*static*/ unsigned emitter::emitOutput_Instr(BYTE* dst, code_t code)
8890 assert(sizeof(code_t) == 4);
8891 *((code_t*)dst) = code;
8893 return sizeof(code_t);
8896 /*****************************************************************************
8898 * Append the machine code corresponding to the given instruction descriptor
8899 * to the code block at '*dp'; the base of the code block is 'bp', and 'ig'
8900 * is the instruction group that contains the instruction. Updates '*dp' to
8901 * point past the generated code, and returns the size of the instruction
8902 * descriptor in bytes.
8905 size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
8910 size_t sz = emitGetInstrDescSize(id); // TODO-ARM64-Cleanup: on ARM, this is set in each case. why?
8911 instruction ins = id->idIns();
8912 insFormat fmt = id->idInsFmt();
8913 emitAttr size = id->idOpSize();
8914 unsigned char callInstrSize = 0;
8919 bool dspOffs = emitComp->opts.dspGCtbls;
8921 bool dspOffs = !emitComp->opts.disDiffable;
8925 assert(REG_NA == (int)REG_NA);
8927 VARSET_TP GCvars(VarSetOps::UninitVal());
8929 /* What instruction format have we got? */
8944 case IF_BI_0A: // BI_0A ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
8945 case IF_BI_0B: // BI_0B ......iiiiiiiiii iiiiiiiiiii..... simm19:00
8947 assert(id->idGCref() == GCT_NONE);
8948 assert(id->idIsBound());
8949 dst = emitOutputLJ(ig, dst, id);
8950 sz = sizeof(instrDescJmp);
8953 case IF_BI_0C: // BI_0C ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
8954 code = emitInsCode(ins, fmt);
8955 sz = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
8956 dst += emitOutputCall(ig, dst, id, code);
8957 // Always call RecordRelocation so that we wire in a JumpStub when we don't reach
8958 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_BRANCH26);
8961 case IF_BI_1A: // BI_1A ......iiiiiiiiii iiiiiiiiiiittttt Rt simm19:00
8962 assert(insOptsNone(id->idInsOpt()));
8963 assert(id->idIsBound());
8965 dst = emitOutputLJ(ig, dst, id);
8966 sz = sizeof(instrDescJmp);
8969 case IF_BI_1B: // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
8970 assert(insOptsNone(id->idInsOpt()));
8971 assert(id->idIsBound());
8973 dst = emitOutputLJ(ig, dst, id);
8974 sz = sizeof(instrDescJmp);
8977 case IF_BR_1A: // BR_1A ................ ......nnnnn..... Rn
8978 assert(insOptsNone(id->idInsOpt()));
8979 assert((ins == INS_ret) || (ins == INS_br));
8980 code = emitInsCode(ins, fmt);
8981 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
8983 dst += emitOutput_Instr(dst, code);
8986 case IF_BR_1B: // BR_1B ................ ......nnnnn..... Rn
8987 assert(insOptsNone(id->idInsOpt()));
8988 assert((ins == INS_br_tail) || (ins == INS_blr));
8989 code = emitInsCode(ins, fmt);
8990 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
8992 sz = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
8993 dst += emitOutputCall(ig, dst, id, code);
8996 case IF_LS_1A: // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB)
8998 assert(insOptsNone(id->idInsOpt()));
8999 assert(id->idIsBound());
9001 dst = emitOutputLJ(ig, dst, id);
9002 sz = sizeof(instrDescJmp);
9005 case IF_LS_2A: // LS_2A .X.......X...... ......nnnnnttttt Rt Rn
9006 assert(insOptsNone(id->idInsOpt()));
9007 code = emitInsCode(ins, fmt);
9008 // Is the target a vector register?
9009 if (isVectorRegister(id->idReg1()))
9011 code &= 0x3FFFFFFF; // clear the size bits
9012 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9013 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9017 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9018 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9020 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9021 dst += emitOutput_Instr(dst, code);
9024 case IF_LS_2B: // LS_2B .X.......Xiiiiii iiiiiinnnnnttttt Rt Rn imm(0-4095)
9025 assert(insOptsNone(id->idInsOpt()));
9026 imm = emitGetInsSC(id);
9027 assert(isValidUimm12(imm));
9028 code = emitInsCode(ins, fmt);
9029 // Is the target a vector register?
9030 if (isVectorRegister(id->idReg1()))
9032 code &= 0x3FFFFFFF; // clear the size bits
9033 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9034 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9038 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9039 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9041 code |= ((code_t)imm << 10); // iiiiiiiiiiii
9042 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9043 dst += emitOutput_Instr(dst, code);
9046 case IF_LS_2C: // LS_2C .X.......X.iiiii iiiiPPnnnnnttttt Rt Rn imm(-256..+255) no/pre/post inc
9047 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9048 imm = emitGetInsSC(id);
9049 assert((imm >= -256) && (imm <= 255)); // signed 9 bits
9050 imm &= 0x1ff; // force into unsigned 9 bit representation
9051 code = emitInsCode(ins, fmt);
9052 // Is the target a vector register?
9053 if (isVectorRegister(id->idReg1()))
9055 code &= 0x3FFFFFFF; // clear the size bits
9056 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9057 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9061 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9062 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9064 code |= insEncodeIndexedOpt(id->idInsOpt()); // PP
9065 code |= ((code_t)imm << 12); // iiiiiiiii
9066 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9067 dst += emitOutput_Instr(dst, code);
9070 case IF_LS_3A: // LS_3A .X.......X.mmmmm oooS..nnnnnttttt Rt Rn Rm ext(Rm) LSL {}
9071 assert(insOptsLSExtend(id->idInsOpt()));
9072 code = emitInsCode(ins, fmt);
9073 // Is the target a vector register?
9074 if (isVectorRegister(id->idReg1()))
9076 code &= 0x3FFFFFFF; // clear the size bits
9077 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9078 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9082 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9083 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9085 code |= insEncodeExtend(id->idInsOpt()); // ooo
9086 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9087 if (id->idIsLclVar())
9089 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9093 code |= insEncodeReg3Scale(id->idReg3Scaled()); // S
9094 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9096 dst += emitOutput_Instr(dst, code);
9099 case IF_LS_3B: // LS_3B X............... .aaaaannnnnddddd Rd Ra Rn
9100 assert(insOptsNone(id->idInsOpt()));
9101 code = emitInsCode(ins, fmt);
9102 // Is the target a vector register?
9103 if (isVectorRegister(id->idReg1()))
9105 code &= 0x3FFFFFFF; // clear the size bits
9106 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9107 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9108 code |= insEncodeReg_Va(id->idReg2()); // aaaaa
9112 code |= insEncodeDatasize(id->idOpSize()); // X
9113 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9114 code |= insEncodeReg_Ra(id->idReg2()); // aaaaa
9116 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9117 dst += emitOutput_Instr(dst, code);
9120 case IF_LS_3C: // LS_3C X......PP.iiiiii iaaaaannnnnddddd Rd Ra Rn imm(im7,sh)
9121 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9122 imm = emitGetInsSC(id);
9123 assert((imm >= -64) && (imm <= 63)); // signed 7 bits
9124 imm &= 0x7f; // force into unsigned 7 bit representation
9125 code = emitInsCode(ins, fmt);
9126 // Is the target a vector register?
9127 if (isVectorRegister(id->idReg1()))
9129 code &= 0x3FFFFFFF; // clear the size bits
9130 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9131 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9132 code |= insEncodeReg_Va(id->idReg2()); // aaaaa
9136 code |= insEncodeDatasize(id->idOpSize()); // X
9137 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9138 code |= insEncodeReg_Ra(id->idReg2()); // aaaaa
9140 code |= insEncodePairIndexedOpt(ins, id->idInsOpt()); // PP
9141 code |= ((code_t)imm << 15); // iiiiiiiii
9142 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9143 dst += emitOutput_Instr(dst, code);
9146 case IF_LS_3D: // LS_3D .X.......X.mmmmm ......nnnnnttttt Wm Rt Rn
9147 code = emitInsCode(ins, fmt);
9148 // Arm64 store exclusive unpredictable cases
9149 assert(id->idReg1() != id->idReg2());
9150 assert(id->idReg1() != id->idReg3());
9151 code |= insEncodeDatasizeLS(code, id->idOpSize()); // X
9152 code |= insEncodeReg_Rm(id->idReg1()); // mmmmm
9153 code |= insEncodeReg_Rt(id->idReg2()); // ttttt
9154 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9155 dst += emitOutput_Instr(dst, code);
9158 case IF_DI_1A: // DI_1A X.......shiiiiii iiiiiinnnnn..... Rn imm(i12,sh)
9159 assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9160 imm = emitGetInsSC(id);
9161 assert(isValidUimm12(imm));
9162 code = emitInsCode(ins, fmt);
9163 code |= insEncodeDatasize(id->idOpSize()); // X
9164 code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9165 code |= ((code_t)imm << 10); // iiiiiiiiiiii
9166 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9167 dst += emitOutput_Instr(dst, code);
9170 case IF_DI_1B: // DI_1B X........hwiiiii iiiiiiiiiiiddddd Rd imm(i16,hw)
9171 imm = emitGetInsSC(id);
9172 assert(isValidImmHWVal(imm, id->idOpSize()));
9173 code = emitInsCode(ins, fmt);
9174 code |= insEncodeDatasize(id->idOpSize()); // X
9175 code |= ((code_t)imm << 5); // hwiiiii iiiiiiiiiii
9176 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9177 dst += emitOutput_Instr(dst, code);
9180 case IF_DI_1C: // DI_1C X........Nrrrrrr ssssssnnnnn..... Rn imm(N,r,s)
9181 imm = emitGetInsSC(id);
9182 assert(isValidImmNRS(imm, id->idOpSize()));
9183 code = emitInsCode(ins, fmt);
9184 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9185 code |= insEncodeDatasize(id->idOpSize()); // X
9186 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9187 dst += emitOutput_Instr(dst, code);
9190 case IF_DI_1D: // DI_1D X........Nrrrrrr ssssss.....ddddd Rd imm(N,r,s)
9191 imm = emitGetInsSC(id);
9192 assert(isValidImmNRS(imm, id->idOpSize()));
9193 code = emitInsCode(ins, fmt);
9194 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9195 code |= insEncodeDatasize(id->idOpSize()); // X
9196 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9197 dst += emitOutput_Instr(dst, code);
9200 case IF_DI_1E: // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
9202 assert(insOptsNone(id->idInsOpt()));
9203 if (id->idIsReloc())
9205 code = emitInsCode(ins, fmt);
9206 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9207 dst += emitOutput_Instr(dst, code);
9208 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEBASE_REL21);
9212 // Local jmp/load case which does not need a relocation.
9213 assert(id->idIsBound());
9214 dst = emitOutputLJ(ig, dst, id);
9216 sz = sizeof(instrDescJmp);
9219 case IF_DI_1F: // DI_1F X..........iiiii cccc..nnnnn.nzcv Rn imm5 nzcv cond
9220 imm = emitGetInsSC(id);
9221 assert(isValidImmCondFlagsImm5(imm));
9224 cfi.immCFVal = (unsigned)imm;
9225 code = emitInsCode(ins, fmt);
9226 code |= insEncodeDatasize(id->idOpSize()); // X
9227 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9228 code |= ((code_t)cfi.imm5 << 16); // iiiii
9229 code |= insEncodeFlags(cfi.flags); // nzcv
9230 code |= insEncodeCond(cfi.cond); // cccc
9231 dst += emitOutput_Instr(dst, code);
9235 case IF_DI_2A: // DI_2A X.......shiiiiii iiiiiinnnnnddddd Rd Rn imm(i12,sh)
9236 assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9237 imm = emitGetInsSC(id);
9238 assert(isValidUimm12(imm));
9239 code = emitInsCode(ins, fmt);
9240 code |= insEncodeDatasize(id->idOpSize()); // X
9241 code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9242 code |= ((code_t)imm << 10); // iiiiiiiiiiii
9243 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9244 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9245 dst += emitOutput_Instr(dst, code);
9247 if (id->idIsReloc())
9249 assert(sz == sizeof(instrDesc));
9250 assert(id->idAddr()->iiaAddr != nullptr);
9251 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEOFFSET_12A);
9255 case IF_DI_2B: // DI_2B X.........Xnnnnn ssssssnnnnnddddd Rd Rn imm(0-63)
9256 code = emitInsCode(ins, fmt);
9257 imm = emitGetInsSC(id);
9258 assert(isValidImmShift(imm, id->idOpSize()));
9259 code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9260 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9261 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9262 code |= insEncodeReg_Rm(id->idReg2()); // Reg2 also in mmmmm
9263 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9264 dst += emitOutput_Instr(dst, code);
9267 case IF_DI_2C: // DI_2C X........Nrrrrrr ssssssnnnnnddddd Rd Rn imm(N,r,s)
9268 imm = emitGetInsSC(id);
9269 assert(isValidImmNRS(imm, id->idOpSize()));
9270 code = emitInsCode(ins, fmt);
9271 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9272 code |= insEncodeDatasize(id->idOpSize()); // X
9273 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9274 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9275 dst += emitOutput_Instr(dst, code);
9278 case IF_DI_2D: // DI_2D X........Nrrrrrr ssssssnnnnnddddd Rd Rn imr, imms (N,r,s)
9279 if (ins == INS_asr || ins == INS_lsl || ins == INS_lsr)
9281 imm = emitGetInsSC(id);
9282 assert(isValidImmShift(imm, id->idOpSize()));
9284 // Shift immediates are aliases of the SBFM/UBFM instructions
9285 // that actually take 2 registers and 2 constants,
9286 // Since we stored the shift immediate value
9287 // we need to calculate the N,R and S values here.
9292 bmi.immN = (size == EA_8BYTE) ? 1 : 0;
9294 bmi.immS = (size == EA_8BYTE) ? 0x3f : 0x1f;
9296 // immR and immS are now set correctly for INS_asr and INS_lsr
9297 // but for INS_lsl we have to adjust the values for immR and immS
9301 bmi.immR = -imm & bmi.immS;
9302 bmi.immS = bmi.immS - imm;
9305 // setup imm with the proper 13 bit value N:R:S
9311 // The other instructions have already have encoded N,R and S values
9312 imm = emitGetInsSC(id);
9314 assert(isValidImmNRS(imm, id->idOpSize()));
9316 code = emitInsCode(ins, fmt);
9317 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9318 code |= insEncodeDatasize(id->idOpSize()); // X
9319 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9320 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9321 dst += emitOutput_Instr(dst, code);
9324 case IF_DR_1D: // DR_1D X............... cccc.......ddddd Rd cond
9325 imm = emitGetInsSC(id);
9326 assert(isValidImmCond(imm));
9329 cfi.immCFVal = (unsigned)imm;
9330 code = emitInsCode(ins, fmt);
9331 code |= insEncodeDatasize(id->idOpSize()); // X
9332 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9333 code |= insEncodeInvertedCond(cfi.cond); // cccc
9334 dst += emitOutput_Instr(dst, code);
9338 case IF_DR_2A: // DR_2A X..........mmmmm ......nnnnn..... Rn Rm
9339 assert(insOptsNone(id->idInsOpt()));
9340 code = emitInsCode(ins, fmt);
9341 code |= insEncodeDatasize(id->idOpSize()); // X
9342 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9343 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9344 dst += emitOutput_Instr(dst, code);
9347 case IF_DR_2B: // DR_2B X.......sh.mmmmm ssssssnnnnn..... Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
9348 code = emitInsCode(ins, fmt);
9349 imm = emitGetInsSC(id);
9350 assert(isValidImmShift(imm, id->idOpSize()));
9351 code |= insEncodeDatasize(id->idOpSize()); // X
9352 code |= insEncodeShiftType(id->idInsOpt()); // sh
9353 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9354 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9355 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9356 dst += emitOutput_Instr(dst, code);
9359 case IF_DR_2C: // DR_2C X..........mmmmm ooosssnnnnn..... Rn Rm ext(Rm) LSL imm(0-4)
9360 code = emitInsCode(ins, fmt);
9361 imm = emitGetInsSC(id);
9362 assert((imm >= 0) && (imm <= 4)); // imm [0..4]
9363 code |= insEncodeDatasize(id->idOpSize()); // X
9364 code |= insEncodeExtend(id->idInsOpt()); // ooo
9365 code |= insEncodeExtendScale(imm); // sss
9366 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9367 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9368 dst += emitOutput_Instr(dst, code);
9371 case IF_DR_2D: // DR_2D X..........nnnnn cccc..nnnnnddddd Rd Rn cond
9372 imm = emitGetInsSC(id);
9373 assert(isValidImmCond(imm));
9376 cfi.immCFVal = (unsigned)imm;
9377 code = emitInsCode(ins, fmt);
9378 code |= insEncodeDatasize(id->idOpSize()); // X
9379 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9380 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9381 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9382 code |= insEncodeInvertedCond(cfi.cond); // cccc
9383 dst += emitOutput_Instr(dst, code);
9387 case IF_DR_2E: // DR_2E X..........mmmmm ...........ddddd Rd Rm
9388 code = emitInsCode(ins, fmt);
9389 code |= insEncodeDatasize(id->idOpSize()); // X
9390 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9391 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9392 dst += emitOutput_Instr(dst, code);
9395 case IF_DR_2F: // DR_2F X.......sh.mmmmm ssssss.....ddddd Rd Rm {LSL,LSR,ASR} imm(0-63)
9396 code = emitInsCode(ins, fmt);
9397 imm = emitGetInsSC(id);
9398 assert(isValidImmShift(imm, id->idOpSize()));
9399 code |= insEncodeDatasize(id->idOpSize()); // X
9400 code |= insEncodeShiftType(id->idInsOpt()); // sh
9401 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9402 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9403 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9404 dst += emitOutput_Instr(dst, code);
9407 case IF_DR_2G: // DR_2G X............... .....xnnnnnddddd Rd Rn
9408 code = emitInsCode(ins, fmt);
9409 code |= insEncodeDatasize(id->idOpSize()); // X
9412 if (size == EA_8BYTE)
9414 code |= 0x00000400; // x - bit at location 10
9417 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9418 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9419 dst += emitOutput_Instr(dst, code);
9422 case IF_DR_2H: // DR_2H X........X...... ......nnnnnddddd Rd Rn
9423 code = emitInsCode(ins, fmt);
9424 code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9425 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9426 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9427 dst += emitOutput_Instr(dst, code);
9430 case IF_DR_2I: // DR_2I X..........mmmmm cccc..nnnnn.nzcv Rn Rm nzcv cond
9431 imm = emitGetInsSC(id);
9432 assert(isValidImmCondFlags(imm));
9435 cfi.immCFVal = (unsigned)imm;
9436 code = emitInsCode(ins, fmt);
9437 code |= insEncodeDatasize(id->idOpSize()); // X
9438 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9439 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9440 code |= insEncodeFlags(cfi.flags); // nzcv
9441 code |= insEncodeCond(cfi.cond); // cccc
9442 dst += emitOutput_Instr(dst, code);
9446 case IF_DR_3A: // DR_3A X..........mmmmm ......nnnnnmmmmm Rd Rn Rm
9447 code = emitInsCode(ins, fmt);
9448 code |= insEncodeDatasize(id->idOpSize()); // X
9449 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9450 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9451 if (id->idIsLclVar())
9453 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9457 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9459 dst += emitOutput_Instr(dst, code);
9462 case IF_DR_3B: // DR_3B X.......sh.mmmmm ssssssnnnnnddddd Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
9463 code = emitInsCode(ins, fmt);
9464 imm = emitGetInsSC(id);
9465 assert(isValidImmShift(imm, id->idOpSize()));
9466 code |= insEncodeDatasize(id->idOpSize()); // X
9467 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9468 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9469 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9470 code |= insEncodeShiftType(id->idInsOpt()); // sh
9471 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9472 dst += emitOutput_Instr(dst, code);
9475 case IF_DR_3C: // DR_3C X..........mmmmm ooosssnnnnnddddd Rd Rn Rm ext(Rm) LSL imm(0-4)
9476 code = emitInsCode(ins, fmt);
9477 imm = emitGetInsSC(id);
9478 assert((imm >= 0) && (imm <= 4)); // imm [0..4]
9479 code |= insEncodeDatasize(id->idOpSize()); // X
9480 code |= insEncodeExtend(id->idInsOpt()); // ooo
9481 code |= insEncodeExtendScale(imm); // sss
9482 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9483 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9484 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9485 dst += emitOutput_Instr(dst, code);
9488 case IF_DR_3D: // DR_3D X..........mmmmm cccc..nnnnnddddd Rd Rn Rm cond
9489 imm = emitGetInsSC(id);
9490 assert(isValidImmCond(imm));
9493 cfi.immCFVal = (unsigned)imm;
9494 code = emitInsCode(ins, fmt);
9495 code |= insEncodeDatasize(id->idOpSize()); // X
9496 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9497 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9498 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9499 code |= insEncodeCond(cfi.cond); // cccc
9500 dst += emitOutput_Instr(dst, code);
9504 case IF_DR_3E: // DR_3E X........X.mmmmm ssssssnnnnnddddd Rd Rn Rm imm(0-63)
9505 code = emitInsCode(ins, fmt);
9506 imm = emitGetInsSC(id);
9507 assert(isValidImmShift(imm, id->idOpSize()));
9508 code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9509 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9510 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9511 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9512 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9513 dst += emitOutput_Instr(dst, code);
9516 case IF_DR_4A: // DR_4A X..........mmmmm .aaaaannnnnmmmmm Rd Rn Rm Ra
9517 code = emitInsCode(ins, fmt);
9518 code |= insEncodeDatasize(id->idOpSize()); // X
9519 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9520 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9521 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9522 code |= insEncodeReg_Ra(id->idReg4()); // aaaaa
9523 dst += emitOutput_Instr(dst, code);
9526 case IF_DV_1A: // DV_1A .........X.iiiii iii........ddddd Vd imm8 (fmov - immediate scalar)
9527 imm = emitGetInsSC(id);
9528 elemsize = id->idOpSize();
9529 code = emitInsCode(ins, fmt);
9530 code |= insEncodeFloatElemsize(elemsize); // X
9531 code |= ((code_t)imm << 13); // iiiii iii
9532 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9533 dst += emitOutput_Instr(dst, code);
9536 case IF_DV_1B: // DV_1B .QX..........iii cmod..iiiiiddddd Vd imm8 (immediate vector)
9537 imm = emitGetInsSC(id) & 0x0ff;
9538 immShift = (emitGetInsSC(id) & 0x700) >> 8;
9539 elemsize = optGetElemsize(id->idInsOpt());
9544 cmode = 0xE; // 1110
9548 cmode |= (immShift << 1); // 10x0
9554 cmode |= (immShift << 1); // 0xx0
9564 cmode = 0xE; // 1110
9571 code = emitInsCode(ins, fmt);
9572 code |= insEncodeVectorsize(id->idOpSize()); // Q
9573 if ((ins == INS_fmov) || (ins == INS_movi))
9575 if (elemsize == EA_8BYTE)
9577 code |= 0x20000000; // X
9580 if (ins != INS_fmov)
9582 assert((cmode >= 0) && (cmode <= 0xF));
9583 code |= (cmode << 12); // cmod
9585 code |= (((code_t)imm >> 5) << 16); // iii
9586 code |= (((code_t)imm & 0x1f) << 5); // iiiii
9587 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9588 dst += emitOutput_Instr(dst, code);
9591 case IF_DV_1C: // DV_1C .........X...... ......nnnnn..... Vn #0.0 (fcmp - with zero)
9592 elemsize = id->idOpSize();
9593 code = emitInsCode(ins, fmt);
9594 code |= insEncodeFloatElemsize(elemsize); // X
9595 code |= insEncodeReg_Vn(id->idReg1()); // nnnnn
9596 dst += emitOutput_Instr(dst, code);
9599 case IF_DV_2A: // DV_2A .Q.......X...... ......nnnnnddddd Vd Vn (fabs, fcvt - vector)
9600 elemsize = optGetElemsize(id->idInsOpt());
9601 code = emitInsCode(ins, fmt);
9602 code |= insEncodeVectorsize(id->idOpSize()); // Q
9603 code |= insEncodeFloatElemsize(elemsize); // X
9604 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9605 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9606 dst += emitOutput_Instr(dst, code);
9609 case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov/smov - to general)
9610 elemsize = id->idOpSize();
9611 index = emitGetInsSC(id);
9612 datasize = (elemsize == EA_8BYTE) ? EA_16BYTE : EA_8BYTE;
9613 if (ins == INS_smov)
9615 datasize = EA_16BYTE;
9617 code = emitInsCode(ins, fmt);
9618 code |= insEncodeVectorsize(datasize); // Q
9619 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9620 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9621 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9622 dst += emitOutput_Instr(dst, code);
9625 case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
9628 datasize = id->idOpSize();
9629 elemsize = optGetElemsize(id->idInsOpt());
9634 datasize = EA_16BYTE;
9635 elemsize = id->idOpSize();
9636 index = emitGetInsSC(id);
9638 code = emitInsCode(ins, fmt);
9639 code |= insEncodeVectorsize(datasize); // Q
9640 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9641 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9642 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9643 dst += emitOutput_Instr(dst, code);
9646 case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
9647 index = emitGetInsSC(id);
9648 elemsize = optGetElemsize(id->idInsOpt());
9649 code = emitInsCode(ins, fmt);
9650 code |= insEncodeVectorsize(id->idOpSize()); // Q
9651 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9652 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9653 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9654 dst += emitOutput_Instr(dst, code);
9657 case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
9658 index = emitGetInsSC(id);
9659 elemsize = id->idOpSize();
9660 code = emitInsCode(ins, fmt);
9661 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9662 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9663 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9664 dst += emitOutput_Instr(dst, code);
9667 case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
9668 elemsize = id->idOpSize();
9669 imm = emitGetInsSC(id);
9670 index = (imm >> 4) & 0xf;
9672 code = emitInsCode(ins, fmt);
9673 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9674 code |= insEncodeVectorIndex2(elemsize, index2); // jjjj
9675 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9676 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9677 dst += emitOutput_Instr(dst, code);
9680 case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov,fcvtXX - register)
9681 elemsize = id->idOpSize();
9682 code = emitInsCode(ins, fmt);
9683 code |= insEncodeFloatElemsize(elemsize); // X
9684 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9685 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9686 dst += emitOutput_Instr(dst, code);
9689 case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov - to general)
9690 elemsize = id->idOpSize();
9691 code = emitInsCode(ins, fmt);
9692 code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X X
9693 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9694 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9695 dst += emitOutput_Instr(dst, code);
9698 case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov - from general)
9699 elemsize = id->idOpSize();
9700 code = emitInsCode(ins, fmt);
9701 code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X X
9702 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9703 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9704 dst += emitOutput_Instr(dst, code);
9707 case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
9708 code = emitInsCode(ins, fmt);
9709 code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // SS DD
9710 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9711 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9712 dst += emitOutput_Instr(dst, code);
9715 case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
9716 elemsize = id->idOpSize();
9717 code = emitInsCode(ins, fmt);
9718 code |= insEncodeFloatElemsize(elemsize); // X
9719 code |= insEncodeReg_Vn(id->idReg1()); // nnnnn
9720 code |= insEncodeReg_Vm(id->idReg2()); // mmmmm
9721 dst += emitOutput_Instr(dst, code);
9724 case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
9725 elemsize = id->idOpSize();
9726 code = emitInsCode(ins, fmt);
9727 code |= insEncodeElemsize(elemsize); // XX
9728 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9729 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9730 dst += emitOutput_Instr(dst, code);
9733 case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
9734 elemsize = optGetElemsize(id->idInsOpt());
9735 code = emitInsCode(ins, fmt);
9736 code |= insEncodeVectorsize(id->idOpSize()); // Q
9737 code |= insEncodeElemsize(elemsize); // XX
9738 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9739 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9740 dst += emitOutput_Instr(dst, code);
9743 case IF_DV_2N: // DV_2N .........iiiiiii ......nnnnnddddd Vd Vn imm (shift - scalar)
9744 imm = emitGetInsSC(id);
9745 code = emitInsCode(ins, fmt);
9746 code |= insEncodeVectorShift(EA_8BYTE, imm); // iiiiiii
9747 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9748 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9749 dst += emitOutput_Instr(dst, code);
9752 case IF_DV_2O: // DV_2O .Q.......iiiiiii ......nnnnnddddd Vd Vn imm (shift - vector)
9753 imm = emitGetInsSC(id);
9754 elemsize = optGetElemsize(id->idInsOpt());
9755 code = emitInsCode(ins, fmt);
9756 code |= insEncodeVectorsize(id->idOpSize()); // Q
9757 code |= insEncodeVectorShift(elemsize, imm); // iiiiiii
9758 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9759 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9760 dst += emitOutput_Instr(dst, code);
9763 case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
9764 code = emitInsCode(ins, fmt);
9765 elemsize = optGetElemsize(id->idInsOpt());
9766 code |= insEncodeVectorsize(id->idOpSize()); // Q
9767 code |= insEncodeElemsize(elemsize); // XX
9768 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9769 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9770 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9771 dst += emitOutput_Instr(dst, code);
9774 case IF_DV_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector)
9775 code = emitInsCode(ins, fmt);
9776 imm = emitGetInsSC(id);
9777 elemsize = optGetElemsize(id->idInsOpt());
9778 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
9779 code |= insEncodeVectorsize(id->idOpSize()); // Q
9780 code |= insEncodeElemsize(elemsize); // XX
9781 code |= insEncodeVectorIndexLMH(elemsize, imm); // LM H
9782 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9783 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9784 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9785 dst += emitOutput_Instr(dst, code);
9788 case IF_DV_3B: // DV_3B .Q.......X.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
9789 code = emitInsCode(ins, fmt);
9790 elemsize = optGetElemsize(id->idInsOpt());
9791 code |= insEncodeVectorsize(id->idOpSize()); // Q
9792 code |= insEncodeFloatElemsize(elemsize); // X
9793 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9794 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9795 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9796 dst += emitOutput_Instr(dst, code);
9799 case IF_DV_3BI: // DV_3BI .Q.......XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
9800 code = emitInsCode(ins, fmt);
9801 imm = emitGetInsSC(id);
9802 elemsize = optGetElemsize(id->idInsOpt());
9803 assert(isValidVectorIndex(id->idOpSize(), elemsize, imm));
9804 code |= insEncodeVectorsize(id->idOpSize()); // Q
9805 code |= insEncodeFloatElemsize(elemsize); // X
9806 code |= insEncodeFloatIndex(elemsize, imm); // L H
9807 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9808 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9809 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9810 dst += emitOutput_Instr(dst, code);
9813 case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
9814 code = emitInsCode(ins, fmt);
9815 code |= insEncodeVectorsize(id->idOpSize()); // Q
9816 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9817 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9818 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9819 dst += emitOutput_Instr(dst, code);
9822 case IF_DV_3D: // DV_3D .........X.mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
9823 code = emitInsCode(ins, fmt);
9824 code |= insEncodeFloatElemsize(id->idOpSize()); // X
9825 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9826 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9827 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9828 dst += emitOutput_Instr(dst, code);
9831 case IF_DV_3DI: // DV_3DI .........XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (scalar by elem)
9832 code = emitInsCode(ins, fmt);
9833 imm = emitGetInsSC(id);
9834 elemsize = id->idOpSize();
9835 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
9836 code |= insEncodeFloatElemsize(elemsize); // X
9837 code |= insEncodeFloatIndex(elemsize, imm); // L H
9838 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9839 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9840 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9841 dst += emitOutput_Instr(dst, code);
9844 case IF_DV_3E: // DV_3E ...........mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
9845 code = emitInsCode(ins, fmt);
9846 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9847 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9848 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9849 dst += emitOutput_Instr(dst, code);
9852 case IF_DV_4A: // DV_4A .........X.mmmmm .aaaaannnnnddddd Vd Va Vn Vm (scalar)
9853 code = emitInsCode(ins, fmt);
9854 elemsize = id->idOpSize();
9855 code |= insEncodeFloatElemsize(elemsize); // X
9856 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9857 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9858 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9859 code |= insEncodeReg_Va(id->idReg4()); // aaaaa
9860 dst += emitOutput_Instr(dst, code);
9863 case IF_SN_0A: // SN_0A ................ ................
9864 code = emitInsCode(ins, fmt);
9865 dst += emitOutput_Instr(dst, code);
9868 case IF_SI_0A: // SI_0A ...........iiiii iiiiiiiiiii..... imm16
9869 imm = emitGetInsSC(id);
9870 assert(isValidUimm16(imm));
9871 code = emitInsCode(ins, fmt);
9872 code |= ((code_t)imm << 5); // iiiii iiiiiiiiiii
9873 dst += emitOutput_Instr(dst, code);
9876 case IF_SI_0B: // SI_0B ................ ....bbbb........ imm4 - barrier
9877 imm = emitGetInsSC(id);
9878 assert((imm >= 0) && (imm <= 15));
9879 code = emitInsCode(ins, fmt);
9880 code |= ((code_t)imm << 8); // bbbb
9881 dst += emitOutput_Instr(dst, code);
9885 assert(!"Unexpected format");
9889 // Determine if any registers now hold GC refs, or whether a register that was overwritten held a GC ref.
9890 // We assume here that "id->idGCref()" is not GC_NONE only if the instruction described by "id" writes a
9891 // GC ref to register "id->idReg1()". (It may, apparently, also not be GC_NONE in other cases, such as
9892 // for stores, but we ignore those cases here.)
9893 if (emitInsMayWriteToGCReg(id)) // True if "id->idIns()" writes to a register than can hold GC ref.
9895 // We assume that "idReg1" is the primary destination register for all instructions
9896 if (id->idGCref() != GCT_NONE)
9898 emitGCregLiveUpd(id->idGCref(), id->idReg1(), dst);
9902 emitGCregDeadUpd(id->idReg1(), dst);
9905 if (emitInsMayWriteMultipleRegs(id))
9908 // "idReg2" is the secondary destination register
9909 if (id->idGCrefReg2() != GCT_NONE)
9911 emitGCregLiveUpd(id->idGCrefReg2(), id->idReg2(), dst);
9915 emitGCregDeadUpd(id->idReg2(), dst);
9920 // Now we determine if the instruction has written to a (local variable) stack location, and either written a GC
9921 // ref or overwritten one.
9922 if (emitInsWritesToLclVarStackLoc(id) || emitInsWritesToLclVarStackLocPair(id))
9924 int varNum = id->idAddr()->iiaLclVar.lvaVarNum();
9925 unsigned ofs = AlignDown(id->idAddr()->iiaLclVar.lvaOffset(), sizeof(size_t));
9927 int adr = emitComp->lvaFrameAddress(varNum, &FPbased);
9928 if (id->idGCref() != GCT_NONE)
9930 emitGCvarLiveUpd(adr + ofs, varNum, id->idGCref(), dst);
9934 // If the type of the local is a gc ref type, update the liveness.
9938 // "Regular" (non-spill-temp) local.
9939 vt = var_types(emitComp->lvaTable[varNum].lvType);
9943 TempDsc* tmpDsc = emitComp->tmpFindNum(varNum);
9944 vt = tmpDsc->tdTempType();
9946 if (vt == TYP_REF || vt == TYP_BYREF)
9947 emitGCvarDeadUpd(adr + ofs, dst);
9949 if (emitInsWritesToLclVarStackLocPair(id))
9951 unsigned ofs2 = ofs + sizeof(size_t);
9952 if (id->idGCrefReg2() != GCT_NONE)
9954 emitGCvarLiveUpd(adr + ofs2, varNum, id->idGCrefReg2(), dst);
9958 // If the type of the local is a gc ref type, update the liveness.
9962 // "Regular" (non-spill-temp) local.
9963 vt = var_types(emitComp->lvaTable[varNum].lvType);
9967 TempDsc* tmpDsc = emitComp->tmpFindNum(varNum);
9968 vt = tmpDsc->tdTempType();
9970 if (vt == TYP_REF || vt == TYP_BYREF)
9971 emitGCvarDeadUpd(adr + ofs2, dst);
9977 /* Make sure we set the instruction descriptor size correctly */
9979 size_t expected = emitSizeOfInsDsc(id);
9980 assert(sz == expected);
9982 if (emitComp->opts.disAsm || emitComp->opts.dspEmit || emitComp->verbose)
9984 emitDispIns(id, false, dspOffs, true, emitCurCodeOffs(odst), *dp, (dst - *dp), ig);
9987 if (emitComp->compDebugBreak)
9989 // For example, set JitBreakEmitOutputInstr=a6 will break when this method is called for
9990 // emitting instruction a6, (i.e. IN00a6 in jitdump).
9991 if ((unsigned)JitConfig.JitBreakEmitOutputInstr() == id->idDebugOnlyInfo()->idNum)
9993 assert(!"JitBreakEmitOutputInstr reached");
9998 /* All instructions are expected to generate code */
10000 assert(*dp != dst);
10007 /*****************************************************************************/
10008 /*****************************************************************************/
10012 /*****************************************************************************
10014 * Display the instruction name
10016 void emitter::emitDispInst(instruction ins)
10018 const char* insstr = codeGen->genInsName(ins);
10019 size_t len = strlen(insstr);
10021 /* Display the instruction name */
10023 printf("%s", insstr);
10026 // Add at least one space after the instruction name
10027 // and add spaces until we have reach the normal size of 8
10035 /*****************************************************************************
10037 * Display an reloc value
10038 * If we are formatting for an assembly listing don't print the hex value
10039 * since it will prevent us from doing assembly diffs
10041 void emitter::emitDispReloc(int value, bool addComma)
10043 if (emitComp->opts.disAsm)
10049 printf("(reloc 0x%x)", dspPtr(value));
10056 /*****************************************************************************
10058 * Display an immediate value
10060 void emitter::emitDispImm(ssize_t imm, bool addComma, bool alwaysHex /* =false */)
10067 // Munge any pointers if we want diff-able disassembly
10068 if (emitComp->opts.disDiffable)
10070 ssize_t top44bits = (imm >> 20);
10071 if ((top44bits != 0) && (top44bits != -1))
10075 if (!alwaysHex && (imm > -1000) && (imm < 1000))
10081 if ((imm < 0) && ((imm & 0xFFFFFFFF00000000LL) == 0xFFFFFFFF00000000LL))
10087 if ((imm & 0xFFFFFFFF00000000LL) != 0)
10089 printf("0x%llx", imm);
10093 printf("0x%02x", imm);
10101 /*****************************************************************************
10103 * Display a float zero constant
10105 void emitter::emitDispFloatZero()
10114 /*****************************************************************************
10116 * Display an encoded float constant value
10118 void emitter::emitDispFloatImm(ssize_t imm8)
10120 assert((0 <= imm8) && (imm8 <= 0x0ff));
10127 fpImm.immFPIVal = (unsigned)imm8;
10128 double result = emitDecodeFloatImm8(fpImm);
10130 printf("%.4f", result);
10133 /*****************************************************************************
10135 * Display an immediate that is optionally LSL12.
10137 void emitter::emitDispImmOptsLSL12(ssize_t imm, insOpts opt)
10139 if (!strictArmAsm && insOptsLSL12(opt))
10143 emitDispImm(imm, false);
10144 if (strictArmAsm && insOptsLSL12(opt))
10146 printf(", LSL #12");
10150 /*****************************************************************************
10152 * Display an ARM64 condition code for the conditional instructions
10154 void emitter::emitDispCond(insCond cond)
10156 const static char* armCond[16] = {"eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc",
10157 "hi", "ls", "ge", "lt", "gt", "le", "AL", "NV"}; // The last two are invalid
10158 unsigned imm = (unsigned)cond;
10159 assert((0 <= imm) && (imm < ArrLen(armCond)));
10160 printf(armCond[imm]);
10163 /*****************************************************************************
10165 * Display an ARM64 flags for the conditional instructions
10167 void emitter::emitDispFlags(insCflags flags)
10169 const static char* armFlags[16] = {"0", "v", "c", "cv", "z", "zv", "zc", "zcv",
10170 "n", "nv", "nc", "ncv", "nz", "nzv", "nzc", "nzcv"};
10171 unsigned imm = (unsigned)flags;
10172 assert((0 <= imm) && (imm < ArrLen(armFlags)));
10173 printf(armFlags[imm]);
10176 /*****************************************************************************
10178 * Display an ARM64 'barrier' for the memory barrier instructions
10180 void emitter::emitDispBarrier(insBarrier barrier)
10182 const static char* armBarriers[16] = {"#0", "oshld", "oshst", "osh", "#4", "nshld", "nshst", "nsh",
10183 "#8", "ishld", "ishst", "ish", "#12", "ld", "st", "sy"};
10184 unsigned imm = (unsigned)barrier;
10185 assert((0 <= imm) && (imm < ArrLen(armBarriers)));
10186 printf(armBarriers[imm]);
10189 /*****************************************************************************
10191 * Prints the encoding for the Shift Type encoding
10194 void emitter::emitDispShiftOpts(insOpts opt)
10196 if (opt == INS_OPTS_LSL)
10198 else if (opt == INS_OPTS_LSR)
10200 else if (opt == INS_OPTS_ASR)
10202 else if (opt == INS_OPTS_ROR)
10204 else if (opt == INS_OPTS_MSL)
10207 assert(!"Bad value");
10210 /*****************************************************************************
10212 * Prints the encoding for the Extend Type encoding
10215 void emitter::emitDispExtendOpts(insOpts opt)
10217 if (opt == INS_OPTS_UXTB)
10219 else if (opt == INS_OPTS_UXTH)
10221 else if (opt == INS_OPTS_UXTW)
10223 else if (opt == INS_OPTS_UXTX)
10225 else if (opt == INS_OPTS_SXTB)
10227 else if (opt == INS_OPTS_SXTH)
10229 else if (opt == INS_OPTS_SXTW)
10231 else if (opt == INS_OPTS_SXTX)
10234 assert(!"Bad value");
10237 /*****************************************************************************
10239 * Prints the encoding for the Extend Type encoding in loads/stores
10242 void emitter::emitDispLSExtendOpts(insOpts opt)
10244 if (opt == INS_OPTS_LSL)
10246 else if (opt == INS_OPTS_UXTW)
10248 else if (opt == INS_OPTS_UXTX)
10250 else if (opt == INS_OPTS_SXTW)
10252 else if (opt == INS_OPTS_SXTX)
10255 assert(!"Bad value");
10258 /*****************************************************************************
10260 * Display a register
10262 void emitter::emitDispReg(regNumber reg, emitAttr attr, bool addComma)
10264 emitAttr size = EA_SIZE(attr);
10265 printf(emitRegName(reg, size));
10271 /*****************************************************************************
10273 * Display a vector register with an arrangement suffix
10275 void emitter::emitDispVectorReg(regNumber reg, insOpts opt, bool addComma)
10277 assert(isVectorRegister(reg));
10278 printf(emitVectorRegName(reg));
10279 emitDispArrangement(opt);
10285 /*****************************************************************************
10287 * Display an vector register index suffix
10289 void emitter::emitDispVectorRegIndex(regNumber reg, emitAttr elemsize, ssize_t index, bool addComma)
10291 assert(isVectorRegister(reg));
10292 printf(emitVectorRegName(reg));
10309 assert(!"invalid elemsize");
10313 printf("[%d]", index);
10319 /*****************************************************************************
10321 * Display an arrangement suffix
10323 void emitter::emitDispArrangement(insOpts opt)
10325 const char* str = "???";
10355 assert(!"Invalid insOpt for vector register");
10361 /*****************************************************************************
10363 * Display a register with an optional shift operation
10365 void emitter::emitDispShiftedReg(regNumber reg, insOpts opt, ssize_t imm, emitAttr attr)
10367 emitAttr size = EA_SIZE(attr);
10368 assert((imm & 0x003F) == imm);
10369 assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
10371 printf(emitRegName(reg, size));
10379 emitDispShiftOpts(opt);
10380 emitDispImm(imm, false);
10384 /*****************************************************************************
10386 * Display a register with an optional extend and scale operations
10388 void emitter::emitDispExtendReg(regNumber reg, insOpts opt, ssize_t imm)
10390 assert((imm >= 0) && (imm <= 4));
10391 assert(insOptsNone(opt) || insOptsAnyExtend(opt) || (opt == INS_OPTS_LSL));
10393 // size is based on the extend option, not the instr size.
10394 emitAttr size = insOpts32BitExtend(opt) ? EA_4BYTE : EA_8BYTE;
10398 if (insOptsNone(opt))
10400 emitDispReg(reg, size, false);
10404 emitDispReg(reg, size, true);
10405 if (opt == INS_OPTS_LSL)
10408 emitDispExtendOpts(opt);
10409 if ((imm > 0) || (opt == INS_OPTS_LSL))
10412 emitDispImm(imm, false);
10416 else // !strictArmAsm
10418 if (insOptsNone(opt))
10420 emitDispReg(reg, size, false);
10424 if (opt != INS_OPTS_LSL)
10426 emitDispExtendOpts(opt);
10428 emitDispReg(reg, size, false);
10435 emitDispImm(1 << imm, false);
10440 /*****************************************************************************
10442 * Display an addressing operand [reg + imm]
10444 void emitter::emitDispAddrRI(regNumber reg, insOpts opt, ssize_t imm)
10446 reg = encodingZRtoSP(reg); // ZR (R31) encodes the SP register
10452 emitDispReg(reg, EA_8BYTE, false);
10454 if (!insOptsPostIndex(opt) && (imm != 0))
10457 emitDispImm(imm, false);
10461 if (insOptsPreIndex(opt))
10465 else if (insOptsPostIndex(opt))
10468 emitDispImm(imm, false);
10471 else // !strictArmAsm
10475 const char* operStr = "++";
10482 if (insOptsPreIndex(opt))
10487 emitDispReg(reg, EA_8BYTE, false);
10489 if (insOptsPostIndex(opt))
10494 if (insOptsIndexed(opt))
10500 printf("%c", operStr[1]);
10502 emitDispImm(imm, false);
10507 /*****************************************************************************
10509 * Display an addressing operand [reg + extended reg]
10511 void emitter::emitDispAddrRRExt(regNumber reg1, regNumber reg2, insOpts opt, bool isScaled, emitAttr size)
10513 reg1 = encodingZRtoSP(reg1); // ZR (R31) encodes the SP register
10515 unsigned scale = 0;
10518 scale = NaturalScale_helper(size);
10525 emitDispReg(reg1, EA_8BYTE, true);
10526 emitDispExtendReg(reg2, opt, scale);
10528 else // !strictArmAsm
10530 emitDispReg(reg1, EA_8BYTE, false);
10532 emitDispExtendReg(reg2, opt, scale);
10538 /*****************************************************************************
10540 * Display (optionally) the instruction encoding in hex
10543 void emitter::emitDispInsHex(BYTE* code, size_t sz)
10545 // We do not display the instruction hex if we want diff-able disassembly
10546 if (!emitComp->opts.disDiffable)
10550 printf(" %08X ", (*((code_t*)code)));
10559 /****************************************************************************
10561 * Display the given instruction.
10564 void emitter::emitDispIns(
10565 instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* pCode, size_t sz, insGroup* ig)
10570 id->idDebugOnlyInfo()->idNum; // Do not remove this! It is needed for VisualStudio conditional breakpoints
10572 printf("IN%04x: ", idNum);
10578 if (!emitComp->opts.dspEmit && !isNew && !asmfm && sz)
10581 /* Display the instruction offset */
10583 emitDispInsOffs(offset, doffs);
10585 /* Display the instruction hex code */
10587 emitDispInsHex(pCode, sz);
10591 /* Get the instruction and format */
10593 instruction ins = id->idIns();
10594 insFormat fmt = id->idInsFmt();
10598 /* If this instruction has just been added, check its size */
10600 assert(isNew == false || (int)emitSizeOfInsDsc(id) == emitCurIGfreeNext - (BYTE*)id);
10602 /* Figure out the operand size */
10603 emitAttr size = id->idOpSize();
10604 emitAttr attr = size;
10605 if (id->idGCref() == GCT_GCREF)
10607 else if (id->idGCref() == GCT_BYREF)
10615 bool isExtendAlias;
10624 const char* methodName;
10632 case IF_BI_0A: // BI_0A ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
10633 case IF_BI_0B: // BI_0B ......iiiiiiiiii iiiiiiiiiii..... simm19:00
10636 if (fmt == IF_LARGEJMP)
10638 printf("(LARGEJMP)");
10640 if (id->idAddr()->iiaHasInstrCount())
10642 int instrCount = id->idAddr()->iiaGetInstrCount();
10646 printf("pc%s%d instructions", (instrCount >= 0) ? "+" : "", instrCount);
10650 unsigned insNum = emitFindInsNum(ig, id);
10651 UNATIVE_OFFSET srcOffs = ig->igOffs + emitFindOffset(ig, insNum + 1);
10652 UNATIVE_OFFSET dstOffs = ig->igOffs + emitFindOffset(ig, insNum + 1 + instrCount);
10653 ssize_t relOffs = (ssize_t)(emitOffsetToPtr(dstOffs) - emitOffsetToPtr(srcOffs));
10654 printf("pc%s%d (%d instructions)", (relOffs >= 0) ? "+" : "", relOffs, instrCount);
10657 else if (id->idIsBound())
10659 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10663 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10668 case IF_BI_0C: // BI_0C ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
10669 if (id->idIsCallAddr())
10671 offs = (ssize_t)id->idAddr()->iiaAddr;
10677 methodName = emitComp->eeGetMethodFullName((CORINFO_METHOD_HANDLE)id->idDebugOnlyInfo()->idMemCookie);
10682 if (id->idIsDspReloc())
10684 printf("%08X", offs);
10688 printf("%s", methodName);
10692 case IF_BI_1A: // BI_1A ......iiiiiiiiii iiiiiiiiiiittttt Rt simm19:00
10693 assert(insOptsNone(id->idInsOpt()));
10694 emitDispReg(id->idReg1(), size, true);
10695 if (id->idIsBound())
10697 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10701 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10705 case IF_BI_1B: // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
10706 assert(insOptsNone(id->idInsOpt()));
10707 emitDispReg(id->idReg1(), size, true);
10708 emitDispImm(emitGetInsSC(id), true);
10709 if (id->idIsBound())
10711 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10715 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10719 case IF_BR_1A: // BR_1A ................ ......nnnnn..... Rn
10720 assert(insOptsNone(id->idInsOpt()));
10721 emitDispReg(id->idReg1(), size, false);
10724 case IF_BR_1B: // BR_1B ................ ......nnnnn..... Rn
10725 assert(insOptsNone(id->idInsOpt()));
10726 emitDispReg(id->idReg3(), size, false);
10729 case IF_LS_1A: // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB)
10730 case IF_DI_1E: // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
10733 assert(insOptsNone(id->idInsOpt()));
10734 emitDispReg(id->idReg1(), size, true);
10735 imm = emitGetInsSC(id);
10737 /* Is this actually a reference to a data section? */
10738 if (fmt == IF_LARGEADR)
10740 printf("(LARGEADR)");
10742 else if (fmt == IF_LARGELDC)
10744 printf("(LARGELDC)");
10748 if (id->idAddr()->iiaIsJitDataOffset())
10750 doffs = Compiler::eeGetJitDataOffs(id->idAddr()->iiaFieldHnd);
10751 /* Display a data section reference */
10754 printf("@CNS%02u", doffs - 1);
10756 printf("@RWD%02u", doffs);
10759 printf("%+Id", imm);
10764 if (id->idIsReloc())
10767 emitDispImm((ssize_t)id->idAddr()->iiaAddr, false);
10769 else if (id->idIsBound())
10771 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10775 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10781 case IF_LS_2A: // LS_2A .X.......X...... ......nnnnnttttt Rt Rn
10782 assert(insOptsNone(id->idInsOpt()));
10783 assert(emitGetInsSC(id) == 0);
10784 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10785 emitDispAddrRI(id->idReg2(), id->idInsOpt(), 0);
10788 case IF_LS_2B: // LS_2B .X.......Xiiiiii iiiiiinnnnnttttt Rt Rn imm(0-4095)
10789 assert(insOptsNone(id->idInsOpt()));
10790 imm = emitGetInsSC(id);
10791 scale = NaturalScale_helper(emitInsLoadStoreSize(id));
10792 imm <<= scale; // The immediate is scaled by the size of the ld/st
10793 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10794 emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
10797 case IF_LS_2C: // LS_2C .X.......X.iiiii iiiiPPnnnnnttttt Rt Rn imm(-256..+255) no/pre/post inc
10798 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
10799 imm = emitGetInsSC(id);
10800 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10801 emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
10804 case IF_LS_3A: // LS_3A .X.......X.mmmmm oooS..nnnnnttttt Rt Rn Rm ext(Rm) LSL {}
10805 assert(insOptsLSExtend(id->idInsOpt()));
10806 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10807 if (id->idIsLclVar())
10809 emitDispAddrRRExt(id->idReg2(), codeGen->rsGetRsvdReg(), id->idInsOpt(), false, size);
10813 emitDispAddrRRExt(id->idReg2(), id->idReg3(), id->idInsOpt(), id->idReg3Scaled(), size);
10817 case IF_LS_3B: // LS_3B X............... .aaaaannnnnddddd Rt Ra Rn
10818 assert(insOptsNone(id->idInsOpt()));
10819 assert(emitGetInsSC(id) == 0);
10820 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10821 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10822 emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
10825 case IF_LS_3C: // LS_3C X.........iiiiii iaaaaannnnnddddd Rt Ra Rn imm(im7,sh)
10826 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
10827 imm = emitGetInsSC(id);
10828 scale = NaturalScale_helper(emitInsLoadStoreSize(id));
10830 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10831 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10832 emitDispAddrRI(id->idReg3(), id->idInsOpt(), imm);
10835 case IF_LS_3D: // LS_3D .X.......X.mmmmm ......nnnnnttttt Wm Rt Rn
10836 assert(insOptsNone(id->idInsOpt()));
10837 emitDispReg(id->idReg1(), EA_4BYTE, true);
10838 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10839 emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
10842 case IF_DI_1A: // DI_1A X.......shiiiiii iiiiiinnnnn..... Rn imm(i12,sh)
10843 emitDispReg(id->idReg1(), size, true);
10844 emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
10847 case IF_DI_1B: // DI_1B X........hwiiiii iiiiiiiiiiiddddd Rd imm(i16,hw)
10848 emitDispReg(id->idReg1(), size, true);
10849 hwi.immHWVal = (unsigned)emitGetInsSC(id);
10850 if (ins == INS_mov)
10852 emitDispImm(emitDecodeHalfwordImm(hwi, size), false);
10854 else // movz, movn, movk
10856 emitDispImm(hwi.immVal, false);
10857 if (hwi.immHW != 0)
10859 emitDispShiftOpts(INS_OPTS_LSL);
10860 emitDispImm(hwi.immHW * 16, false);
10865 case IF_DI_1C: // DI_1C X........Nrrrrrr ssssssnnnnn..... Rn imm(N,r,s)
10866 emitDispReg(id->idReg1(), size, true);
10867 bmi.immNRS = (unsigned)emitGetInsSC(id);
10868 emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
10871 case IF_DI_1D: // DI_1D X........Nrrrrrr ssssss.....ddddd Rd imm(N,r,s)
10872 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
10873 bmi.immNRS = (unsigned)emitGetInsSC(id);
10874 emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
10877 case IF_DI_2A: // DI_2A X.......shiiiiii iiiiiinnnnnddddd Rd Rn imm(i12,sh)
10878 if ((ins == INS_add) || (ins == INS_sub))
10880 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
10881 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
10885 emitDispReg(id->idReg1(), size, true);
10886 emitDispReg(id->idReg2(), size, true);
10888 emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
10891 case IF_DI_2B: // DI_2B X........X.nnnnn ssssssnnnnnddddd Rd Rn imm(0-63)
10892 emitDispReg(id->idReg1(), size, true);
10893 emitDispReg(id->idReg2(), size, true);
10894 emitDispImm(emitGetInsSC(id), false);
10897 case IF_DI_2C: // DI_2C X........Nrrrrrr ssssssnnnnnddddd Rd Rn imm(N,r,s)
10898 if (ins == INS_ands)
10900 emitDispReg(id->idReg1(), size, true);
10904 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
10906 emitDispReg(id->idReg2(), size, true);
10907 bmi.immNRS = (unsigned)emitGetInsSC(id);
10908 emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
10911 case IF_DI_2D: // DI_2D X........Nrrrrrr ssssssnnnnnddddd Rd Rn imr, ims (N,r,s)
10912 emitDispReg(id->idReg1(), size, true);
10913 emitDispReg(id->idReg2(), size, true);
10915 imm = emitGetInsSC(id);
10916 bmi.immNRS = (unsigned)imm;
10923 emitDispImm(bmi.immR, true);
10924 emitDispImm(bmi.immS, false);
10930 emitDispImm(getBitWidth(size) - bmi.immR, true);
10931 emitDispImm(bmi.immS + 1, false);
10937 emitDispImm(bmi.immR, true);
10938 emitDispImm(bmi.immS - bmi.immR + 1, false);
10944 emitDispImm(imm, false);
10948 assert(!"Unexpected instruction in IF_DI_2D");
10953 case IF_DI_1F: // DI_1F X..........iiiii cccc..nnnnn.nzcv Rn imm5 nzcv cond
10954 emitDispReg(id->idReg1(), size, true);
10955 cfi.immCFVal = (unsigned)emitGetInsSC(id);
10956 emitDispImm(cfi.imm5, true);
10957 emitDispFlags(cfi.flags);
10959 emitDispCond(cfi.cond);
10962 case IF_DR_1D: // DR_1D X............... cccc.......mmmmm Rd cond
10963 emitDispReg(id->idReg1(), size, true);
10964 cfi.immCFVal = (unsigned)emitGetInsSC(id);
10965 emitDispCond(cfi.cond);
10968 case IF_DR_2A: // DR_2A X..........mmmmm ......nnnnn..... Rn Rm
10969 emitDispReg(id->idReg1(), size, true);
10970 emitDispReg(id->idReg2(), size, false);
10973 case IF_DR_2B: // DR_2B X.......sh.mmmmm ssssssnnnnn..... Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
10974 emitDispReg(id->idReg1(), size, true);
10975 emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
10978 case IF_DR_2C: // DR_2C X..........mmmmm ooosssnnnnn..... Rn Rm ext(Rm) LSL imm(0-4)
10979 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
10980 imm = emitGetInsSC(id);
10981 emitDispExtendReg(id->idReg2(), id->idInsOpt(), imm);
10984 case IF_DR_2D: // DR_2D X..........nnnnn cccc..nnnnnddddd Rd Rn cond
10985 emitDispReg(id->idReg1(), size, true);
10986 emitDispReg(id->idReg2(), size, true);
10987 cfi.immCFVal = (unsigned)emitGetInsSC(id);
10988 emitDispCond(cfi.cond);
10991 case IF_DR_2E: // DR_2E X..........mmmmm ...........ddddd Rd Rm
10992 emitDispReg(id->idReg1(), size, true);
10993 emitDispReg(id->idReg2(), size, false);
10996 case IF_DR_2F: // DR_2F X.......sh.mmmmm ssssss.....ddddd Rd Rm {LSL,LSR,ASR} imm(0-63)
10997 emitDispReg(id->idReg1(), size, true);
10998 emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
11001 case IF_DR_2G: // DR_2G X............... ......nnnnnddddd Rd Rn
11002 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11003 emitDispReg(encodingZRtoSP(id->idReg2()), size, false);
11006 case IF_DR_2H: // DR_2H X........X...... ......nnnnnddddd Rd Rn
11007 emitDispReg(id->idReg1(), size, true);
11008 emitDispReg(id->idReg2(), size, false);
11011 case IF_DR_2I: // DR_2I X..........mmmmm cccc..nnnnn.nzcv Rn Rm nzcv cond
11012 emitDispReg(id->idReg1(), size, true);
11013 emitDispReg(id->idReg2(), size, true);
11014 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11015 emitDispFlags(cfi.flags);
11017 emitDispCond(cfi.cond);
11020 case IF_DR_3A: // DR_3A X..........mmmmm ......nnnnnmmmmm Rd Rn Rm
11021 if ((ins == INS_add) || (ins == INS_sub))
11023 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11024 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11026 else if ((ins == INS_smull) || (ins == INS_smulh))
11028 // Rd is always 8 bytes
11029 emitDispReg(id->idReg1(), EA_8BYTE, true);
11031 // Rn, Rm effective size depends on instruction type
11032 size = (ins == INS_smulh) ? EA_8BYTE : EA_4BYTE;
11033 emitDispReg(id->idReg2(), size, true);
11037 emitDispReg(id->idReg1(), size, true);
11038 emitDispReg(id->idReg2(), size, true);
11040 if (id->idIsLclVar())
11042 emitDispReg(codeGen->rsGetRsvdReg(), size, false);
11046 emitDispReg(id->idReg3(), size, false);
11051 case IF_DR_3B: // DR_3B X.......sh.mmmmm ssssssnnnnnddddd Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
11052 emitDispReg(id->idReg1(), size, true);
11053 emitDispReg(id->idReg2(), size, true);
11054 emitDispShiftedReg(id->idReg3(), id->idInsOpt(), emitGetInsSC(id), size);
11057 case IF_DR_3C: // DR_3C X..........mmmmm ooosssnnnnnddddd Rd Rn Rm ext(Rm) LSL imm(0-4)
11058 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11059 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11060 imm = emitGetInsSC(id);
11061 emitDispExtendReg(id->idReg3(), id->idInsOpt(), imm);
11064 case IF_DR_3D: // DR_3D X..........mmmmm cccc..nnnnnmmmmm Rd Rn Rm cond
11065 emitDispReg(id->idReg1(), size, true);
11066 emitDispReg(id->idReg2(), size, true);
11067 emitDispReg(id->idReg3(), size, true);
11068 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11069 emitDispCond(cfi.cond);
11072 case IF_DR_3E: // DR_3E X........X.mmmmm ssssssnnnnnddddd Rd Rn Rm imm(0-63)
11073 emitDispReg(id->idReg1(), size, true);
11074 emitDispReg(id->idReg2(), size, true);
11075 emitDispReg(id->idReg3(), size, true);
11076 emitDispImm(emitGetInsSC(id), false);
11079 case IF_DR_4A: // DR_4A X..........mmmmm .aaaaannnnnmmmmm Rd Rn Rm Ra
11080 emitDispReg(id->idReg1(), size, true);
11081 emitDispReg(id->idReg2(), size, true);
11082 emitDispReg(id->idReg3(), size, true);
11083 emitDispReg(id->idReg4(), size, false);
11086 case IF_DV_1A: // DV_1A .........X.iiiii iii........ddddd Vd imm8 (fmov - immediate scalar)
11087 elemsize = id->idOpSize();
11088 emitDispReg(id->idReg1(), elemsize, true);
11089 emitDispFloatImm(emitGetInsSC(id));
11092 case IF_DV_1B: // DV_1B .QX..........iii cmod..iiiiiddddd Vd imm8 (immediate vector)
11093 imm = emitGetInsSC(id) & 0x0ff;
11094 immShift = (emitGetInsSC(id) & 0x700) >> 8;
11095 hasShift = (immShift != 0);
11096 elemsize = optGetElemsize(id->idInsOpt());
11097 if (id->idInsOpt() == INS_OPTS_1D)
11099 assert(elemsize == size);
11100 emitDispReg(id->idReg1(), size, true);
11104 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11106 if (ins == INS_fmov)
11108 emitDispFloatImm(imm);
11109 assert(hasShift == false);
11113 if (elemsize == EA_8BYTE)
11115 assert(ins == INS_movi);
11117 const ssize_t mask8 = 0xFF;
11118 for (unsigned b = 0; b < 8; b++)
11120 if (imm & (1 << b))
11122 imm64 |= (mask8 << (b * 8));
11125 emitDispImm(imm64, hasShift, true);
11129 emitDispImm(imm, hasShift, true);
11133 insOpts opt = (immShift & 0x4) ? INS_OPTS_MSL : INS_OPTS_LSL;
11134 unsigned shift = (immShift & 0x3) * 8;
11135 emitDispShiftOpts(opt);
11136 emitDispImm(shift, false);
11141 case IF_DV_1C: // DV_1C .........X...... ......nnnnn..... Vn #0.0 (fcmp - with zero)
11142 elemsize = id->idOpSize();
11143 emitDispReg(id->idReg1(), elemsize, true);
11144 emitDispFloatZero();
11147 case IF_DV_2A: // DV_2A .Q.......X...... ......nnnnnddddd Vd Vn (fabs, fcvt - vector)
11148 case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
11149 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11150 emitDispVectorReg(id->idReg2(), id->idInsOpt(), false);
11153 case IF_DV_2N: // DV_2N .........iiiiiii ......nnnnnddddd Vd Vn imm (shift - scalar)
11154 elemsize = id->idOpSize();
11155 emitDispReg(id->idReg1(), elemsize, true);
11156 emitDispReg(id->idReg2(), elemsize, true);
11157 emitDispImm(emitGetInsSC(id), false);
11160 case IF_DV_2O: // DV_2O .Q.......iiiiiii ......nnnnnddddd Vd Vn imm (shift - vector)
11161 imm = emitGetInsSC(id);
11162 // Do we have a sxtl or uxtl instruction?
11163 isExtendAlias = ((ins == INS_sxtl) || (ins == INS_sxtl2) || (ins == INS_uxtl) || (ins == INS_uxtl2));
11164 code = emitInsCode(ins, fmt);
11165 if (code & 0x00008000) // widen/narrow opcodes
11167 if (code & 0x00002000) // SHL opcodes
11169 emitDispVectorReg(id->idReg1(), optWidenElemsize(id->idInsOpt()), true);
11170 emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11172 else // SHR opcodes
11174 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11175 emitDispVectorReg(id->idReg2(), optWidenElemsize(id->idInsOpt()), !isExtendAlias);
11180 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11181 emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11183 // Print the immediate unless we have a sxtl or uxtl instruction
11184 if (!isExtendAlias)
11186 emitDispImm(imm, false);
11190 case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov/smov - to general)
11191 srcsize = id->idOpSize();
11192 index = emitGetInsSC(id);
11193 if (ins == INS_smov)
11195 dstsize = EA_8BYTE;
11197 else // INS_umov or INS_mov
11199 dstsize = (srcsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE;
11201 emitDispReg(id->idReg1(), dstsize, true);
11202 emitDispVectorRegIndex(id->idReg2(), srcsize, index, false);
11205 case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
11206 if (ins == INS_dup)
11208 datasize = id->idOpSize();
11209 assert(isValidVectorDatasize(datasize));
11210 assert(isValidArrangement(datasize, id->idInsOpt()));
11211 elemsize = optGetElemsize(id->idInsOpt());
11212 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11216 elemsize = id->idOpSize();
11217 index = emitGetInsSC(id);
11218 assert(isValidVectorElemsize(elemsize));
11219 emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11221 emitDispReg(id->idReg2(), (elemsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE, false);
11224 case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
11225 datasize = id->idOpSize();
11226 assert(isValidVectorDatasize(datasize));
11227 assert(isValidArrangement(datasize, id->idInsOpt()));
11228 elemsize = optGetElemsize(id->idInsOpt());
11229 index = emitGetInsSC(id);
11230 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11231 emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11234 case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
11235 elemsize = id->idOpSize();
11236 index = emitGetInsSC(id);
11237 emitDispReg(id->idReg1(), elemsize, true);
11238 emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11241 case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
11242 imm = emitGetInsSC(id);
11243 index = (imm >> 4) & 0xf;
11244 index2 = imm & 0xf;
11245 elemsize = id->idOpSize();
11246 emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11247 emitDispVectorRegIndex(id->idReg2(), elemsize, index2, false);
11250 case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov, fcvtXX - register)
11251 case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
11252 case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
11253 elemsize = id->idOpSize();
11254 emitDispReg(id->idReg1(), elemsize, true);
11255 emitDispReg(id->idReg2(), elemsize, false);
11258 case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov, fcvtXX - to general)
11259 case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov, Xcvtf - from general)
11260 case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
11261 dstsize = optGetDstsize(id->idInsOpt());
11262 srcsize = optGetSrcsize(id->idInsOpt());
11264 emitDispReg(id->idReg1(), dstsize, true);
11265 emitDispReg(id->idReg2(), srcsize, false);
11268 case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11269 case IF_DV_3B: // DV_3B .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11270 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11271 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11272 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11275 case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11276 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11277 if (ins != INS_mov)
11279 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11281 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11284 case IF_DV_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
11285 case IF_DV_3BI: // DV_3BI .Q........Lmmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
11286 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11287 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11288 elemsize = optGetElemsize(id->idInsOpt());
11289 emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11292 case IF_DV_3D: // DV_3D .........X.mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
11293 case IF_DV_3E: // DV_3E ...........mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
11294 emitDispReg(id->idReg1(), size, true);
11295 emitDispReg(id->idReg2(), size, true);
11296 emitDispReg(id->idReg3(), size, false);
11299 case IF_DV_3DI: // DV_3DI .........XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (scalar by elem)
11300 emitDispReg(id->idReg1(), size, true);
11301 emitDispReg(id->idReg2(), size, true);
11303 emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11306 case IF_DV_4A: // DV_4A .........X.mmmmm .aaaaannnnnddddd Vd Va Vn Vm (scalar)
11307 emitDispReg(id->idReg1(), size, true);
11308 emitDispReg(id->idReg2(), size, true);
11309 emitDispReg(id->idReg3(), size, true);
11310 emitDispReg(id->idReg4(), size, false);
11313 case IF_SN_0A: // SN_0A ................ ................
11316 case IF_SI_0A: // SI_0A ...........iiiii iiiiiiiiiii..... imm16
11317 emitDispImm(emitGetInsSC(id), false);
11320 case IF_SI_0B: // SI_0B ................ ....bbbb........ imm4 - barrier
11321 emitDispBarrier((insBarrier)emitGetInsSC(id));
11325 printf("unexpected format %s", emitIfName(id->idInsFmt()));
11326 assert(!"unexpectedFormat");
11330 if (id->idDebugOnlyInfo()->idVarRefOffs)
11333 emitDispFrameRef(id->idAddr()->iiaLclVar.lvaVarNum(), id->idAddr()->iiaLclVar.lvaOffset(),
11334 id->idDebugOnlyInfo()->idVarRefOffs, asmfm);
11340 /*****************************************************************************
11342 * Display a stack frame reference.
11345 void emitter::emitDispFrameRef(int varx, int disp, int offs, bool asmfm)
11350 printf("TEMP_%02u", -varx);
11352 emitComp->gtDispLclVar(+varx, false);
11355 printf("-0x%02x", -disp);
11357 printf("+0x%02x", +disp);
11361 if (varx >= 0 && emitComp->opts.varNames)
11364 const char* varName;
11366 assert((unsigned)varx < emitComp->lvaCount);
11367 varDsc = emitComp->lvaTable + varx;
11368 varName = emitComp->compLocalVarName(varx, offs);
11372 printf("'%s", varName);
11375 printf("-%d", -disp);
11377 printf("+%d", +disp);
11386 // Generate code for a load or store operation with a potentially complex addressing mode
11387 // This method handles the case of a GT_IND with contained GT_LEA op1 of the x86 form [base + index*sccale + offset]
11388 // Since Arm64 does not directly support this complex of an addressing mode
11389 // we may generates up to three instructions for this for Arm64
11391 void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataReg, GenTreeIndir* indir)
11393 emitAttr ldstAttr = isVectorRegister(dataReg) ? attr : emitInsAdjustLoadStoreAttr(ins, attr);
11395 GenTree* addr = indir->Addr();
11397 if (addr->isContained())
11399 assert(addr->OperGet() == GT_LCL_VAR_ADDR || addr->OperGet() == GT_LEA);
11404 if (addr->OperGet() == GT_LEA)
11406 offset = addr->AsAddrMode()->Offset();
11407 if (addr->AsAddrMode()->gtScale > 0)
11409 assert(isPow2(addr->AsAddrMode()->gtScale));
11410 BitScanForward(&lsl, addr->AsAddrMode()->gtScale);
11414 GenTree* memBase = indir->Base();
11416 if (indir->HasIndex())
11418 GenTree* index = indir->Index();
11422 regNumber tmpReg = indir->GetSingleTempReg();
11424 emitAttr addType = varTypeIsGC(memBase) ? EA_BYREF : EA_PTRSIZE;
11426 if (emitIns_valid_imm_for_add(offset, EA_8BYTE))
11430 // Generate code to set tmpReg = base + index*scale
11431 emitIns_R_R_R_I(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum, lsl,
11436 // Generate code to set tmpReg = base + index
11437 emitIns_R_R_R(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum);
11440 noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11442 // Then load/store dataReg from/to [tmpReg + offset]
11443 emitIns_R_R_I(ins, ldstAttr, dataReg, tmpReg, offset);
11445 else // large offset
11447 // First load/store tmpReg with the large offset constant
11448 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11449 // Then add the base register
11451 emitIns_R_R_R(INS_add, addType, tmpReg, tmpReg, memBase->gtRegNum);
11453 noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11454 noway_assert(tmpReg != index->gtRegNum);
11456 // Then load/store dataReg from/to [tmpReg + index*scale]
11457 emitIns_R_R_R_I(ins, ldstAttr, dataReg, tmpReg, index->gtRegNum, lsl, INS_OPTS_LSL);
11460 else // (offset == 0)
11464 // Then load/store dataReg from/to [memBase + index*scale]
11465 emitIns_R_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum, lsl, INS_OPTS_LSL);
11469 // Then load/store dataReg from/to [memBase + index]
11470 emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum);
11474 else // no Index register
11476 if (emitIns_valid_imm_for_ldst_offset(offset, EA_SIZE(attr)))
11478 // Then load/store dataReg from/to [memBase + offset]
11479 emitIns_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, offset);
11483 // We require a tmpReg to hold the offset
11484 regNumber tmpReg = indir->GetSingleTempReg();
11486 // First load/store tmpReg with the large offset constant
11487 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11489 // Then load/store dataReg from/to [memBase + tmpReg]
11490 emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, tmpReg);
11494 else // addr is not contained, so we evaluate it into a register
11496 // Then load/store dataReg from/to [addrReg]
11497 emitIns_R_R(ins, ldstAttr, dataReg, addr->gtRegNum);
11501 // Generates an integer data section constant and returns a field handle representing
11502 // the data offset to access the constant via a load instruction.
11503 // This is called during ngen for any relocatable constants
11505 CORINFO_FIELD_HANDLE emitter::emitLiteralConst(ssize_t cnsValIn, emitAttr attr /*=EA_8BYTE*/)
11507 ssize_t constValue = cnsValIn;
11508 void* cnsAddr = &constValue;
11511 if (attr == EA_4BYTE)
11517 assert(attr == EA_8BYTE);
11521 // Access to inline data is 'abstracted' by a special type of static member
11522 // (produced by eeFindJitDataOffs) which the emitter recognizes as being a reference
11523 // to constant data, not a real static field.
11525 UNATIVE_OFFSET cnsSize = (attr == EA_4BYTE) ? 4 : 8;
11526 UNATIVE_OFFSET cnum = emitDataConst(cnsAddr, cnsSize, dblAlign);
11527 return emitComp->eeFindJitDataOffs(cnum);
11530 // Generates a float or double data section constant and returns field handle representing
11531 // the data offset to access the constant. This is called by emitInsBinary() in case
11532 // of contained float of double constants.
11533 CORINFO_FIELD_HANDLE emitter::emitFltOrDblConst(GenTreeDblCon* tree, emitAttr attr /*=EA_UNKNOWN*/)
11535 if (attr == EA_UNKNOWN)
11537 attr = emitTypeSize(tree->TypeGet());
11541 assert(emitTypeSize(tree->TypeGet()) == attr);
11544 double constValue = tree->gtDblCon.gtDconVal;
11549 if (attr == EA_4BYTE)
11551 f = forceCastToFloat(constValue);
11557 cnsAddr = &constValue;
11561 // Access to inline data is 'abstracted' by a special type of static member
11562 // (produced by eeFindJitDataOffs) which the emitter recognizes as being a reference
11563 // to constant data, not a real static field.
11565 UNATIVE_OFFSET cnsSize = (attr == EA_4BYTE) ? 4 : 8;
11566 UNATIVE_OFFSET cnum = emitDataConst(cnsAddr, cnsSize, dblAlign);
11567 return emitComp->eeFindJitDataOffs(cnum);
11570 // The callee must call genConsumeReg() for any non-contained srcs
11571 // and genProduceReg() for any non-contained dsts.
11573 regNumber emitter::emitInsBinary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src)
11575 regNumber result = REG_NA;
11577 // dst can only be a reg
11578 assert(!dst->isContained());
11580 // src can be immed or reg
11581 assert(!src->isContained() || src->isContainedIntOrIImmed());
11583 // find immed (if any) - it cannot be a dst
11584 GenTreeIntConCommon* intConst = nullptr;
11585 if (src->isContainedIntOrIImmed())
11587 intConst = src->AsIntConCommon();
11592 emitIns_R_I(ins, attr, dst->gtRegNum, intConst->IconValue());
11593 return dst->gtRegNum;
11597 emitIns_R_R(ins, attr, dst->gtRegNum, src->gtRegNum);
11598 return dst->gtRegNum;
11602 // The callee must call genConsumeReg() for any non-contained srcs
11603 // and genProduceReg() for any non-contained dsts.
11605 regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src1, GenTree* src2)
11607 regNumber result = REG_NA;
11609 // dst can only be a reg
11610 assert(!dst->isContained());
11612 // find immed (if any) - it cannot be a dst
11613 // Only one src can be an int.
11614 GenTreeIntConCommon* intConst = nullptr;
11615 GenTree* nonIntReg = nullptr;
11617 if (varTypeIsFloating(dst))
11619 // src1 can only be a reg
11620 assert(!src1->isContained());
11621 // src2 can only be a reg
11622 assert(!src2->isContained());
11624 else // not floating point
11626 // src2 can be immed or reg
11627 assert(!src2->isContained() || src2->isContainedIntOrIImmed());
11629 // Check src2 first as we can always allow it to be a contained immediate
11630 if (src2->isContainedIntOrIImmed())
11632 intConst = src2->AsIntConCommon();
11635 // Only for commutative operations do we check src1 and allow it to be a contained immediate
11636 else if (dst->OperIsCommutative())
11638 // src1 can be immed or reg
11639 assert(!src1->isContained() || src1->isContainedIntOrIImmed());
11641 // Check src1 and allow it to be a contained immediate
11642 if (src1->isContainedIntOrIImmed())
11644 assert(!src2->isContainedIntOrIImmed());
11645 intConst = src1->AsIntConCommon();
11651 // src1 can only be a reg
11652 assert(!src1->isContained());
11656 bool isMulOverflow = false;
11657 if (dst->gtOverflowEx())
11659 if ((ins == INS_add) || (ins == INS_adds))
11663 else if ((ins == INS_sub) || (ins == INS_subs))
11667 else if (ins == INS_mul)
11669 isMulOverflow = true;
11670 assert(intConst == nullptr); // overflow format doesn't support an int constant operand
11674 assert(!"Invalid ins for overflow check");
11677 if (intConst != nullptr)
11679 emitIns_R_R_I(ins, attr, dst->gtRegNum, nonIntReg->gtRegNum, intConst->IconValue());
11685 regNumber extraReg = dst->GetSingleTempReg();
11686 assert(extraReg != dst->gtRegNum);
11688 if ((dst->gtFlags & GTF_UNSIGNED) != 0)
11690 if (attr == EA_4BYTE)
11692 // Compute 8 byte results from 4 byte by 4 byte multiplication.
11693 emitIns_R_R_R(INS_umull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11695 // Get the high result by shifting dst.
11696 emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11700 assert(attr == EA_8BYTE);
11701 // Compute the high result.
11702 emitIns_R_R_R(INS_umulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11704 // Now multiply without skewing the high result.
11705 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11708 // zero-sign bit comparison to detect overflow.
11709 emitIns_R_I(INS_cmp, attr, extraReg, 0);
11714 if (attr == EA_4BYTE)
11716 // Compute 8 byte results from 4 byte by 4 byte multiplication.
11717 emitIns_R_R_R(INS_smull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11719 // Get the high result by shifting dst.
11720 emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11726 assert(attr == EA_8BYTE);
11727 // Save the high result in a temporary register.
11728 emitIns_R_R_R(INS_smulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11730 // Now multiply without skewing the high result.
11731 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11736 // Sign bit comparison to detect overflow.
11737 emitIns_R_R_I(INS_cmp, attr, extraReg, dst->gtRegNum, bitShift, INS_OPTS_ASR);
11742 // We can just multiply.
11743 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11747 if (dst->gtOverflowEx())
11749 assert(!varTypeIsFloating(dst));
11750 codeGen->genCheckOverflow(dst);
11753 return dst->gtRegNum;
11756 #endif // defined(_TARGET_ARM64_)