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 // size is determined by instruction
3991 assert(size == EA_8BYTE);
3993 else // ins == INS_xtn2
3995 assert(size == EA_16BYTE);
3997 assert(elemsize != EA_8BYTE); // Narrowing must not end with 8 byte data
4005 assert(isValidGeneralDatasize(size));
4017 assert(isValidGeneralLSDatasize(size));
4018 assert(isGeneralRegisterOrZR(reg1));
4019 assert(isGeneralRegisterOrSP(reg2));
4020 assert(insOptsNone(opt));
4022 reg2 = encodingSPtoZR(reg2);
4040 assert(insOptsNone(opt));
4041 emitIns_R_R_I(ins, attr, reg1, reg2, 0, INS_OPTS_NONE);
4045 assert(isValidVectorElemsizeFloat(size));
4047 // Is the mov even necessary?
4053 if (isVectorRegister(reg1))
4055 if (isVectorRegister(reg2))
4057 assert(insOptsNone(opt));
4062 assert(isGeneralRegister(reg2));
4064 // if the optional conversion specifier is not present we calculate it
4065 if (opt == INS_OPTS_NONE)
4067 opt = (size == EA_4BYTE) ? INS_OPTS_4BYTE_TO_S : INS_OPTS_8BYTE_TO_D;
4069 assert(insOptsConvertIntToFloat(opt));
4076 assert(isGeneralRegister(reg1));
4077 assert(isVectorRegister(reg2));
4079 // if the optional conversion specifier is not present we calculate it
4080 if (opt == INS_OPTS_NONE)
4082 opt = (size == EA_4BYTE) ? INS_OPTS_S_TO_4BYTE : INS_OPTS_D_TO_8BYTE;
4084 assert(insOptsConvertFloatToInt(opt));
4092 assert(insOptsNone(opt));
4093 assert(isValidVectorElemsizeFloat(size));
4094 assert(isVectorRegister(reg1));
4095 assert(isVectorRegister(reg2));
4109 if (insOptsAnyArrangement(opt))
4112 assert(isVectorRegister(reg1));
4113 assert(isVectorRegister(reg2));
4114 assert(isValidVectorDatasize(size));
4115 assert(isValidArrangement(size, opt));
4116 elemsize = optGetElemsize(opt);
4117 assert(isValidVectorElemsizeFloat(elemsize));
4118 assert(opt != INS_OPTS_1D); // Reserved encoding
4124 assert(isVectorRegister(reg2));
4125 if (isVectorRegister(reg1))
4127 assert(insOptsNone(opt));
4128 assert(isValidVectorElemsizeFloat(size));
4133 assert(isGeneralRegister(reg1));
4134 assert(insOptsConvertFloatToInt(opt));
4135 assert(isValidVectorElemsizeFloat(size));
4145 assert(isVectorRegister(reg1));
4146 assert(isVectorRegister(reg2));
4147 assert(isValidVectorDatasize(size));
4148 assert(insOptsNone(opt));
4149 assert(size == EA_8BYTE); // Narrowing from Double or Widening to Double (Half not supported)
4155 if (insOptsAnyArrangement(opt))
4158 assert(isVectorRegister(reg1));
4159 assert(isVectorRegister(reg2));
4160 assert(isValidVectorDatasize(size));
4161 assert(isValidArrangement(size, opt));
4162 elemsize = optGetElemsize(opt);
4163 assert(isValidVectorElemsizeFloat(elemsize));
4164 assert(opt != INS_OPTS_1D); // Reserved encoding
4170 assert(isVectorRegister(reg1));
4171 if (isVectorRegister(reg2))
4173 assert(insOptsNone(opt));
4174 assert(isValidVectorElemsizeFloat(size));
4179 assert(isGeneralRegister(reg2));
4180 assert(insOptsConvertIntToFloat(opt));
4181 assert(isValidVectorElemsizeFloat(size));
4197 if (insOptsAnyArrangement(opt))
4200 assert(isVectorRegister(reg1));
4201 assert(isVectorRegister(reg2));
4202 assert(isValidVectorDatasize(size));
4203 assert(isValidArrangement(size, opt));
4204 elemsize = optGetElemsize(opt);
4205 assert(isValidVectorElemsizeFloat(elemsize));
4206 assert(opt != INS_OPTS_1D); // Reserved encoding
4212 assert(insOptsNone(opt));
4213 assert(isValidVectorElemsizeFloat(size));
4214 assert(isVectorRegister(reg1));
4215 assert(isVectorRegister(reg2));
4222 assert(insOptsNone(opt));
4223 assert(isValidVectorElemsizeFloat(size));
4224 assert(isVectorRegister(reg1));
4225 assert(isVectorRegister(reg2));
4230 assert(insOptsConvertFloatToFloat(opt));
4231 assert(isValidVectorFcvtsize(size));
4232 assert(isVectorRegister(reg1));
4233 assert(isVectorRegister(reg2));
4241 } // end switch (ins)
4243 assert(fmt != IF_NONE);
4245 instrDesc* id = emitNewInstrSmall(attr);
4258 /*****************************************************************************
4260 * Add an instruction referencing a register and two constants.
4263 void emitter::emitIns_R_I_I(
4264 instruction ins, emitAttr attr, regNumber reg, ssize_t imm1, ssize_t imm2, insOpts opt /* = INS_OPTS_NONE */)
4266 emitAttr size = EA_SIZE(attr);
4267 insFormat fmt = IF_NONE;
4268 size_t immOut = 0; // composed from imm1 and imm2 and stored in the instrDesc
4270 /* Figure out the encoding format of the instruction */
4277 ins = INS_movz; // INS_mov with LSL is an alias for INS_movz LSL
4283 assert(isValidGeneralDatasize(size));
4284 assert(isGeneralRegister(reg));
4285 assert(isValidUimm16(imm1));
4286 assert(insOptsLSL(opt)); // Must be INS_OPTS_LSL
4288 if (size == EA_8BYTE)
4290 assert((imm2 == 0) || (imm2 == 16) || // shift amount: 0, 16, 32 or 48
4291 (imm2 == 32) || (imm2 == 48));
4295 assert((imm2 == 0) || (imm2 == 16)); // shift amount: 0 or 16
4330 immOut = hwi.immHWVal;
4331 assert(isValidImmHWVal(immOut, size));
4340 } // end switch (ins)
4342 assert(fmt != IF_NONE);
4344 instrDesc* id = emitNewInstrSC(attr, immOut);
4355 /*****************************************************************************
4357 * Add an instruction referencing two registers and a constant.
4360 void emitter::emitIns_R_R_I(
4361 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm, insOpts opt /* = INS_OPTS_NONE */)
4363 emitAttr size = EA_SIZE(attr);
4364 emitAttr elemsize = EA_UNKNOWN;
4365 insFormat fmt = IF_NONE;
4366 bool isLdSt = false;
4367 bool isSIMD = false;
4368 bool isAddSub = false;
4369 bool setFlags = false;
4371 bool unscaledOp = false;
4373 /* Figure out the encoding format of the instruction */
4380 // Check for the 'mov' aliases for the vector registers
4381 assert(insOptsNone(opt));
4382 assert(isValidVectorElemsize(size));
4384 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4386 if (isVectorRegister(reg1))
4388 if (isGeneralRegisterOrZR(reg2))
4390 fmt = IF_DV_2C; // Alias for 'ins'
4393 else if (isVectorRegister(reg2))
4395 fmt = IF_DV_2E; // Alias for 'dup'
4399 else // isGeneralRegister(reg1)
4401 assert(isGeneralRegister(reg1));
4402 if (isVectorRegister(reg2))
4404 fmt = IF_DV_2B; // Alias for 'umov'
4408 assert(!" invalid INS_mov operands");
4414 assert(insOptsNone(opt));
4415 assert(isValidGeneralDatasize(size));
4416 assert(isGeneralRegister(reg1));
4417 assert(isGeneralRegister(reg2));
4418 assert(isValidImmShift(imm, size));
4423 assert(insOptsNone(opt));
4424 assert(isValidGeneralDatasize(size));
4425 assert(isGeneralRegister(reg1));
4426 assert(isGeneralRegister(reg2));
4427 assert(isValidImmShift(imm, size));
4442 assert(isVectorRegister(reg1));
4443 assert(isVectorRegister(reg2));
4444 if (insOptsAnyArrangement(opt))
4447 assert(isValidVectorDatasize(size));
4448 assert(isValidArrangement(size, opt));
4449 elemsize = optGetElemsize(opt);
4450 assert(isValidVectorElemsize(elemsize));
4451 assert(isValidImmShift(imm, elemsize));
4452 assert(opt != INS_OPTS_1D); // Reserved encoding
4459 assert(insOptsNone(opt));
4460 assert(size == EA_8BYTE); // only supported size
4461 assert(isValidImmShift(imm, size));
4475 assert(isVectorRegister(reg1));
4476 assert(isVectorRegister(reg2));
4478 assert(size == EA_8BYTE);
4479 assert(isValidArrangement(size, opt));
4480 elemsize = optGetElemsize(opt);
4481 assert(elemsize != EA_8BYTE); // Reserved encodings
4482 assert(isValidVectorElemsize(elemsize));
4483 assert(isValidImmShift(imm, elemsize));
4496 assert(isVectorRegister(reg1));
4497 assert(isVectorRegister(reg2));
4499 assert(size == EA_16BYTE);
4500 assert(isValidArrangement(size, opt));
4501 elemsize = optGetElemsize(opt);
4502 assert(elemsize != EA_8BYTE); // Reserved encodings
4503 assert(isValidVectorElemsize(elemsize));
4504 assert(isValidImmShift(imm, elemsize));
4511 assert(isValidGeneralDatasize(size));
4512 assert(isGeneralRegister(reg1));
4513 assert(isGeneralRegisterOrZR(reg2));
4517 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4525 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
4529 assert(insOptsAluShift(opt)); // a non-zero imm, must select shift kind, can't use ROR
4531 assert(isValidImmShift(imm, size));
4537 assert(isValidGeneralDatasize(size));
4538 assert(isGeneralRegisterOrZR(reg1));
4539 assert(isGeneralRegister(reg2));
4541 if (insOptsAnyShift(opt))
4543 assert(isValidImmShift(imm, size) && (imm != 0));
4548 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4556 assert(isValidGeneralDatasize(size));
4557 assert(isGeneralRegisterOrSP(reg1));
4558 assert(isGeneralRegister(reg2));
4560 reg1 = encodingSPtoZR(reg1);
4561 if (insOptsAnyExtend(opt))
4563 assert((imm >= 0) && (imm <= 4));
4569 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4575 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
4576 assert(isValidImmShift(imm, size));
4585 assert(insOptsNone(opt));
4586 assert(isGeneralRegister(reg2));
4587 if (ins == INS_ands)
4589 assert(isGeneralRegister(reg1));
4593 assert(isGeneralRegisterOrSP(reg1));
4594 reg1 = encodingSPtoZR(reg1);
4598 canEncode = canEncodeBitMaskImm(imm, size, &bmi);
4602 assert(isValidImmNRS(imm, size));
4607 case INS_dup: // by element, imm selects the element of reg2
4608 assert(isVectorRegister(reg1));
4609 if (isVectorRegister(reg2))
4611 if (insOptsAnyArrangement(opt))
4614 assert(isValidVectorDatasize(size));
4615 assert(isValidArrangement(size, opt));
4616 elemsize = optGetElemsize(opt);
4617 assert(isValidVectorElemsize(elemsize));
4618 assert(isValidVectorIndex(size, elemsize, imm));
4619 assert(opt != INS_OPTS_1D); // Reserved encoding
4626 assert(insOptsNone(opt));
4628 assert(isValidVectorElemsize(elemsize));
4629 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4636 case INS_ins: // (MOV from general)
4637 assert(insOptsNone(opt));
4638 assert(isValidVectorElemsize(size));
4639 assert(isVectorRegister(reg1));
4640 assert(isGeneralRegisterOrZR(reg2));
4642 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4646 case INS_umov: // (MOV to general)
4647 assert(insOptsNone(opt));
4648 assert(isValidVectorElemsize(size));
4649 assert(isGeneralRegister(reg1));
4650 assert(isVectorRegister(reg2));
4652 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4657 assert(insOptsNone(opt));
4658 assert(isValidVectorElemsize(size));
4659 assert(size != EA_8BYTE); // no encoding, use INS_umov
4660 assert(isGeneralRegister(reg1));
4661 assert(isVectorRegister(reg2));
4663 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4681 // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4682 assert(isValidGeneralDatasize(size));
4683 unscaledOp = (ins == INS_ldursb);
4690 // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4691 assert(isValidGeneralDatasize(size));
4692 unscaledOp = (ins == INS_ldursh);
4699 // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4700 assert(size == EA_8BYTE);
4701 unscaledOp = (ins == INS_ldursw);
4740 // Is the target a vector register?
4741 if (isVectorRegister(reg1))
4743 assert(isValidVectorLSDatasize(size));
4744 assert(isGeneralRegisterOrSP(reg2));
4749 assert(isValidGeneralDatasize(size));
4752 scale = NaturalScale_helper(size);
4758 // Is the target a vector register?
4759 if (isVectorRegister(reg1))
4761 assert(isValidVectorLSDatasize(size));
4762 assert(isGeneralRegisterOrSP(reg2));
4767 assert(isValidGeneralDatasize(size));
4778 } // end switch (ins)
4786 assert(isValidVectorLSDatasize(size));
4787 assert(isVectorRegister(reg1));
4788 assert((scale >= 0) && (scale <= 4));
4792 assert(isValidGeneralLSDatasize(size));
4793 assert(isGeneralRegisterOrZR(reg1));
4794 assert((scale >= 0) && (scale <= 3));
4797 assert(isGeneralRegisterOrSP(reg2));
4799 // Load/Store reserved encodings:
4800 if (insOptsIndexed(opt))
4802 assert(reg1 != reg2);
4805 reg2 = encodingSPtoZR(reg2);
4807 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
4810 assert(insOptsNone(opt)); // PRE/POST Index doesn't make sense with an immediate of zero
4814 else if (insOptsIndexed(opt) || unscaledOp || (imm < 0) || ((imm & mask) != 0))
4816 if ((imm >= -256) && (imm <= 255))
4822 assert(!"Instruction cannot be encoded: IF_LS_2C");
4827 assert(insOptsNone(opt));
4828 assert(!unscaledOp);
4830 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
4832 imm >>= scale; // The immediate is scaled by the size of the ld/st
4838 assert(!"Instruction cannot be encoded: IF_LS_2B");
4845 assert(insOptsNone(opt));
4847 if (setFlags) // Can't encode SP with setFlags
4849 assert(isGeneralRegister(reg1));
4850 assert(isGeneralRegister(reg2));
4854 assert(isGeneralRegisterOrSP(reg1));
4855 assert(isGeneralRegisterOrSP(reg2));
4857 // Is it just a mov?
4860 // Is the mov even necessary?
4863 emitIns_R_R(INS_mov, attr, reg1, reg2);
4868 reg1 = encodingSPtoZR(reg1);
4869 reg2 = encodingSPtoZR(reg2);
4872 if (unsigned_abs(imm) <= 0x0fff)
4876 ins = insReverse(ins);
4879 assert(isValidUimm12(imm));
4882 else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
4884 // Encoding will use a 12-bit left shift of the immediate
4885 opt = INS_OPTS_LSL12;
4888 ins = insReverse(ins);
4891 assert((imm & 0xfff) == 0);
4893 assert(isValidUimm12(imm));
4898 assert(!"Instruction cannot be encoded: IF_DI_2A");
4902 assert(fmt != IF_NONE);
4904 instrDesc* id = emitNewInstrSC(attr, imm);
4917 /*****************************************************************************
4919 * Add an instruction referencing two registers and a constant.
4920 * Also checks for a large immediate that needs a second instruction
4921 * and will load it in reg1
4923 * - Supports instructions: add, adds, sub, subs, and, ands, eor and orr
4924 * - Requires that reg1 is a general register and not SP or ZR
4925 * - Requires that reg1 != reg2
4927 void emitter::emitIns_R_R_Imm(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm)
4929 assert(isGeneralRegister(reg1));
4930 assert(reg1 != reg2);
4932 bool immFits = true;
4940 immFits = emitter::emitIns_valid_imm_for_add(imm, attr);
4947 immFits = emitter::emitIns_valid_imm_for_alu(imm, attr);
4951 assert(!"Unsupported instruction in emitIns_R_R_Imm");
4956 emitIns_R_R_I(ins, attr, reg1, reg2, imm);
4960 // Load 'imm' into the reg1 register
4961 // then issue: 'ins' reg1, reg2, reg1
4963 codeGen->instGen_Set_Reg_To_Imm(attr, reg1, imm);
4964 emitIns_R_R_R(ins, attr, reg1, reg2, reg1);
4968 /*****************************************************************************
4970 * Add an instruction referencing three registers.
4973 void emitter::emitIns_R_R_R(
4974 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insOpts opt) /* = INS_OPTS_NONE */
4976 emitAttr size = EA_SIZE(attr);
4977 emitAttr elemsize = EA_UNKNOWN;
4978 insFormat fmt = IF_NONE;
4980 /* Figure out the encoding format of the instruction */
5004 assert(insOptsNone(opt));
5005 assert(isValidGeneralDatasize(size));
5006 assert(isGeneralRegister(reg1));
5007 assert(isGeneralRegister(reg2));
5008 assert(isGeneralRegister(reg3));
5013 if (insOptsNone(opt))
5016 assert(isValidGeneralDatasize(size));
5017 assert(isGeneralRegister(reg1));
5018 assert(isGeneralRegister(reg2));
5019 assert(isGeneralRegister(reg3));
5028 assert(insOptsAnyArrangement(opt));
5029 assert(isVectorRegister(reg1));
5030 assert(isVectorRegister(reg2));
5031 assert(isVectorRegister(reg3));
5032 assert(isValidVectorDatasize(size));
5033 assert(isValidArrangement(size, opt));
5034 elemsize = optGetElemsize(opt);
5035 if (ins == INS_pmul)
5037 assert(elemsize == EA_1BYTE); // only supports 8B or 16B
5039 else // INS_mul, INS_mla, INS_mls
5041 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
5048 if (isVectorRegister(reg1))
5050 assert(isVectorRegister(reg2));
5051 assert(isVectorRegister(reg3));
5053 if (insOptsAnyArrangement(opt))
5056 assert(opt != INS_OPTS_1D); // Reserved encoding
5057 assert(isValidVectorDatasize(size));
5058 assert(isValidArrangement(size, opt));
5064 assert(insOptsNone(opt));
5065 assert(size == EA_8BYTE);
5074 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, INS_OPTS_NONE);
5083 assert(isVectorRegister(reg1));
5084 assert(isVectorRegister(reg2));
5085 assert(isVectorRegister(reg3));
5087 if (isValidVectorDatasize(size))
5090 assert(insOptsAnyArrangement(opt));
5091 assert(isValidArrangement(size, opt));
5092 elemsize = optGetElemsize(opt);
5099 assert(size == EA_8BYTE); // Only Double supported
5107 assert(isVectorRegister(reg1));
5108 assert(isVectorRegister(reg2));
5109 assert(isVectorRegister(reg3));
5111 if (isValidVectorDatasize(size))
5114 assert(insOptsAnyArrangement(opt));
5115 assert(isValidArrangement(size, opt));
5116 elemsize = optGetElemsize(opt);
5117 assert((elemsize == EA_8BYTE) || (elemsize == EA_4BYTE)); // Only Double/Float supported
5118 assert(opt != INS_OPTS_1D); // Reserved encoding
5125 assert((size == EA_8BYTE) || (size == EA_4BYTE)); // Only Double/Float supported
5138 assert(isVectorRegister(reg1));
5139 assert(isVectorRegister(reg2));
5140 assert(isVectorRegister(reg3));
5141 assert(insOptsAnyArrangement(opt));
5144 assert(isValidVectorDatasize(size));
5145 assert(isValidArrangement(size, opt));
5146 elemsize = optGetElemsize(opt);
5147 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
5153 assert(isVectorRegister(reg1));
5154 assert(isVectorRegister(reg2));
5155 assert(reg2 == reg3);
5156 assert(isValidVectorDatasize(size));
5157 // INS_mov is an alias for INS_orr (vector register)
5158 if (opt == INS_OPTS_NONE)
5160 elemsize = EA_1BYTE;
5161 opt = optMakeArrangement(size, elemsize);
5163 assert(isValidArrangement(size, opt));
5172 if (isVectorRegister(reg1))
5174 assert(isValidVectorDatasize(size));
5175 assert(isVectorRegister(reg2));
5176 assert(isVectorRegister(reg3));
5177 if (opt == INS_OPTS_NONE)
5179 elemsize = EA_1BYTE;
5180 opt = optMakeArrangement(size, elemsize);
5182 assert(isValidArrangement(size, opt));
5191 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, INS_OPTS_NONE);
5197 assert(isValidVectorDatasize(size));
5198 assert(isVectorRegister(reg1));
5199 assert(isVectorRegister(reg2));
5200 assert(isVectorRegister(reg3));
5201 if (opt == INS_OPTS_NONE)
5203 elemsize = EA_1BYTE;
5204 opt = optMakeArrangement(size, elemsize);
5206 assert(isValidArrangement(size, opt));
5218 assert(isVectorRegister(reg1));
5219 assert(isVectorRegister(reg2));
5220 assert(isVectorRegister(reg3));
5221 if (insOptsAnyArrangement(opt))
5224 assert(isValidVectorDatasize(size));
5225 assert(isValidArrangement(size, opt));
5226 elemsize = optGetElemsize(opt);
5227 assert(isValidVectorElemsizeFloat(elemsize));
5228 assert(opt != INS_OPTS_1D); // Reserved encoding
5234 assert(insOptsNone(opt));
5235 assert(isValidScalarDatasize(size));
5242 assert(insOptsNone(opt));
5243 assert(isVectorRegister(reg1));
5244 assert(isVectorRegister(reg2));
5245 assert(isVectorRegister(reg3));
5246 assert(isValidScalarDatasize(size));
5253 assert(isVectorRegister(reg1));
5254 assert(isVectorRegister(reg2));
5255 assert(isVectorRegister(reg3));
5256 assert(insOptsAnyArrangement(opt)); // no scalar encoding, use 4-operand 'fmadd' or 'fmsub'
5259 assert(isValidVectorDatasize(size));
5260 assert(isValidArrangement(size, opt));
5261 elemsize = optGetElemsize(opt);
5262 assert(isValidVectorElemsizeFloat(elemsize));
5263 assert(opt != INS_OPTS_1D); // Reserved encoding
5276 emitIns_R_R_R_Ext(ins, attr, reg1, reg2, reg3, opt);
5284 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0);
5293 assert(isGeneralRegisterOrZR(reg1));
5294 assert(isGeneralRegisterOrZR(reg2));
5295 assert(isGeneralRegisterOrSP(reg3));
5303 } // end switch (ins)
5305 assert(fmt != IF_NONE);
5307 instrDesc* id = emitNewInstr(attr);
5321 /*****************************************************************************
5323 * Add an instruction referencing three registers and a constant.
5326 void emitter::emitIns_R_R_R_I(instruction ins,
5332 insOpts opt /* = INS_OPTS_NONE */,
5333 emitAttr attrReg2 /* = EA_UNKNOWN */)
5335 emitAttr size = EA_SIZE(attr);
5336 emitAttr elemsize = EA_UNKNOWN;
5337 insFormat fmt = IF_NONE;
5338 bool isLdSt = false;
5339 bool isSIMD = false;
5340 bool isAddSub = false;
5341 bool setFlags = false;
5344 /* Figure out the encoding format of the instruction */
5348 assert(insOptsNone(opt));
5349 assert(isValidGeneralDatasize(size));
5350 assert(isGeneralRegister(reg1));
5351 assert(isGeneralRegister(reg2));
5352 assert(isGeneralRegister(reg3));
5353 assert(isValidImmShift(imm, size));
5365 assert(isValidGeneralDatasize(size));
5366 assert(isGeneralRegister(reg1));
5367 assert(isGeneralRegister(reg2));
5368 assert(isGeneralRegister(reg3));
5369 assert(isValidImmShift(imm, size));
5372 assert(insOptsNone(opt)); // a zero imm, means no shift kind
5377 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
5382 case INS_fmul: // by element, imm[0..3] selects the element of reg3
5386 assert(isVectorRegister(reg1));
5387 assert(isVectorRegister(reg2));
5388 assert(isVectorRegister(reg3));
5389 if (insOptsAnyArrangement(opt))
5392 assert(isValidVectorDatasize(size));
5393 assert(isValidArrangement(size, opt));
5394 elemsize = optGetElemsize(opt);
5395 assert(isValidVectorElemsizeFloat(elemsize));
5396 assert(isValidVectorIndex(size, elemsize, imm));
5397 assert(opt != INS_OPTS_1D); // Reserved encoding
5403 assert(insOptsNone(opt));
5404 assert(isValidScalarDatasize(size));
5406 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
5411 case INS_mul: // by element, imm[0..7] selects the element of reg3
5414 assert(isVectorRegister(reg1));
5415 assert(isVectorRegister(reg2));
5416 assert(isVectorRegister(reg3));
5418 assert(insOptsAnyArrangement(opt));
5419 assert(isValidVectorDatasize(size));
5420 assert(isValidArrangement(size, opt));
5421 elemsize = optGetElemsize(opt);
5422 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
5423 // Only has encodings for H or S elemsize
5424 assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE));
5425 // Only has encodings for V0..V15
5426 if ((elemsize == EA_2BYTE) && (reg3 >= REG_V16))
5428 noway_assert(!"Invalid reg3");
5452 assert(insOptsNone(opt)); // Can't use Pre/Post index on these two instructions
5457 // Is the target a vector register?
5458 if (isVectorRegister(reg1))
5460 scale = NaturalScale_helper(size);
5465 scale = (size == EA_8BYTE) ? 3 : 2;
5474 } // end switch (ins)
5479 assert(isGeneralRegisterOrSP(reg3));
5480 assert(insOptsNone(opt) || insOptsIndexed(opt));
5484 assert(isValidVectorLSPDatasize(size));
5485 assert(isVectorRegister(reg1));
5486 assert(isVectorRegister(reg2));
5487 assert((scale >= 2) && (scale <= 4));
5491 assert(isValidGeneralDatasize(size));
5492 assert(isGeneralRegisterOrZR(reg1));
5493 assert(isGeneralRegisterOrZR(reg2));
5494 assert((scale == 2) || (scale == 3));
5497 // Load/Store Pair reserved encodings:
5498 if (emitInsIsLoad(ins))
5500 assert(reg1 != reg2);
5502 if (insOptsIndexed(opt))
5504 assert(reg1 != reg3);
5505 assert(reg2 != reg3);
5508 reg3 = encodingSPtoZR(reg3);
5510 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
5513 assert(insOptsNone(opt)); // PRE/POST Index doesn't make sense with an immediate of zero
5519 if ((imm & mask) == 0)
5521 imm >>= scale; // The immediate is scaled by the size of the ld/st
5523 if ((imm >= -64) && (imm <= 63))
5529 if (fmt != IF_LS_3C)
5531 assert(!"Instruction cannot be encoded: IF_LS_3C");
5538 bool reg2IsSP = (reg2 == REG_SP);
5540 assert(isValidGeneralDatasize(size));
5541 assert(isGeneralRegister(reg3));
5543 if (setFlags || insOptsAluShift(opt)) // Can't encode SP in reg1 with setFlags or AluShift option
5545 assert(isGeneralRegisterOrZR(reg1));
5549 assert(isGeneralRegisterOrSP(reg1));
5550 reg1 = encodingSPtoZR(reg1);
5553 if (insOptsAluShift(opt)) // Can't encode SP in reg2 with AluShift option
5555 assert(isGeneralRegister(reg2));
5559 assert(isGeneralRegisterOrSP(reg2));
5560 reg2 = encodingSPtoZR(reg2);
5563 if (insOptsAnyExtend(opt))
5565 assert((imm >= 0) && (imm <= 4));
5569 else if (insOptsAluShift(opt))
5571 // imm should be non-zero and in [1..63]
5572 assert(isValidImmShift(imm, size) && (imm != 0));
5577 assert(insOptsNone(opt));
5581 // To encode the SP register as reg2 we must use the IF_DR_3C encoding
5582 // and also specify a LSL of zero (imm == 0)
5593 assert(!"Instruction cannot be encoded: Add/Sub IF_DR_3A");
5596 assert(fmt != IF_NONE);
5598 instrDesc* id = emitNewInstrCns(attr, imm);
5608 // Record the attribute for the second register in the pair
5609 id->idGCrefReg2(GCT_NONE);
5610 if (attrReg2 != EA_UNKNOWN)
5612 // Record the attribute for the second register in the pair
5613 assert((fmt == IF_LS_3B) || (fmt == IF_LS_3C));
5614 if (EA_IS_GCREF(attrReg2))
5616 id->idGCrefReg2(GCT_GCREF);
5618 else if (EA_IS_BYREF(attrReg2))
5620 id->idGCrefReg2(GCT_BYREF);
5628 /*****************************************************************************
5630 * Add an instruction referencing three registers, with an extend option
5633 void emitter::emitIns_R_R_R_Ext(instruction ins,
5638 insOpts opt, /* = INS_OPTS_NONE */
5639 int shiftAmount) /* = -1 -- unset */
5641 emitAttr size = EA_SIZE(attr);
5642 insFormat fmt = IF_NONE;
5643 bool isSIMD = false;
5646 /* Figure out the encoding format of the instruction */
5667 // Is the target a vector register?
5668 if (isVectorRegister(reg1))
5670 assert(isValidVectorLSDatasize(size));
5671 scale = NaturalScale_helper(size);
5676 assert(isValidGeneralDatasize(size));
5677 scale = (size == EA_8BYTE) ? 3 : 2;
5686 } // end switch (ins)
5688 assert(scale != -1);
5689 assert(insOptsLSExtend(opt));
5693 assert(isValidVectorLSDatasize(size));
5694 assert(isVectorRegister(reg1));
5698 assert(isValidGeneralLSDatasize(size));
5699 assert(isGeneralRegisterOrZR(reg1));
5702 assert(isGeneralRegisterOrSP(reg2));
5703 assert(isGeneralRegister(reg3));
5705 // Load/Store reserved encodings:
5706 if (insOptsIndexed(opt))
5708 assert(reg1 != reg2);
5711 if (shiftAmount == -1)
5713 shiftAmount = insOptsLSL(opt) ? scale : 0;
5715 assert((shiftAmount == scale) || (shiftAmount == 0));
5717 reg2 = encodingSPtoZR(reg2);
5720 instrDesc* id = emitNewInstr(attr);
5729 id->idReg3Scaled(shiftAmount == scale);
5735 /*****************************************************************************
5737 * Add an instruction referencing two registers and two constants.
5740 void emitter::emitIns_R_R_I_I(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, int imm1, int imm2)
5742 emitAttr size = EA_SIZE(attr);
5743 emitAttr elemsize = EA_UNKNOWN;
5744 insFormat fmt = IF_NONE;
5745 size_t immOut = 0; // composed from imm1 and imm2 and stored in the instrDesc
5747 /* Figure out the encoding format of the instruction */
5757 assert(isGeneralRegister(reg1));
5758 assert(isGeneralRegister(reg2));
5759 assert(isValidImmShift(imm1, size));
5760 assert(isValidImmShift(imm2, size));
5762 bmi.immN = (size == EA_8BYTE);
5765 immOut = bmi.immNRS;
5772 assert(isGeneralRegister(reg1));
5773 assert(isGeneralRegister(reg2));
5774 lsb = getBitWidth(size) - imm1;
5776 assert(isValidImmShift(lsb, size));
5777 assert(isValidImmShift(width, size));
5779 bmi.immN = (size == EA_8BYTE);
5782 immOut = bmi.immNRS;
5789 assert(isGeneralRegister(reg1));
5790 assert(isGeneralRegister(reg2));
5792 width = imm2 + imm1 - 1;
5793 assert(isValidImmShift(lsb, size));
5794 assert(isValidImmShift(width, size));
5796 bmi.immN = (size == EA_8BYTE);
5798 bmi.immS = imm2 + imm1 - 1;
5799 immOut = bmi.immNRS;
5805 assert(isVectorRegister(reg1));
5806 assert(isVectorRegister(reg2));
5808 assert(isValidVectorElemsize(elemsize));
5809 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm1));
5810 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm2));
5811 immOut = (imm1 << 4) + imm2;
5819 assert(fmt != IF_NONE);
5821 instrDesc* id = emitNewInstrSC(attr, immOut);
5833 /*****************************************************************************
5835 * Add an instruction referencing four registers.
5838 void emitter::emitIns_R_R_R_R(
5839 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, regNumber reg4)
5841 emitAttr size = EA_SIZE(attr);
5842 insFormat fmt = IF_NONE;
5844 /* Figure out the encoding format of the instruction */
5853 assert(isValidGeneralDatasize(size));
5854 assert(isGeneralRegister(reg1));
5855 assert(isGeneralRegister(reg2));
5856 assert(isGeneralRegister(reg3));
5857 assert(isGeneralRegister(reg4));
5866 assert(isValidScalarDatasize(size));
5867 assert(isVectorRegister(reg1));
5868 assert(isVectorRegister(reg2));
5869 assert(isVectorRegister(reg3));
5870 assert(isVectorRegister(reg4));
5882 assert(fmt != IF_NONE);
5884 instrDesc* id = emitNewInstr(attr);
5898 /*****************************************************************************
5900 * Add an instruction referencing a register and a condition code
5903 void emitter::emitIns_R_COND(instruction ins, emitAttr attr, regNumber reg, insCond cond)
5905 emitAttr size = EA_SIZE(attr);
5906 insFormat fmt = IF_NONE;
5910 /* Figure out the encoding format of the instruction */
5915 assert(isGeneralRegister(reg));
5924 } // end switch (ins)
5926 assert(fmt != IF_NONE);
5927 assert(isValidImmCond(cfi.immCFVal));
5929 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
5933 id->idInsOpt(INS_OPTS_NONE);
5941 /*****************************************************************************
5943 * Add an instruction referencing two registers and a condition code
5946 void emitter::emitIns_R_R_COND(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insCond cond)
5948 emitAttr size = EA_SIZE(attr);
5949 insFormat fmt = IF_NONE;
5953 /* Figure out the encoding format of the instruction */
5959 assert(isGeneralRegister(reg1));
5960 assert(isGeneralRegister(reg2));
5968 } // end switch (ins)
5970 assert(fmt != IF_NONE);
5971 assert(isValidImmCond(cfi.immCFVal));
5973 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
5977 id->idInsOpt(INS_OPTS_NONE);
5986 /*****************************************************************************
5988 * Add an instruction referencing two registers and a condition code
5991 void emitter::emitIns_R_R_R_COND(
5992 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insCond cond)
5994 emitAttr size = EA_SIZE(attr);
5995 insFormat fmt = IF_NONE;
5999 /* Figure out the encoding format of the instruction */
6006 assert(isGeneralRegister(reg1));
6007 assert(isGeneralRegister(reg2));
6008 assert(isGeneralRegister(reg3));
6017 } // end switch (ins)
6019 assert(fmt != IF_NONE);
6020 assert(isValidImmCond(cfi.immCFVal));
6022 instrDesc* id = emitNewInstr(attr);
6026 id->idInsOpt(INS_OPTS_NONE);
6031 id->idSmallCns(cfi.immCFVal);
6037 /*****************************************************************************
6039 * Add an instruction referencing two registers the flags and a condition code
6042 void emitter::emitIns_R_R_FLAGS_COND(
6043 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insCflags flags, insCond cond)
6045 emitAttr size = EA_SIZE(attr);
6046 insFormat fmt = IF_NONE;
6050 /* Figure out the encoding format of the instruction */
6055 assert(isGeneralRegister(reg1));
6056 assert(isGeneralRegister(reg2));
6064 } // end switch (ins)
6066 assert(fmt != IF_NONE);
6067 assert(isValidImmCondFlags(cfi.immCFVal));
6069 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6073 id->idInsOpt(INS_OPTS_NONE);
6082 /*****************************************************************************
6084 * Add an instruction referencing a register, an immediate, the flags and a condition code
6087 void emitter::emitIns_R_I_FLAGS_COND(
6088 instruction ins, emitAttr attr, regNumber reg, int imm, insCflags flags, insCond cond)
6090 emitAttr size = EA_SIZE(attr);
6091 insFormat fmt = IF_NONE;
6095 /* Figure out the encoding format of the instruction */
6100 assert(isGeneralRegister(reg));
6103 ins = insReverse(ins);
6106 if ((imm >= 0) && (imm <= 31))
6115 assert(!"Instruction cannot be encoded: ccmp/ccmn imm5");
6121 } // end switch (ins)
6123 assert(fmt != IF_NONE);
6124 assert(isValidImmCondFlagsImm5(cfi.immCFVal));
6126 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6130 id->idInsOpt(INS_OPTS_NONE);
6138 /*****************************************************************************
6140 * Add a memory barrier instruction with a 'barrier' immediate
6143 void emitter::emitIns_BARR(instruction ins, insBarrier barrier)
6145 insFormat fmt = IF_NONE;
6148 /* Figure out the encoding format of the instruction */
6156 imm = (ssize_t)barrier;
6161 } // end switch (ins)
6163 assert(fmt != IF_NONE);
6165 instrDesc* id = emitNewInstrSC(EA_8BYTE, imm);
6169 id->idInsOpt(INS_OPTS_NONE);
6175 /*****************************************************************************
6177 * Add an instruction with a static data member operand. If 'size' is 0, the
6178 * instruction operates on the address of the static member instead of its
6179 * value (e.g. "push offset clsvar", rather than "push dword ptr [clsvar]").
6182 void emitter::emitIns_C(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, int offs)
6187 /*****************************************************************************
6189 * Add an instruction referencing stack-based local variable.
6192 void emitter::emitIns_S(instruction ins, emitAttr attr, int varx, int offs)
6197 /*****************************************************************************
6199 * Add an instruction referencing a register and a stack-based local variable.
6201 void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
6203 emitAttr size = EA_SIZE(attr);
6204 insFormat fmt = IF_NONE;
6210 // TODO-ARM64-CQ: use unscaled loads?
6211 /* Figure out the encoding format of the instruction */
6232 assert(isValidGeneralDatasize(size) || isValidVectorDatasize(size));
6233 scale = genLog2(EA_SIZE_IN_BYTES(size));
6237 assert(size == EA_8BYTE);
6242 NYI("emitIns_R_S"); // FP locals?
6245 } // end switch (ins)
6247 /* Figure out the variable's frame position */
6252 base = emitComp->lvaFrameAddress(varx, &FPbased);
6254 assert((scale >= 0) && (scale <= 4));
6256 regNumber reg2 = FPbased ? REG_FPBASE : REG_SPBASE;
6257 reg2 = encodingSPtoZR(reg2);
6274 fmt = IF_DI_2A; // add reg1,reg2,#disp
6278 regNumber rsvdReg = codeGen->rsGetRsvdReg();
6279 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6280 fmt = IF_DR_3A; // add reg1,reg2,rsvdReg
6285 bool useRegForImm = false;
6286 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6293 else if ((imm < 0) || ((imm & mask) != 0))
6295 if ((imm >= -256) && (imm <= 255))
6301 useRegForImm = true;
6306 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
6308 imm >>= scale; // The immediate is scaled by the size of the ld/st
6314 useRegForImm = true;
6320 regNumber rsvdReg = codeGen->rsGetRsvdReg();
6321 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6326 assert(fmt != IF_NONE);
6328 instrDesc* id = emitNewInstrCns(attr, imm);
6332 id->idInsOpt(INS_OPTS_NONE);
6336 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6337 id->idSetIsLclVar();
6340 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6347 /*****************************************************************************
6349 * Add an instruction referencing two register and consectutive stack-based local variable slots.
6351 void emitter::emitIns_R_R_S_S(
6352 instruction ins, emitAttr attr1, emitAttr attr2, regNumber reg1, regNumber reg2, int varx, int offs)
6354 assert((ins == INS_ldp) || (ins == INS_ldnp));
6355 assert(EA_8BYTE == EA_SIZE(attr1));
6356 assert(EA_8BYTE == EA_SIZE(attr2));
6357 assert(isGeneralRegisterOrZR(reg1));
6358 assert(isGeneralRegisterOrZR(reg2));
6361 insFormat fmt = IF_LS_3B;
6363 const unsigned scale = 3;
6365 /* Figure out the variable's frame position */
6369 base = emitComp->lvaFrameAddress(varx, &FPbased);
6372 // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6373 regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE;
6374 reg3 = encodingSPtoZR(reg3);
6376 bool useRegForAdr = true;
6378 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6381 useRegForAdr = false;
6385 if ((imm & mask) == 0)
6387 ssize_t immShift = imm >> scale; // The immediate is scaled by the size of the ld/st
6389 if ((immShift >= -64) && (immShift <= 63))
6392 useRegForAdr = false;
6400 regNumber rsvd = codeGen->rsGetRsvdReg();
6401 emitIns_R_R_Imm(INS_add, EA_PTRSIZE, rsvd, reg3, imm);
6406 assert(fmt != IF_NONE);
6408 instrDesc* id = emitNewInstrCns(attr1, imm);
6412 id->idInsOpt(INS_OPTS_NONE);
6414 // Record the attribute for the second register in the pair
6415 if (EA_IS_GCREF(attr2))
6417 id->idGCrefReg2(GCT_GCREF);
6419 else if (EA_IS_BYREF(attr2))
6421 id->idGCrefReg2(GCT_BYREF);
6425 id->idGCrefReg2(GCT_NONE);
6431 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6432 id->idSetIsLclVar();
6435 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6442 /*****************************************************************************
6444 * Add an instruction referencing a stack-based local variable and a register
6446 void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
6449 emitAttr size = EA_SIZE(attr);
6450 insFormat fmt = IF_NONE;
6453 bool isVectorStore = false;
6455 // TODO-ARM64-CQ: use unscaled loads?
6456 /* Figure out the encoding format of the instruction */
6461 assert(isGeneralRegisterOrZR(reg1));
6466 assert(isGeneralRegisterOrZR(reg1));
6470 if (isGeneralRegisterOrZR(reg1))
6472 assert(isValidGeneralDatasize(size));
6473 scale = (size == EA_8BYTE) ? 3 : 2;
6477 assert(isVectorRegister(reg1));
6478 assert(isValidVectorLSDatasize(size));
6479 scale = NaturalScale_helper(size);
6480 isVectorStore = true;
6485 NYI("emitIns_S_R"); // FP locals?
6488 } // end switch (ins)
6490 /* Figure out the variable's frame position */
6494 base = emitComp->lvaFrameAddress(varx, &FPbased);
6506 // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6507 regNumber reg2 = FPbased ? REG_FPBASE : REG_SPBASE;
6508 reg2 = encodingSPtoZR(reg2);
6510 bool useRegForImm = false;
6512 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6517 else if ((imm < 0) || ((imm & mask) != 0))
6519 if ((imm >= -256) && (imm <= 255))
6525 useRegForImm = true;
6530 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
6532 imm >>= scale; // The immediate is scaled by the size of the ld/st
6538 useRegForImm = true;
6544 // The reserved register is not stored in idReg3() since that field overlaps with iiaLclVar.
6545 // It is instead implicit when idSetIsLclVar() is set, with this encoding format.
6546 regNumber rsvdReg = codeGen->rsGetRsvdReg();
6547 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6551 assert(fmt != IF_NONE);
6553 instrDesc* id = emitNewInstrCns(attr, imm);
6557 id->idInsOpt(INS_OPTS_NONE);
6561 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6562 id->idSetIsLclVar();
6565 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6572 /*****************************************************************************
6574 * Add an instruction referencing consecutive stack-based local variable slots and two registers
6576 void emitter::emitIns_S_S_R_R(
6577 instruction ins, emitAttr attr1, emitAttr attr2, regNumber reg1, regNumber reg2, int varx, int offs)
6579 assert((ins == INS_stp) || (ins == INS_stnp));
6580 assert(EA_8BYTE == EA_SIZE(attr1));
6581 assert(EA_8BYTE == EA_SIZE(attr2));
6582 assert(isGeneralRegisterOrZR(reg1));
6583 assert(isGeneralRegisterOrZR(reg2));
6586 insFormat fmt = IF_LS_3B;
6588 const unsigned scale = 3;
6590 /* Figure out the variable's frame position */
6594 base = emitComp->lvaFrameAddress(varx, &FPbased);
6597 // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6598 regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE;
6599 reg3 = encodingSPtoZR(reg3);
6601 bool useRegForAdr = true;
6603 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6606 useRegForAdr = false;
6610 if ((imm & mask) == 0)
6612 ssize_t immShift = imm >> scale; // The immediate is scaled by the size of the ld/st
6614 if ((immShift >= -64) && (immShift <= 63))
6617 useRegForAdr = false;
6625 regNumber rsvd = codeGen->rsGetRsvdReg();
6626 emitIns_R_R_Imm(INS_add, EA_PTRSIZE, rsvd, reg3, imm);
6631 assert(fmt != IF_NONE);
6633 instrDesc* id = emitNewInstrCns(attr1, imm);
6637 id->idInsOpt(INS_OPTS_NONE);
6639 // Record the attribute for the second register in the pair
6640 if (EA_IS_GCREF(attr2))
6642 id->idGCrefReg2(GCT_GCREF);
6644 else if (EA_IS_BYREF(attr2))
6646 id->idGCrefReg2(GCT_BYREF);
6650 id->idGCrefReg2(GCT_NONE);
6656 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6657 id->idSetIsLclVar();
6660 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6667 /*****************************************************************************
6669 * Add an instruction referencing stack-based local variable and an immediate
6671 void emitter::emitIns_S_I(instruction ins, emitAttr attr, int varx, int offs, int val)
6676 /*****************************************************************************
6678 * Add an instruction with a register + static member operands.
6679 * Constant is stored into JIT data which is adjacent to code.
6680 * No relocation is needed. PC-relative offset will be encoded directly into instruction.
6683 void emitter::emitIns_R_C(
6684 instruction ins, emitAttr attr, regNumber reg, regNumber addrReg, CORINFO_FIELD_HANDLE fldHnd, int offs)
6687 assert(instrDesc::fitsInSmallCns(offs));
6689 emitAttr size = EA_SIZE(attr);
6690 insFormat fmt = IF_NONE;
6692 instrDescJmp* id = emitNewInstrJmp();
6697 // This is case to get address to the constant data.
6699 assert(isGeneralRegister(reg));
6700 assert(isValidGeneralDatasize(size));
6705 if (isVectorRegister(reg))
6707 assert(isValidScalarDatasize(size));
6708 // For vector (float/double) register, we should have an integer address reg to
6709 // compute long address which consists of page address and page offset.
6710 // For integer constant, this is not needed since the dest reg can be used to
6711 // compute address as well as contain the final contents.
6712 assert(isGeneralRegister(reg) || (addrReg != REG_NA));
6716 assert(isGeneralRegister(reg));
6717 assert(isValidGeneralDatasize(size));
6724 assert(fmt != IF_NONE);
6728 id->idInsOpt(INS_OPTS_NONE);
6729 id->idSmallCns(offs);
6731 id->idAddr()->iiaFieldHnd = fldHnd;
6732 id->idSetIsBound(); // We won't patch address since we will know the exact distance once JIT code and data are
6733 // allocated together.
6735 id->idReg1(reg); // destination register that will get the constant value.
6736 if (addrReg != REG_NA)
6738 id->idReg2(addrReg); // integer register to compute long address (used for vector dest when we end up with long
6741 id->idjShort = false; // Assume loading constant from long address
6743 // Keep it long if it's in cold code.
6744 id->idjKeepLong = emitComp->fgIsBlockCold(emitComp->compCurBB);
6747 if (emitComp->opts.compLongAddress)
6748 id->idjKeepLong = 1;
6751 // If it's possible to be shortened, then put it in jump list
6752 // to be revisited by emitJumpDistBind.
6753 if (!id->idjKeepLong)
6755 /* Record the jump's IG and offset within it */
6756 id->idjIG = emitCurIG;
6757 id->idjOffs = emitCurIGsize;
6759 /* Append this jump to this IG's jump list */
6760 id->idjNext = emitCurIGjmpList;
6761 emitCurIGjmpList = id;
6772 /*****************************************************************************
6774 * Add an instruction with a static member + constant.
6777 void emitter::emitIns_C_I(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, ssize_t offs, ssize_t val)
6782 /*****************************************************************************
6784 * Add an instruction with a static member + register operands.
6787 void emitter::emitIns_C_R(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, regNumber reg, int offs)
6789 assert(!"emitIns_C_R not supported for RyuJIT backend");
6792 void emitter::emitIns_R_AR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
6794 NYI("emitIns_R_AR");
6797 // This computes address from the immediate which is relocatable.
6798 void emitter::emitIns_R_AI(instruction ins, emitAttr attr, regNumber ireg, ssize_t addr)
6800 assert(EA_IS_RELOC(attr));
6801 emitAttr size = EA_SIZE(attr);
6802 insFormat fmt = IF_DI_1E;
6803 bool needAdd = false;
6804 instrDescJmp* id = emitNewInstrJmp();
6809 // This computes page address.
6810 // page offset is needed using add.
6821 id->idInsOpt(INS_OPTS_NONE);
6823 id->idAddr()->iiaAddr = (BYTE*)addr;
6825 id->idSetIsDspReloc();
6832 // add reg, reg, imm
6835 instrDesc* id = emitAllocInstr(attr);
6836 assert(id->idIsReloc());
6840 id->idInsOpt(INS_OPTS_NONE);
6842 id->idAddr()->iiaAddr = (BYTE*)addr;
6851 void emitter::emitIns_AR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
6853 NYI("emitIns_AR_R");
6856 void emitter::emitIns_R_ARR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
6858 NYI("emitIns_R_ARR");
6861 void emitter::emitIns_ARR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
6863 NYI("emitIns_R_ARR");
6866 void emitter::emitIns_R_ARX(
6867 instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, unsigned mul, int disp)
6869 NYI("emitIns_R_ARR");
6872 /*****************************************************************************
6874 * Record that a jump instruction uses the short encoding
6877 void emitter::emitSetShortJump(instrDescJmp* id)
6879 if (id->idjKeepLong)
6882 insFormat fmt = IF_NONE;
6883 if (emitIsCondJump(id))
6885 switch (id->idIns())
6900 else if (emitIsLoadLabel(id))
6904 else if (emitIsLoadConstant(id))
6914 id->idjShort = true;
6917 /*****************************************************************************
6919 * Add a label instruction.
6922 void emitter::emitIns_R_L(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
6924 assert(dst->bbFlags & BBF_JMP_TARGET);
6926 insFormat fmt = IF_NONE;
6937 instrDescJmp* id = emitNewInstrJmp();
6941 id->idjShort = false;
6942 id->idAddr()->iiaBBlabel = dst;
6944 id->idOpSize(EA_PTRSIZE);
6947 // Mark the catch return
6948 if (emitComp->compCurBB->bbJumpKind == BBJ_EHCATCHRET)
6950 id->idDebugOnlyInfo()->idCatchRet = true;
6954 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
6957 if (emitComp->opts.compLongAddress)
6958 id->idjKeepLong = 1;
6961 /* Record the jump's IG and offset within it */
6963 id->idjIG = emitCurIG;
6964 id->idjOffs = emitCurIGsize;
6966 /* Append this jump to this IG's jump list */
6968 id->idjNext = emitCurIGjmpList;
6969 emitCurIGjmpList = id;
6979 /*****************************************************************************
6981 * Add a data label instruction.
6984 void emitter::emitIns_R_D(instruction ins, emitAttr attr, unsigned offs, regNumber reg)
6989 void emitter::emitIns_J_R(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
6991 assert((ins == INS_cbz) || (ins == INS_cbnz));
6993 assert(dst != nullptr);
6994 assert((dst->bbFlags & BBF_JMP_TARGET) != 0);
6996 insFormat fmt = IF_LARGEJMP;
6998 instrDescJmp* id = emitNewInstrJmp();
7003 id->idjShort = false;
7004 id->idOpSize(EA_SIZE(attr));
7006 id->idAddr()->iiaBBlabel = dst;
7007 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7009 /* Record the jump's IG and offset within it */
7011 id->idjIG = emitCurIG;
7012 id->idjOffs = emitCurIGsize;
7014 /* Append this jump to this IG's jump list */
7016 id->idjNext = emitCurIGjmpList;
7017 emitCurIGjmpList = id;
7027 void emitter::emitIns_J_R_I(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg, int imm)
7029 assert((ins == INS_tbz) || (ins == INS_tbnz));
7031 assert(dst != nullptr);
7032 assert((dst->bbFlags & BBF_JMP_TARGET) != 0);
7033 assert((EA_SIZE(attr) == EA_4BYTE) || (EA_SIZE(attr) == EA_8BYTE));
7034 assert(imm < ((EA_SIZE(attr) == EA_4BYTE) ? 32 : 64));
7036 insFormat fmt = IF_LARGEJMP;
7038 instrDescJmp* id = emitNewInstrJmp();
7043 id->idjShort = false;
7044 id->idSmallCns(imm);
7045 id->idOpSize(EA_SIZE(attr));
7047 id->idAddr()->iiaBBlabel = dst;
7048 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7050 /* Record the jump's IG and offset within it */
7052 id->idjIG = emitCurIG;
7053 id->idjOffs = emitCurIGsize;
7055 /* Append this jump to this IG's jump list */
7057 id->idjNext = emitCurIGjmpList;
7058 emitCurIGjmpList = id;
7068 void emitter::emitIns_J(instruction ins, BasicBlock* dst, int instrCount)
7070 insFormat fmt = IF_NONE;
7074 assert(dst->bbFlags & BBF_JMP_TARGET);
7078 assert(instrCount != 0);
7081 /* Figure out the encoding format of the instruction */
7083 bool idjShort = false;
7088 // Unconditional jump is a single form.
7107 // Assume conditional jump is long.
7116 instrDescJmp* id = emitNewInstrJmp();
7120 id->idjShort = idjShort;
7123 // Mark the finally call
7124 if (ins == INS_bl_local && emitComp->compCurBB->bbJumpKind == BBJ_CALLFINALLY)
7126 id->idDebugOnlyInfo()->idFinallyCall = true;
7132 id->idAddr()->iiaBBlabel = dst;
7134 // Skip unconditional jump that has a single form.
7135 // TODO-ARM64-NYI: enable hot/cold splittingNYI.
7136 // The target needs to be relocated.
7139 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7142 if (emitComp->opts.compLongAddress) // Force long branches
7143 id->idjKeepLong = 1;
7149 id->idAddr()->iiaSetInstrCount(instrCount);
7150 id->idjKeepLong = false;
7151 /* This jump must be short */
7152 emitSetShortJump(id);
7156 /* Record the jump's IG and offset within it */
7158 id->idjIG = emitCurIG;
7159 id->idjOffs = emitCurIGsize;
7161 /* Append this jump to this IG's jump list */
7163 id->idjNext = emitCurIGjmpList;
7164 emitCurIGjmpList = id;
7174 /*****************************************************************************
7176 * Add a call instruction (direct or indirect).
7177 * argSize<0 means that the caller will pop the arguments
7179 * The other arguments are interpreted depending on callType as shown:
7180 * Unless otherwise specified, ireg,xreg,xmul,disp should have default values.
7182 * EC_FUNC_TOKEN : addr is the method address
7183 * EC_FUNC_ADDR : addr is the absolute address of the function
7185 * If callType is one of these emitCallTypes, addr has to be NULL.
7186 * EC_INDIR_R : "call ireg".
7188 * For ARM xreg, xmul and disp are never used and should always be 0/REG_NA.
7190 * Please consult the "debugger team notification" comment in genFnProlog().
7193 void emitter::emitIns_Call(EmitCallType callType,
7194 CORINFO_METHOD_HANDLE methHnd,
7195 INDEBUG_LDISASM_COMMA(CORINFO_SIG_INFO* sigInfo) // used to report call sites to the EE
7199 emitAttr secondRetSize,
7200 VARSET_VALARG_TP ptrVars,
7201 regMaskTP gcrefRegs,
7202 regMaskTP byrefRegs,
7203 IL_OFFSETX ilOffset /* = BAD_IL_OFFSET */,
7204 regNumber ireg /* = REG_NA */,
7205 regNumber xreg /* = REG_NA */,
7206 unsigned xmul /* = 0 */,
7207 ssize_t disp /* = 0 */,
7208 bool isJump /* = false */,
7209 bool isNoGC /* = false */,
7210 bool isProfLeaveCB /* = false */)
7212 /* Sanity check the arguments depending on callType */
7214 assert(callType < EC_COUNT);
7215 assert((callType != EC_FUNC_TOKEN && callType != EC_FUNC_ADDR) ||
7216 (ireg == REG_NA && xreg == REG_NA && xmul == 0 && disp == 0));
7217 assert(callType < EC_INDIR_R || addr == NULL);
7218 assert(callType != EC_INDIR_R || (ireg < REG_COUNT && xreg == REG_NA && xmul == 0 && disp == 0));
7220 // ARM never uses these
7221 assert(xreg == REG_NA && xmul == 0 && disp == 0);
7223 // Our stack level should be always greater than the bytes of arguments we push. Just
7225 assert((unsigned)abs(argSize) <= codeGen->genStackLevel);
7230 /* This is the saved set of registers after a normal call */
7231 regMaskTP savedSet = RBM_CALLEE_SAVED;
7233 /* some special helper calls have a different saved set registers */
7237 assert(emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
7239 // Get the set of registers that this call kills and remove it from the saved set.
7240 savedSet = RBM_ALLINT & ~emitComp->compNoGCHelperCallKillSet(Compiler::eeGetHelperNum(methHnd));
7242 // In case of Leave profiler callback, we need to preserve liveness of REG_PROFILER_RET_SCRATCH
7245 savedSet |= RBM_PROFILER_RET_SCRATCH;
7250 assert(!emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
7253 /* Trim out any callee-trashed registers from the live set */
7255 gcrefRegs &= savedSet;
7256 byrefRegs &= savedSet;
7259 if (EMIT_GC_VERBOSE)
7261 printf("Call: GCvars=%s ", VarSetOps::ToString(emitComp, ptrVars));
7262 dumpConvertedVarSet(emitComp, ptrVars);
7263 printf(", gcrefRegs=");
7264 printRegMaskInt(gcrefRegs);
7265 emitDispRegSet(gcrefRegs);
7266 printf(", byrefRegs=");
7267 printRegMaskInt(byrefRegs);
7268 emitDispRegSet(byrefRegs);
7273 assert(argSize % REGSIZE_BYTES == 0);
7274 argCnt = (int)(argSize / (int)REGSIZE_BYTES);
7276 /* Managed RetVal: emit sequence point for the call */
7277 if (emitComp->opts.compDbgInfo && ilOffset != BAD_IL_OFFSET)
7279 codeGen->genIPmappingAdd(ilOffset, false);
7283 We need to allocate the appropriate instruction descriptor based
7284 on whether this is a direct/indirect call, and whether we need to
7285 record an updated set of live GC variables.
7288 if (callType >= EC_INDIR_R)
7290 /* Indirect call, virtual calls */
7292 assert(callType == EC_INDIR_R);
7294 id = emitNewInstrCallInd(argCnt, disp, ptrVars, gcrefRegs, byrefRegs, retSize, secondRetSize);
7298 /* Helper/static/nonvirtual/function calls (direct or through handle),
7299 and calls to an absolute addr. */
7301 assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
7303 id = emitNewInstrCallDir(argCnt, ptrVars, gcrefRegs, byrefRegs, retSize, secondRetSize);
7306 /* Update the emitter's live GC ref sets */
7308 VarSetOps::Assign(emitComp, emitThisGCrefVars, ptrVars);
7309 emitThisGCrefRegs = gcrefRegs;
7310 emitThisByrefRegs = byrefRegs;
7312 /* Set the instruction - special case jumping a function */
7314 insFormat fmt = IF_NONE;
7316 id->idSetIsNoGC(isNoGC);
7318 /* Record the address: method, indirection, or funcptr */
7320 if (callType > EC_FUNC_ADDR)
7322 /* This is an indirect call (either a virtual call or func ptr call) */
7326 case EC_INDIR_R: // the address is in a register
7328 id->idSetIsCallRegPtr();
7332 ins = INS_br_tail; // INS_br_tail Reg
7336 ins = INS_blr; // INS_blr Reg
7344 assert(xreg == REG_NA);
7348 NO_WAY("unexpected instruction");
7354 /* This is a simple direct call: "call helper/method/addr" */
7356 assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
7358 assert(addr != NULL);
7362 ins = INS_b_tail; // INS_b_tail imm28
7366 ins = INS_bl; // INS_bl imm28
7373 id->idAddr()->iiaAddr = (BYTE*)addr;
7375 if (callType == EC_FUNC_ADDR)
7377 id->idSetIsCallAddr();
7380 if (emitComp->opts.compReloc)
7382 id->idSetIsDspReloc();
7387 if (EMIT_GC_VERBOSE)
7389 if (id->idIsLargeCall())
7391 printf("[%02u] Rec call GC vars = %s\n", id->idDebugOnlyInfo()->idNum,
7392 VarSetOps::ToString(emitComp, ((instrDescCGCA*)id)->idcGCvars));
7396 id->idDebugOnlyInfo()->idMemCookie = (size_t)methHnd; // method token
7397 id->idDebugOnlyInfo()->idCallSig = sigInfo;
7401 if (addr != nullptr)
7403 codeGen->getDisAssembler().disSetMethod((size_t)addr, methHnd);
7405 #endif // LATE_DISASM
7411 /*****************************************************************************
7413 * Returns true if 'imm' is valid Cond encoding
7416 /*static*/ bool emitter::isValidImmCond(ssize_t imm)
7418 // range check the ssize_t value, to make sure it is a small unsigned value
7419 // and that only the bits in the cfi.cond are set
7420 if ((imm < 0) || (imm > 0xF))
7424 cfi.immCFVal = (unsigned)imm;
7426 return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7429 /*****************************************************************************
7431 * Returns true if 'imm' is valid Cond/Flags encoding
7434 /*static*/ bool emitter::isValidImmCondFlags(ssize_t imm)
7436 // range check the ssize_t value, to make sure it is a small unsigned value
7437 // and that only the bits in the cfi.cond or cfi.flags are set
7438 if ((imm < 0) || (imm > 0xFF))
7442 cfi.immCFVal = (unsigned)imm;
7444 return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7447 /*****************************************************************************
7449 * Returns true if 'imm' is valid Cond/Flags/Imm5 encoding
7452 /*static*/ bool emitter::isValidImmCondFlagsImm5(ssize_t imm)
7454 // range check the ssize_t value, to make sure it is a small unsigned value
7455 // and that only the bits in the cfi.cond, cfi.flags or cfi.imm5 are set
7456 if ((imm < 0) || (imm > 0x1FFF))
7460 cfi.immCFVal = (unsigned)imm;
7462 return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7465 /*****************************************************************************
7467 * Returns an encoding for the specified register used in the 'Rd' position
7470 /*static*/ emitter::code_t emitter::insEncodeReg_Rd(regNumber reg)
7472 assert(isIntegerRegister(reg));
7473 emitter::code_t ureg = (emitter::code_t)reg;
7474 assert((ureg >= 0) && (ureg <= 31));
7478 /*****************************************************************************
7480 * Returns an encoding for the specified register used in the 'Rt' position
7483 /*static*/ emitter::code_t emitter::insEncodeReg_Rt(regNumber reg)
7485 assert(isIntegerRegister(reg));
7486 emitter::code_t ureg = (emitter::code_t)reg;
7487 assert((ureg >= 0) && (ureg <= 31));
7491 /*****************************************************************************
7493 * Returns an encoding for the specified register used in the 'Rn' position
7496 /*static*/ emitter::code_t emitter::insEncodeReg_Rn(regNumber reg)
7498 assert(isIntegerRegister(reg));
7499 emitter::code_t ureg = (emitter::code_t)reg;
7500 assert((ureg >= 0) && (ureg <= 31));
7504 /*****************************************************************************
7506 * Returns an encoding for the specified register used in the 'Rm' position
7509 /*static*/ emitter::code_t emitter::insEncodeReg_Rm(regNumber reg)
7511 assert(isIntegerRegister(reg));
7512 emitter::code_t ureg = (emitter::code_t)reg;
7513 assert((ureg >= 0) && (ureg <= 31));
7517 /*****************************************************************************
7519 * Returns an encoding for the specified register used in the 'Ra' position
7522 /*static*/ emitter::code_t emitter::insEncodeReg_Ra(regNumber reg)
7524 assert(isIntegerRegister(reg));
7525 emitter::code_t ureg = (emitter::code_t)reg;
7526 assert((ureg >= 0) && (ureg <= 31));
7530 /*****************************************************************************
7532 * Returns an encoding for the specified register used in the 'Vd' position
7535 /*static*/ emitter::code_t emitter::insEncodeReg_Vd(regNumber reg)
7537 assert(emitter::isVectorRegister(reg));
7538 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7539 assert((ureg >= 0) && (ureg <= 31));
7543 /*****************************************************************************
7545 * Returns an encoding for the specified register used in the 'Vt' position
7548 /*static*/ emitter::code_t emitter::insEncodeReg_Vt(regNumber reg)
7550 assert(emitter::isVectorRegister(reg));
7551 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7552 assert((ureg >= 0) && (ureg <= 31));
7556 /*****************************************************************************
7558 * Returns an encoding for the specified register used in the 'Vn' position
7561 /*static*/ emitter::code_t emitter::insEncodeReg_Vn(regNumber reg)
7563 assert(emitter::isVectorRegister(reg));
7564 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7565 assert((ureg >= 0) && (ureg <= 31));
7569 /*****************************************************************************
7571 * Returns an encoding for the specified register used in the 'Vm' position
7574 /*static*/ emitter::code_t emitter::insEncodeReg_Vm(regNumber reg)
7576 assert(emitter::isVectorRegister(reg));
7577 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7578 assert((ureg >= 0) && (ureg <= 31));
7582 /*****************************************************************************
7584 * Returns an encoding for the specified register used in the 'Va' position
7587 /*static*/ emitter::code_t emitter::insEncodeReg_Va(regNumber reg)
7589 assert(emitter::isVectorRegister(reg));
7590 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7591 assert((ureg >= 0) && (ureg <= 31));
7595 /*****************************************************************************
7597 * Returns an encoding for the specified condition code.
7600 /*static*/ emitter::code_t emitter::insEncodeCond(insCond cond)
7602 emitter::code_t uimm = (emitter::code_t)cond;
7606 /*****************************************************************************
7608 * Returns an encoding for the condition code with the lowest bit inverted (marked by invert(<cond>) in the
7609 * architecture manual).
7612 /*static*/ emitter::code_t emitter::insEncodeInvertedCond(insCond cond)
7614 emitter::code_t uimm = (emitter::code_t)cond;
7615 uimm ^= 1; // invert the lowest bit
7619 /*****************************************************************************
7621 * Returns an encoding for the specified flags.
7624 /*static*/ emitter::code_t emitter::insEncodeFlags(insCflags flags)
7626 emitter::code_t uimm = (emitter::code_t)flags;
7630 /*****************************************************************************
7632 * Returns the encoding for the Shift Count bits to be used for Arm64 encodings
7635 /*static*/ emitter::code_t emitter::insEncodeShiftCount(ssize_t imm, emitAttr size)
7637 assert((imm & 0x003F) == imm);
7638 assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
7640 return (emitter::code_t)imm << 10;
7643 /*****************************************************************************
7645 * Returns the encoding to select a 64-bit datasize for an Arm64 instruction
7648 /*static*/ emitter::code_t emitter::insEncodeDatasize(emitAttr size)
7650 if (size == EA_8BYTE)
7652 return 0x80000000; // set the bit at location 31
7656 assert(size == EA_4BYTE);
7661 /*****************************************************************************
7663 * Returns the encoding to select the datasize for the general load/store Arm64 instructions
7667 /*static*/ emitter::code_t emitter::insEncodeDatasizeLS(emitter::code_t code, emitAttr size)
7669 bool exclusive = ((code & 0x35000000) == 0);
7671 if ((code & 0x00800000) && !exclusive) // Is this a sign-extending opcode? (i.e. ldrsw, ldrsh, ldrsb)
7673 if ((code & 0x80000000) == 0) // Is it a ldrsh or ldrsb and not ldrsw ?
7675 if (EA_SIZE(size) != EA_8BYTE) // Do we need to encode the 32-bit Rt size bit?
7677 return 0x00400000; // set the bit at location 22
7681 else if (code & 0x80000000) // Is this a ldr/str/ldur/stur opcode?
7683 if (EA_SIZE(size) == EA_8BYTE) // Do we need to encode the 64-bit size bit?
7685 return 0x40000000; // set the bit at location 30
7691 /*****************************************************************************
7693 * Returns the encoding to select the datasize for the vector load/store Arm64 instructions
7697 /*static*/ emitter::code_t emitter::insEncodeDatasizeVLS(emitter::code_t code, emitAttr size)
7702 if ((code & 0x20000000) == 0)
7706 if (size == EA_16BYTE)
7708 // set the operation size in bit 31
7709 result = 0x80000000;
7711 else if (size == EA_8BYTE)
7713 // set the operation size in bit 30
7714 result = 0x40000000;
7718 assert(size == EA_4BYTE);
7720 result = 0x00000000;
7727 if (size == EA_16BYTE)
7729 // The operation size in bits 31 and 30 are zero
7730 // Bit 23 specifies a 128-bit Load/Store
7731 result = 0x00800000;
7733 else if (size == EA_8BYTE)
7735 // set the operation size in bits 31 and 30
7736 result = 0xC0000000;
7738 else if (size == EA_4BYTE)
7740 // set the operation size in bit 31
7741 result = 0x80000000;
7743 else if (size == EA_2BYTE)
7745 // set the operation size in bit 30
7746 result = 0x40000000;
7750 assert(size == EA_1BYTE);
7751 // The operation size in bits 31 and 30 are zero
7752 result = 0x00000000;
7756 // Or in bit 26 to indicate a Vector register is used as 'target'
7757 result |= 0x04000000;
7762 /*****************************************************************************
7764 * Returns the encoding to select the datasize for the vector load/store Arm64 instructions
7768 /*static*/ emitter::code_t emitter::insEncodeDatasizeVPLS(emitter::code_t code, emitAttr size)
7772 if (size == EA_16BYTE)
7774 // The operation size in bits 31 and 30 are zero
7775 // Bit 23 specifies a 128-bit Load/Store
7776 result = 0x80000000;
7778 else if (size == EA_8BYTE)
7780 // set the operation size in bits 31 and 30
7781 result = 0x40000000;
7783 else if (size == EA_4BYTE)
7785 // set the operation size in bit 31
7786 result = 0x00000000;
7789 // Or in bit 26 to indicate a Vector register is used as 'target'
7790 result |= 0x04000000;
7795 /*****************************************************************************
7797 * Returns the encoding to set the size bit and the N bits for a 'bitfield' instruction
7801 /*static*/ emitter::code_t emitter::insEncodeDatasizeBF(emitter::code_t code, emitAttr size)
7803 // is bit 30 equal to 0?
7804 if ((code & 0x40000000) == 0) // is the opcode one of extr, sxtb, sxth or sxtw
7806 if (size == EA_8BYTE) // Do we need to set the sf and N bits?
7808 return 0x80400000; // set the sf-bit at location 31 and the N-bit at location 22
7811 return 0; // don't set any bits
7814 /*****************************************************************************
7816 * Returns the encoding to select the 64/128-bit datasize for an Arm64 vector instruction
7819 /*static*/ emitter::code_t emitter::insEncodeVectorsize(emitAttr size)
7821 if (size == EA_16BYTE)
7823 return 0x40000000; // set the bit at location 30
7827 assert(size == EA_8BYTE);
7832 /*****************************************************************************
7834 * Returns the encoding to select 'index' for an Arm64 vector elem instruction
7836 /*static*/ emitter::code_t emitter::insEncodeVectorIndex(emitAttr elemsize, ssize_t index)
7838 code_t bits = (code_t)index;
7839 if (elemsize == EA_1BYTE)
7844 else if (elemsize == EA_2BYTE)
7849 else if (elemsize == EA_4BYTE)
7856 assert(elemsize == EA_8BYTE);
7860 assert((bits >= 1) && (bits <= 0x1f));
7862 return (bits << 16); // bits at locations [20,19,18,17,16]
7865 /*****************************************************************************
7867 * Returns the encoding to select 'index2' for an Arm64 'ins' elem instruction
7869 /*static*/ emitter::code_t emitter::insEncodeVectorIndex2(emitAttr elemsize, ssize_t index2)
7871 code_t bits = (code_t)index2;
7872 if (elemsize == EA_1BYTE)
7876 else if (elemsize == EA_2BYTE)
7880 else if (elemsize == EA_4BYTE)
7886 assert(elemsize == EA_8BYTE);
7889 assert((bits >= 0) && (bits <= 0xf));
7891 return (bits << 11); // bits at locations [14,13,12,11]
7894 /*****************************************************************************
7896 * Returns the encoding to select the 'index' for an Arm64 'mul' by elem instruction
7898 /*static*/ emitter::code_t emitter::insEncodeVectorIndexLMH(emitAttr elemsize, ssize_t index)
7902 if (elemsize == EA_2BYTE)
7904 assert((index >= 0) && (index <= 7));
7907 bits |= (1 << 11); // set bit 11 'H'
7911 bits |= (1 << 21); // set bit 21 'L'
7915 bits |= (1 << 20); // set bit 20 'M'
7918 else if (elemsize == EA_4BYTE)
7920 assert((index >= 0) && (index <= 3));
7923 bits |= (1 << 11); // set bit 11 'H'
7927 bits |= (1 << 21); // set bit 21 'L'
7932 assert(!"Invalid 'elemsize' value");
7938 /*****************************************************************************
7940 * Returns the encoding to shift by 'shift' for an Arm64 vector or scalar instruction
7943 /*static*/ emitter::code_t emitter::insEncodeVectorShift(emitAttr size, ssize_t shift)
7945 assert(shift < getBitWidth(size));
7947 code_t imm = (code_t)(getBitWidth(size) + shift);
7952 /*****************************************************************************
7954 * Returns the encoding to select the 1/2/4/8 byte elemsize for an Arm64 vector instruction
7957 /*static*/ emitter::code_t emitter::insEncodeElemsize(emitAttr size)
7959 if (size == EA_8BYTE)
7961 return 0x00C00000; // set the bit at location 23 and 22
7963 else if (size == EA_4BYTE)
7965 return 0x00800000; // set the bit at location 23
7967 else if (size == EA_2BYTE)
7969 return 0x00400000; // set the bit at location 22
7971 assert(size == EA_1BYTE);
7975 /*****************************************************************************
7977 * Returns the encoding to select the 4/8 byte elemsize for an Arm64 float vector instruction
7980 /*static*/ emitter::code_t emitter::insEncodeFloatElemsize(emitAttr size)
7982 if (size == EA_8BYTE)
7984 return 0x00400000; // set the bit at location 22
7986 assert(size == EA_4BYTE);
7990 // Returns the encoding to select the index for an Arm64 float vector by elem instruction
7991 /*static*/ emitter::code_t emitter::insEncodeFloatIndex(emitAttr elemsize, ssize_t index)
7993 code_t result = 0x00000000;
7994 if (elemsize == EA_8BYTE)
7996 assert((index >= 0) && (index <= 1));
7999 result |= 0x00000800; // 'H' - set the bit at location 11
8004 assert(elemsize == EA_4BYTE);
8005 assert((index >= 0) && (index <= 3));
8008 result |= 0x00000800; // 'H' - set the bit at location 11
8012 result |= 0x00200000; // 'L' - set the bit at location 21
8018 /*****************************************************************************
8020 * Returns the encoding to select the fcvt operation for Arm64 instructions
8022 /*static*/ emitter::code_t emitter::insEncodeConvertOpt(insFormat fmt, insOpts conversion)
8027 case INS_OPTS_S_TO_D: // Single to Double
8028 assert(fmt == IF_DV_2J);
8029 result = 0x00008000; // type=00, opc=01
8032 case INS_OPTS_D_TO_S: // Double to Single
8033 assert(fmt == IF_DV_2J);
8034 result = 0x00400000; // type=01, opc=00
8037 case INS_OPTS_H_TO_S: // Half to Single
8038 assert(fmt == IF_DV_2J);
8039 result = 0x00C00000; // type=11, opc=00
8042 case INS_OPTS_H_TO_D: // Half to Double
8043 assert(fmt == IF_DV_2J);
8044 result = 0x00C08000; // type=11, opc=01
8047 case INS_OPTS_S_TO_H: // Single to Half
8048 assert(fmt == IF_DV_2J);
8049 result = 0x00018000; // type=00, opc=11
8052 case INS_OPTS_D_TO_H: // Double to Half
8053 assert(fmt == IF_DV_2J);
8054 result = 0x00418000; // type=01, opc=11
8057 case INS_OPTS_S_TO_4BYTE: // Single to INT32
8058 assert(fmt == IF_DV_2H);
8059 result = 0x00000000; // sf=0, type=00
8062 case INS_OPTS_D_TO_4BYTE: // Double to INT32
8063 assert(fmt == IF_DV_2H);
8064 result = 0x00400000; // sf=0, type=01
8067 case INS_OPTS_S_TO_8BYTE: // Single to INT64
8068 assert(fmt == IF_DV_2H);
8069 result = 0x80000000; // sf=1, type=00
8072 case INS_OPTS_D_TO_8BYTE: // Double to INT64
8073 assert(fmt == IF_DV_2H);
8074 result = 0x80400000; // sf=1, type=01
8077 case INS_OPTS_4BYTE_TO_S: // INT32 to Single
8078 assert(fmt == IF_DV_2I);
8079 result = 0x00000000; // sf=0, type=00
8082 case INS_OPTS_4BYTE_TO_D: // INT32 to Double
8083 assert(fmt == IF_DV_2I);
8084 result = 0x00400000; // sf=0, type=01
8087 case INS_OPTS_8BYTE_TO_S: // INT64 to Single
8088 assert(fmt == IF_DV_2I);
8089 result = 0x80000000; // sf=1, type=00
8092 case INS_OPTS_8BYTE_TO_D: // INT64 to Double
8093 assert(fmt == IF_DV_2I);
8094 result = 0x80400000; // sf=1, type=01
8098 assert(!"Invalid 'conversion' value");
8104 /*****************************************************************************
8106 * Returns the encoding to have the Rn register be updated Pre/Post indexed
8110 /*static*/ emitter::code_t emitter::insEncodeIndexedOpt(insOpts opt)
8112 assert(emitter::insOptsNone(opt) || emitter::insOptsIndexed(opt));
8114 if (emitter::insOptsIndexed(opt))
8116 if (emitter::insOptsPostIndex(opt))
8118 return 0x00000400; // set the bit at location 10
8122 assert(emitter::insOptsPreIndex(opt));
8123 return 0x00000C00; // set the bit at location 10 and 11
8128 assert(emitter::insOptsNone(opt));
8129 return 0; // bits 10 and 11 are zero
8133 /*****************************************************************************
8135 * Returns the encoding for a ldp/stp instruction to have the Rn register
8136 * be updated Pre/Post indexed or not updated
8139 /*static*/ emitter::code_t emitter::insEncodePairIndexedOpt(instruction ins, insOpts opt)
8141 assert(emitter::insOptsNone(opt) || emitter::insOptsIndexed(opt));
8143 if ((ins == INS_ldnp) || (ins == INS_stnp))
8145 assert(emitter::insOptsNone(opt));
8146 return 0; // bits 23 and 24 are zero
8150 if (emitter::insOptsIndexed(opt))
8152 if (emitter::insOptsPostIndex(opt))
8154 return 0x00800000; // set the bit at location 23
8158 assert(emitter::insOptsPreIndex(opt));
8159 return 0x01800000; // set the bit at location 24 and 23
8164 assert(emitter::insOptsNone(opt));
8165 return 0x01000000; // set the bit at location 24
8170 /*****************************************************************************
8172 * Returns the encoding to apply a Shift Type on the Rm register
8175 /*static*/ emitter::code_t emitter::insEncodeShiftType(insOpts opt)
8177 if (emitter::insOptsNone(opt))
8179 // None implies the we encode LSL (with a zero immediate)
8182 assert(emitter::insOptsAnyShift(opt));
8184 emitter::code_t option = (emitter::code_t)opt - (emitter::code_t)INS_OPTS_LSL;
8185 assert(option <= 3);
8187 return option << 22; // bits 23, 22
8190 /*****************************************************************************
8192 * Returns the encoding to apply a 12 bit left shift to the immediate
8195 /*static*/ emitter::code_t emitter::insEncodeShiftImm12(insOpts opt)
8197 if (emitter::insOptsLSL12(opt))
8199 return 0x00400000; // set the bit at location 22
8204 /*****************************************************************************
8206 * Returns the encoding to have the Rm register use an extend operation
8209 /*static*/ emitter::code_t emitter::insEncodeExtend(insOpts opt)
8211 if (emitter::insOptsNone(opt) || (opt == INS_OPTS_LSL))
8213 // None or LSL implies the we encode UXTX
8214 opt = INS_OPTS_UXTX;
8216 assert(emitter::insOptsAnyExtend(opt));
8218 emitter::code_t option = (emitter::code_t)opt - (emitter::code_t)INS_OPTS_UXTB;
8219 assert(option <= 7);
8221 return option << 13; // bits 15,14,13
8224 /*****************************************************************************
8226 * Returns the encoding to scale the Rm register by {0,1,2,3,4}
8227 * when using an extend operation
8230 /*static*/ emitter::code_t emitter::insEncodeExtendScale(ssize_t imm)
8232 assert((imm >= 0) && (imm <= 4));
8234 return (emitter::code_t)imm << 10; // bits 12,11,10
8237 /*****************************************************************************
8239 * Returns the encoding to have the Rm register be auto scaled by the ld/st size
8242 /*static*/ emitter::code_t emitter::insEncodeReg3Scale(bool isScaled)
8246 return 0x00001000; // set the bit at location 12
8254 BYTE* emitter::emitOutputLoadLabel(BYTE* dst, BYTE* srcAddr, BYTE* dstAddr, instrDescJmp* id)
8256 instruction ins = id->idIns();
8257 insFormat fmt = id->idInsFmt();
8258 regNumber dstReg = id->idReg1();
8261 // adr x, [rel addr] -- compute address: current addr(ip) + rel addr.
8262 assert(ins == INS_adr);
8263 assert(fmt == IF_DI_1E);
8264 ssize_t distVal = (ssize_t)(dstAddr - srcAddr);
8265 dst = emitOutputShortAddress(dst, ins, fmt, distVal, dstReg);
8269 // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8270 assert(fmt == IF_LARGEADR);
8271 ssize_t relPageAddr =
8272 (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8273 dst = emitOutputShortAddress(dst, INS_adrp, IF_DI_1E, relPageAddr, dstReg);
8275 // add x, x, page offs -- compute address = page addr + page offs
8276 ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8277 assert(isValidUimm12(imm12));
8279 emitInsCode(INS_add, IF_DI_2A); // DI_2A X0010001shiiiiii iiiiiinnnnnddddd 1100 0000 imm(i12, sh)
8280 code |= insEncodeDatasize(EA_8BYTE); // X
8281 code |= ((code_t)imm12 << 10); // iiiiiiiiiiii
8282 code |= insEncodeReg_Rd(dstReg); // ddddd
8283 code |= insEncodeReg_Rn(dstReg); // nnnnn
8284 dst += emitOutput_Instr(dst, code);
8289 /*****************************************************************************
8291 * Output a local jump or other instruction with a pc-relative immediate.
8292 * Note that this may be invoked to overwrite an existing jump instruction at 'dst'
8293 * to handle forward branch patching.
8296 BYTE* emitter::emitOutputLJ(insGroup* ig, BYTE* dst, instrDesc* i)
8298 instrDescJmp* id = (instrDescJmp*)i;
8307 // Set default ins/fmt from id.
8308 instruction ins = id->idIns();
8309 insFormat fmt = id->idInsFmt();
8311 bool loadLabel = false;
8312 bool isJump = false;
8313 bool loadConstant = false;
8330 loadConstant = true;
8339 /* Figure out the distance to the target */
8341 srcOffs = emitCurCodeOffs(dst);
8342 srcAddr = emitOffsetToPtr(srcOffs);
8344 if (id->idAddr()->iiaIsJitDataOffset())
8346 assert(loadConstant || loadLabel);
8347 int doff = id->idAddr()->iiaGetJitDataOffset();
8349 ssize_t imm = emitGetInsSC(id);
8350 assert((imm >= 0) && (imm < 0x1000)); // 0x1000 is arbitrary, currently 'imm' is always 0
8352 unsigned dataOffs = (unsigned)(doff + imm);
8353 assert(dataOffs < emitDataSize());
8354 dstAddr = emitDataOffsetToPtr(dataOffs);
8356 regNumber dstReg = id->idReg1();
8357 regNumber addrReg = dstReg; // an integer register to compute long address.
8358 emitAttr opSize = id->idOpSize();
8364 // ldr x/v, [rel addr] -- load constant from current addr(ip) + rel addr.
8365 assert(ins == INS_ldr);
8366 assert(fmt == IF_LS_1A);
8367 distVal = (ssize_t)(dstAddr - srcAddr);
8368 dst = emitOutputShortConstant(dst, ins, fmt, distVal, dstReg, opSize);
8372 // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8373 assert(fmt == IF_LARGELDC);
8374 ssize_t relPageAddr =
8375 (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8376 if (isVectorRegister(dstReg))
8378 // Update addrReg with the reserved integer register
8379 // since we cannot use dstReg (vector) to load constant directly from memory.
8380 addrReg = id->idReg2();
8381 assert(isGeneralRegister(addrReg));
8385 dst = emitOutputShortAddress(dst, ins, fmt, relPageAddr, addrReg);
8387 // ldr x, [x, page offs] -- load constant from page address + page offset into integer register.
8388 ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8389 assert(isValidUimm12(imm12));
8392 dst = emitOutputShortConstant(dst, ins, fmt, imm12, addrReg, opSize);
8394 // fmov v, d -- copy constant in integer register to vector register.
8395 // This is needed only for vector constant.
8396 if (addrReg != dstReg)
8398 // fmov Vd,Rn DV_2I X00111100X100111 000000nnnnnddddd 1E27 0000 Vd,Rn
8399 // (scalar, from general)
8400 assert(isVectorRegister(dstReg) && isGeneralRegister(addrReg));
8403 code_t code = emitInsCode(ins, fmt);
8405 code |= insEncodeReg_Vd(dstReg); // ddddd
8406 code |= insEncodeReg_Rn(addrReg); // nnnnn
8407 if (id->idOpSize() == EA_8BYTE)
8409 code |= 0x80400000; // X ... X
8411 dst += emitOutput_Instr(dst, code);
8418 dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8424 assert(loadLabel || isJump);
8426 if (id->idAddr()->iiaHasInstrCount())
8429 int instrCount = id->idAddr()->iiaGetInstrCount();
8430 unsigned insNum = emitFindInsNum(ig, id);
8433 // Backward branches using instruction count must be within the same instruction group.
8434 assert(insNum + 1 >= (unsigned)(-instrCount));
8436 dstOffs = ig->igOffs + emitFindOffset(ig, (insNum + 1 + instrCount));
8437 dstAddr = emitOffsetToPtr(dstOffs);
8441 dstOffs = id->idAddr()->iiaIGlabel->igOffs;
8442 dstAddr = emitOffsetToPtr(dstOffs);
8445 distVal = (ssize_t)(dstAddr - srcAddr);
8447 if (dstOffs <= srcOffs)
8450 /* This is a backward jump - distance is known at this point */
8452 if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8454 size_t blkOffs = id->idjIG->igOffs;
8456 if (INTERESTING_JUMP_NUM == 0)
8457 printf("[3] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8458 printf("[3] Jump block is at %08X - %02X = %08X\n", blkOffs, emitOffsAdj, blkOffs - emitOffsAdj);
8459 printf("[3] Jump is at %08X - %02X = %08X\n", srcOffs, emitOffsAdj, srcOffs - emitOffsAdj);
8460 printf("[3] Label block is at %08X - %02X = %08X\n", dstOffs, emitOffsAdj, dstOffs - emitOffsAdj);
8466 /* This is a forward jump - distance will be an upper limit */
8468 emitFwdJumps = true;
8470 /* The target offset will be closer by at least 'emitOffsAdj', but only if this
8471 jump doesn't cross the hot-cold boundary. */
8473 if (!emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8475 dstOffs -= emitOffsAdj;
8476 distVal -= emitOffsAdj;
8479 /* Record the location of the jump for later patching */
8481 id->idjOffs = dstOffs;
8483 /* Are we overflowing the id->idjOffs bitfield? */
8484 if (id->idjOffs != dstOffs)
8485 IMPL_LIMITATION("Method is too large");
8488 if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8490 size_t blkOffs = id->idjIG->igOffs;
8492 if (INTERESTING_JUMP_NUM == 0)
8493 printf("[4] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8494 printf("[4] Jump block is at %08X\n", blkOffs);
8495 printf("[4] Jump is at %08X\n", srcOffs);
8496 printf("[4] Label block is at %08X - %02X = %08X\n", dstOffs + emitOffsAdj, emitOffsAdj, dstOffs);
8502 if (0 && emitComp->verbose)
8505 int distValSize = id->idjShort ? 4 : 8;
8506 printf("; %s jump [%08X/%03u] from %0*X to %0*X: dist = %08XH\n", (dstOffs <= srcOffs) ? "Fwd" : "Bwd",
8507 dspPtr(id), id->idDebugOnlyInfo()->idNum, distValSize, srcOffs + sz, distValSize, dstOffs, distVal);
8511 /* For forward jumps, record the address of the distance value */
8512 id->idjTemp.idjAddr = (distVal > 0) ? dst : NULL;
8514 if (emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8516 assert(!id->idjShort);
8517 NYI_ARM64("Relocation Support for long address");
8520 assert(insOptsNone(id->idInsOpt()));
8526 // Short conditional/unconditional jump
8527 assert(!id->idjKeepLong);
8528 assert(emitJumpCrossHotColdBoundary(srcOffs, dstOffs) == false);
8529 assert((fmt == IF_BI_0A) || (fmt == IF_BI_0B) || (fmt == IF_BI_1A) || (fmt == IF_BI_1B));
8533 // Long conditional jump
8534 assert(fmt == IF_LARGEJMP);
8535 // This is a pseudo-instruction format representing a large conditional branch, to allow
8536 // us to get a greater branch target range than we can get by using a straightforward conditional
8537 // branch. It is encoded as a short conditional branch that branches around a long unconditional
8540 // Conceptually, we have:
8544 // The code we emit is:
8546 // b<!cond> L_not // 4 bytes. Note that we reverse the condition.
8547 // b L_target // 4 bytes
8550 // Note that we don't actually insert any blocks: we simply encode "b <!cond> L_not" as a branch with
8551 // the correct offset. Note also that this works for both integer and floating-point conditions, because
8552 // the condition inversion takes ordered/unordered into account, preserving NaN behavior. For example,
8553 // "GT" (greater than) is inverted to "LE" (less than, equal, or unordered).
8555 instruction reverseIns;
8556 insFormat reverseFmt;
8561 reverseIns = INS_cbnz;
8562 reverseFmt = IF_BI_1A;
8565 reverseIns = INS_cbz;
8566 reverseFmt = IF_BI_1A;
8569 reverseIns = INS_tbnz;
8570 reverseFmt = IF_BI_1B;
8573 reverseIns = INS_tbz;
8574 reverseFmt = IF_BI_1B;
8577 reverseIns = emitJumpKindToIns(emitReverseJumpKind(emitInsToJumpKind(ins)));
8578 reverseFmt = IF_BI_0B;
8582 emitOutputShortBranch(dst,
8583 reverseIns, // reverse the conditional instruction
8585 8, /* 8 bytes from start of this large conditional pseudo-instruction to L_not. */
8588 // Now, pretend we've got a normal unconditional branch, and fall through to the code to emit that.
8592 // The distVal was computed based on the beginning of the pseudo-instruction,
8593 // So subtract the size of the conditional branch so that it is relative to the
8594 // unconditional branch.
8598 dst = emitOutputShortBranch(dst, ins, fmt, distVal, id);
8602 dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8608 /*****************************************************************************
8610 * Output a short branch instruction.
8612 BYTE* emitter::emitOutputShortBranch(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, instrDescJmp* id)
8614 code_t code = emitInsCode(ins, fmt);
8616 ssize_t loBits = (distVal & 3);
8617 noway_assert(loBits == 0);
8618 distVal >>= 2; // branch offset encodings are scaled by 4.
8620 if (fmt == IF_BI_0A)
8622 // INS_b or INS_bl_local
8623 noway_assert(isValidSimm26(distVal));
8624 distVal &= 0x3FFFFFFLL;
8627 else if (fmt == IF_BI_0B) // BI_0B 01010100iiiiiiii iiiiiiiiiiiXXXXX simm19:00
8629 // INS_beq, INS_bne, etc...
8630 noway_assert(isValidSimm19(distVal));
8631 distVal &= 0x7FFFFLL;
8632 code |= distVal << 5;
8634 else if (fmt == IF_BI_1A) // BI_1A X.......iiiiiiii iiiiiiiiiiittttt Rt simm19:00
8636 // INS_cbz or INS_cbnz
8637 assert(id != nullptr);
8638 code |= insEncodeDatasize(id->idOpSize()); // X
8639 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
8641 noway_assert(isValidSimm19(distVal));
8642 distVal &= 0x7FFFFLL; // 19 bits
8643 code |= distVal << 5;
8645 else if (fmt == IF_BI_1B) // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
8647 // INS_tbz or INS_tbnz
8648 assert(id != nullptr);
8649 ssize_t imm = emitGetInsSC(id);
8650 assert(isValidImmShift(imm, id->idOpSize()));
8652 if (imm & 0x20) // test bit 32-63 ?
8654 code |= 0x80000000; // B
8656 code |= ((imm & 0x1F) << 19); // bbbbb
8657 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
8659 noway_assert(isValidSimm14(distVal));
8660 distVal &= 0x3FFFLL; // 14 bits
8661 code |= distVal << 5;
8665 assert(!"Unknown fmt for emitOutputShortBranch");
8668 dst += emitOutput_Instr(dst, code);
8673 /*****************************************************************************
8675 * Output a short address instruction.
8677 BYTE* emitter::emitOutputShortAddress(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, regNumber reg)
8679 ssize_t loBits = (distVal & 3);
8682 code_t code = emitInsCode(ins, fmt);
8683 if (fmt == IF_DI_1E) // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
8685 // INS_adr or INS_adrp
8686 code |= insEncodeReg_Rd(reg); // ddddd
8688 noway_assert(isValidSimm19(distVal));
8689 distVal &= 0x7FFFFLL; // 19 bits
8690 code |= distVal << 5;
8691 code |= loBits << 29; // 2 bits
8695 assert(!"Unknown fmt for emitOutputShortAddress");
8698 dst += emitOutput_Instr(dst, code);
8703 /*****************************************************************************
8705 * Output a short constant instruction.
8707 BYTE* emitter::emitOutputShortConstant(
8708 BYTE* dst, instruction ins, insFormat fmt, ssize_t imm, regNumber reg, emitAttr opSize)
8710 code_t code = emitInsCode(ins, fmt);
8712 if (fmt == IF_LS_1A)
8714 // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt simm21
8715 // INS_ldr or INS_ldrsw (PC-Relative)
8717 ssize_t loBits = (imm & 3);
8718 noway_assert(loBits == 0);
8719 ssize_t distVal = imm >>= 2; // load offset encodings are scaled by 4.
8721 noway_assert(isValidSimm19(distVal));
8723 // Is the target a vector register?
8724 if (isVectorRegister(reg))
8726 code |= insEncodeDatasizeVLS(code, opSize); // XX V
8727 code |= insEncodeReg_Vt(reg); // ttttt
8731 assert(isGeneralRegister(reg));
8732 // insEncodeDatasizeLS is not quite right for this case.
8733 // So just specialize it.
8734 if ((ins == INS_ldr) && (opSize == EA_8BYTE))
8736 // set the operation size in bit 30
8740 code |= insEncodeReg_Rt(reg); // ttttt
8743 distVal &= 0x7FFFFLL; // 19 bits
8744 code |= distVal << 5;
8746 else if (fmt == IF_LS_2B)
8748 // ldr Rt,[Xn+pimm12] LS_2B 1X11100101iiiiii iiiiiinnnnnttttt B940 0000 imm(0-4095<<{2,3})
8749 // INS_ldr or INS_ldrsw (PC-Relative)
8750 noway_assert(isValidUimm12(imm));
8751 assert(isGeneralRegister(reg));
8753 if (opSize == EA_8BYTE)
8755 // insEncodeDatasizeLS is not quite right for this case.
8756 // So just specialize it.
8759 // set the operation size in bit 30
8762 // Low 3 bits should be 0 -- 8 byte JIT data should be aligned on 8 byte.
8763 assert((imm & 7) == 0);
8768 assert(opSize == EA_4BYTE);
8769 // Low 2 bits should be 0 -- 4 byte aligned data.
8770 assert((imm & 3) == 0);
8774 code |= insEncodeReg_Rt(reg); // ttttt
8775 code |= insEncodeReg_Rn(reg); // nnnnn
8780 assert(!"Unknown fmt for emitOutputShortConstant");
8783 dst += emitOutput_Instr(dst, code);
8787 /*****************************************************************************
8789 * Output a call instruction.
8792 unsigned emitter::emitOutputCall(insGroup* ig, BYTE* dst, instrDesc* id, code_t code)
8794 const unsigned char callInstrSize = sizeof(code_t); // 4 bytes
8795 regMaskTP gcrefRegs;
8796 regMaskTP byrefRegs;
8798 VARSET_TP GCvars(VarSetOps::UninitVal());
8800 // Is this a "fat" call descriptor?
8801 if (id->idIsLargeCall())
8803 instrDescCGCA* idCall = (instrDescCGCA*)id;
8804 gcrefRegs = idCall->idcGcrefRegs;
8805 byrefRegs = idCall->idcByrefRegs;
8806 VarSetOps::Assign(emitComp, GCvars, idCall->idcGCvars);
8810 assert(!id->idIsLargeDsp());
8811 assert(!id->idIsLargeCns());
8813 gcrefRegs = emitDecodeCallGCregs(id);
8815 VarSetOps::AssignNoCopy(emitComp, GCvars, VarSetOps::MakeEmpty(emitComp));
8818 /* We update the GC info before the call as the variables cannot be
8819 used by the call. Killing variables before the call helps with
8820 boundary conditions if the call is CORINFO_HELP_THROW - see bug 50029.
8821 If we ever track aliased variables (which could be used by the
8822 call), we would have to keep them alive past the call. */
8824 emitUpdateLiveGCvars(GCvars, dst);
8826 // Now output the call instruction and update the 'dst' pointer
8828 unsigned outputInstrSize = emitOutput_Instr(dst, code);
8829 dst += outputInstrSize;
8831 // All call instructions are 4-byte in size on ARM64
8833 assert(outputInstrSize == callInstrSize);
8835 // If the method returns a GC ref, mark INTRET (R0) appropriately.
8836 if (id->idGCref() == GCT_GCREF)
8838 gcrefRegs |= RBM_INTRET;
8840 else if (id->idGCref() == GCT_BYREF)
8842 byrefRegs |= RBM_INTRET;
8845 // If is a multi-register return method is called, mark INTRET_1 (X1) appropriately
8846 if (id->idIsLargeCall())
8848 instrDescCGCA* idCall = (instrDescCGCA*)id;
8849 if (idCall->idSecondGCref() == GCT_GCREF)
8851 gcrefRegs |= RBM_INTRET_1;
8853 else if (idCall->idSecondGCref() == GCT_BYREF)
8855 byrefRegs |= RBM_INTRET_1;
8859 // If the GC register set has changed, report the new set.
8860 if (gcrefRegs != emitThisGCrefRegs)
8862 emitUpdateLiveGCregs(GCT_GCREF, gcrefRegs, dst);
8864 // If the Byref register set has changed, report the new set.
8865 if (byrefRegs != emitThisByrefRegs)
8867 emitUpdateLiveGCregs(GCT_BYREF, byrefRegs, dst);
8870 // Some helper calls may be marked as not requiring GC info to be recorded.
8871 if ((!id->idIsNoGC()))
8873 // On ARM64, as on AMD64, we don't change the stack pointer to push/pop args.
8874 // So we're not really doing a "stack pop" here (note that "args" is 0), but we use this mechanism
8875 // to record the call for GC info purposes. (It might be best to use an alternate call,
8876 // and protect "emitStackPop" under the EMIT_TRACK_STACK_DEPTH preprocessor variable.)
8877 emitStackPop(dst, /*isCall*/ true, callInstrSize, /*args*/ 0);
8879 // Do we need to record a call location for GC purposes?
8881 if (!emitFullGCinfo)
8883 emitRecordGCcall(dst, callInstrSize);
8886 return callInstrSize;
8889 /*****************************************************************************
8891 * Emit a 32-bit Arm64 instruction
8894 /*static*/ unsigned emitter::emitOutput_Instr(BYTE* dst, code_t code)
8896 assert(sizeof(code_t) == 4);
8897 *((code_t*)dst) = code;
8899 return sizeof(code_t);
8902 /*****************************************************************************
8904 * Append the machine code corresponding to the given instruction descriptor
8905 * to the code block at '*dp'; the base of the code block is 'bp', and 'ig'
8906 * is the instruction group that contains the instruction. Updates '*dp' to
8907 * point past the generated code, and returns the size of the instruction
8908 * descriptor in bytes.
8911 size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
8916 size_t sz = emitGetInstrDescSize(id); // TODO-ARM64-Cleanup: on ARM, this is set in each case. why?
8917 instruction ins = id->idIns();
8918 insFormat fmt = id->idInsFmt();
8919 emitAttr size = id->idOpSize();
8920 unsigned char callInstrSize = 0;
8925 bool dspOffs = emitComp->opts.dspGCtbls;
8927 bool dspOffs = !emitComp->opts.disDiffable;
8931 assert(REG_NA == (int)REG_NA);
8933 VARSET_TP GCvars(VarSetOps::UninitVal());
8935 /* What instruction format have we got? */
8950 case IF_BI_0A: // BI_0A ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
8951 case IF_BI_0B: // BI_0B ......iiiiiiiiii iiiiiiiiiii..... simm19:00
8953 assert(id->idGCref() == GCT_NONE);
8954 assert(id->idIsBound());
8955 dst = emitOutputLJ(ig, dst, id);
8956 sz = sizeof(instrDescJmp);
8959 case IF_BI_0C: // BI_0C ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
8960 code = emitInsCode(ins, fmt);
8961 sz = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
8962 dst += emitOutputCall(ig, dst, id, code);
8963 // Always call RecordRelocation so that we wire in a JumpStub when we don't reach
8964 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_BRANCH26);
8967 case IF_BI_1A: // BI_1A ......iiiiiiiiii iiiiiiiiiiittttt Rt simm19:00
8968 assert(insOptsNone(id->idInsOpt()));
8969 assert(id->idIsBound());
8971 dst = emitOutputLJ(ig, dst, id);
8972 sz = sizeof(instrDescJmp);
8975 case IF_BI_1B: // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
8976 assert(insOptsNone(id->idInsOpt()));
8977 assert(id->idIsBound());
8979 dst = emitOutputLJ(ig, dst, id);
8980 sz = sizeof(instrDescJmp);
8983 case IF_BR_1A: // BR_1A ................ ......nnnnn..... Rn
8984 assert(insOptsNone(id->idInsOpt()));
8985 assert((ins == INS_ret) || (ins == INS_br));
8986 code = emitInsCode(ins, fmt);
8987 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
8989 dst += emitOutput_Instr(dst, code);
8992 case IF_BR_1B: // BR_1B ................ ......nnnnn..... Rn
8993 assert(insOptsNone(id->idInsOpt()));
8994 assert((ins == INS_br_tail) || (ins == INS_blr));
8995 code = emitInsCode(ins, fmt);
8996 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
8998 sz = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
8999 dst += emitOutputCall(ig, dst, id, code);
9002 case IF_LS_1A: // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB)
9004 assert(insOptsNone(id->idInsOpt()));
9005 assert(id->idIsBound());
9007 dst = emitOutputLJ(ig, dst, id);
9008 sz = sizeof(instrDescJmp);
9011 case IF_LS_2A: // LS_2A .X.......X...... ......nnnnnttttt Rt Rn
9012 assert(insOptsNone(id->idInsOpt()));
9013 code = emitInsCode(ins, fmt);
9014 // Is the target a vector register?
9015 if (isVectorRegister(id->idReg1()))
9017 code &= 0x3FFFFFFF; // clear the size bits
9018 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9019 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9023 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9024 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9026 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9027 dst += emitOutput_Instr(dst, code);
9030 case IF_LS_2B: // LS_2B .X.......Xiiiiii iiiiiinnnnnttttt Rt Rn imm(0-4095)
9031 assert(insOptsNone(id->idInsOpt()));
9032 imm = emitGetInsSC(id);
9033 assert(isValidUimm12(imm));
9034 code = emitInsCode(ins, fmt);
9035 // Is the target a vector register?
9036 if (isVectorRegister(id->idReg1()))
9038 code &= 0x3FFFFFFF; // clear the size bits
9039 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9040 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9044 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9045 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9047 code |= ((code_t)imm << 10); // iiiiiiiiiiii
9048 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9049 dst += emitOutput_Instr(dst, code);
9052 case IF_LS_2C: // LS_2C .X.......X.iiiii iiiiPPnnnnnttttt Rt Rn imm(-256..+255) no/pre/post inc
9053 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9054 imm = emitGetInsSC(id);
9055 assert((imm >= -256) && (imm <= 255)); // signed 9 bits
9056 imm &= 0x1ff; // force into unsigned 9 bit representation
9057 code = emitInsCode(ins, fmt);
9058 // Is the target a vector register?
9059 if (isVectorRegister(id->idReg1()))
9061 code &= 0x3FFFFFFF; // clear the size bits
9062 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9063 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9067 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9068 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9070 code |= insEncodeIndexedOpt(id->idInsOpt()); // PP
9071 code |= ((code_t)imm << 12); // iiiiiiiii
9072 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9073 dst += emitOutput_Instr(dst, code);
9076 case IF_LS_3A: // LS_3A .X.......X.mmmmm oooS..nnnnnttttt Rt Rn Rm ext(Rm) LSL {}
9077 assert(insOptsLSExtend(id->idInsOpt()));
9078 code = emitInsCode(ins, fmt);
9079 // Is the target a vector register?
9080 if (isVectorRegister(id->idReg1()))
9082 code &= 0x3FFFFFFF; // clear the size bits
9083 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9084 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9088 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9089 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9091 code |= insEncodeExtend(id->idInsOpt()); // ooo
9092 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9093 if (id->idIsLclVar())
9095 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9099 code |= insEncodeReg3Scale(id->idReg3Scaled()); // S
9100 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9102 dst += emitOutput_Instr(dst, code);
9105 case IF_LS_3B: // LS_3B X............... .aaaaannnnnddddd Rd Ra Rn
9106 assert(insOptsNone(id->idInsOpt()));
9107 code = emitInsCode(ins, fmt);
9108 // Is the target a vector register?
9109 if (isVectorRegister(id->idReg1()))
9111 code &= 0x3FFFFFFF; // clear the size bits
9112 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9113 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9114 code |= insEncodeReg_Va(id->idReg2()); // aaaaa
9118 code |= insEncodeDatasize(id->idOpSize()); // X
9119 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9120 code |= insEncodeReg_Ra(id->idReg2()); // aaaaa
9122 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9123 dst += emitOutput_Instr(dst, code);
9126 case IF_LS_3C: // LS_3C X......PP.iiiiii iaaaaannnnnddddd Rd Ra Rn imm(im7,sh)
9127 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9128 imm = emitGetInsSC(id);
9129 assert((imm >= -64) && (imm <= 63)); // signed 7 bits
9130 imm &= 0x7f; // force into unsigned 7 bit representation
9131 code = emitInsCode(ins, fmt);
9132 // Is the target a vector register?
9133 if (isVectorRegister(id->idReg1()))
9135 code &= 0x3FFFFFFF; // clear the size bits
9136 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9137 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9138 code |= insEncodeReg_Va(id->idReg2()); // aaaaa
9142 code |= insEncodeDatasize(id->idOpSize()); // X
9143 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9144 code |= insEncodeReg_Ra(id->idReg2()); // aaaaa
9146 code |= insEncodePairIndexedOpt(ins, id->idInsOpt()); // PP
9147 code |= ((code_t)imm << 15); // iiiiiiiii
9148 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9149 dst += emitOutput_Instr(dst, code);
9152 case IF_LS_3D: // LS_3D .X.......X.mmmmm ......nnnnnttttt Wm Rt Rn
9153 code = emitInsCode(ins, fmt);
9154 // Arm64 store exclusive unpredictable cases
9155 assert(id->idReg1() != id->idReg2());
9156 assert(id->idReg1() != id->idReg3());
9157 code |= insEncodeDatasizeLS(code, id->idOpSize()); // X
9158 code |= insEncodeReg_Rm(id->idReg1()); // mmmmm
9159 code |= insEncodeReg_Rt(id->idReg2()); // ttttt
9160 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9161 dst += emitOutput_Instr(dst, code);
9164 case IF_DI_1A: // DI_1A X.......shiiiiii iiiiiinnnnn..... Rn imm(i12,sh)
9165 assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9166 imm = emitGetInsSC(id);
9167 assert(isValidUimm12(imm));
9168 code = emitInsCode(ins, fmt);
9169 code |= insEncodeDatasize(id->idOpSize()); // X
9170 code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9171 code |= ((code_t)imm << 10); // iiiiiiiiiiii
9172 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9173 dst += emitOutput_Instr(dst, code);
9176 case IF_DI_1B: // DI_1B X........hwiiiii iiiiiiiiiiiddddd Rd imm(i16,hw)
9177 imm = emitGetInsSC(id);
9178 assert(isValidImmHWVal(imm, id->idOpSize()));
9179 code = emitInsCode(ins, fmt);
9180 code |= insEncodeDatasize(id->idOpSize()); // X
9181 code |= ((code_t)imm << 5); // hwiiiii iiiiiiiiiii
9182 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9183 dst += emitOutput_Instr(dst, code);
9186 case IF_DI_1C: // DI_1C X........Nrrrrrr ssssssnnnnn..... Rn imm(N,r,s)
9187 imm = emitGetInsSC(id);
9188 assert(isValidImmNRS(imm, id->idOpSize()));
9189 code = emitInsCode(ins, fmt);
9190 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9191 code |= insEncodeDatasize(id->idOpSize()); // X
9192 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9193 dst += emitOutput_Instr(dst, code);
9196 case IF_DI_1D: // DI_1D X........Nrrrrrr ssssss.....ddddd Rd imm(N,r,s)
9197 imm = emitGetInsSC(id);
9198 assert(isValidImmNRS(imm, id->idOpSize()));
9199 code = emitInsCode(ins, fmt);
9200 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9201 code |= insEncodeDatasize(id->idOpSize()); // X
9202 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9203 dst += emitOutput_Instr(dst, code);
9206 case IF_DI_1E: // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
9208 assert(insOptsNone(id->idInsOpt()));
9209 if (id->idIsReloc())
9211 code = emitInsCode(ins, fmt);
9212 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9213 dst += emitOutput_Instr(dst, code);
9214 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEBASE_REL21);
9218 // Local jmp/load case which does not need a relocation.
9219 assert(id->idIsBound());
9220 dst = emitOutputLJ(ig, dst, id);
9222 sz = sizeof(instrDescJmp);
9225 case IF_DI_1F: // DI_1F X..........iiiii cccc..nnnnn.nzcv Rn imm5 nzcv cond
9226 imm = emitGetInsSC(id);
9227 assert(isValidImmCondFlagsImm5(imm));
9230 cfi.immCFVal = (unsigned)imm;
9231 code = emitInsCode(ins, fmt);
9232 code |= insEncodeDatasize(id->idOpSize()); // X
9233 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9234 code |= ((code_t)cfi.imm5 << 16); // iiiii
9235 code |= insEncodeFlags(cfi.flags); // nzcv
9236 code |= insEncodeCond(cfi.cond); // cccc
9237 dst += emitOutput_Instr(dst, code);
9241 case IF_DI_2A: // DI_2A X.......shiiiiii iiiiiinnnnnddddd Rd Rn imm(i12,sh)
9242 assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9243 imm = emitGetInsSC(id);
9244 assert(isValidUimm12(imm));
9245 code = emitInsCode(ins, fmt);
9246 code |= insEncodeDatasize(id->idOpSize()); // X
9247 code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9248 code |= ((code_t)imm << 10); // iiiiiiiiiiii
9249 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9250 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9251 dst += emitOutput_Instr(dst, code);
9253 if (id->idIsReloc())
9255 assert(sz == sizeof(instrDesc));
9256 assert(id->idAddr()->iiaAddr != nullptr);
9257 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEOFFSET_12A);
9261 case IF_DI_2B: // DI_2B X.........Xnnnnn ssssssnnnnnddddd Rd Rn imm(0-63)
9262 code = emitInsCode(ins, fmt);
9263 imm = emitGetInsSC(id);
9264 assert(isValidImmShift(imm, id->idOpSize()));
9265 code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9266 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9267 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9268 code |= insEncodeReg_Rm(id->idReg2()); // Reg2 also in mmmmm
9269 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9270 dst += emitOutput_Instr(dst, code);
9273 case IF_DI_2C: // DI_2C X........Nrrrrrr ssssssnnnnnddddd Rd Rn imm(N,r,s)
9274 imm = emitGetInsSC(id);
9275 assert(isValidImmNRS(imm, id->idOpSize()));
9276 code = emitInsCode(ins, fmt);
9277 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9278 code |= insEncodeDatasize(id->idOpSize()); // X
9279 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9280 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9281 dst += emitOutput_Instr(dst, code);
9284 case IF_DI_2D: // DI_2D X........Nrrrrrr ssssssnnnnnddddd Rd Rn imr, imms (N,r,s)
9285 if (ins == INS_asr || ins == INS_lsl || ins == INS_lsr)
9287 imm = emitGetInsSC(id);
9288 assert(isValidImmShift(imm, id->idOpSize()));
9290 // Shift immediates are aliases of the SBFM/UBFM instructions
9291 // that actually take 2 registers and 2 constants,
9292 // Since we stored the shift immediate value
9293 // we need to calculate the N,R and S values here.
9298 bmi.immN = (size == EA_8BYTE) ? 1 : 0;
9300 bmi.immS = (size == EA_8BYTE) ? 0x3f : 0x1f;
9302 // immR and immS are now set correctly for INS_asr and INS_lsr
9303 // but for INS_lsl we have to adjust the values for immR and immS
9307 bmi.immR = -imm & bmi.immS;
9308 bmi.immS = bmi.immS - imm;
9311 // setup imm with the proper 13 bit value N:R:S
9317 // The other instructions have already have encoded N,R and S values
9318 imm = emitGetInsSC(id);
9320 assert(isValidImmNRS(imm, id->idOpSize()));
9322 code = emitInsCode(ins, fmt);
9323 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9324 code |= insEncodeDatasize(id->idOpSize()); // X
9325 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9326 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9327 dst += emitOutput_Instr(dst, code);
9330 case IF_DR_1D: // DR_1D X............... cccc.......ddddd Rd cond
9331 imm = emitGetInsSC(id);
9332 assert(isValidImmCond(imm));
9335 cfi.immCFVal = (unsigned)imm;
9336 code = emitInsCode(ins, fmt);
9337 code |= insEncodeDatasize(id->idOpSize()); // X
9338 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9339 code |= insEncodeInvertedCond(cfi.cond); // cccc
9340 dst += emitOutput_Instr(dst, code);
9344 case IF_DR_2A: // DR_2A X..........mmmmm ......nnnnn..... Rn Rm
9345 assert(insOptsNone(id->idInsOpt()));
9346 code = emitInsCode(ins, fmt);
9347 code |= insEncodeDatasize(id->idOpSize()); // X
9348 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9349 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9350 dst += emitOutput_Instr(dst, code);
9353 case IF_DR_2B: // DR_2B X.......sh.mmmmm ssssssnnnnn..... Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
9354 code = emitInsCode(ins, fmt);
9355 imm = emitGetInsSC(id);
9356 assert(isValidImmShift(imm, id->idOpSize()));
9357 code |= insEncodeDatasize(id->idOpSize()); // X
9358 code |= insEncodeShiftType(id->idInsOpt()); // sh
9359 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9360 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9361 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9362 dst += emitOutput_Instr(dst, code);
9365 case IF_DR_2C: // DR_2C X..........mmmmm ooosssnnnnn..... Rn Rm ext(Rm) LSL imm(0-4)
9366 code = emitInsCode(ins, fmt);
9367 imm = emitGetInsSC(id);
9368 assert((imm >= 0) && (imm <= 4)); // imm [0..4]
9369 code |= insEncodeDatasize(id->idOpSize()); // X
9370 code |= insEncodeExtend(id->idInsOpt()); // ooo
9371 code |= insEncodeExtendScale(imm); // sss
9372 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9373 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9374 dst += emitOutput_Instr(dst, code);
9377 case IF_DR_2D: // DR_2D X..........nnnnn cccc..nnnnnddddd Rd Rn cond
9378 imm = emitGetInsSC(id);
9379 assert(isValidImmCond(imm));
9382 cfi.immCFVal = (unsigned)imm;
9383 code = emitInsCode(ins, fmt);
9384 code |= insEncodeDatasize(id->idOpSize()); // X
9385 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9386 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9387 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9388 code |= insEncodeInvertedCond(cfi.cond); // cccc
9389 dst += emitOutput_Instr(dst, code);
9393 case IF_DR_2E: // DR_2E X..........mmmmm ...........ddddd Rd Rm
9394 code = emitInsCode(ins, fmt);
9395 code |= insEncodeDatasize(id->idOpSize()); // X
9396 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9397 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9398 dst += emitOutput_Instr(dst, code);
9401 case IF_DR_2F: // DR_2F X.......sh.mmmmm ssssss.....ddddd Rd Rm {LSL,LSR,ASR} imm(0-63)
9402 code = emitInsCode(ins, fmt);
9403 imm = emitGetInsSC(id);
9404 assert(isValidImmShift(imm, id->idOpSize()));
9405 code |= insEncodeDatasize(id->idOpSize()); // X
9406 code |= insEncodeShiftType(id->idInsOpt()); // sh
9407 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9408 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9409 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9410 dst += emitOutput_Instr(dst, code);
9413 case IF_DR_2G: // DR_2G X............... .....xnnnnnddddd Rd Rn
9414 code = emitInsCode(ins, fmt);
9415 code |= insEncodeDatasize(id->idOpSize()); // X
9418 if (size == EA_8BYTE)
9420 code |= 0x00000400; // x - bit at location 10
9423 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9424 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9425 dst += emitOutput_Instr(dst, code);
9428 case IF_DR_2H: // DR_2H X........X...... ......nnnnnddddd Rd Rn
9429 code = emitInsCode(ins, fmt);
9430 code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9431 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9432 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9433 dst += emitOutput_Instr(dst, code);
9436 case IF_DR_2I: // DR_2I X..........mmmmm cccc..nnnnn.nzcv Rn Rm nzcv cond
9437 imm = emitGetInsSC(id);
9438 assert(isValidImmCondFlags(imm));
9441 cfi.immCFVal = (unsigned)imm;
9442 code = emitInsCode(ins, fmt);
9443 code |= insEncodeDatasize(id->idOpSize()); // X
9444 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9445 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9446 code |= insEncodeFlags(cfi.flags); // nzcv
9447 code |= insEncodeCond(cfi.cond); // cccc
9448 dst += emitOutput_Instr(dst, code);
9452 case IF_DR_3A: // DR_3A X..........mmmmm ......nnnnnmmmmm Rd Rn Rm
9453 code = emitInsCode(ins, fmt);
9454 code |= insEncodeDatasize(id->idOpSize()); // X
9455 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9456 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9457 if (id->idIsLclVar())
9459 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9463 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9465 dst += emitOutput_Instr(dst, code);
9468 case IF_DR_3B: // DR_3B X.......sh.mmmmm ssssssnnnnnddddd Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
9469 code = emitInsCode(ins, fmt);
9470 imm = emitGetInsSC(id);
9471 assert(isValidImmShift(imm, id->idOpSize()));
9472 code |= insEncodeDatasize(id->idOpSize()); // X
9473 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9474 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9475 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9476 code |= insEncodeShiftType(id->idInsOpt()); // sh
9477 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9478 dst += emitOutput_Instr(dst, code);
9481 case IF_DR_3C: // DR_3C X..........mmmmm ooosssnnnnnddddd Rd Rn Rm ext(Rm) LSL imm(0-4)
9482 code = emitInsCode(ins, fmt);
9483 imm = emitGetInsSC(id);
9484 assert((imm >= 0) && (imm <= 4)); // imm [0..4]
9485 code |= insEncodeDatasize(id->idOpSize()); // X
9486 code |= insEncodeExtend(id->idInsOpt()); // ooo
9487 code |= insEncodeExtendScale(imm); // sss
9488 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9489 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9490 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9491 dst += emitOutput_Instr(dst, code);
9494 case IF_DR_3D: // DR_3D X..........mmmmm cccc..nnnnnddddd Rd Rn Rm cond
9495 imm = emitGetInsSC(id);
9496 assert(isValidImmCond(imm));
9499 cfi.immCFVal = (unsigned)imm;
9500 code = emitInsCode(ins, fmt);
9501 code |= insEncodeDatasize(id->idOpSize()); // X
9502 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9503 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9504 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9505 code |= insEncodeCond(cfi.cond); // cccc
9506 dst += emitOutput_Instr(dst, code);
9510 case IF_DR_3E: // DR_3E X........X.mmmmm ssssssnnnnnddddd Rd Rn Rm imm(0-63)
9511 code = emitInsCode(ins, fmt);
9512 imm = emitGetInsSC(id);
9513 assert(isValidImmShift(imm, id->idOpSize()));
9514 code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9515 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9516 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9517 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9518 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9519 dst += emitOutput_Instr(dst, code);
9522 case IF_DR_4A: // DR_4A X..........mmmmm .aaaaannnnnmmmmm Rd Rn Rm Ra
9523 code = emitInsCode(ins, fmt);
9524 code |= insEncodeDatasize(id->idOpSize()); // X
9525 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9526 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9527 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9528 code |= insEncodeReg_Ra(id->idReg4()); // aaaaa
9529 dst += emitOutput_Instr(dst, code);
9532 case IF_DV_1A: // DV_1A .........X.iiiii iii........ddddd Vd imm8 (fmov - immediate scalar)
9533 imm = emitGetInsSC(id);
9534 elemsize = id->idOpSize();
9535 code = emitInsCode(ins, fmt);
9536 code |= insEncodeFloatElemsize(elemsize); // X
9537 code |= ((code_t)imm << 13); // iiiii iii
9538 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9539 dst += emitOutput_Instr(dst, code);
9542 case IF_DV_1B: // DV_1B .QX..........iii cmod..iiiiiddddd Vd imm8 (immediate vector)
9543 imm = emitGetInsSC(id) & 0x0ff;
9544 immShift = (emitGetInsSC(id) & 0x700) >> 8;
9545 elemsize = optGetElemsize(id->idInsOpt());
9550 cmode = 0xE; // 1110
9554 cmode |= (immShift << 1); // 10x0
9560 cmode |= (immShift << 1); // 0xx0
9570 cmode = 0xE; // 1110
9577 code = emitInsCode(ins, fmt);
9578 code |= insEncodeVectorsize(id->idOpSize()); // Q
9579 if ((ins == INS_fmov) || (ins == INS_movi))
9581 if (elemsize == EA_8BYTE)
9583 code |= 0x20000000; // X
9586 if (ins != INS_fmov)
9588 assert((cmode >= 0) && (cmode <= 0xF));
9589 code |= (cmode << 12); // cmod
9591 code |= (((code_t)imm >> 5) << 16); // iii
9592 code |= (((code_t)imm & 0x1f) << 5); // iiiii
9593 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9594 dst += emitOutput_Instr(dst, code);
9597 case IF_DV_1C: // DV_1C .........X...... ......nnnnn..... Vn #0.0 (fcmp - with zero)
9598 elemsize = id->idOpSize();
9599 code = emitInsCode(ins, fmt);
9600 code |= insEncodeFloatElemsize(elemsize); // X
9601 code |= insEncodeReg_Vn(id->idReg1()); // nnnnn
9602 dst += emitOutput_Instr(dst, code);
9605 case IF_DV_2A: // DV_2A .Q.......X...... ......nnnnnddddd Vd Vn (fabs, fcvt - vector)
9606 elemsize = optGetElemsize(id->idInsOpt());
9607 code = emitInsCode(ins, fmt);
9608 code |= insEncodeVectorsize(id->idOpSize()); // Q
9609 code |= insEncodeFloatElemsize(elemsize); // X
9610 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9611 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9612 dst += emitOutput_Instr(dst, code);
9615 case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov/smov - to general)
9616 elemsize = id->idOpSize();
9617 index = emitGetInsSC(id);
9618 datasize = (elemsize == EA_8BYTE) ? EA_16BYTE : EA_8BYTE;
9619 if (ins == INS_smov)
9621 datasize = EA_16BYTE;
9623 code = emitInsCode(ins, fmt);
9624 code |= insEncodeVectorsize(datasize); // Q
9625 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9626 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9627 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9628 dst += emitOutput_Instr(dst, code);
9631 case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
9634 datasize = id->idOpSize();
9635 elemsize = optGetElemsize(id->idInsOpt());
9640 datasize = EA_16BYTE;
9641 elemsize = id->idOpSize();
9642 index = emitGetInsSC(id);
9644 code = emitInsCode(ins, fmt);
9645 code |= insEncodeVectorsize(datasize); // Q
9646 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9647 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9648 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9649 dst += emitOutput_Instr(dst, code);
9652 case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
9653 index = emitGetInsSC(id);
9654 elemsize = optGetElemsize(id->idInsOpt());
9655 code = emitInsCode(ins, fmt);
9656 code |= insEncodeVectorsize(id->idOpSize()); // Q
9657 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9658 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9659 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9660 dst += emitOutput_Instr(dst, code);
9663 case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
9664 index = emitGetInsSC(id);
9665 elemsize = id->idOpSize();
9666 code = emitInsCode(ins, fmt);
9667 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9668 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9669 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9670 dst += emitOutput_Instr(dst, code);
9673 case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
9674 elemsize = id->idOpSize();
9675 imm = emitGetInsSC(id);
9676 index = (imm >> 4) & 0xf;
9678 code = emitInsCode(ins, fmt);
9679 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9680 code |= insEncodeVectorIndex2(elemsize, index2); // jjjj
9681 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9682 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9683 dst += emitOutput_Instr(dst, code);
9686 case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov,fcvtXX - register)
9687 elemsize = id->idOpSize();
9688 code = emitInsCode(ins, fmt);
9689 code |= insEncodeFloatElemsize(elemsize); // X
9690 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9691 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9692 dst += emitOutput_Instr(dst, code);
9695 case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov - to general)
9696 elemsize = id->idOpSize();
9697 code = emitInsCode(ins, fmt);
9698 code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X X
9699 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9700 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9701 dst += emitOutput_Instr(dst, code);
9704 case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov - from general)
9705 elemsize = id->idOpSize();
9706 code = emitInsCode(ins, fmt);
9707 code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X X
9708 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9709 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9710 dst += emitOutput_Instr(dst, code);
9713 case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
9714 code = emitInsCode(ins, fmt);
9715 code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // SS DD
9716 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9717 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9718 dst += emitOutput_Instr(dst, code);
9721 case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
9722 elemsize = id->idOpSize();
9723 code = emitInsCode(ins, fmt);
9724 code |= insEncodeFloatElemsize(elemsize); // X
9725 code |= insEncodeReg_Vn(id->idReg1()); // nnnnn
9726 code |= insEncodeReg_Vm(id->idReg2()); // mmmmm
9727 dst += emitOutput_Instr(dst, code);
9730 case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
9731 elemsize = id->idOpSize();
9732 code = emitInsCode(ins, fmt);
9733 code |= insEncodeElemsize(elemsize); // XX
9734 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9735 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9736 dst += emitOutput_Instr(dst, code);
9739 case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
9740 elemsize = optGetElemsize(id->idInsOpt());
9741 code = emitInsCode(ins, fmt);
9742 code |= insEncodeVectorsize(id->idOpSize()); // Q
9743 code |= insEncodeElemsize(elemsize); // XX
9744 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9745 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9746 dst += emitOutput_Instr(dst, code);
9749 case IF_DV_2N: // DV_2N .........iiiiiii ......nnnnnddddd Vd Vn imm (shift - scalar)
9750 imm = emitGetInsSC(id);
9751 code = emitInsCode(ins, fmt);
9752 code |= insEncodeVectorShift(EA_8BYTE, imm); // iiiiiii
9753 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9754 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9755 dst += emitOutput_Instr(dst, code);
9758 case IF_DV_2O: // DV_2O .Q.......iiiiiii ......nnnnnddddd Vd Vn imm (shift - vector)
9759 imm = emitGetInsSC(id);
9760 elemsize = optGetElemsize(id->idInsOpt());
9761 code = emitInsCode(ins, fmt);
9762 code |= insEncodeVectorsize(id->idOpSize()); // Q
9763 code |= insEncodeVectorShift(elemsize, imm); // iiiiiii
9764 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9765 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9766 dst += emitOutput_Instr(dst, code);
9769 case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
9770 code = emitInsCode(ins, fmt);
9771 elemsize = optGetElemsize(id->idInsOpt());
9772 code |= insEncodeVectorsize(id->idOpSize()); // Q
9773 code |= insEncodeElemsize(elemsize); // XX
9774 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9775 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9776 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9777 dst += emitOutput_Instr(dst, code);
9780 case IF_DV_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector)
9781 code = emitInsCode(ins, fmt);
9782 imm = emitGetInsSC(id);
9783 elemsize = optGetElemsize(id->idInsOpt());
9784 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
9785 code |= insEncodeVectorsize(id->idOpSize()); // Q
9786 code |= insEncodeElemsize(elemsize); // XX
9787 code |= insEncodeVectorIndexLMH(elemsize, imm); // LM H
9788 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9789 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9790 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9791 dst += emitOutput_Instr(dst, code);
9794 case IF_DV_3B: // DV_3B .Q.......X.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
9795 code = emitInsCode(ins, fmt);
9796 elemsize = optGetElemsize(id->idInsOpt());
9797 code |= insEncodeVectorsize(id->idOpSize()); // Q
9798 code |= insEncodeFloatElemsize(elemsize); // X
9799 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9800 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9801 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9802 dst += emitOutput_Instr(dst, code);
9805 case IF_DV_3BI: // DV_3BI .Q.......XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
9806 code = emitInsCode(ins, fmt);
9807 imm = emitGetInsSC(id);
9808 elemsize = optGetElemsize(id->idInsOpt());
9809 assert(isValidVectorIndex(id->idOpSize(), elemsize, imm));
9810 code |= insEncodeVectorsize(id->idOpSize()); // Q
9811 code |= insEncodeFloatElemsize(elemsize); // X
9812 code |= insEncodeFloatIndex(elemsize, imm); // L H
9813 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9814 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9815 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9816 dst += emitOutput_Instr(dst, code);
9819 case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
9820 code = emitInsCode(ins, fmt);
9821 code |= insEncodeVectorsize(id->idOpSize()); // Q
9822 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9823 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9824 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9825 dst += emitOutput_Instr(dst, code);
9828 case IF_DV_3D: // DV_3D .........X.mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
9829 code = emitInsCode(ins, fmt);
9830 code |= insEncodeFloatElemsize(id->idOpSize()); // X
9831 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9832 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9833 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9834 dst += emitOutput_Instr(dst, code);
9837 case IF_DV_3DI: // DV_3DI .........XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (scalar by elem)
9838 code = emitInsCode(ins, fmt);
9839 imm = emitGetInsSC(id);
9840 elemsize = id->idOpSize();
9841 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
9842 code |= insEncodeFloatElemsize(elemsize); // X
9843 code |= insEncodeFloatIndex(elemsize, imm); // L H
9844 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9845 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9846 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9847 dst += emitOutput_Instr(dst, code);
9850 case IF_DV_3E: // DV_3E ...........mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
9851 code = emitInsCode(ins, fmt);
9852 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9853 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9854 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9855 dst += emitOutput_Instr(dst, code);
9858 case IF_DV_4A: // DV_4A .........X.mmmmm .aaaaannnnnddddd Vd Va Vn Vm (scalar)
9859 code = emitInsCode(ins, fmt);
9860 elemsize = id->idOpSize();
9861 code |= insEncodeFloatElemsize(elemsize); // X
9862 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9863 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9864 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9865 code |= insEncodeReg_Va(id->idReg4()); // aaaaa
9866 dst += emitOutput_Instr(dst, code);
9869 case IF_SN_0A: // SN_0A ................ ................
9870 code = emitInsCode(ins, fmt);
9871 dst += emitOutput_Instr(dst, code);
9874 case IF_SI_0A: // SI_0A ...........iiiii iiiiiiiiiii..... imm16
9875 imm = emitGetInsSC(id);
9876 assert(isValidUimm16(imm));
9877 code = emitInsCode(ins, fmt);
9878 code |= ((code_t)imm << 5); // iiiii iiiiiiiiiii
9879 dst += emitOutput_Instr(dst, code);
9882 case IF_SI_0B: // SI_0B ................ ....bbbb........ imm4 - barrier
9883 imm = emitGetInsSC(id);
9884 assert((imm >= 0) && (imm <= 15));
9885 code = emitInsCode(ins, fmt);
9886 code |= ((code_t)imm << 8); // bbbb
9887 dst += emitOutput_Instr(dst, code);
9891 assert(!"Unexpected format");
9895 // Determine if any registers now hold GC refs, or whether a register that was overwritten held a GC ref.
9896 // We assume here that "id->idGCref()" is not GC_NONE only if the instruction described by "id" writes a
9897 // GC ref to register "id->idReg1()". (It may, apparently, also not be GC_NONE in other cases, such as
9898 // for stores, but we ignore those cases here.)
9899 if (emitInsMayWriteToGCReg(id)) // True if "id->idIns()" writes to a register than can hold GC ref.
9901 // We assume that "idReg1" is the primary destination register for all instructions
9902 if (id->idGCref() != GCT_NONE)
9904 emitGCregLiveUpd(id->idGCref(), id->idReg1(), dst);
9908 emitGCregDeadUpd(id->idReg1(), dst);
9911 if (emitInsMayWriteMultipleRegs(id))
9914 // "idReg2" is the secondary destination register
9915 if (id->idGCrefReg2() != GCT_NONE)
9917 emitGCregLiveUpd(id->idGCrefReg2(), id->idReg2(), dst);
9921 emitGCregDeadUpd(id->idReg2(), dst);
9926 // Now we determine if the instruction has written to a (local variable) stack location, and either written a GC
9927 // ref or overwritten one.
9928 if (emitInsWritesToLclVarStackLoc(id) || emitInsWritesToLclVarStackLocPair(id))
9930 int varNum = id->idAddr()->iiaLclVar.lvaVarNum();
9931 unsigned ofs = AlignDown(id->idAddr()->iiaLclVar.lvaOffset(), TARGET_POINTER_SIZE);
9933 int adr = emitComp->lvaFrameAddress(varNum, &FPbased);
9934 if (id->idGCref() != GCT_NONE)
9936 emitGCvarLiveUpd(adr + ofs, varNum, id->idGCref(), dst);
9940 // If the type of the local is a gc ref type, update the liveness.
9944 // "Regular" (non-spill-temp) local.
9945 vt = var_types(emitComp->lvaTable[varNum].lvType);
9949 TempDsc* tmpDsc = emitComp->tmpFindNum(varNum);
9950 vt = tmpDsc->tdTempType();
9952 if (vt == TYP_REF || vt == TYP_BYREF)
9953 emitGCvarDeadUpd(adr + ofs, dst);
9955 if (emitInsWritesToLclVarStackLocPair(id))
9957 unsigned ofs2 = ofs + TARGET_POINTER_SIZE;
9958 if (id->idGCrefReg2() != GCT_NONE)
9960 emitGCvarLiveUpd(adr + ofs2, varNum, id->idGCrefReg2(), dst);
9964 // If the type of the local is a gc ref type, update the liveness.
9968 // "Regular" (non-spill-temp) local.
9969 vt = var_types(emitComp->lvaTable[varNum].lvType);
9973 TempDsc* tmpDsc = emitComp->tmpFindNum(varNum);
9974 vt = tmpDsc->tdTempType();
9976 if (vt == TYP_REF || vt == TYP_BYREF)
9977 emitGCvarDeadUpd(adr + ofs2, dst);
9983 /* Make sure we set the instruction descriptor size correctly */
9985 size_t expected = emitSizeOfInsDsc(id);
9986 assert(sz == expected);
9988 if (emitComp->opts.disAsm || emitComp->opts.dspEmit || emitComp->verbose)
9990 emitDispIns(id, false, dspOffs, true, emitCurCodeOffs(odst), *dp, (dst - *dp), ig);
9993 if (emitComp->compDebugBreak)
9995 // For example, set JitBreakEmitOutputInstr=a6 will break when this method is called for
9996 // emitting instruction a6, (i.e. IN00a6 in jitdump).
9997 if ((unsigned)JitConfig.JitBreakEmitOutputInstr() == id->idDebugOnlyInfo()->idNum)
9999 assert(!"JitBreakEmitOutputInstr reached");
10004 /* All instructions are expected to generate code */
10006 assert(*dp != dst);
10013 /*****************************************************************************/
10014 /*****************************************************************************/
10018 /*****************************************************************************
10020 * Display the instruction name
10022 void emitter::emitDispInst(instruction ins)
10024 const char* insstr = codeGen->genInsName(ins);
10025 size_t len = strlen(insstr);
10027 /* Display the instruction name */
10029 printf("%s", insstr);
10032 // Add at least one space after the instruction name
10033 // and add spaces until we have reach the normal size of 8
10041 /*****************************************************************************
10043 * Display an reloc value
10044 * If we are formatting for an assembly listing don't print the hex value
10045 * since it will prevent us from doing assembly diffs
10047 void emitter::emitDispReloc(int value, bool addComma)
10049 if (emitComp->opts.disAsm)
10055 printf("(reloc 0x%x)", dspPtr(value));
10062 /*****************************************************************************
10064 * Display an immediate value
10066 void emitter::emitDispImm(ssize_t imm, bool addComma, bool alwaysHex /* =false */)
10073 // Munge any pointers if we want diff-able disassembly
10074 if (emitComp->opts.disDiffable)
10076 ssize_t top44bits = (imm >> 20);
10077 if ((top44bits != 0) && (top44bits != -1))
10081 if (!alwaysHex && (imm > -1000) && (imm < 1000))
10087 if ((imm < 0) && ((imm & 0xFFFFFFFF00000000LL) == 0xFFFFFFFF00000000LL))
10093 if ((imm & 0xFFFFFFFF00000000LL) != 0)
10095 printf("0x%llx", imm);
10099 printf("0x%02x", imm);
10107 /*****************************************************************************
10109 * Display a float zero constant
10111 void emitter::emitDispFloatZero()
10120 /*****************************************************************************
10122 * Display an encoded float constant value
10124 void emitter::emitDispFloatImm(ssize_t imm8)
10126 assert((0 <= imm8) && (imm8 <= 0x0ff));
10133 fpImm.immFPIVal = (unsigned)imm8;
10134 double result = emitDecodeFloatImm8(fpImm);
10136 printf("%.4f", result);
10139 /*****************************************************************************
10141 * Display an immediate that is optionally LSL12.
10143 void emitter::emitDispImmOptsLSL12(ssize_t imm, insOpts opt)
10145 if (!strictArmAsm && insOptsLSL12(opt))
10149 emitDispImm(imm, false);
10150 if (strictArmAsm && insOptsLSL12(opt))
10152 printf(", LSL #12");
10156 /*****************************************************************************
10158 * Display an ARM64 condition code for the conditional instructions
10160 void emitter::emitDispCond(insCond cond)
10162 const static char* armCond[16] = {"eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc",
10163 "hi", "ls", "ge", "lt", "gt", "le", "AL", "NV"}; // The last two are invalid
10164 unsigned imm = (unsigned)cond;
10165 assert((0 <= imm) && (imm < ArrLen(armCond)));
10166 printf(armCond[imm]);
10169 /*****************************************************************************
10171 * Display an ARM64 flags for the conditional instructions
10173 void emitter::emitDispFlags(insCflags flags)
10175 const static char* armFlags[16] = {"0", "v", "c", "cv", "z", "zv", "zc", "zcv",
10176 "n", "nv", "nc", "ncv", "nz", "nzv", "nzc", "nzcv"};
10177 unsigned imm = (unsigned)flags;
10178 assert((0 <= imm) && (imm < ArrLen(armFlags)));
10179 printf(armFlags[imm]);
10182 /*****************************************************************************
10184 * Display an ARM64 'barrier' for the memory barrier instructions
10186 void emitter::emitDispBarrier(insBarrier barrier)
10188 const static char* armBarriers[16] = {"#0", "oshld", "oshst", "osh", "#4", "nshld", "nshst", "nsh",
10189 "#8", "ishld", "ishst", "ish", "#12", "ld", "st", "sy"};
10190 unsigned imm = (unsigned)barrier;
10191 assert((0 <= imm) && (imm < ArrLen(armBarriers)));
10192 printf(armBarriers[imm]);
10195 /*****************************************************************************
10197 * Prints the encoding for the Shift Type encoding
10200 void emitter::emitDispShiftOpts(insOpts opt)
10202 if (opt == INS_OPTS_LSL)
10204 else if (opt == INS_OPTS_LSR)
10206 else if (opt == INS_OPTS_ASR)
10208 else if (opt == INS_OPTS_ROR)
10210 else if (opt == INS_OPTS_MSL)
10213 assert(!"Bad value");
10216 /*****************************************************************************
10218 * Prints the encoding for the Extend Type encoding
10221 void emitter::emitDispExtendOpts(insOpts opt)
10223 if (opt == INS_OPTS_UXTB)
10225 else if (opt == INS_OPTS_UXTH)
10227 else if (opt == INS_OPTS_UXTW)
10229 else if (opt == INS_OPTS_UXTX)
10231 else if (opt == INS_OPTS_SXTB)
10233 else if (opt == INS_OPTS_SXTH)
10235 else if (opt == INS_OPTS_SXTW)
10237 else if (opt == INS_OPTS_SXTX)
10240 assert(!"Bad value");
10243 /*****************************************************************************
10245 * Prints the encoding for the Extend Type encoding in loads/stores
10248 void emitter::emitDispLSExtendOpts(insOpts opt)
10250 if (opt == INS_OPTS_LSL)
10252 else if (opt == INS_OPTS_UXTW)
10254 else if (opt == INS_OPTS_UXTX)
10256 else if (opt == INS_OPTS_SXTW)
10258 else if (opt == INS_OPTS_SXTX)
10261 assert(!"Bad value");
10264 /*****************************************************************************
10266 * Display a register
10268 void emitter::emitDispReg(regNumber reg, emitAttr attr, bool addComma)
10270 emitAttr size = EA_SIZE(attr);
10271 printf(emitRegName(reg, size));
10277 /*****************************************************************************
10279 * Display a vector register with an arrangement suffix
10281 void emitter::emitDispVectorReg(regNumber reg, insOpts opt, bool addComma)
10283 assert(isVectorRegister(reg));
10284 printf(emitVectorRegName(reg));
10285 emitDispArrangement(opt);
10291 /*****************************************************************************
10293 * Display an vector register index suffix
10295 void emitter::emitDispVectorRegIndex(regNumber reg, emitAttr elemsize, ssize_t index, bool addComma)
10297 assert(isVectorRegister(reg));
10298 printf(emitVectorRegName(reg));
10315 assert(!"invalid elemsize");
10319 printf("[%d]", index);
10325 /*****************************************************************************
10327 * Display an arrangement suffix
10329 void emitter::emitDispArrangement(insOpts opt)
10331 const char* str = "???";
10361 assert(!"Invalid insOpt for vector register");
10367 /*****************************************************************************
10369 * Display a register with an optional shift operation
10371 void emitter::emitDispShiftedReg(regNumber reg, insOpts opt, ssize_t imm, emitAttr attr)
10373 emitAttr size = EA_SIZE(attr);
10374 assert((imm & 0x003F) == imm);
10375 assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
10377 printf(emitRegName(reg, size));
10385 emitDispShiftOpts(opt);
10386 emitDispImm(imm, false);
10390 /*****************************************************************************
10392 * Display a register with an optional extend and scale operations
10394 void emitter::emitDispExtendReg(regNumber reg, insOpts opt, ssize_t imm)
10396 assert((imm >= 0) && (imm <= 4));
10397 assert(insOptsNone(opt) || insOptsAnyExtend(opt) || (opt == INS_OPTS_LSL));
10399 // size is based on the extend option, not the instr size.
10400 emitAttr size = insOpts32BitExtend(opt) ? EA_4BYTE : EA_8BYTE;
10404 if (insOptsNone(opt))
10406 emitDispReg(reg, size, false);
10410 emitDispReg(reg, size, true);
10411 if (opt == INS_OPTS_LSL)
10414 emitDispExtendOpts(opt);
10415 if ((imm > 0) || (opt == INS_OPTS_LSL))
10418 emitDispImm(imm, false);
10422 else // !strictArmAsm
10424 if (insOptsNone(opt))
10426 emitDispReg(reg, size, false);
10430 if (opt != INS_OPTS_LSL)
10432 emitDispExtendOpts(opt);
10434 emitDispReg(reg, size, false);
10441 emitDispImm(1 << imm, false);
10446 /*****************************************************************************
10448 * Display an addressing operand [reg + imm]
10450 void emitter::emitDispAddrRI(regNumber reg, insOpts opt, ssize_t imm)
10452 reg = encodingZRtoSP(reg); // ZR (R31) encodes the SP register
10458 emitDispReg(reg, EA_8BYTE, false);
10460 if (!insOptsPostIndex(opt) && (imm != 0))
10463 emitDispImm(imm, false);
10467 if (insOptsPreIndex(opt))
10471 else if (insOptsPostIndex(opt))
10474 emitDispImm(imm, false);
10477 else // !strictArmAsm
10481 const char* operStr = "++";
10488 if (insOptsPreIndex(opt))
10493 emitDispReg(reg, EA_8BYTE, false);
10495 if (insOptsPostIndex(opt))
10500 if (insOptsIndexed(opt))
10506 printf("%c", operStr[1]);
10508 emitDispImm(imm, false);
10513 /*****************************************************************************
10515 * Display an addressing operand [reg + extended reg]
10517 void emitter::emitDispAddrRRExt(regNumber reg1, regNumber reg2, insOpts opt, bool isScaled, emitAttr size)
10519 reg1 = encodingZRtoSP(reg1); // ZR (R31) encodes the SP register
10521 unsigned scale = 0;
10524 scale = NaturalScale_helper(size);
10531 emitDispReg(reg1, EA_8BYTE, true);
10532 emitDispExtendReg(reg2, opt, scale);
10534 else // !strictArmAsm
10536 emitDispReg(reg1, EA_8BYTE, false);
10538 emitDispExtendReg(reg2, opt, scale);
10544 /*****************************************************************************
10546 * Display (optionally) the instruction encoding in hex
10549 void emitter::emitDispInsHex(BYTE* code, size_t sz)
10551 // We do not display the instruction hex if we want diff-able disassembly
10552 if (!emitComp->opts.disDiffable)
10556 printf(" %08X ", (*((code_t*)code)));
10565 /****************************************************************************
10567 * Display the given instruction.
10570 void emitter::emitDispIns(
10571 instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* pCode, size_t sz, insGroup* ig)
10576 id->idDebugOnlyInfo()->idNum; // Do not remove this! It is needed for VisualStudio conditional breakpoints
10578 printf("IN%04x: ", idNum);
10584 if (!emitComp->opts.dspEmit && !isNew && !asmfm && sz)
10587 /* Display the instruction offset */
10589 emitDispInsOffs(offset, doffs);
10591 /* Display the instruction hex code */
10593 emitDispInsHex(pCode, sz);
10597 /* Get the instruction and format */
10599 instruction ins = id->idIns();
10600 insFormat fmt = id->idInsFmt();
10604 /* If this instruction has just been added, check its size */
10606 assert(isNew == false || (int)emitSizeOfInsDsc(id) == emitCurIGfreeNext - (BYTE*)id);
10608 /* Figure out the operand size */
10609 emitAttr size = id->idOpSize();
10610 emitAttr attr = size;
10611 if (id->idGCref() == GCT_GCREF)
10613 else if (id->idGCref() == GCT_BYREF)
10621 bool isExtendAlias;
10630 const char* methodName;
10638 case IF_BI_0A: // BI_0A ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
10639 case IF_BI_0B: // BI_0B ......iiiiiiiiii iiiiiiiiiii..... simm19:00
10642 if (fmt == IF_LARGEJMP)
10644 printf("(LARGEJMP)");
10646 if (id->idAddr()->iiaHasInstrCount())
10648 int instrCount = id->idAddr()->iiaGetInstrCount();
10652 printf("pc%s%d instructions", (instrCount >= 0) ? "+" : "", instrCount);
10656 unsigned insNum = emitFindInsNum(ig, id);
10657 UNATIVE_OFFSET srcOffs = ig->igOffs + emitFindOffset(ig, insNum + 1);
10658 UNATIVE_OFFSET dstOffs = ig->igOffs + emitFindOffset(ig, insNum + 1 + instrCount);
10659 ssize_t relOffs = (ssize_t)(emitOffsetToPtr(dstOffs) - emitOffsetToPtr(srcOffs));
10660 printf("pc%s%d (%d instructions)", (relOffs >= 0) ? "+" : "", relOffs, instrCount);
10663 else if (id->idIsBound())
10665 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10669 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10674 case IF_BI_0C: // BI_0C ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
10675 if (id->idIsCallAddr())
10677 offs = (ssize_t)id->idAddr()->iiaAddr;
10683 methodName = emitComp->eeGetMethodFullName((CORINFO_METHOD_HANDLE)id->idDebugOnlyInfo()->idMemCookie);
10688 if (id->idIsDspReloc())
10690 printf("%08X", offs);
10694 printf("%s", methodName);
10698 case IF_BI_1A: // BI_1A ......iiiiiiiiii iiiiiiiiiiittttt Rt simm19:00
10699 assert(insOptsNone(id->idInsOpt()));
10700 emitDispReg(id->idReg1(), size, true);
10701 if (id->idIsBound())
10703 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10707 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10711 case IF_BI_1B: // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
10712 assert(insOptsNone(id->idInsOpt()));
10713 emitDispReg(id->idReg1(), size, true);
10714 emitDispImm(emitGetInsSC(id), true);
10715 if (id->idIsBound())
10717 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10721 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10725 case IF_BR_1A: // BR_1A ................ ......nnnnn..... Rn
10726 assert(insOptsNone(id->idInsOpt()));
10727 emitDispReg(id->idReg1(), size, false);
10730 case IF_BR_1B: // BR_1B ................ ......nnnnn..... Rn
10731 assert(insOptsNone(id->idInsOpt()));
10732 emitDispReg(id->idReg3(), size, false);
10735 case IF_LS_1A: // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB)
10736 case IF_DI_1E: // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
10739 assert(insOptsNone(id->idInsOpt()));
10740 emitDispReg(id->idReg1(), size, true);
10741 imm = emitGetInsSC(id);
10743 /* Is this actually a reference to a data section? */
10744 if (fmt == IF_LARGEADR)
10746 printf("(LARGEADR)");
10748 else if (fmt == IF_LARGELDC)
10750 printf("(LARGELDC)");
10754 if (id->idAddr()->iiaIsJitDataOffset())
10756 doffs = Compiler::eeGetJitDataOffs(id->idAddr()->iiaFieldHnd);
10757 /* Display a data section reference */
10760 printf("@CNS%02u", doffs - 1);
10762 printf("@RWD%02u", doffs);
10765 printf("%+Id", imm);
10770 if (id->idIsReloc())
10773 emitDispImm((ssize_t)id->idAddr()->iiaAddr, false);
10775 else if (id->idIsBound())
10777 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10781 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10787 case IF_LS_2A: // LS_2A .X.......X...... ......nnnnnttttt Rt Rn
10788 assert(insOptsNone(id->idInsOpt()));
10789 assert(emitGetInsSC(id) == 0);
10790 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10791 emitDispAddrRI(id->idReg2(), id->idInsOpt(), 0);
10794 case IF_LS_2B: // LS_2B .X.......Xiiiiii iiiiiinnnnnttttt Rt Rn imm(0-4095)
10795 assert(insOptsNone(id->idInsOpt()));
10796 imm = emitGetInsSC(id);
10797 scale = NaturalScale_helper(emitInsLoadStoreSize(id));
10798 imm <<= scale; // The immediate is scaled by the size of the ld/st
10799 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10800 emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
10803 case IF_LS_2C: // LS_2C .X.......X.iiiii iiiiPPnnnnnttttt Rt Rn imm(-256..+255) no/pre/post inc
10804 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
10805 imm = emitGetInsSC(id);
10806 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10807 emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
10810 case IF_LS_3A: // LS_3A .X.......X.mmmmm oooS..nnnnnttttt Rt Rn Rm ext(Rm) LSL {}
10811 assert(insOptsLSExtend(id->idInsOpt()));
10812 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10813 if (id->idIsLclVar())
10815 emitDispAddrRRExt(id->idReg2(), codeGen->rsGetRsvdReg(), id->idInsOpt(), false, size);
10819 emitDispAddrRRExt(id->idReg2(), id->idReg3(), id->idInsOpt(), id->idReg3Scaled(), size);
10823 case IF_LS_3B: // LS_3B X............... .aaaaannnnnddddd Rt Ra Rn
10824 assert(insOptsNone(id->idInsOpt()));
10825 assert(emitGetInsSC(id) == 0);
10826 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10827 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10828 emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
10831 case IF_LS_3C: // LS_3C X.........iiiiii iaaaaannnnnddddd Rt Ra Rn imm(im7,sh)
10832 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
10833 imm = emitGetInsSC(id);
10834 scale = NaturalScale_helper(emitInsLoadStoreSize(id));
10836 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10837 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10838 emitDispAddrRI(id->idReg3(), id->idInsOpt(), imm);
10841 case IF_LS_3D: // LS_3D .X.......X.mmmmm ......nnnnnttttt Wm Rt Rn
10842 assert(insOptsNone(id->idInsOpt()));
10843 emitDispReg(id->idReg1(), EA_4BYTE, true);
10844 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10845 emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
10848 case IF_DI_1A: // DI_1A X.......shiiiiii iiiiiinnnnn..... Rn imm(i12,sh)
10849 emitDispReg(id->idReg1(), size, true);
10850 emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
10853 case IF_DI_1B: // DI_1B X........hwiiiii iiiiiiiiiiiddddd Rd imm(i16,hw)
10854 emitDispReg(id->idReg1(), size, true);
10855 hwi.immHWVal = (unsigned)emitGetInsSC(id);
10856 if (ins == INS_mov)
10858 emitDispImm(emitDecodeHalfwordImm(hwi, size), false);
10860 else // movz, movn, movk
10862 emitDispImm(hwi.immVal, false);
10863 if (hwi.immHW != 0)
10865 emitDispShiftOpts(INS_OPTS_LSL);
10866 emitDispImm(hwi.immHW * 16, false);
10871 case IF_DI_1C: // DI_1C X........Nrrrrrr ssssssnnnnn..... Rn imm(N,r,s)
10872 emitDispReg(id->idReg1(), size, true);
10873 bmi.immNRS = (unsigned)emitGetInsSC(id);
10874 emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
10877 case IF_DI_1D: // DI_1D X........Nrrrrrr ssssss.....ddddd Rd imm(N,r,s)
10878 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
10879 bmi.immNRS = (unsigned)emitGetInsSC(id);
10880 emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
10883 case IF_DI_2A: // DI_2A X.......shiiiiii iiiiiinnnnnddddd Rd Rn imm(i12,sh)
10884 if ((ins == INS_add) || (ins == INS_sub))
10886 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
10887 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
10891 emitDispReg(id->idReg1(), size, true);
10892 emitDispReg(id->idReg2(), size, true);
10894 emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
10897 case IF_DI_2B: // DI_2B X........X.nnnnn ssssssnnnnnddddd Rd Rn imm(0-63)
10898 emitDispReg(id->idReg1(), size, true);
10899 emitDispReg(id->idReg2(), size, true);
10900 emitDispImm(emitGetInsSC(id), false);
10903 case IF_DI_2C: // DI_2C X........Nrrrrrr ssssssnnnnnddddd Rd Rn imm(N,r,s)
10904 if (ins == INS_ands)
10906 emitDispReg(id->idReg1(), size, true);
10910 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
10912 emitDispReg(id->idReg2(), size, true);
10913 bmi.immNRS = (unsigned)emitGetInsSC(id);
10914 emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
10917 case IF_DI_2D: // DI_2D X........Nrrrrrr ssssssnnnnnddddd Rd Rn imr, ims (N,r,s)
10918 emitDispReg(id->idReg1(), size, true);
10919 emitDispReg(id->idReg2(), size, true);
10921 imm = emitGetInsSC(id);
10922 bmi.immNRS = (unsigned)imm;
10929 emitDispImm(bmi.immR, true);
10930 emitDispImm(bmi.immS, false);
10936 emitDispImm(getBitWidth(size) - bmi.immR, true);
10937 emitDispImm(bmi.immS + 1, false);
10943 emitDispImm(bmi.immR, true);
10944 emitDispImm(bmi.immS - bmi.immR + 1, false);
10950 emitDispImm(imm, false);
10954 assert(!"Unexpected instruction in IF_DI_2D");
10959 case IF_DI_1F: // DI_1F X..........iiiii cccc..nnnnn.nzcv Rn imm5 nzcv cond
10960 emitDispReg(id->idReg1(), size, true);
10961 cfi.immCFVal = (unsigned)emitGetInsSC(id);
10962 emitDispImm(cfi.imm5, true);
10963 emitDispFlags(cfi.flags);
10965 emitDispCond(cfi.cond);
10968 case IF_DR_1D: // DR_1D X............... cccc.......mmmmm Rd cond
10969 emitDispReg(id->idReg1(), size, true);
10970 cfi.immCFVal = (unsigned)emitGetInsSC(id);
10971 emitDispCond(cfi.cond);
10974 case IF_DR_2A: // DR_2A X..........mmmmm ......nnnnn..... Rn Rm
10975 emitDispReg(id->idReg1(), size, true);
10976 emitDispReg(id->idReg2(), size, false);
10979 case IF_DR_2B: // DR_2B X.......sh.mmmmm ssssssnnnnn..... Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
10980 emitDispReg(id->idReg1(), size, true);
10981 emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
10984 case IF_DR_2C: // DR_2C X..........mmmmm ooosssnnnnn..... Rn Rm ext(Rm) LSL imm(0-4)
10985 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
10986 imm = emitGetInsSC(id);
10987 emitDispExtendReg(id->idReg2(), id->idInsOpt(), imm);
10990 case IF_DR_2D: // DR_2D X..........nnnnn cccc..nnnnnddddd Rd Rn cond
10991 emitDispReg(id->idReg1(), size, true);
10992 emitDispReg(id->idReg2(), size, true);
10993 cfi.immCFVal = (unsigned)emitGetInsSC(id);
10994 emitDispCond(cfi.cond);
10997 case IF_DR_2E: // DR_2E X..........mmmmm ...........ddddd Rd Rm
10998 emitDispReg(id->idReg1(), size, true);
10999 emitDispReg(id->idReg2(), size, false);
11002 case IF_DR_2F: // DR_2F X.......sh.mmmmm ssssss.....ddddd Rd Rm {LSL,LSR,ASR} imm(0-63)
11003 emitDispReg(id->idReg1(), size, true);
11004 emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
11007 case IF_DR_2G: // DR_2G X............... ......nnnnnddddd Rd Rn
11008 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11009 emitDispReg(encodingZRtoSP(id->idReg2()), size, false);
11012 case IF_DR_2H: // DR_2H X........X...... ......nnnnnddddd Rd Rn
11013 emitDispReg(id->idReg1(), size, true);
11014 emitDispReg(id->idReg2(), size, false);
11017 case IF_DR_2I: // DR_2I X..........mmmmm cccc..nnnnn.nzcv Rn Rm nzcv cond
11018 emitDispReg(id->idReg1(), size, true);
11019 emitDispReg(id->idReg2(), size, true);
11020 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11021 emitDispFlags(cfi.flags);
11023 emitDispCond(cfi.cond);
11026 case IF_DR_3A: // DR_3A X..........mmmmm ......nnnnnmmmmm Rd Rn Rm
11027 if ((ins == INS_add) || (ins == INS_sub))
11029 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11030 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11032 else if ((ins == INS_smull) || (ins == INS_smulh))
11034 // Rd is always 8 bytes
11035 emitDispReg(id->idReg1(), EA_8BYTE, true);
11037 // Rn, Rm effective size depends on instruction type
11038 size = (ins == INS_smulh) ? EA_8BYTE : EA_4BYTE;
11039 emitDispReg(id->idReg2(), size, true);
11043 emitDispReg(id->idReg1(), size, true);
11044 emitDispReg(id->idReg2(), size, true);
11046 if (id->idIsLclVar())
11048 emitDispReg(codeGen->rsGetRsvdReg(), size, false);
11052 emitDispReg(id->idReg3(), size, false);
11057 case IF_DR_3B: // DR_3B X.......sh.mmmmm ssssssnnnnnddddd Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
11058 emitDispReg(id->idReg1(), size, true);
11059 emitDispReg(id->idReg2(), size, true);
11060 emitDispShiftedReg(id->idReg3(), id->idInsOpt(), emitGetInsSC(id), size);
11063 case IF_DR_3C: // DR_3C X..........mmmmm ooosssnnnnnddddd Rd Rn Rm ext(Rm) LSL imm(0-4)
11064 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11065 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11066 imm = emitGetInsSC(id);
11067 emitDispExtendReg(id->idReg3(), id->idInsOpt(), imm);
11070 case IF_DR_3D: // DR_3D X..........mmmmm cccc..nnnnnmmmmm Rd Rn Rm cond
11071 emitDispReg(id->idReg1(), size, true);
11072 emitDispReg(id->idReg2(), size, true);
11073 emitDispReg(id->idReg3(), size, true);
11074 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11075 emitDispCond(cfi.cond);
11078 case IF_DR_3E: // DR_3E X........X.mmmmm ssssssnnnnnddddd Rd Rn Rm imm(0-63)
11079 emitDispReg(id->idReg1(), size, true);
11080 emitDispReg(id->idReg2(), size, true);
11081 emitDispReg(id->idReg3(), size, true);
11082 emitDispImm(emitGetInsSC(id), false);
11085 case IF_DR_4A: // DR_4A X..........mmmmm .aaaaannnnnmmmmm Rd Rn Rm Ra
11086 emitDispReg(id->idReg1(), size, true);
11087 emitDispReg(id->idReg2(), size, true);
11088 emitDispReg(id->idReg3(), size, true);
11089 emitDispReg(id->idReg4(), size, false);
11092 case IF_DV_1A: // DV_1A .........X.iiiii iii........ddddd Vd imm8 (fmov - immediate scalar)
11093 elemsize = id->idOpSize();
11094 emitDispReg(id->idReg1(), elemsize, true);
11095 emitDispFloatImm(emitGetInsSC(id));
11098 case IF_DV_1B: // DV_1B .QX..........iii cmod..iiiiiddddd Vd imm8 (immediate vector)
11099 imm = emitGetInsSC(id) & 0x0ff;
11100 immShift = (emitGetInsSC(id) & 0x700) >> 8;
11101 hasShift = (immShift != 0);
11102 elemsize = optGetElemsize(id->idInsOpt());
11103 if (id->idInsOpt() == INS_OPTS_1D)
11105 assert(elemsize == size);
11106 emitDispReg(id->idReg1(), size, true);
11110 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11112 if (ins == INS_fmov)
11114 emitDispFloatImm(imm);
11115 assert(hasShift == false);
11119 if (elemsize == EA_8BYTE)
11121 assert(ins == INS_movi);
11123 const ssize_t mask8 = 0xFF;
11124 for (unsigned b = 0; b < 8; b++)
11126 if (imm & (1 << b))
11128 imm64 |= (mask8 << (b * 8));
11131 emitDispImm(imm64, hasShift, true);
11135 emitDispImm(imm, hasShift, true);
11139 insOpts opt = (immShift & 0x4) ? INS_OPTS_MSL : INS_OPTS_LSL;
11140 unsigned shift = (immShift & 0x3) * 8;
11141 emitDispShiftOpts(opt);
11142 emitDispImm(shift, false);
11147 case IF_DV_1C: // DV_1C .........X...... ......nnnnn..... Vn #0.0 (fcmp - with zero)
11148 elemsize = id->idOpSize();
11149 emitDispReg(id->idReg1(), elemsize, true);
11150 emitDispFloatZero();
11153 case IF_DV_2A: // DV_2A .Q.......X...... ......nnnnnddddd Vd Vn (fabs, fcvt - vector)
11154 case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
11155 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11156 emitDispVectorReg(id->idReg2(), id->idInsOpt(), false);
11159 case IF_DV_2N: // DV_2N .........iiiiiii ......nnnnnddddd Vd Vn imm (shift - scalar)
11160 elemsize = id->idOpSize();
11161 emitDispReg(id->idReg1(), elemsize, true);
11162 emitDispReg(id->idReg2(), elemsize, true);
11163 emitDispImm(emitGetInsSC(id), false);
11166 case IF_DV_2O: // DV_2O .Q.......iiiiiii ......nnnnnddddd Vd Vn imm (shift - vector)
11167 imm = emitGetInsSC(id);
11168 // Do we have a sxtl or uxtl instruction?
11169 isExtendAlias = ((ins == INS_sxtl) || (ins == INS_sxtl2) || (ins == INS_uxtl) || (ins == INS_uxtl2));
11170 code = emitInsCode(ins, fmt);
11171 if (code & 0x00008000) // widen/narrow opcodes
11173 if (code & 0x00002000) // SHL opcodes
11175 emitDispVectorReg(id->idReg1(), optWidenElemsize(id->idInsOpt()), true);
11176 emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11178 else // SHR opcodes
11180 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11181 emitDispVectorReg(id->idReg2(), optWidenElemsize(id->idInsOpt()), !isExtendAlias);
11186 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11187 emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11189 // Print the immediate unless we have a sxtl or uxtl instruction
11190 if (!isExtendAlias)
11192 emitDispImm(imm, false);
11196 case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov/smov - to general)
11197 srcsize = id->idOpSize();
11198 index = emitGetInsSC(id);
11199 if (ins == INS_smov)
11201 dstsize = EA_8BYTE;
11203 else // INS_umov or INS_mov
11205 dstsize = (srcsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE;
11207 emitDispReg(id->idReg1(), dstsize, true);
11208 emitDispVectorRegIndex(id->idReg2(), srcsize, index, false);
11211 case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
11212 if (ins == INS_dup)
11214 datasize = id->idOpSize();
11215 assert(isValidVectorDatasize(datasize));
11216 assert(isValidArrangement(datasize, id->idInsOpt()));
11217 elemsize = optGetElemsize(id->idInsOpt());
11218 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11222 elemsize = id->idOpSize();
11223 index = emitGetInsSC(id);
11224 assert(isValidVectorElemsize(elemsize));
11225 emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11227 emitDispReg(id->idReg2(), (elemsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE, false);
11230 case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
11231 datasize = id->idOpSize();
11232 assert(isValidVectorDatasize(datasize));
11233 assert(isValidArrangement(datasize, id->idInsOpt()));
11234 elemsize = optGetElemsize(id->idInsOpt());
11235 index = emitGetInsSC(id);
11236 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11237 emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11240 case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
11241 elemsize = id->idOpSize();
11242 index = emitGetInsSC(id);
11243 emitDispReg(id->idReg1(), elemsize, true);
11244 emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11247 case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
11248 imm = emitGetInsSC(id);
11249 index = (imm >> 4) & 0xf;
11250 index2 = imm & 0xf;
11251 elemsize = id->idOpSize();
11252 emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11253 emitDispVectorRegIndex(id->idReg2(), elemsize, index2, false);
11256 case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov, fcvtXX - register)
11257 case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
11258 case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
11259 elemsize = id->idOpSize();
11260 emitDispReg(id->idReg1(), elemsize, true);
11261 emitDispReg(id->idReg2(), elemsize, false);
11264 case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov, fcvtXX - to general)
11265 case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov, Xcvtf - from general)
11266 case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
11267 dstsize = optGetDstsize(id->idInsOpt());
11268 srcsize = optGetSrcsize(id->idInsOpt());
11270 emitDispReg(id->idReg1(), dstsize, true);
11271 emitDispReg(id->idReg2(), srcsize, false);
11274 case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11275 case IF_DV_3B: // DV_3B .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11276 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11277 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11278 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11281 case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11282 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11283 if (ins != INS_mov)
11285 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11287 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11290 case IF_DV_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
11291 case IF_DV_3BI: // DV_3BI .Q........Lmmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
11292 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11293 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11294 elemsize = optGetElemsize(id->idInsOpt());
11295 emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11298 case IF_DV_3D: // DV_3D .........X.mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
11299 case IF_DV_3E: // DV_3E ...........mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
11300 emitDispReg(id->idReg1(), size, true);
11301 emitDispReg(id->idReg2(), size, true);
11302 emitDispReg(id->idReg3(), size, false);
11305 case IF_DV_3DI: // DV_3DI .........XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (scalar by elem)
11306 emitDispReg(id->idReg1(), size, true);
11307 emitDispReg(id->idReg2(), size, true);
11309 emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11312 case IF_DV_4A: // DV_4A .........X.mmmmm .aaaaannnnnddddd Vd Va Vn Vm (scalar)
11313 emitDispReg(id->idReg1(), size, true);
11314 emitDispReg(id->idReg2(), size, true);
11315 emitDispReg(id->idReg3(), size, true);
11316 emitDispReg(id->idReg4(), size, false);
11319 case IF_SN_0A: // SN_0A ................ ................
11322 case IF_SI_0A: // SI_0A ...........iiiii iiiiiiiiiii..... imm16
11323 emitDispImm(emitGetInsSC(id), false);
11326 case IF_SI_0B: // SI_0B ................ ....bbbb........ imm4 - barrier
11327 emitDispBarrier((insBarrier)emitGetInsSC(id));
11331 printf("unexpected format %s", emitIfName(id->idInsFmt()));
11332 assert(!"unexpectedFormat");
11336 if (id->idDebugOnlyInfo()->idVarRefOffs)
11339 emitDispFrameRef(id->idAddr()->iiaLclVar.lvaVarNum(), id->idAddr()->iiaLclVar.lvaOffset(),
11340 id->idDebugOnlyInfo()->idVarRefOffs, asmfm);
11346 /*****************************************************************************
11348 * Display a stack frame reference.
11351 void emitter::emitDispFrameRef(int varx, int disp, int offs, bool asmfm)
11356 printf("TEMP_%02u", -varx);
11358 emitComp->gtDispLclVar(+varx, false);
11361 printf("-0x%02x", -disp);
11363 printf("+0x%02x", +disp);
11367 if (varx >= 0 && emitComp->opts.varNames)
11370 const char* varName;
11372 assert((unsigned)varx < emitComp->lvaCount);
11373 varDsc = emitComp->lvaTable + varx;
11374 varName = emitComp->compLocalVarName(varx, offs);
11378 printf("'%s", varName);
11381 printf("-%d", -disp);
11383 printf("+%d", +disp);
11392 // Generate code for a load or store operation with a potentially complex addressing mode
11393 // This method handles the case of a GT_IND with contained GT_LEA op1 of the x86 form [base + index*sccale + offset]
11394 // Since Arm64 does not directly support this complex of an addressing mode
11395 // we may generates up to three instructions for this for Arm64
11397 void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataReg, GenTreeIndir* indir)
11399 emitAttr ldstAttr = isVectorRegister(dataReg) ? attr : emitInsAdjustLoadStoreAttr(ins, attr);
11401 GenTree* addr = indir->Addr();
11403 if (addr->isContained())
11405 assert(addr->OperGet() == GT_LCL_VAR_ADDR || addr->OperGet() == GT_LEA);
11410 if (addr->OperGet() == GT_LEA)
11412 offset = addr->AsAddrMode()->Offset();
11413 if (addr->AsAddrMode()->gtScale > 0)
11415 assert(isPow2(addr->AsAddrMode()->gtScale));
11416 BitScanForward(&lsl, addr->AsAddrMode()->gtScale);
11420 GenTree* memBase = indir->Base();
11422 if (indir->HasIndex())
11424 GenTree* index = indir->Index();
11428 regNumber tmpReg = indir->GetSingleTempReg();
11430 emitAttr addType = varTypeIsGC(memBase) ? EA_BYREF : EA_PTRSIZE;
11432 if (emitIns_valid_imm_for_add(offset, EA_8BYTE))
11436 // Generate code to set tmpReg = base + index*scale
11437 emitIns_R_R_R_I(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum, lsl,
11442 // Generate code to set tmpReg = base + index
11443 emitIns_R_R_R(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum);
11446 noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11448 // Then load/store dataReg from/to [tmpReg + offset]
11449 emitIns_R_R_I(ins, ldstAttr, dataReg, tmpReg, offset);
11451 else // large offset
11453 // First load/store tmpReg with the large offset constant
11454 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11455 // Then add the base register
11457 emitIns_R_R_R(INS_add, addType, tmpReg, tmpReg, memBase->gtRegNum);
11459 noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11460 noway_assert(tmpReg != index->gtRegNum);
11462 // Then load/store dataReg from/to [tmpReg + index*scale]
11463 emitIns_R_R_R_I(ins, ldstAttr, dataReg, tmpReg, index->gtRegNum, lsl, INS_OPTS_LSL);
11466 else // (offset == 0)
11470 // Then load/store dataReg from/to [memBase + index*scale]
11471 emitIns_R_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum, lsl, INS_OPTS_LSL);
11475 // Then load/store dataReg from/to [memBase + index]
11476 emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum);
11480 else // no Index register
11482 if (emitIns_valid_imm_for_ldst_offset(offset, EA_SIZE(attr)))
11484 // Then load/store dataReg from/to [memBase + offset]
11485 emitIns_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, offset);
11489 // We require a tmpReg to hold the offset
11490 regNumber tmpReg = indir->GetSingleTempReg();
11492 // First load/store tmpReg with the large offset constant
11493 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11495 // Then load/store dataReg from/to [memBase + tmpReg]
11496 emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, tmpReg);
11500 else // addr is not contained, so we evaluate it into a register
11502 // Then load/store dataReg from/to [addrReg]
11503 emitIns_R_R(ins, ldstAttr, dataReg, addr->gtRegNum);
11507 // The callee must call genConsumeReg() for any non-contained srcs
11508 // and genProduceReg() for any non-contained dsts.
11510 regNumber emitter::emitInsBinary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src)
11512 regNumber result = REG_NA;
11514 // dst can only be a reg
11515 assert(!dst->isContained());
11517 // src can be immed or reg
11518 assert(!src->isContained() || src->isContainedIntOrIImmed());
11520 // find immed (if any) - it cannot be a dst
11521 GenTreeIntConCommon* intConst = nullptr;
11522 if (src->isContainedIntOrIImmed())
11524 intConst = src->AsIntConCommon();
11529 emitIns_R_I(ins, attr, dst->gtRegNum, intConst->IconValue());
11530 return dst->gtRegNum;
11534 emitIns_R_R(ins, attr, dst->gtRegNum, src->gtRegNum);
11535 return dst->gtRegNum;
11539 // The callee must call genConsumeReg() for any non-contained srcs
11540 // and genProduceReg() for any non-contained dsts.
11542 regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src1, GenTree* src2)
11544 regNumber result = REG_NA;
11546 // dst can only be a reg
11547 assert(!dst->isContained());
11549 // find immed (if any) - it cannot be a dst
11550 // Only one src can be an int.
11551 GenTreeIntConCommon* intConst = nullptr;
11552 GenTree* nonIntReg = nullptr;
11554 if (varTypeIsFloating(dst))
11556 // src1 can only be a reg
11557 assert(!src1->isContained());
11558 // src2 can only be a reg
11559 assert(!src2->isContained());
11561 else // not floating point
11563 // src2 can be immed or reg
11564 assert(!src2->isContained() || src2->isContainedIntOrIImmed());
11566 // Check src2 first as we can always allow it to be a contained immediate
11567 if (src2->isContainedIntOrIImmed())
11569 intConst = src2->AsIntConCommon();
11572 // Only for commutative operations do we check src1 and allow it to be a contained immediate
11573 else if (dst->OperIsCommutative())
11575 // src1 can be immed or reg
11576 assert(!src1->isContained() || src1->isContainedIntOrIImmed());
11578 // Check src1 and allow it to be a contained immediate
11579 if (src1->isContainedIntOrIImmed())
11581 assert(!src2->isContainedIntOrIImmed());
11582 intConst = src1->AsIntConCommon();
11588 // src1 can only be a reg
11589 assert(!src1->isContained());
11593 bool isMulOverflow = false;
11594 if (dst->gtOverflowEx())
11596 if ((ins == INS_add) || (ins == INS_adds))
11600 else if ((ins == INS_sub) || (ins == INS_subs))
11604 else if (ins == INS_mul)
11606 isMulOverflow = true;
11607 assert(intConst == nullptr); // overflow format doesn't support an int constant operand
11611 assert(!"Invalid ins for overflow check");
11614 if (intConst != nullptr)
11616 emitIns_R_R_I(ins, attr, dst->gtRegNum, nonIntReg->gtRegNum, intConst->IconValue());
11622 regNumber extraReg = dst->GetSingleTempReg();
11623 assert(extraReg != dst->gtRegNum);
11625 if ((dst->gtFlags & GTF_UNSIGNED) != 0)
11627 if (attr == EA_4BYTE)
11629 // Compute 8 byte results from 4 byte by 4 byte multiplication.
11630 emitIns_R_R_R(INS_umull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11632 // Get the high result by shifting dst.
11633 emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11637 assert(attr == EA_8BYTE);
11638 // Compute the high result.
11639 emitIns_R_R_R(INS_umulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11641 // Now multiply without skewing the high result.
11642 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11645 // zero-sign bit comparison to detect overflow.
11646 emitIns_R_I(INS_cmp, attr, extraReg, 0);
11651 if (attr == EA_4BYTE)
11653 // Compute 8 byte results from 4 byte by 4 byte multiplication.
11654 emitIns_R_R_R(INS_smull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11656 // Get the high result by shifting dst.
11657 emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11663 assert(attr == EA_8BYTE);
11664 // Save the high result in a temporary register.
11665 emitIns_R_R_R(INS_smulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11667 // Now multiply without skewing the high result.
11668 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11673 // Sign bit comparison to detect overflow.
11674 emitIns_R_R_I(INS_cmp, attr, extraReg, dst->gtRegNum, bitShift, INS_OPTS_ASR);
11679 // We can just multiply.
11680 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11684 if (dst->gtOverflowEx())
11686 assert(!varTypeIsFloating(dst));
11687 codeGen->genCheckOverflow(dst);
11690 return dst->gtRegNum;
11693 #endif // defined(_TARGET_ARM64_)