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));
4242 assert(isVectorRegister(reg1));
4243 assert(isVectorRegister(reg2));
4245 if (isValidVectorDatasize(size))
4248 assert(insOptsAnyArrangement(opt));
4249 assert(isValidArrangement(size, opt));
4250 elemsize = optGetElemsize(opt);
4257 assert(size == EA_8BYTE); // Only Double supported
4267 assert(isVectorRegister(reg1));
4268 assert(isVectorRegister(reg2));
4270 if (isValidVectorDatasize(size))
4273 assert(insOptsAnyArrangement(opt));
4274 assert(isValidArrangement(size, opt));
4275 elemsize = optGetElemsize(opt);
4276 assert((elemsize == EA_8BYTE) || (elemsize == EA_4BYTE)); // Only Double/Float supported
4277 assert(opt != INS_OPTS_1D); // Reserved encoding
4284 assert((size == EA_8BYTE) || (size == EA_4BYTE)); // Only Double/Float supported
4293 } // end switch (ins)
4295 assert(fmt != IF_NONE);
4297 instrDesc* id = emitNewInstrSmall(attr);
4310 /*****************************************************************************
4312 * Add an instruction referencing a register and two constants.
4315 void emitter::emitIns_R_I_I(
4316 instruction ins, emitAttr attr, regNumber reg, ssize_t imm1, ssize_t imm2, insOpts opt /* = INS_OPTS_NONE */)
4318 emitAttr size = EA_SIZE(attr);
4319 insFormat fmt = IF_NONE;
4320 size_t immOut = 0; // composed from imm1 and imm2 and stored in the instrDesc
4322 /* Figure out the encoding format of the instruction */
4329 ins = INS_movz; // INS_mov with LSL is an alias for INS_movz LSL
4335 assert(isValidGeneralDatasize(size));
4336 assert(isGeneralRegister(reg));
4337 assert(isValidUimm16(imm1));
4338 assert(insOptsLSL(opt)); // Must be INS_OPTS_LSL
4340 if (size == EA_8BYTE)
4342 assert((imm2 == 0) || (imm2 == 16) || // shift amount: 0, 16, 32 or 48
4343 (imm2 == 32) || (imm2 == 48));
4347 assert((imm2 == 0) || (imm2 == 16)); // shift amount: 0 or 16
4382 immOut = hwi.immHWVal;
4383 assert(isValidImmHWVal(immOut, size));
4392 } // end switch (ins)
4394 assert(fmt != IF_NONE);
4396 instrDesc* id = emitNewInstrSC(attr, immOut);
4407 /*****************************************************************************
4409 * Add an instruction referencing two registers and a constant.
4412 void emitter::emitIns_R_R_I(
4413 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm, insOpts opt /* = INS_OPTS_NONE */)
4415 emitAttr size = EA_SIZE(attr);
4416 emitAttr elemsize = EA_UNKNOWN;
4417 insFormat fmt = IF_NONE;
4418 bool isLdSt = false;
4419 bool isSIMD = false;
4420 bool isAddSub = false;
4421 bool setFlags = false;
4423 bool unscaledOp = false;
4425 /* Figure out the encoding format of the instruction */
4432 // Check for the 'mov' aliases for the vector registers
4433 assert(insOptsNone(opt));
4434 assert(isValidVectorElemsize(size));
4436 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4438 if (isVectorRegister(reg1))
4440 if (isGeneralRegisterOrZR(reg2))
4442 fmt = IF_DV_2C; // Alias for 'ins'
4445 else if (isVectorRegister(reg2))
4447 fmt = IF_DV_2E; // Alias for 'dup'
4451 else // isGeneralRegister(reg1)
4453 assert(isGeneralRegister(reg1));
4454 if (isVectorRegister(reg2))
4456 fmt = IF_DV_2B; // Alias for 'umov'
4460 assert(!" invalid INS_mov operands");
4466 assert(insOptsNone(opt));
4467 assert(isValidGeneralDatasize(size));
4468 assert(isGeneralRegister(reg1));
4469 assert(isGeneralRegister(reg2));
4470 assert(isValidImmShift(imm, size));
4475 assert(insOptsNone(opt));
4476 assert(isValidGeneralDatasize(size));
4477 assert(isGeneralRegister(reg1));
4478 assert(isGeneralRegister(reg2));
4479 assert(isValidImmShift(imm, size));
4494 assert(isVectorRegister(reg1));
4495 assert(isVectorRegister(reg2));
4496 if (insOptsAnyArrangement(opt))
4499 assert(isValidVectorDatasize(size));
4500 assert(isValidArrangement(size, opt));
4501 elemsize = optGetElemsize(opt);
4502 assert(isValidVectorElemsize(elemsize));
4503 assert(isValidImmShift(imm, elemsize));
4504 assert(opt != INS_OPTS_1D); // Reserved encoding
4511 assert(insOptsNone(opt));
4512 assert(size == EA_8BYTE); // only supported size
4513 assert(isValidImmShift(imm, size));
4527 assert(isVectorRegister(reg1));
4528 assert(isVectorRegister(reg2));
4530 assert(size == EA_8BYTE);
4531 assert(isValidArrangement(size, opt));
4532 elemsize = optGetElemsize(opt);
4533 assert(elemsize != EA_8BYTE); // Reserved encodings
4534 assert(isValidVectorElemsize(elemsize));
4535 assert(isValidImmShift(imm, elemsize));
4548 assert(isVectorRegister(reg1));
4549 assert(isVectorRegister(reg2));
4551 assert(size == EA_16BYTE);
4552 assert(isValidArrangement(size, opt));
4553 elemsize = optGetElemsize(opt);
4554 assert(elemsize != EA_8BYTE); // Reserved encodings
4555 assert(isValidVectorElemsize(elemsize));
4556 assert(isValidImmShift(imm, elemsize));
4563 assert(isValidGeneralDatasize(size));
4564 assert(isGeneralRegister(reg1));
4565 assert(isGeneralRegisterOrZR(reg2));
4569 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4577 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
4581 assert(insOptsAluShift(opt)); // a non-zero imm, must select shift kind, can't use ROR
4583 assert(isValidImmShift(imm, size));
4589 assert(isValidGeneralDatasize(size));
4590 assert(isGeneralRegisterOrZR(reg1));
4591 assert(isGeneralRegister(reg2));
4593 if (insOptsAnyShift(opt))
4595 assert(isValidImmShift(imm, size) && (imm != 0));
4600 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4608 assert(isValidGeneralDatasize(size));
4609 assert(isGeneralRegisterOrSP(reg1));
4610 assert(isGeneralRegister(reg2));
4612 reg1 = encodingSPtoZR(reg1);
4613 if (insOptsAnyExtend(opt))
4615 assert((imm >= 0) && (imm <= 4));
4621 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4627 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
4628 assert(isValidImmShift(imm, size));
4637 assert(insOptsNone(opt));
4638 assert(isGeneralRegister(reg2));
4639 if (ins == INS_ands)
4641 assert(isGeneralRegister(reg1));
4645 assert(isGeneralRegisterOrSP(reg1));
4646 reg1 = encodingSPtoZR(reg1);
4650 canEncode = canEncodeBitMaskImm(imm, size, &bmi);
4654 assert(isValidImmNRS(imm, size));
4659 case INS_dup: // by element, imm selects the element of reg2
4660 assert(isVectorRegister(reg1));
4661 if (isVectorRegister(reg2))
4663 if (insOptsAnyArrangement(opt))
4666 assert(isValidVectorDatasize(size));
4667 assert(isValidArrangement(size, opt));
4668 elemsize = optGetElemsize(opt);
4669 assert(isValidVectorElemsize(elemsize));
4670 assert(isValidVectorIndex(size, elemsize, imm));
4671 assert(opt != INS_OPTS_1D); // Reserved encoding
4678 assert(insOptsNone(opt));
4680 assert(isValidVectorElemsize(elemsize));
4681 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4688 case INS_ins: // (MOV from general)
4689 assert(insOptsNone(opt));
4690 assert(isValidVectorElemsize(size));
4691 assert(isVectorRegister(reg1));
4692 assert(isGeneralRegisterOrZR(reg2));
4694 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4698 case INS_umov: // (MOV to general)
4699 assert(insOptsNone(opt));
4700 assert(isValidVectorElemsize(size));
4701 assert(isGeneralRegister(reg1));
4702 assert(isVectorRegister(reg2));
4704 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4709 assert(insOptsNone(opt));
4710 assert(isValidVectorElemsize(size));
4711 assert(size != EA_8BYTE); // no encoding, use INS_umov
4712 assert(isGeneralRegister(reg1));
4713 assert(isVectorRegister(reg2));
4715 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4733 // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4734 assert(isValidGeneralDatasize(size));
4735 unscaledOp = (ins == INS_ldursb);
4742 // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4743 assert(isValidGeneralDatasize(size));
4744 unscaledOp = (ins == INS_ldursh);
4751 // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4752 assert(size == EA_8BYTE);
4753 unscaledOp = (ins == INS_ldursw);
4792 // Is the target a vector register?
4793 if (isVectorRegister(reg1))
4795 assert(isValidVectorLSDatasize(size));
4796 assert(isGeneralRegisterOrSP(reg2));
4801 assert(isValidGeneralDatasize(size));
4804 scale = NaturalScale_helper(size);
4810 // Is the target a vector register?
4811 if (isVectorRegister(reg1))
4813 assert(isValidVectorLSDatasize(size));
4814 assert(isGeneralRegisterOrSP(reg2));
4819 assert(isValidGeneralDatasize(size));
4830 } // end switch (ins)
4838 assert(isValidVectorLSDatasize(size));
4839 assert(isVectorRegister(reg1));
4840 assert((scale >= 0) && (scale <= 4));
4844 assert(isValidGeneralLSDatasize(size));
4845 assert(isGeneralRegisterOrZR(reg1));
4846 assert((scale >= 0) && (scale <= 3));
4849 assert(isGeneralRegisterOrSP(reg2));
4851 // Load/Store reserved encodings:
4852 if (insOptsIndexed(opt))
4854 assert(reg1 != reg2);
4857 reg2 = encodingSPtoZR(reg2);
4859 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
4862 assert(insOptsNone(opt)); // PRE/POST Index doesn't make sense with an immediate of zero
4866 else if (insOptsIndexed(opt) || unscaledOp || (imm < 0) || ((imm & mask) != 0))
4868 if ((imm >= -256) && (imm <= 255))
4874 assert(!"Instruction cannot be encoded: IF_LS_2C");
4879 assert(insOptsNone(opt));
4880 assert(!unscaledOp);
4882 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
4884 imm >>= scale; // The immediate is scaled by the size of the ld/st
4890 assert(!"Instruction cannot be encoded: IF_LS_2B");
4897 assert(insOptsNone(opt));
4899 if (setFlags) // Can't encode SP with setFlags
4901 assert(isGeneralRegister(reg1));
4902 assert(isGeneralRegister(reg2));
4906 assert(isGeneralRegisterOrSP(reg1));
4907 assert(isGeneralRegisterOrSP(reg2));
4909 // Is it just a mov?
4912 // Is the mov even necessary?
4915 emitIns_R_R(INS_mov, attr, reg1, reg2);
4920 reg1 = encodingSPtoZR(reg1);
4921 reg2 = encodingSPtoZR(reg2);
4924 if (unsigned_abs(imm) <= 0x0fff)
4928 ins = insReverse(ins);
4931 assert(isValidUimm12(imm));
4934 else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
4936 // Encoding will use a 12-bit left shift of the immediate
4937 opt = INS_OPTS_LSL12;
4940 ins = insReverse(ins);
4943 assert((imm & 0xfff) == 0);
4945 assert(isValidUimm12(imm));
4950 assert(!"Instruction cannot be encoded: IF_DI_2A");
4954 assert(fmt != IF_NONE);
4956 instrDesc* id = emitNewInstrSC(attr, imm);
4969 /*****************************************************************************
4971 * Add an instruction referencing two registers and a constant.
4972 * Also checks for a large immediate that needs a second instruction
4973 * and will load it in reg1
4975 * - Supports instructions: add, adds, sub, subs, and, ands, eor and orr
4976 * - Requires that reg1 is a general register and not SP or ZR
4977 * - Requires that reg1 != reg2
4979 void emitter::emitIns_R_R_Imm(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm)
4981 assert(isGeneralRegister(reg1));
4982 assert(reg1 != reg2);
4984 bool immFits = true;
4992 immFits = emitter::emitIns_valid_imm_for_add(imm, attr);
4999 immFits = emitter::emitIns_valid_imm_for_alu(imm, attr);
5003 assert(!"Unsupported instruction in emitIns_R_R_Imm");
5008 emitIns_R_R_I(ins, attr, reg1, reg2, imm);
5012 // Load 'imm' into the reg1 register
5013 // then issue: 'ins' reg1, reg2, reg1
5015 codeGen->instGen_Set_Reg_To_Imm(attr, reg1, imm);
5016 emitIns_R_R_R(ins, attr, reg1, reg2, reg1);
5020 /*****************************************************************************
5022 * Add an instruction referencing three registers.
5025 void emitter::emitIns_R_R_R(
5026 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insOpts opt) /* = INS_OPTS_NONE */
5028 emitAttr size = EA_SIZE(attr);
5029 emitAttr elemsize = EA_UNKNOWN;
5030 insFormat fmt = IF_NONE;
5032 /* Figure out the encoding format of the instruction */
5056 assert(insOptsNone(opt));
5057 assert(isValidGeneralDatasize(size));
5058 assert(isGeneralRegister(reg1));
5059 assert(isGeneralRegister(reg2));
5060 assert(isGeneralRegister(reg3));
5065 if (insOptsNone(opt))
5068 assert(isValidGeneralDatasize(size));
5069 assert(isGeneralRegister(reg1));
5070 assert(isGeneralRegister(reg2));
5071 assert(isGeneralRegister(reg3));
5080 assert(insOptsAnyArrangement(opt));
5081 assert(isVectorRegister(reg1));
5082 assert(isVectorRegister(reg2));
5083 assert(isVectorRegister(reg3));
5084 assert(isValidVectorDatasize(size));
5085 assert(isValidArrangement(size, opt));
5086 elemsize = optGetElemsize(opt);
5087 if (ins == INS_pmul)
5089 assert(elemsize == EA_1BYTE); // only supports 8B or 16B
5091 else // INS_mul, INS_mla, INS_mls
5093 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
5100 if (isVectorRegister(reg1))
5102 assert(isVectorRegister(reg2));
5103 assert(isVectorRegister(reg3));
5105 if (insOptsAnyArrangement(opt))
5108 assert(opt != INS_OPTS_1D); // Reserved encoding
5109 assert(isValidVectorDatasize(size));
5110 assert(isValidArrangement(size, opt));
5116 assert(insOptsNone(opt));
5117 assert(size == EA_8BYTE);
5126 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, INS_OPTS_NONE);
5135 assert(isVectorRegister(reg1));
5136 assert(isVectorRegister(reg2));
5137 assert(isVectorRegister(reg3));
5139 if (isValidVectorDatasize(size))
5142 assert(insOptsAnyArrangement(opt));
5143 assert(isValidArrangement(size, opt));
5144 elemsize = optGetElemsize(opt);
5151 assert(size == EA_8BYTE); // Only Double supported
5159 assert(isVectorRegister(reg1));
5160 assert(isVectorRegister(reg2));
5161 assert(isVectorRegister(reg3));
5163 if (isValidVectorDatasize(size))
5166 assert(insOptsAnyArrangement(opt));
5167 assert(isValidArrangement(size, opt));
5168 elemsize = optGetElemsize(opt);
5169 assert((elemsize == EA_8BYTE) || (elemsize == EA_4BYTE)); // Only Double/Float supported
5170 assert(opt != INS_OPTS_1D); // Reserved encoding
5177 assert((size == EA_8BYTE) || (size == EA_4BYTE)); // Only Double/Float supported
5190 assert(isVectorRegister(reg1));
5191 assert(isVectorRegister(reg2));
5192 assert(isVectorRegister(reg3));
5193 assert(insOptsAnyArrangement(opt));
5196 assert(isValidVectorDatasize(size));
5197 assert(isValidArrangement(size, opt));
5198 elemsize = optGetElemsize(opt);
5199 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
5205 assert(isVectorRegister(reg1));
5206 assert(isVectorRegister(reg2));
5207 assert(reg2 == reg3);
5208 assert(isValidVectorDatasize(size));
5209 // INS_mov is an alias for INS_orr (vector register)
5210 if (opt == INS_OPTS_NONE)
5212 elemsize = EA_1BYTE;
5213 opt = optMakeArrangement(size, elemsize);
5215 assert(isValidArrangement(size, opt));
5224 if (isVectorRegister(reg1))
5226 assert(isValidVectorDatasize(size));
5227 assert(isVectorRegister(reg2));
5228 assert(isVectorRegister(reg3));
5229 if (opt == INS_OPTS_NONE)
5231 elemsize = EA_1BYTE;
5232 opt = optMakeArrangement(size, elemsize);
5234 assert(isValidArrangement(size, opt));
5243 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, INS_OPTS_NONE);
5249 assert(isValidVectorDatasize(size));
5250 assert(isVectorRegister(reg1));
5251 assert(isVectorRegister(reg2));
5252 assert(isVectorRegister(reg3));
5253 if (opt == INS_OPTS_NONE)
5255 elemsize = EA_1BYTE;
5256 opt = optMakeArrangement(size, elemsize);
5258 assert(isValidArrangement(size, opt));
5270 assert(isVectorRegister(reg1));
5271 assert(isVectorRegister(reg2));
5272 assert(isVectorRegister(reg3));
5273 if (insOptsAnyArrangement(opt))
5276 assert(isValidVectorDatasize(size));
5277 assert(isValidArrangement(size, opt));
5278 elemsize = optGetElemsize(opt);
5279 assert(isValidVectorElemsizeFloat(elemsize));
5280 assert(opt != INS_OPTS_1D); // Reserved encoding
5286 assert(insOptsNone(opt));
5287 assert(isValidScalarDatasize(size));
5294 assert(insOptsNone(opt));
5295 assert(isVectorRegister(reg1));
5296 assert(isVectorRegister(reg2));
5297 assert(isVectorRegister(reg3));
5298 assert(isValidScalarDatasize(size));
5305 assert(isVectorRegister(reg1));
5306 assert(isVectorRegister(reg2));
5307 assert(isVectorRegister(reg3));
5308 assert(insOptsAnyArrangement(opt)); // no scalar encoding, use 4-operand 'fmadd' or 'fmsub'
5311 assert(isValidVectorDatasize(size));
5312 assert(isValidArrangement(size, opt));
5313 elemsize = optGetElemsize(opt);
5314 assert(isValidVectorElemsizeFloat(elemsize));
5315 assert(opt != INS_OPTS_1D); // Reserved encoding
5328 emitIns_R_R_R_Ext(ins, attr, reg1, reg2, reg3, opt);
5336 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0);
5345 assert(isGeneralRegisterOrZR(reg1));
5346 assert(isGeneralRegisterOrZR(reg2));
5347 assert(isGeneralRegisterOrSP(reg3));
5355 } // end switch (ins)
5357 assert(fmt != IF_NONE);
5359 instrDesc* id = emitNewInstr(attr);
5373 /*****************************************************************************
5375 * Add an instruction referencing three registers and a constant.
5378 void emitter::emitIns_R_R_R_I(instruction ins,
5384 insOpts opt /* = INS_OPTS_NONE */,
5385 emitAttr attrReg2 /* = EA_UNKNOWN */)
5387 emitAttr size = EA_SIZE(attr);
5388 emitAttr elemsize = EA_UNKNOWN;
5389 insFormat fmt = IF_NONE;
5390 bool isLdSt = false;
5391 bool isSIMD = false;
5392 bool isAddSub = false;
5393 bool setFlags = false;
5396 /* Figure out the encoding format of the instruction */
5400 assert(insOptsNone(opt));
5401 assert(isValidGeneralDatasize(size));
5402 assert(isGeneralRegister(reg1));
5403 assert(isGeneralRegister(reg2));
5404 assert(isGeneralRegister(reg3));
5405 assert(isValidImmShift(imm, size));
5417 assert(isValidGeneralDatasize(size));
5418 assert(isGeneralRegister(reg1));
5419 assert(isGeneralRegister(reg2));
5420 assert(isGeneralRegister(reg3));
5421 assert(isValidImmShift(imm, size));
5424 assert(insOptsNone(opt)); // a zero imm, means no shift kind
5429 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
5434 case INS_fmul: // by element, imm[0..3] selects the element of reg3
5438 assert(isVectorRegister(reg1));
5439 assert(isVectorRegister(reg2));
5440 assert(isVectorRegister(reg3));
5441 if (insOptsAnyArrangement(opt))
5444 assert(isValidVectorDatasize(size));
5445 assert(isValidArrangement(size, opt));
5446 elemsize = optGetElemsize(opt);
5447 assert(isValidVectorElemsizeFloat(elemsize));
5448 assert(isValidVectorIndex(size, elemsize, imm));
5449 assert(opt != INS_OPTS_1D); // Reserved encoding
5455 assert(insOptsNone(opt));
5456 assert(isValidScalarDatasize(size));
5458 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
5463 case INS_mul: // by element, imm[0..7] selects the element of reg3
5466 assert(isVectorRegister(reg1));
5467 assert(isVectorRegister(reg2));
5468 assert(isVectorRegister(reg3));
5470 assert(insOptsAnyArrangement(opt));
5471 assert(isValidVectorDatasize(size));
5472 assert(isValidArrangement(size, opt));
5473 elemsize = optGetElemsize(opt);
5474 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
5475 // Only has encodings for H or S elemsize
5476 assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE));
5477 // Only has encodings for V0..V15
5478 if ((elemsize == EA_2BYTE) && (reg3 >= REG_V16))
5480 noway_assert(!"Invalid reg3");
5504 assert(insOptsNone(opt)); // Can't use Pre/Post index on these two instructions
5509 // Is the target a vector register?
5510 if (isVectorRegister(reg1))
5512 scale = NaturalScale_helper(size);
5517 scale = (size == EA_8BYTE) ? 3 : 2;
5526 } // end switch (ins)
5531 assert(isGeneralRegisterOrSP(reg3));
5532 assert(insOptsNone(opt) || insOptsIndexed(opt));
5536 assert(isValidVectorLSPDatasize(size));
5537 assert(isVectorRegister(reg1));
5538 assert(isVectorRegister(reg2));
5539 assert((scale >= 2) && (scale <= 4));
5543 assert(isValidGeneralDatasize(size));
5544 assert(isGeneralRegisterOrZR(reg1));
5545 assert(isGeneralRegisterOrZR(reg2));
5546 assert((scale == 2) || (scale == 3));
5549 // Load/Store Pair reserved encodings:
5550 if (emitInsIsLoad(ins))
5552 assert(reg1 != reg2);
5554 if (insOptsIndexed(opt))
5556 assert(reg1 != reg3);
5557 assert(reg2 != reg3);
5560 reg3 = encodingSPtoZR(reg3);
5562 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
5565 assert(insOptsNone(opt)); // PRE/POST Index doesn't make sense with an immediate of zero
5571 if ((imm & mask) == 0)
5573 imm >>= scale; // The immediate is scaled by the size of the ld/st
5575 if ((imm >= -64) && (imm <= 63))
5581 if (fmt != IF_LS_3C)
5583 assert(!"Instruction cannot be encoded: IF_LS_3C");
5590 bool reg2IsSP = (reg2 == REG_SP);
5592 assert(isValidGeneralDatasize(size));
5593 assert(isGeneralRegister(reg3));
5595 if (setFlags || insOptsAluShift(opt)) // Can't encode SP in reg1 with setFlags or AluShift option
5597 assert(isGeneralRegisterOrZR(reg1));
5601 assert(isGeneralRegisterOrSP(reg1));
5602 reg1 = encodingSPtoZR(reg1);
5605 if (insOptsAluShift(opt)) // Can't encode SP in reg2 with AluShift option
5607 assert(isGeneralRegister(reg2));
5611 assert(isGeneralRegisterOrSP(reg2));
5612 reg2 = encodingSPtoZR(reg2);
5615 if (insOptsAnyExtend(opt))
5617 assert((imm >= 0) && (imm <= 4));
5621 else if (insOptsAluShift(opt))
5623 // imm should be non-zero and in [1..63]
5624 assert(isValidImmShift(imm, size) && (imm != 0));
5629 assert(insOptsNone(opt));
5633 // To encode the SP register as reg2 we must use the IF_DR_3C encoding
5634 // and also specify a LSL of zero (imm == 0)
5645 assert(!"Instruction cannot be encoded: Add/Sub IF_DR_3A");
5648 assert(fmt != IF_NONE);
5650 instrDesc* id = emitNewInstrCns(attr, imm);
5660 // Record the attribute for the second register in the pair
5661 id->idGCrefReg2(GCT_NONE);
5662 if (attrReg2 != EA_UNKNOWN)
5664 // Record the attribute for the second register in the pair
5665 assert((fmt == IF_LS_3B) || (fmt == IF_LS_3C));
5666 if (EA_IS_GCREF(attrReg2))
5668 id->idGCrefReg2(GCT_GCREF);
5670 else if (EA_IS_BYREF(attrReg2))
5672 id->idGCrefReg2(GCT_BYREF);
5680 /*****************************************************************************
5682 * Add an instruction referencing three registers, with an extend option
5685 void emitter::emitIns_R_R_R_Ext(instruction ins,
5690 insOpts opt, /* = INS_OPTS_NONE */
5691 int shiftAmount) /* = -1 -- unset */
5693 emitAttr size = EA_SIZE(attr);
5694 insFormat fmt = IF_NONE;
5695 bool isSIMD = false;
5698 /* Figure out the encoding format of the instruction */
5719 // Is the target a vector register?
5720 if (isVectorRegister(reg1))
5722 assert(isValidVectorLSDatasize(size));
5723 scale = NaturalScale_helper(size);
5728 assert(isValidGeneralDatasize(size));
5729 scale = (size == EA_8BYTE) ? 3 : 2;
5738 } // end switch (ins)
5740 assert(scale != -1);
5741 assert(insOptsLSExtend(opt));
5745 assert(isValidVectorLSDatasize(size));
5746 assert(isVectorRegister(reg1));
5750 assert(isValidGeneralLSDatasize(size));
5751 assert(isGeneralRegisterOrZR(reg1));
5754 assert(isGeneralRegisterOrSP(reg2));
5755 assert(isGeneralRegister(reg3));
5757 // Load/Store reserved encodings:
5758 if (insOptsIndexed(opt))
5760 assert(reg1 != reg2);
5763 if (shiftAmount == -1)
5765 shiftAmount = insOptsLSL(opt) ? scale : 0;
5767 assert((shiftAmount == scale) || (shiftAmount == 0));
5769 reg2 = encodingSPtoZR(reg2);
5772 instrDesc* id = emitNewInstr(attr);
5781 id->idReg3Scaled(shiftAmount == scale);
5787 /*****************************************************************************
5789 * Add an instruction referencing two registers and two constants.
5792 void emitter::emitIns_R_R_I_I(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, int imm1, int imm2)
5794 emitAttr size = EA_SIZE(attr);
5795 emitAttr elemsize = EA_UNKNOWN;
5796 insFormat fmt = IF_NONE;
5797 size_t immOut = 0; // composed from imm1 and imm2 and stored in the instrDesc
5799 /* Figure out the encoding format of the instruction */
5809 assert(isGeneralRegister(reg1));
5810 assert(isGeneralRegister(reg2));
5811 assert(isValidImmShift(imm1, size));
5812 assert(isValidImmShift(imm2, size));
5814 bmi.immN = (size == EA_8BYTE);
5817 immOut = bmi.immNRS;
5824 assert(isGeneralRegister(reg1));
5825 assert(isGeneralRegister(reg2));
5826 lsb = getBitWidth(size) - imm1;
5828 assert(isValidImmShift(lsb, size));
5829 assert(isValidImmShift(width, size));
5831 bmi.immN = (size == EA_8BYTE);
5834 immOut = bmi.immNRS;
5841 assert(isGeneralRegister(reg1));
5842 assert(isGeneralRegister(reg2));
5844 width = imm2 + imm1 - 1;
5845 assert(isValidImmShift(lsb, size));
5846 assert(isValidImmShift(width, size));
5848 bmi.immN = (size == EA_8BYTE);
5850 bmi.immS = imm2 + imm1 - 1;
5851 immOut = bmi.immNRS;
5857 assert(isVectorRegister(reg1));
5858 assert(isVectorRegister(reg2));
5860 assert(isValidVectorElemsize(elemsize));
5861 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm1));
5862 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm2));
5863 immOut = (imm1 << 4) + imm2;
5871 assert(fmt != IF_NONE);
5873 instrDesc* id = emitNewInstrSC(attr, immOut);
5885 /*****************************************************************************
5887 * Add an instruction referencing four registers.
5890 void emitter::emitIns_R_R_R_R(
5891 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, regNumber reg4)
5893 emitAttr size = EA_SIZE(attr);
5894 insFormat fmt = IF_NONE;
5896 /* Figure out the encoding format of the instruction */
5905 assert(isValidGeneralDatasize(size));
5906 assert(isGeneralRegister(reg1));
5907 assert(isGeneralRegister(reg2));
5908 assert(isGeneralRegister(reg3));
5909 assert(isGeneralRegister(reg4));
5918 assert(isValidScalarDatasize(size));
5919 assert(isVectorRegister(reg1));
5920 assert(isVectorRegister(reg2));
5921 assert(isVectorRegister(reg3));
5922 assert(isVectorRegister(reg4));
5934 assert(fmt != IF_NONE);
5936 instrDesc* id = emitNewInstr(attr);
5950 /*****************************************************************************
5952 * Add an instruction referencing a register and a condition code
5955 void emitter::emitIns_R_COND(instruction ins, emitAttr attr, regNumber reg, insCond cond)
5957 emitAttr size = EA_SIZE(attr);
5958 insFormat fmt = IF_NONE;
5962 /* Figure out the encoding format of the instruction */
5967 assert(isGeneralRegister(reg));
5976 } // end switch (ins)
5978 assert(fmt != IF_NONE);
5979 assert(isValidImmCond(cfi.immCFVal));
5981 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
5985 id->idInsOpt(INS_OPTS_NONE);
5993 /*****************************************************************************
5995 * Add an instruction referencing two registers and a condition code
5998 void emitter::emitIns_R_R_COND(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insCond cond)
6000 emitAttr size = EA_SIZE(attr);
6001 insFormat fmt = IF_NONE;
6005 /* Figure out the encoding format of the instruction */
6011 assert(isGeneralRegister(reg1));
6012 assert(isGeneralRegister(reg2));
6020 } // end switch (ins)
6022 assert(fmt != IF_NONE);
6023 assert(isValidImmCond(cfi.immCFVal));
6025 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6029 id->idInsOpt(INS_OPTS_NONE);
6038 /*****************************************************************************
6040 * Add an instruction referencing two registers and a condition code
6043 void emitter::emitIns_R_R_R_COND(
6044 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insCond cond)
6046 emitAttr size = EA_SIZE(attr);
6047 insFormat fmt = IF_NONE;
6051 /* Figure out the encoding format of the instruction */
6058 assert(isGeneralRegister(reg1));
6059 assert(isGeneralRegister(reg2));
6060 assert(isGeneralRegister(reg3));
6069 } // end switch (ins)
6071 assert(fmt != IF_NONE);
6072 assert(isValidImmCond(cfi.immCFVal));
6074 instrDesc* id = emitNewInstr(attr);
6078 id->idInsOpt(INS_OPTS_NONE);
6083 id->idSmallCns(cfi.immCFVal);
6089 /*****************************************************************************
6091 * Add an instruction referencing two registers the flags and a condition code
6094 void emitter::emitIns_R_R_FLAGS_COND(
6095 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insCflags flags, insCond cond)
6097 emitAttr size = EA_SIZE(attr);
6098 insFormat fmt = IF_NONE;
6102 /* Figure out the encoding format of the instruction */
6107 assert(isGeneralRegister(reg1));
6108 assert(isGeneralRegister(reg2));
6116 } // end switch (ins)
6118 assert(fmt != IF_NONE);
6119 assert(isValidImmCondFlags(cfi.immCFVal));
6121 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6125 id->idInsOpt(INS_OPTS_NONE);
6134 /*****************************************************************************
6136 * Add an instruction referencing a register, an immediate, the flags and a condition code
6139 void emitter::emitIns_R_I_FLAGS_COND(
6140 instruction ins, emitAttr attr, regNumber reg, int imm, insCflags flags, insCond cond)
6142 emitAttr size = EA_SIZE(attr);
6143 insFormat fmt = IF_NONE;
6147 /* Figure out the encoding format of the instruction */
6152 assert(isGeneralRegister(reg));
6155 ins = insReverse(ins);
6158 if ((imm >= 0) && (imm <= 31))
6167 assert(!"Instruction cannot be encoded: ccmp/ccmn imm5");
6173 } // end switch (ins)
6175 assert(fmt != IF_NONE);
6176 assert(isValidImmCondFlagsImm5(cfi.immCFVal));
6178 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6182 id->idInsOpt(INS_OPTS_NONE);
6190 /*****************************************************************************
6192 * Add a memory barrier instruction with a 'barrier' immediate
6195 void emitter::emitIns_BARR(instruction ins, insBarrier barrier)
6197 insFormat fmt = IF_NONE;
6200 /* Figure out the encoding format of the instruction */
6208 imm = (ssize_t)barrier;
6213 } // end switch (ins)
6215 assert(fmt != IF_NONE);
6217 instrDesc* id = emitNewInstrSC(EA_8BYTE, imm);
6221 id->idInsOpt(INS_OPTS_NONE);
6227 /*****************************************************************************
6229 * Add an instruction with a static data member operand. If 'size' is 0, the
6230 * instruction operates on the address of the static member instead of its
6231 * value (e.g. "push offset clsvar", rather than "push dword ptr [clsvar]").
6234 void emitter::emitIns_C(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, int offs)
6239 /*****************************************************************************
6241 * Add an instruction referencing stack-based local variable.
6244 void emitter::emitIns_S(instruction ins, emitAttr attr, int varx, int offs)
6249 /*****************************************************************************
6251 * Add an instruction referencing a register and a stack-based local variable.
6253 void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
6255 emitAttr size = EA_SIZE(attr);
6256 insFormat fmt = IF_NONE;
6262 // TODO-ARM64-CQ: use unscaled loads?
6263 /* Figure out the encoding format of the instruction */
6284 assert(isValidGeneralDatasize(size) || isValidVectorDatasize(size));
6285 scale = genLog2(EA_SIZE_IN_BYTES(size));
6289 assert(size == EA_8BYTE);
6294 NYI("emitIns_R_S"); // FP locals?
6297 } // end switch (ins)
6299 /* Figure out the variable's frame position */
6304 base = emitComp->lvaFrameAddress(varx, &FPbased);
6306 assert((scale >= 0) && (scale <= 4));
6308 regNumber reg2 = FPbased ? REG_FPBASE : REG_SPBASE;
6309 reg2 = encodingSPtoZR(reg2);
6326 fmt = IF_DI_2A; // add reg1,reg2,#disp
6330 regNumber rsvdReg = codeGen->rsGetRsvdReg();
6331 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6332 fmt = IF_DR_3A; // add reg1,reg2,rsvdReg
6337 bool useRegForImm = false;
6338 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6345 else if ((imm < 0) || ((imm & mask) != 0))
6347 if ((imm >= -256) && (imm <= 255))
6353 useRegForImm = true;
6358 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
6360 imm >>= scale; // The immediate is scaled by the size of the ld/st
6366 useRegForImm = true;
6372 regNumber rsvdReg = codeGen->rsGetRsvdReg();
6373 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6378 assert(fmt != IF_NONE);
6380 instrDesc* id = emitNewInstrCns(attr, imm);
6384 id->idInsOpt(INS_OPTS_NONE);
6388 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6389 id->idSetIsLclVar();
6392 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6399 /*****************************************************************************
6401 * Add an instruction referencing two register and consectutive stack-based local variable slots.
6403 void emitter::emitIns_R_R_S_S(
6404 instruction ins, emitAttr attr1, emitAttr attr2, regNumber reg1, regNumber reg2, int varx, int offs)
6406 assert((ins == INS_ldp) || (ins == INS_ldnp));
6407 assert(EA_8BYTE == EA_SIZE(attr1));
6408 assert(EA_8BYTE == EA_SIZE(attr2));
6409 assert(isGeneralRegisterOrZR(reg1));
6410 assert(isGeneralRegisterOrZR(reg2));
6413 insFormat fmt = IF_LS_3B;
6415 const unsigned scale = 3;
6417 /* Figure out the variable's frame position */
6421 base = emitComp->lvaFrameAddress(varx, &FPbased);
6424 // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6425 regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE;
6426 reg3 = encodingSPtoZR(reg3);
6428 bool useRegForAdr = true;
6430 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6433 useRegForAdr = false;
6437 if ((imm & mask) == 0)
6439 ssize_t immShift = imm >> scale; // The immediate is scaled by the size of the ld/st
6441 if ((immShift >= -64) && (immShift <= 63))
6444 useRegForAdr = false;
6452 regNumber rsvd = codeGen->rsGetRsvdReg();
6453 emitIns_R_R_Imm(INS_add, EA_PTRSIZE, rsvd, reg3, imm);
6458 assert(fmt != IF_NONE);
6460 instrDesc* id = emitNewInstrCns(attr1, imm);
6464 id->idInsOpt(INS_OPTS_NONE);
6466 // Record the attribute for the second register in the pair
6467 if (EA_IS_GCREF(attr2))
6469 id->idGCrefReg2(GCT_GCREF);
6471 else if (EA_IS_BYREF(attr2))
6473 id->idGCrefReg2(GCT_BYREF);
6477 id->idGCrefReg2(GCT_NONE);
6483 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6484 id->idSetIsLclVar();
6487 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6494 /*****************************************************************************
6496 * Add an instruction referencing a stack-based local variable and a register
6498 void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
6501 emitAttr size = EA_SIZE(attr);
6502 insFormat fmt = IF_NONE;
6505 bool isVectorStore = false;
6507 // TODO-ARM64-CQ: use unscaled loads?
6508 /* Figure out the encoding format of the instruction */
6513 assert(isGeneralRegisterOrZR(reg1));
6518 assert(isGeneralRegisterOrZR(reg1));
6522 if (isGeneralRegisterOrZR(reg1))
6524 assert(isValidGeneralDatasize(size));
6525 scale = (size == EA_8BYTE) ? 3 : 2;
6529 assert(isVectorRegister(reg1));
6530 assert(isValidVectorLSDatasize(size));
6531 scale = NaturalScale_helper(size);
6532 isVectorStore = true;
6537 NYI("emitIns_S_R"); // FP locals?
6540 } // end switch (ins)
6542 /* Figure out the variable's frame position */
6546 base = emitComp->lvaFrameAddress(varx, &FPbased);
6558 // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6559 regNumber reg2 = FPbased ? REG_FPBASE : REG_SPBASE;
6560 reg2 = encodingSPtoZR(reg2);
6562 bool useRegForImm = false;
6564 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6569 else if ((imm < 0) || ((imm & mask) != 0))
6571 if ((imm >= -256) && (imm <= 255))
6577 useRegForImm = true;
6582 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
6584 imm >>= scale; // The immediate is scaled by the size of the ld/st
6590 useRegForImm = true;
6596 // The reserved register is not stored in idReg3() since that field overlaps with iiaLclVar.
6597 // It is instead implicit when idSetIsLclVar() is set, with this encoding format.
6598 regNumber rsvdReg = codeGen->rsGetRsvdReg();
6599 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6603 assert(fmt != IF_NONE);
6605 instrDesc* id = emitNewInstrCns(attr, imm);
6609 id->idInsOpt(INS_OPTS_NONE);
6613 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6614 id->idSetIsLclVar();
6617 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6624 /*****************************************************************************
6626 * Add an instruction referencing consecutive stack-based local variable slots and two registers
6628 void emitter::emitIns_S_S_R_R(
6629 instruction ins, emitAttr attr1, emitAttr attr2, regNumber reg1, regNumber reg2, int varx, int offs)
6631 assert((ins == INS_stp) || (ins == INS_stnp));
6632 assert(EA_8BYTE == EA_SIZE(attr1));
6633 assert(EA_8BYTE == EA_SIZE(attr2));
6634 assert(isGeneralRegisterOrZR(reg1));
6635 assert(isGeneralRegisterOrZR(reg2));
6638 insFormat fmt = IF_LS_3B;
6640 const unsigned scale = 3;
6642 /* Figure out the variable's frame position */
6646 base = emitComp->lvaFrameAddress(varx, &FPbased);
6649 // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6650 regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE;
6651 reg3 = encodingSPtoZR(reg3);
6653 bool useRegForAdr = true;
6655 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6658 useRegForAdr = false;
6662 if ((imm & mask) == 0)
6664 ssize_t immShift = imm >> scale; // The immediate is scaled by the size of the ld/st
6666 if ((immShift >= -64) && (immShift <= 63))
6669 useRegForAdr = false;
6677 regNumber rsvd = codeGen->rsGetRsvdReg();
6678 emitIns_R_R_Imm(INS_add, EA_PTRSIZE, rsvd, reg3, imm);
6683 assert(fmt != IF_NONE);
6685 instrDesc* id = emitNewInstrCns(attr1, imm);
6689 id->idInsOpt(INS_OPTS_NONE);
6691 // Record the attribute for the second register in the pair
6692 if (EA_IS_GCREF(attr2))
6694 id->idGCrefReg2(GCT_GCREF);
6696 else if (EA_IS_BYREF(attr2))
6698 id->idGCrefReg2(GCT_BYREF);
6702 id->idGCrefReg2(GCT_NONE);
6708 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6709 id->idSetIsLclVar();
6712 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6719 /*****************************************************************************
6721 * Add an instruction referencing stack-based local variable and an immediate
6723 void emitter::emitIns_S_I(instruction ins, emitAttr attr, int varx, int offs, int val)
6728 /*****************************************************************************
6730 * Add an instruction with a register + static member operands.
6731 * Constant is stored into JIT data which is adjacent to code.
6732 * No relocation is needed. PC-relative offset will be encoded directly into instruction.
6735 void emitter::emitIns_R_C(
6736 instruction ins, emitAttr attr, regNumber reg, regNumber addrReg, CORINFO_FIELD_HANDLE fldHnd, int offs)
6739 assert(instrDesc::fitsInSmallCns(offs));
6741 emitAttr size = EA_SIZE(attr);
6742 insFormat fmt = IF_NONE;
6744 instrDescJmp* id = emitNewInstrJmp();
6749 // This is case to get address to the constant data.
6751 assert(isGeneralRegister(reg));
6752 assert(isValidGeneralDatasize(size));
6757 if (isVectorRegister(reg))
6759 assert(isValidScalarDatasize(size));
6760 // For vector (float/double) register, we should have an integer address reg to
6761 // compute long address which consists of page address and page offset.
6762 // For integer constant, this is not needed since the dest reg can be used to
6763 // compute address as well as contain the final contents.
6764 assert(isGeneralRegister(reg) || (addrReg != REG_NA));
6768 assert(isGeneralRegister(reg));
6769 assert(isValidGeneralDatasize(size));
6776 assert(fmt != IF_NONE);
6780 id->idInsOpt(INS_OPTS_NONE);
6781 id->idSmallCns(offs);
6783 id->idAddr()->iiaFieldHnd = fldHnd;
6784 id->idSetIsBound(); // We won't patch address since we will know the exact distance once JIT code and data are
6785 // allocated together.
6787 id->idReg1(reg); // destination register that will get the constant value.
6788 if (addrReg != REG_NA)
6790 id->idReg2(addrReg); // integer register to compute long address (used for vector dest when we end up with long
6793 id->idjShort = false; // Assume loading constant from long address
6795 // Keep it long if it's in cold code.
6796 id->idjKeepLong = emitComp->fgIsBlockCold(emitComp->compCurBB);
6799 if (emitComp->opts.compLongAddress)
6800 id->idjKeepLong = 1;
6803 // If it's possible to be shortened, then put it in jump list
6804 // to be revisited by emitJumpDistBind.
6805 if (!id->idjKeepLong)
6807 /* Record the jump's IG and offset within it */
6808 id->idjIG = emitCurIG;
6809 id->idjOffs = emitCurIGsize;
6811 /* Append this jump to this IG's jump list */
6812 id->idjNext = emitCurIGjmpList;
6813 emitCurIGjmpList = id;
6824 /*****************************************************************************
6826 * Add an instruction with a static member + constant.
6829 void emitter::emitIns_C_I(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, ssize_t offs, ssize_t val)
6834 /*****************************************************************************
6836 * Add an instruction with a static member + register operands.
6839 void emitter::emitIns_C_R(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, regNumber reg, int offs)
6841 assert(!"emitIns_C_R not supported for RyuJIT backend");
6844 void emitter::emitIns_R_AR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
6846 NYI("emitIns_R_AR");
6849 // This computes address from the immediate which is relocatable.
6850 void emitter::emitIns_R_AI(instruction ins, emitAttr attr, regNumber ireg, ssize_t addr)
6852 assert(EA_IS_RELOC(attr));
6853 emitAttr size = EA_SIZE(attr);
6854 insFormat fmt = IF_DI_1E;
6855 bool needAdd = false;
6856 instrDescJmp* id = emitNewInstrJmp();
6861 // This computes page address.
6862 // page offset is needed using add.
6873 id->idInsOpt(INS_OPTS_NONE);
6875 id->idAddr()->iiaAddr = (BYTE*)addr;
6877 id->idSetIsDspReloc();
6884 // add reg, reg, imm
6887 instrDesc* id = emitAllocInstr(attr);
6888 assert(id->idIsReloc());
6892 id->idInsOpt(INS_OPTS_NONE);
6894 id->idAddr()->iiaAddr = (BYTE*)addr;
6903 void emitter::emitIns_AR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
6905 NYI("emitIns_AR_R");
6908 void emitter::emitIns_R_ARR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
6910 NYI("emitIns_R_ARR");
6913 void emitter::emitIns_ARR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
6915 NYI("emitIns_R_ARR");
6918 void emitter::emitIns_R_ARX(
6919 instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, unsigned mul, int disp)
6921 NYI("emitIns_R_ARR");
6924 /*****************************************************************************
6926 * Record that a jump instruction uses the short encoding
6929 void emitter::emitSetShortJump(instrDescJmp* id)
6931 if (id->idjKeepLong)
6934 insFormat fmt = IF_NONE;
6935 if (emitIsCondJump(id))
6937 switch (id->idIns())
6952 else if (emitIsLoadLabel(id))
6956 else if (emitIsLoadConstant(id))
6966 id->idjShort = true;
6969 /*****************************************************************************
6971 * Add a label instruction.
6974 void emitter::emitIns_R_L(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
6976 assert(dst->bbFlags & BBF_JMP_TARGET);
6978 insFormat fmt = IF_NONE;
6989 instrDescJmp* id = emitNewInstrJmp();
6993 id->idjShort = false;
6994 id->idAddr()->iiaBBlabel = dst;
6996 id->idOpSize(EA_PTRSIZE);
6999 // Mark the catch return
7000 if (emitComp->compCurBB->bbJumpKind == BBJ_EHCATCHRET)
7002 id->idDebugOnlyInfo()->idCatchRet = true;
7006 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7009 if (emitComp->opts.compLongAddress)
7010 id->idjKeepLong = 1;
7013 /* Record the jump's IG and offset within it */
7015 id->idjIG = emitCurIG;
7016 id->idjOffs = emitCurIGsize;
7018 /* Append this jump to this IG's jump list */
7020 id->idjNext = emitCurIGjmpList;
7021 emitCurIGjmpList = id;
7031 /*****************************************************************************
7033 * Add a data label instruction.
7036 void emitter::emitIns_R_D(instruction ins, emitAttr attr, unsigned offs, regNumber reg)
7041 void emitter::emitIns_J_R(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
7043 assert((ins == INS_cbz) || (ins == INS_cbnz));
7045 assert(dst != nullptr);
7046 assert((dst->bbFlags & BBF_JMP_TARGET) != 0);
7048 insFormat fmt = IF_LARGEJMP;
7050 instrDescJmp* id = emitNewInstrJmp();
7055 id->idjShort = false;
7056 id->idOpSize(EA_SIZE(attr));
7058 id->idAddr()->iiaBBlabel = dst;
7059 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7061 /* Record the jump's IG and offset within it */
7063 id->idjIG = emitCurIG;
7064 id->idjOffs = emitCurIGsize;
7066 /* Append this jump to this IG's jump list */
7068 id->idjNext = emitCurIGjmpList;
7069 emitCurIGjmpList = id;
7079 void emitter::emitIns_J_R_I(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg, int imm)
7081 assert((ins == INS_tbz) || (ins == INS_tbnz));
7083 assert(dst != nullptr);
7084 assert((dst->bbFlags & BBF_JMP_TARGET) != 0);
7085 assert((EA_SIZE(attr) == EA_4BYTE) || (EA_SIZE(attr) == EA_8BYTE));
7086 assert(imm < ((EA_SIZE(attr) == EA_4BYTE) ? 32 : 64));
7088 insFormat fmt = IF_LARGEJMP;
7090 instrDescJmp* id = emitNewInstrJmp();
7095 id->idjShort = false;
7096 id->idSmallCns(imm);
7097 id->idOpSize(EA_SIZE(attr));
7099 id->idAddr()->iiaBBlabel = dst;
7100 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7102 /* Record the jump's IG and offset within it */
7104 id->idjIG = emitCurIG;
7105 id->idjOffs = emitCurIGsize;
7107 /* Append this jump to this IG's jump list */
7109 id->idjNext = emitCurIGjmpList;
7110 emitCurIGjmpList = id;
7120 void emitter::emitIns_J(instruction ins, BasicBlock* dst, int instrCount)
7122 insFormat fmt = IF_NONE;
7126 assert(dst->bbFlags & BBF_JMP_TARGET);
7130 assert(instrCount != 0);
7133 /* Figure out the encoding format of the instruction */
7135 bool idjShort = false;
7140 // Unconditional jump is a single form.
7159 // Assume conditional jump is long.
7168 instrDescJmp* id = emitNewInstrJmp();
7172 id->idjShort = idjShort;
7175 // Mark the finally call
7176 if (ins == INS_bl_local && emitComp->compCurBB->bbJumpKind == BBJ_CALLFINALLY)
7178 id->idDebugOnlyInfo()->idFinallyCall = true;
7184 id->idAddr()->iiaBBlabel = dst;
7186 // Skip unconditional jump that has a single form.
7187 // TODO-ARM64-NYI: enable hot/cold splittingNYI.
7188 // The target needs to be relocated.
7191 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7194 if (emitComp->opts.compLongAddress) // Force long branches
7195 id->idjKeepLong = 1;
7201 id->idAddr()->iiaSetInstrCount(instrCount);
7202 id->idjKeepLong = false;
7203 /* This jump must be short */
7204 emitSetShortJump(id);
7208 /* Record the jump's IG and offset within it */
7210 id->idjIG = emitCurIG;
7211 id->idjOffs = emitCurIGsize;
7213 /* Append this jump to this IG's jump list */
7215 id->idjNext = emitCurIGjmpList;
7216 emitCurIGjmpList = id;
7226 /*****************************************************************************
7228 * Add a call instruction (direct or indirect).
7229 * argSize<0 means that the caller will pop the arguments
7231 * The other arguments are interpreted depending on callType as shown:
7232 * Unless otherwise specified, ireg,xreg,xmul,disp should have default values.
7234 * EC_FUNC_TOKEN : addr is the method address
7235 * EC_FUNC_ADDR : addr is the absolute address of the function
7237 * If callType is one of these emitCallTypes, addr has to be NULL.
7238 * EC_INDIR_R : "call ireg".
7240 * For ARM xreg, xmul and disp are never used and should always be 0/REG_NA.
7242 * Please consult the "debugger team notification" comment in genFnProlog().
7245 void emitter::emitIns_Call(EmitCallType callType,
7246 CORINFO_METHOD_HANDLE methHnd,
7247 INDEBUG_LDISASM_COMMA(CORINFO_SIG_INFO* sigInfo) // used to report call sites to the EE
7251 emitAttr secondRetSize,
7252 VARSET_VALARG_TP ptrVars,
7253 regMaskTP gcrefRegs,
7254 regMaskTP byrefRegs,
7255 IL_OFFSETX ilOffset /* = BAD_IL_OFFSET */,
7256 regNumber ireg /* = REG_NA */,
7257 regNumber xreg /* = REG_NA */,
7258 unsigned xmul /* = 0 */,
7259 ssize_t disp /* = 0 */,
7260 bool isJump /* = false */,
7261 bool isNoGC /* = false */,
7262 bool isProfLeaveCB /* = false */)
7264 /* Sanity check the arguments depending on callType */
7266 assert(callType < EC_COUNT);
7267 assert((callType != EC_FUNC_TOKEN && callType != EC_FUNC_ADDR) ||
7268 (ireg == REG_NA && xreg == REG_NA && xmul == 0 && disp == 0));
7269 assert(callType < EC_INDIR_R || addr == NULL);
7270 assert(callType != EC_INDIR_R || (ireg < REG_COUNT && xreg == REG_NA && xmul == 0 && disp == 0));
7272 // ARM never uses these
7273 assert(xreg == REG_NA && xmul == 0 && disp == 0);
7275 // Our stack level should be always greater than the bytes of arguments we push. Just
7277 assert((unsigned)abs(argSize) <= codeGen->genStackLevel);
7282 /* This is the saved set of registers after a normal call */
7283 regMaskTP savedSet = RBM_CALLEE_SAVED;
7285 /* some special helper calls have a different saved set registers */
7289 assert(emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
7291 // Get the set of registers that this call kills and remove it from the saved set.
7292 savedSet = RBM_ALLINT & ~emitComp->compNoGCHelperCallKillSet(Compiler::eeGetHelperNum(methHnd));
7294 // In case of Leave profiler callback, we need to preserve liveness of REG_PROFILER_RET_SCRATCH
7297 savedSet |= RBM_PROFILER_RET_SCRATCH;
7302 assert(!emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
7305 /* Trim out any callee-trashed registers from the live set */
7307 gcrefRegs &= savedSet;
7308 byrefRegs &= savedSet;
7311 if (EMIT_GC_VERBOSE)
7313 printf("Call: GCvars=%s ", VarSetOps::ToString(emitComp, ptrVars));
7314 dumpConvertedVarSet(emitComp, ptrVars);
7315 printf(", gcrefRegs=");
7316 printRegMaskInt(gcrefRegs);
7317 emitDispRegSet(gcrefRegs);
7318 printf(", byrefRegs=");
7319 printRegMaskInt(byrefRegs);
7320 emitDispRegSet(byrefRegs);
7325 assert(argSize % REGSIZE_BYTES == 0);
7326 argCnt = (int)(argSize / (int)REGSIZE_BYTES);
7328 /* Managed RetVal: emit sequence point for the call */
7329 if (emitComp->opts.compDbgInfo && ilOffset != BAD_IL_OFFSET)
7331 codeGen->genIPmappingAdd(ilOffset, false);
7335 We need to allocate the appropriate instruction descriptor based
7336 on whether this is a direct/indirect call, and whether we need to
7337 record an updated set of live GC variables.
7340 if (callType >= EC_INDIR_R)
7342 /* Indirect call, virtual calls */
7344 assert(callType == EC_INDIR_R);
7346 id = emitNewInstrCallInd(argCnt, disp, ptrVars, gcrefRegs, byrefRegs, retSize, secondRetSize);
7350 /* Helper/static/nonvirtual/function calls (direct or through handle),
7351 and calls to an absolute addr. */
7353 assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
7355 id = emitNewInstrCallDir(argCnt, ptrVars, gcrefRegs, byrefRegs, retSize, secondRetSize);
7358 /* Update the emitter's live GC ref sets */
7360 VarSetOps::Assign(emitComp, emitThisGCrefVars, ptrVars);
7361 emitThisGCrefRegs = gcrefRegs;
7362 emitThisByrefRegs = byrefRegs;
7364 /* Set the instruction - special case jumping a function */
7366 insFormat fmt = IF_NONE;
7368 id->idSetIsNoGC(isNoGC);
7370 /* Record the address: method, indirection, or funcptr */
7372 if (callType > EC_FUNC_ADDR)
7374 /* This is an indirect call (either a virtual call or func ptr call) */
7378 case EC_INDIR_R: // the address is in a register
7380 id->idSetIsCallRegPtr();
7384 ins = INS_br_tail; // INS_br_tail Reg
7388 ins = INS_blr; // INS_blr Reg
7396 assert(xreg == REG_NA);
7400 NO_WAY("unexpected instruction");
7406 /* This is a simple direct call: "call helper/method/addr" */
7408 assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
7410 assert(addr != NULL);
7414 ins = INS_b_tail; // INS_b_tail imm28
7418 ins = INS_bl; // INS_bl imm28
7425 id->idAddr()->iiaAddr = (BYTE*)addr;
7427 if (callType == EC_FUNC_ADDR)
7429 id->idSetIsCallAddr();
7432 if (emitComp->opts.compReloc)
7434 id->idSetIsDspReloc();
7439 if (EMIT_GC_VERBOSE)
7441 if (id->idIsLargeCall())
7443 printf("[%02u] Rec call GC vars = %s\n", id->idDebugOnlyInfo()->idNum,
7444 VarSetOps::ToString(emitComp, ((instrDescCGCA*)id)->idcGCvars));
7448 id->idDebugOnlyInfo()->idMemCookie = (size_t)methHnd; // method token
7449 id->idDebugOnlyInfo()->idCallSig = sigInfo;
7453 if (addr != nullptr)
7455 codeGen->getDisAssembler().disSetMethod((size_t)addr, methHnd);
7457 #endif // LATE_DISASM
7463 /*****************************************************************************
7465 * Returns true if 'imm' is valid Cond encoding
7468 /*static*/ bool emitter::isValidImmCond(ssize_t imm)
7470 // range check the ssize_t value, to make sure it is a small unsigned value
7471 // and that only the bits in the cfi.cond are set
7472 if ((imm < 0) || (imm > 0xF))
7476 cfi.immCFVal = (unsigned)imm;
7478 return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7481 /*****************************************************************************
7483 * Returns true if 'imm' is valid Cond/Flags encoding
7486 /*static*/ bool emitter::isValidImmCondFlags(ssize_t imm)
7488 // range check the ssize_t value, to make sure it is a small unsigned value
7489 // and that only the bits in the cfi.cond or cfi.flags are set
7490 if ((imm < 0) || (imm > 0xFF))
7494 cfi.immCFVal = (unsigned)imm;
7496 return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7499 /*****************************************************************************
7501 * Returns true if 'imm' is valid Cond/Flags/Imm5 encoding
7504 /*static*/ bool emitter::isValidImmCondFlagsImm5(ssize_t imm)
7506 // range check the ssize_t value, to make sure it is a small unsigned value
7507 // and that only the bits in the cfi.cond, cfi.flags or cfi.imm5 are set
7508 if ((imm < 0) || (imm > 0x1FFF))
7512 cfi.immCFVal = (unsigned)imm;
7514 return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7517 /*****************************************************************************
7519 * Returns an encoding for the specified register used in the 'Rd' position
7522 /*static*/ emitter::code_t emitter::insEncodeReg_Rd(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 'Rt' position
7535 /*static*/ emitter::code_t emitter::insEncodeReg_Rt(regNumber reg)
7537 assert(isIntegerRegister(reg));
7538 emitter::code_t ureg = (emitter::code_t)reg;
7539 assert((ureg >= 0) && (ureg <= 31));
7543 /*****************************************************************************
7545 * Returns an encoding for the specified register used in the 'Rn' position
7548 /*static*/ emitter::code_t emitter::insEncodeReg_Rn(regNumber reg)
7550 assert(isIntegerRegister(reg));
7551 emitter::code_t ureg = (emitter::code_t)reg;
7552 assert((ureg >= 0) && (ureg <= 31));
7556 /*****************************************************************************
7558 * Returns an encoding for the specified register used in the 'Rm' position
7561 /*static*/ emitter::code_t emitter::insEncodeReg_Rm(regNumber reg)
7563 assert(isIntegerRegister(reg));
7564 emitter::code_t ureg = (emitter::code_t)reg;
7565 assert((ureg >= 0) && (ureg <= 31));
7569 /*****************************************************************************
7571 * Returns an encoding for the specified register used in the 'Ra' position
7574 /*static*/ emitter::code_t emitter::insEncodeReg_Ra(regNumber reg)
7576 assert(isIntegerRegister(reg));
7577 emitter::code_t ureg = (emitter::code_t)reg;
7578 assert((ureg >= 0) && (ureg <= 31));
7582 /*****************************************************************************
7584 * Returns an encoding for the specified register used in the 'Vd' position
7587 /*static*/ emitter::code_t emitter::insEncodeReg_Vd(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 register used in the 'Vt' position
7600 /*static*/ emitter::code_t emitter::insEncodeReg_Vt(regNumber reg)
7602 assert(emitter::isVectorRegister(reg));
7603 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7604 assert((ureg >= 0) && (ureg <= 31));
7608 /*****************************************************************************
7610 * Returns an encoding for the specified register used in the 'Vn' position
7613 /*static*/ emitter::code_t emitter::insEncodeReg_Vn(regNumber reg)
7615 assert(emitter::isVectorRegister(reg));
7616 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7617 assert((ureg >= 0) && (ureg <= 31));
7621 /*****************************************************************************
7623 * Returns an encoding for the specified register used in the 'Vm' position
7626 /*static*/ emitter::code_t emitter::insEncodeReg_Vm(regNumber reg)
7628 assert(emitter::isVectorRegister(reg));
7629 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7630 assert((ureg >= 0) && (ureg <= 31));
7634 /*****************************************************************************
7636 * Returns an encoding for the specified register used in the 'Va' position
7639 /*static*/ emitter::code_t emitter::insEncodeReg_Va(regNumber reg)
7641 assert(emitter::isVectorRegister(reg));
7642 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7643 assert((ureg >= 0) && (ureg <= 31));
7647 /*****************************************************************************
7649 * Returns an encoding for the specified condition code.
7652 /*static*/ emitter::code_t emitter::insEncodeCond(insCond cond)
7654 emitter::code_t uimm = (emitter::code_t)cond;
7658 /*****************************************************************************
7660 * Returns an encoding for the condition code with the lowest bit inverted (marked by invert(<cond>) in the
7661 * architecture manual).
7664 /*static*/ emitter::code_t emitter::insEncodeInvertedCond(insCond cond)
7666 emitter::code_t uimm = (emitter::code_t)cond;
7667 uimm ^= 1; // invert the lowest bit
7671 /*****************************************************************************
7673 * Returns an encoding for the specified flags.
7676 /*static*/ emitter::code_t emitter::insEncodeFlags(insCflags flags)
7678 emitter::code_t uimm = (emitter::code_t)flags;
7682 /*****************************************************************************
7684 * Returns the encoding for the Shift Count bits to be used for Arm64 encodings
7687 /*static*/ emitter::code_t emitter::insEncodeShiftCount(ssize_t imm, emitAttr size)
7689 assert((imm & 0x003F) == imm);
7690 assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
7692 return (emitter::code_t)imm << 10;
7695 /*****************************************************************************
7697 * Returns the encoding to select a 64-bit datasize for an Arm64 instruction
7700 /*static*/ emitter::code_t emitter::insEncodeDatasize(emitAttr size)
7702 if (size == EA_8BYTE)
7704 return 0x80000000; // set the bit at location 31
7708 assert(size == EA_4BYTE);
7713 /*****************************************************************************
7715 * Returns the encoding to select the datasize for the general load/store Arm64 instructions
7719 /*static*/ emitter::code_t emitter::insEncodeDatasizeLS(emitter::code_t code, emitAttr size)
7721 bool exclusive = ((code & 0x35000000) == 0);
7723 if ((code & 0x00800000) && !exclusive) // Is this a sign-extending opcode? (i.e. ldrsw, ldrsh, ldrsb)
7725 if ((code & 0x80000000) == 0) // Is it a ldrsh or ldrsb and not ldrsw ?
7727 if (EA_SIZE(size) != EA_8BYTE) // Do we need to encode the 32-bit Rt size bit?
7729 return 0x00400000; // set the bit at location 22
7733 else if (code & 0x80000000) // Is this a ldr/str/ldur/stur opcode?
7735 if (EA_SIZE(size) == EA_8BYTE) // Do we need to encode the 64-bit size bit?
7737 return 0x40000000; // set the bit at location 30
7743 /*****************************************************************************
7745 * Returns the encoding to select the datasize for the vector load/store Arm64 instructions
7749 /*static*/ emitter::code_t emitter::insEncodeDatasizeVLS(emitter::code_t code, emitAttr size)
7754 if ((code & 0x20000000) == 0)
7758 if (size == EA_16BYTE)
7760 // set the operation size in bit 31
7761 result = 0x80000000;
7763 else if (size == EA_8BYTE)
7765 // set the operation size in bit 30
7766 result = 0x40000000;
7770 assert(size == EA_4BYTE);
7772 result = 0x00000000;
7779 if (size == EA_16BYTE)
7781 // The operation size in bits 31 and 30 are zero
7782 // Bit 23 specifies a 128-bit Load/Store
7783 result = 0x00800000;
7785 else if (size == EA_8BYTE)
7787 // set the operation size in bits 31 and 30
7788 result = 0xC0000000;
7790 else if (size == EA_4BYTE)
7792 // set the operation size in bit 31
7793 result = 0x80000000;
7795 else if (size == EA_2BYTE)
7797 // set the operation size in bit 30
7798 result = 0x40000000;
7802 assert(size == EA_1BYTE);
7803 // The operation size in bits 31 and 30 are zero
7804 result = 0x00000000;
7808 // Or in bit 26 to indicate a Vector register is used as 'target'
7809 result |= 0x04000000;
7814 /*****************************************************************************
7816 * Returns the encoding to select the datasize for the vector load/store Arm64 instructions
7820 /*static*/ emitter::code_t emitter::insEncodeDatasizeVPLS(emitter::code_t code, emitAttr size)
7824 if (size == EA_16BYTE)
7826 // The operation size in bits 31 and 30 are zero
7827 // Bit 23 specifies a 128-bit Load/Store
7828 result = 0x80000000;
7830 else if (size == EA_8BYTE)
7832 // set the operation size in bits 31 and 30
7833 result = 0x40000000;
7835 else if (size == EA_4BYTE)
7837 // set the operation size in bit 31
7838 result = 0x00000000;
7841 // Or in bit 26 to indicate a Vector register is used as 'target'
7842 result |= 0x04000000;
7847 /*****************************************************************************
7849 * Returns the encoding to set the size bit and the N bits for a 'bitfield' instruction
7853 /*static*/ emitter::code_t emitter::insEncodeDatasizeBF(emitter::code_t code, emitAttr size)
7855 // is bit 30 equal to 0?
7856 if ((code & 0x40000000) == 0) // is the opcode one of extr, sxtb, sxth or sxtw
7858 if (size == EA_8BYTE) // Do we need to set the sf and N bits?
7860 return 0x80400000; // set the sf-bit at location 31 and the N-bit at location 22
7863 return 0; // don't set any bits
7866 /*****************************************************************************
7868 * Returns the encoding to select the 64/128-bit datasize for an Arm64 vector instruction
7871 /*static*/ emitter::code_t emitter::insEncodeVectorsize(emitAttr size)
7873 if (size == EA_16BYTE)
7875 return 0x40000000; // set the bit at location 30
7879 assert(size == EA_8BYTE);
7884 /*****************************************************************************
7886 * Returns the encoding to select 'index' for an Arm64 vector elem instruction
7888 /*static*/ emitter::code_t emitter::insEncodeVectorIndex(emitAttr elemsize, ssize_t index)
7890 code_t bits = (code_t)index;
7891 if (elemsize == EA_1BYTE)
7896 else if (elemsize == EA_2BYTE)
7901 else if (elemsize == EA_4BYTE)
7908 assert(elemsize == EA_8BYTE);
7912 assert((bits >= 1) && (bits <= 0x1f));
7914 return (bits << 16); // bits at locations [20,19,18,17,16]
7917 /*****************************************************************************
7919 * Returns the encoding to select 'index2' for an Arm64 'ins' elem instruction
7921 /*static*/ emitter::code_t emitter::insEncodeVectorIndex2(emitAttr elemsize, ssize_t index2)
7923 code_t bits = (code_t)index2;
7924 if (elemsize == EA_1BYTE)
7928 else if (elemsize == EA_2BYTE)
7932 else if (elemsize == EA_4BYTE)
7938 assert(elemsize == EA_8BYTE);
7941 assert((bits >= 0) && (bits <= 0xf));
7943 return (bits << 11); // bits at locations [14,13,12,11]
7946 /*****************************************************************************
7948 * Returns the encoding to select the 'index' for an Arm64 'mul' by elem instruction
7950 /*static*/ emitter::code_t emitter::insEncodeVectorIndexLMH(emitAttr elemsize, ssize_t index)
7954 if (elemsize == EA_2BYTE)
7956 assert((index >= 0) && (index <= 7));
7959 bits |= (1 << 11); // set bit 11 'H'
7963 bits |= (1 << 21); // set bit 21 'L'
7967 bits |= (1 << 20); // set bit 20 'M'
7970 else if (elemsize == EA_4BYTE)
7972 assert((index >= 0) && (index <= 3));
7975 bits |= (1 << 11); // set bit 11 'H'
7979 bits |= (1 << 21); // set bit 21 'L'
7984 assert(!"Invalid 'elemsize' value");
7990 /*****************************************************************************
7992 * Returns the encoding to shift by 'shift' for an Arm64 vector or scalar instruction
7995 /*static*/ emitter::code_t emitter::insEncodeVectorShift(emitAttr size, ssize_t shift)
7997 assert(shift < getBitWidth(size));
7999 code_t imm = (code_t)(getBitWidth(size) + shift);
8004 /*****************************************************************************
8006 * Returns the encoding to select the 1/2/4/8 byte elemsize for an Arm64 vector instruction
8009 /*static*/ emitter::code_t emitter::insEncodeElemsize(emitAttr size)
8011 if (size == EA_8BYTE)
8013 return 0x00C00000; // set the bit at location 23 and 22
8015 else if (size == EA_4BYTE)
8017 return 0x00800000; // set the bit at location 23
8019 else if (size == EA_2BYTE)
8021 return 0x00400000; // set the bit at location 22
8023 assert(size == EA_1BYTE);
8027 /*****************************************************************************
8029 * Returns the encoding to select the 4/8 byte elemsize for an Arm64 float vector instruction
8032 /*static*/ emitter::code_t emitter::insEncodeFloatElemsize(emitAttr size)
8034 if (size == EA_8BYTE)
8036 return 0x00400000; // set the bit at location 22
8038 assert(size == EA_4BYTE);
8042 // Returns the encoding to select the index for an Arm64 float vector by elem instruction
8043 /*static*/ emitter::code_t emitter::insEncodeFloatIndex(emitAttr elemsize, ssize_t index)
8045 code_t result = 0x00000000;
8046 if (elemsize == EA_8BYTE)
8048 assert((index >= 0) && (index <= 1));
8051 result |= 0x00000800; // 'H' - set the bit at location 11
8056 assert(elemsize == EA_4BYTE);
8057 assert((index >= 0) && (index <= 3));
8060 result |= 0x00000800; // 'H' - set the bit at location 11
8064 result |= 0x00200000; // 'L' - set the bit at location 21
8070 /*****************************************************************************
8072 * Returns the encoding to select the fcvt operation for Arm64 instructions
8074 /*static*/ emitter::code_t emitter::insEncodeConvertOpt(insFormat fmt, insOpts conversion)
8079 case INS_OPTS_S_TO_D: // Single to Double
8080 assert(fmt == IF_DV_2J);
8081 result = 0x00008000; // type=00, opc=01
8084 case INS_OPTS_D_TO_S: // Double to Single
8085 assert(fmt == IF_DV_2J);
8086 result = 0x00400000; // type=01, opc=00
8089 case INS_OPTS_H_TO_S: // Half to Single
8090 assert(fmt == IF_DV_2J);
8091 result = 0x00C00000; // type=11, opc=00
8094 case INS_OPTS_H_TO_D: // Half to Double
8095 assert(fmt == IF_DV_2J);
8096 result = 0x00C08000; // type=11, opc=01
8099 case INS_OPTS_S_TO_H: // Single to Half
8100 assert(fmt == IF_DV_2J);
8101 result = 0x00018000; // type=00, opc=11
8104 case INS_OPTS_D_TO_H: // Double to Half
8105 assert(fmt == IF_DV_2J);
8106 result = 0x00418000; // type=01, opc=11
8109 case INS_OPTS_S_TO_4BYTE: // Single to INT32
8110 assert(fmt == IF_DV_2H);
8111 result = 0x00000000; // sf=0, type=00
8114 case INS_OPTS_D_TO_4BYTE: // Double to INT32
8115 assert(fmt == IF_DV_2H);
8116 result = 0x00400000; // sf=0, type=01
8119 case INS_OPTS_S_TO_8BYTE: // Single to INT64
8120 assert(fmt == IF_DV_2H);
8121 result = 0x80000000; // sf=1, type=00
8124 case INS_OPTS_D_TO_8BYTE: // Double to INT64
8125 assert(fmt == IF_DV_2H);
8126 result = 0x80400000; // sf=1, type=01
8129 case INS_OPTS_4BYTE_TO_S: // INT32 to Single
8130 assert(fmt == IF_DV_2I);
8131 result = 0x00000000; // sf=0, type=00
8134 case INS_OPTS_4BYTE_TO_D: // INT32 to Double
8135 assert(fmt == IF_DV_2I);
8136 result = 0x00400000; // sf=0, type=01
8139 case INS_OPTS_8BYTE_TO_S: // INT64 to Single
8140 assert(fmt == IF_DV_2I);
8141 result = 0x80000000; // sf=1, type=00
8144 case INS_OPTS_8BYTE_TO_D: // INT64 to Double
8145 assert(fmt == IF_DV_2I);
8146 result = 0x80400000; // sf=1, type=01
8150 assert(!"Invalid 'conversion' value");
8156 /*****************************************************************************
8158 * Returns the encoding to have the Rn register be updated Pre/Post indexed
8162 /*static*/ emitter::code_t emitter::insEncodeIndexedOpt(insOpts opt)
8164 assert(emitter::insOptsNone(opt) || emitter::insOptsIndexed(opt));
8166 if (emitter::insOptsIndexed(opt))
8168 if (emitter::insOptsPostIndex(opt))
8170 return 0x00000400; // set the bit at location 10
8174 assert(emitter::insOptsPreIndex(opt));
8175 return 0x00000C00; // set the bit at location 10 and 11
8180 assert(emitter::insOptsNone(opt));
8181 return 0; // bits 10 and 11 are zero
8185 /*****************************************************************************
8187 * Returns the encoding for a ldp/stp instruction to have the Rn register
8188 * be updated Pre/Post indexed or not updated
8191 /*static*/ emitter::code_t emitter::insEncodePairIndexedOpt(instruction ins, insOpts opt)
8193 assert(emitter::insOptsNone(opt) || emitter::insOptsIndexed(opt));
8195 if ((ins == INS_ldnp) || (ins == INS_stnp))
8197 assert(emitter::insOptsNone(opt));
8198 return 0; // bits 23 and 24 are zero
8202 if (emitter::insOptsIndexed(opt))
8204 if (emitter::insOptsPostIndex(opt))
8206 return 0x00800000; // set the bit at location 23
8210 assert(emitter::insOptsPreIndex(opt));
8211 return 0x01800000; // set the bit at location 24 and 23
8216 assert(emitter::insOptsNone(opt));
8217 return 0x01000000; // set the bit at location 24
8222 /*****************************************************************************
8224 * Returns the encoding to apply a Shift Type on the Rm register
8227 /*static*/ emitter::code_t emitter::insEncodeShiftType(insOpts opt)
8229 if (emitter::insOptsNone(opt))
8231 // None implies the we encode LSL (with a zero immediate)
8234 assert(emitter::insOptsAnyShift(opt));
8236 emitter::code_t option = (emitter::code_t)opt - (emitter::code_t)INS_OPTS_LSL;
8237 assert(option <= 3);
8239 return option << 22; // bits 23, 22
8242 /*****************************************************************************
8244 * Returns the encoding to apply a 12 bit left shift to the immediate
8247 /*static*/ emitter::code_t emitter::insEncodeShiftImm12(insOpts opt)
8249 if (emitter::insOptsLSL12(opt))
8251 return 0x00400000; // set the bit at location 22
8256 /*****************************************************************************
8258 * Returns the encoding to have the Rm register use an extend operation
8261 /*static*/ emitter::code_t emitter::insEncodeExtend(insOpts opt)
8263 if (emitter::insOptsNone(opt) || (opt == INS_OPTS_LSL))
8265 // None or LSL implies the we encode UXTX
8266 opt = INS_OPTS_UXTX;
8268 assert(emitter::insOptsAnyExtend(opt));
8270 emitter::code_t option = (emitter::code_t)opt - (emitter::code_t)INS_OPTS_UXTB;
8271 assert(option <= 7);
8273 return option << 13; // bits 15,14,13
8276 /*****************************************************************************
8278 * Returns the encoding to scale the Rm register by {0,1,2,3,4}
8279 * when using an extend operation
8282 /*static*/ emitter::code_t emitter::insEncodeExtendScale(ssize_t imm)
8284 assert((imm >= 0) && (imm <= 4));
8286 return (emitter::code_t)imm << 10; // bits 12,11,10
8289 /*****************************************************************************
8291 * Returns the encoding to have the Rm register be auto scaled by the ld/st size
8294 /*static*/ emitter::code_t emitter::insEncodeReg3Scale(bool isScaled)
8298 return 0x00001000; // set the bit at location 12
8306 BYTE* emitter::emitOutputLoadLabel(BYTE* dst, BYTE* srcAddr, BYTE* dstAddr, instrDescJmp* id)
8308 instruction ins = id->idIns();
8309 insFormat fmt = id->idInsFmt();
8310 regNumber dstReg = id->idReg1();
8313 // adr x, [rel addr] -- compute address: current addr(ip) + rel addr.
8314 assert(ins == INS_adr);
8315 assert(fmt == IF_DI_1E);
8316 ssize_t distVal = (ssize_t)(dstAddr - srcAddr);
8317 dst = emitOutputShortAddress(dst, ins, fmt, distVal, dstReg);
8321 // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8322 assert(fmt == IF_LARGEADR);
8323 ssize_t relPageAddr =
8324 (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8325 dst = emitOutputShortAddress(dst, INS_adrp, IF_DI_1E, relPageAddr, dstReg);
8327 // add x, x, page offs -- compute address = page addr + page offs
8328 ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8329 assert(isValidUimm12(imm12));
8331 emitInsCode(INS_add, IF_DI_2A); // DI_2A X0010001shiiiiii iiiiiinnnnnddddd 1100 0000 imm(i12, sh)
8332 code |= insEncodeDatasize(EA_8BYTE); // X
8333 code |= ((code_t)imm12 << 10); // iiiiiiiiiiii
8334 code |= insEncodeReg_Rd(dstReg); // ddddd
8335 code |= insEncodeReg_Rn(dstReg); // nnnnn
8336 dst += emitOutput_Instr(dst, code);
8341 /*****************************************************************************
8343 * Output a local jump or other instruction with a pc-relative immediate.
8344 * Note that this may be invoked to overwrite an existing jump instruction at 'dst'
8345 * to handle forward branch patching.
8348 BYTE* emitter::emitOutputLJ(insGroup* ig, BYTE* dst, instrDesc* i)
8350 instrDescJmp* id = (instrDescJmp*)i;
8359 // Set default ins/fmt from id.
8360 instruction ins = id->idIns();
8361 insFormat fmt = id->idInsFmt();
8363 bool loadLabel = false;
8364 bool isJump = false;
8365 bool loadConstant = false;
8382 loadConstant = true;
8391 /* Figure out the distance to the target */
8393 srcOffs = emitCurCodeOffs(dst);
8394 srcAddr = emitOffsetToPtr(srcOffs);
8396 if (id->idAddr()->iiaIsJitDataOffset())
8398 assert(loadConstant || loadLabel);
8399 int doff = id->idAddr()->iiaGetJitDataOffset();
8401 ssize_t imm = emitGetInsSC(id);
8402 assert((imm >= 0) && (imm < 0x1000)); // 0x1000 is arbitrary, currently 'imm' is always 0
8404 unsigned dataOffs = (unsigned)(doff + imm);
8405 assert(dataOffs < emitDataSize());
8406 dstAddr = emitDataOffsetToPtr(dataOffs);
8408 regNumber dstReg = id->idReg1();
8409 regNumber addrReg = dstReg; // an integer register to compute long address.
8410 emitAttr opSize = id->idOpSize();
8416 // ldr x/v, [rel addr] -- load constant from current addr(ip) + rel addr.
8417 assert(ins == INS_ldr);
8418 assert(fmt == IF_LS_1A);
8419 distVal = (ssize_t)(dstAddr - srcAddr);
8420 dst = emitOutputShortConstant(dst, ins, fmt, distVal, dstReg, opSize);
8424 // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8425 assert(fmt == IF_LARGELDC);
8426 ssize_t relPageAddr =
8427 (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8428 if (isVectorRegister(dstReg))
8430 // Update addrReg with the reserved integer register
8431 // since we cannot use dstReg (vector) to load constant directly from memory.
8432 addrReg = id->idReg2();
8433 assert(isGeneralRegister(addrReg));
8437 dst = emitOutputShortAddress(dst, ins, fmt, relPageAddr, addrReg);
8439 // ldr x, [x, page offs] -- load constant from page address + page offset into integer register.
8440 ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8441 assert(isValidUimm12(imm12));
8444 dst = emitOutputShortConstant(dst, ins, fmt, imm12, addrReg, opSize);
8446 // fmov v, d -- copy constant in integer register to vector register.
8447 // This is needed only for vector constant.
8448 if (addrReg != dstReg)
8450 // fmov Vd,Rn DV_2I X00111100X100111 000000nnnnnddddd 1E27 0000 Vd,Rn
8451 // (scalar, from general)
8452 assert(isVectorRegister(dstReg) && isGeneralRegister(addrReg));
8455 code_t code = emitInsCode(ins, fmt);
8457 code |= insEncodeReg_Vd(dstReg); // ddddd
8458 code |= insEncodeReg_Rn(addrReg); // nnnnn
8459 if (id->idOpSize() == EA_8BYTE)
8461 code |= 0x80400000; // X ... X
8463 dst += emitOutput_Instr(dst, code);
8470 dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8476 assert(loadLabel || isJump);
8478 if (id->idAddr()->iiaHasInstrCount())
8481 int instrCount = id->idAddr()->iiaGetInstrCount();
8482 unsigned insNum = emitFindInsNum(ig, id);
8485 // Backward branches using instruction count must be within the same instruction group.
8486 assert(insNum + 1 >= (unsigned)(-instrCount));
8488 dstOffs = ig->igOffs + emitFindOffset(ig, (insNum + 1 + instrCount));
8489 dstAddr = emitOffsetToPtr(dstOffs);
8493 dstOffs = id->idAddr()->iiaIGlabel->igOffs;
8494 dstAddr = emitOffsetToPtr(dstOffs);
8497 distVal = (ssize_t)(dstAddr - srcAddr);
8499 if (dstOffs <= srcOffs)
8502 /* This is a backward jump - distance is known at this point */
8504 if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8506 size_t blkOffs = id->idjIG->igOffs;
8508 if (INTERESTING_JUMP_NUM == 0)
8509 printf("[3] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8510 printf("[3] Jump block is at %08X - %02X = %08X\n", blkOffs, emitOffsAdj, blkOffs - emitOffsAdj);
8511 printf("[3] Jump is at %08X - %02X = %08X\n", srcOffs, emitOffsAdj, srcOffs - emitOffsAdj);
8512 printf("[3] Label block is at %08X - %02X = %08X\n", dstOffs, emitOffsAdj, dstOffs - emitOffsAdj);
8518 /* This is a forward jump - distance will be an upper limit */
8520 emitFwdJumps = true;
8522 /* The target offset will be closer by at least 'emitOffsAdj', but only if this
8523 jump doesn't cross the hot-cold boundary. */
8525 if (!emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8527 dstOffs -= emitOffsAdj;
8528 distVal -= emitOffsAdj;
8531 /* Record the location of the jump for later patching */
8533 id->idjOffs = dstOffs;
8535 /* Are we overflowing the id->idjOffs bitfield? */
8536 if (id->idjOffs != dstOffs)
8537 IMPL_LIMITATION("Method is too large");
8540 if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8542 size_t blkOffs = id->idjIG->igOffs;
8544 if (INTERESTING_JUMP_NUM == 0)
8545 printf("[4] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8546 printf("[4] Jump block is at %08X\n", blkOffs);
8547 printf("[4] Jump is at %08X\n", srcOffs);
8548 printf("[4] Label block is at %08X - %02X = %08X\n", dstOffs + emitOffsAdj, emitOffsAdj, dstOffs);
8554 if (0 && emitComp->verbose)
8557 int distValSize = id->idjShort ? 4 : 8;
8558 printf("; %s jump [%08X/%03u] from %0*X to %0*X: dist = %08XH\n", (dstOffs <= srcOffs) ? "Fwd" : "Bwd",
8559 dspPtr(id), id->idDebugOnlyInfo()->idNum, distValSize, srcOffs + sz, distValSize, dstOffs, distVal);
8563 /* For forward jumps, record the address of the distance value */
8564 id->idjTemp.idjAddr = (distVal > 0) ? dst : NULL;
8566 if (emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8568 assert(!id->idjShort);
8569 NYI_ARM64("Relocation Support for long address");
8572 assert(insOptsNone(id->idInsOpt()));
8578 // Short conditional/unconditional jump
8579 assert(!id->idjKeepLong);
8580 assert(emitJumpCrossHotColdBoundary(srcOffs, dstOffs) == false);
8581 assert((fmt == IF_BI_0A) || (fmt == IF_BI_0B) || (fmt == IF_BI_1A) || (fmt == IF_BI_1B));
8585 // Long conditional jump
8586 assert(fmt == IF_LARGEJMP);
8587 // This is a pseudo-instruction format representing a large conditional branch, to allow
8588 // us to get a greater branch target range than we can get by using a straightforward conditional
8589 // branch. It is encoded as a short conditional branch that branches around a long unconditional
8592 // Conceptually, we have:
8596 // The code we emit is:
8598 // b<!cond> L_not // 4 bytes. Note that we reverse the condition.
8599 // b L_target // 4 bytes
8602 // Note that we don't actually insert any blocks: we simply encode "b <!cond> L_not" as a branch with
8603 // the correct offset. Note also that this works for both integer and floating-point conditions, because
8604 // the condition inversion takes ordered/unordered into account, preserving NaN behavior. For example,
8605 // "GT" (greater than) is inverted to "LE" (less than, equal, or unordered).
8607 instruction reverseIns;
8608 insFormat reverseFmt;
8613 reverseIns = INS_cbnz;
8614 reverseFmt = IF_BI_1A;
8617 reverseIns = INS_cbz;
8618 reverseFmt = IF_BI_1A;
8621 reverseIns = INS_tbnz;
8622 reverseFmt = IF_BI_1B;
8625 reverseIns = INS_tbz;
8626 reverseFmt = IF_BI_1B;
8629 reverseIns = emitJumpKindToIns(emitReverseJumpKind(emitInsToJumpKind(ins)));
8630 reverseFmt = IF_BI_0B;
8634 emitOutputShortBranch(dst,
8635 reverseIns, // reverse the conditional instruction
8637 8, /* 8 bytes from start of this large conditional pseudo-instruction to L_not. */
8640 // Now, pretend we've got a normal unconditional branch, and fall through to the code to emit that.
8644 // The distVal was computed based on the beginning of the pseudo-instruction,
8645 // So subtract the size of the conditional branch so that it is relative to the
8646 // unconditional branch.
8650 dst = emitOutputShortBranch(dst, ins, fmt, distVal, id);
8654 dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8660 /*****************************************************************************
8662 * Output a short branch instruction.
8664 BYTE* emitter::emitOutputShortBranch(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, instrDescJmp* id)
8666 code_t code = emitInsCode(ins, fmt);
8668 ssize_t loBits = (distVal & 3);
8669 noway_assert(loBits == 0);
8670 distVal >>= 2; // branch offset encodings are scaled by 4.
8672 if (fmt == IF_BI_0A)
8674 // INS_b or INS_bl_local
8675 noway_assert(isValidSimm26(distVal));
8676 distVal &= 0x3FFFFFFLL;
8679 else if (fmt == IF_BI_0B) // BI_0B 01010100iiiiiiii iiiiiiiiiiiXXXXX simm19:00
8681 // INS_beq, INS_bne, etc...
8682 noway_assert(isValidSimm19(distVal));
8683 distVal &= 0x7FFFFLL;
8684 code |= distVal << 5;
8686 else if (fmt == IF_BI_1A) // BI_1A X.......iiiiiiii iiiiiiiiiiittttt Rt simm19:00
8688 // INS_cbz or INS_cbnz
8689 assert(id != nullptr);
8690 code |= insEncodeDatasize(id->idOpSize()); // X
8691 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
8693 noway_assert(isValidSimm19(distVal));
8694 distVal &= 0x7FFFFLL; // 19 bits
8695 code |= distVal << 5;
8697 else if (fmt == IF_BI_1B) // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
8699 // INS_tbz or INS_tbnz
8700 assert(id != nullptr);
8701 ssize_t imm = emitGetInsSC(id);
8702 assert(isValidImmShift(imm, id->idOpSize()));
8704 if (imm & 0x20) // test bit 32-63 ?
8706 code |= 0x80000000; // B
8708 code |= ((imm & 0x1F) << 19); // bbbbb
8709 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
8711 noway_assert(isValidSimm14(distVal));
8712 distVal &= 0x3FFFLL; // 14 bits
8713 code |= distVal << 5;
8717 assert(!"Unknown fmt for emitOutputShortBranch");
8720 dst += emitOutput_Instr(dst, code);
8725 /*****************************************************************************
8727 * Output a short address instruction.
8729 BYTE* emitter::emitOutputShortAddress(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, regNumber reg)
8731 ssize_t loBits = (distVal & 3);
8734 code_t code = emitInsCode(ins, fmt);
8735 if (fmt == IF_DI_1E) // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
8737 // INS_adr or INS_adrp
8738 code |= insEncodeReg_Rd(reg); // ddddd
8740 noway_assert(isValidSimm19(distVal));
8741 distVal &= 0x7FFFFLL; // 19 bits
8742 code |= distVal << 5;
8743 code |= loBits << 29; // 2 bits
8747 assert(!"Unknown fmt for emitOutputShortAddress");
8750 dst += emitOutput_Instr(dst, code);
8755 /*****************************************************************************
8757 * Output a short constant instruction.
8759 BYTE* emitter::emitOutputShortConstant(
8760 BYTE* dst, instruction ins, insFormat fmt, ssize_t imm, regNumber reg, emitAttr opSize)
8762 code_t code = emitInsCode(ins, fmt);
8764 if (fmt == IF_LS_1A)
8766 // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt simm21
8767 // INS_ldr or INS_ldrsw (PC-Relative)
8769 ssize_t loBits = (imm & 3);
8770 noway_assert(loBits == 0);
8771 ssize_t distVal = imm >>= 2; // load offset encodings are scaled by 4.
8773 noway_assert(isValidSimm19(distVal));
8775 // Is the target a vector register?
8776 if (isVectorRegister(reg))
8778 code |= insEncodeDatasizeVLS(code, opSize); // XX V
8779 code |= insEncodeReg_Vt(reg); // ttttt
8783 assert(isGeneralRegister(reg));
8784 // insEncodeDatasizeLS is not quite right for this case.
8785 // So just specialize it.
8786 if ((ins == INS_ldr) && (opSize == EA_8BYTE))
8788 // set the operation size in bit 30
8792 code |= insEncodeReg_Rt(reg); // ttttt
8795 distVal &= 0x7FFFFLL; // 19 bits
8796 code |= distVal << 5;
8798 else if (fmt == IF_LS_2B)
8800 // ldr Rt,[Xn+pimm12] LS_2B 1X11100101iiiiii iiiiiinnnnnttttt B940 0000 imm(0-4095<<{2,3})
8801 // INS_ldr or INS_ldrsw (PC-Relative)
8802 noway_assert(isValidUimm12(imm));
8803 assert(isGeneralRegister(reg));
8805 if (opSize == EA_8BYTE)
8807 // insEncodeDatasizeLS is not quite right for this case.
8808 // So just specialize it.
8811 // set the operation size in bit 30
8814 // Low 3 bits should be 0 -- 8 byte JIT data should be aligned on 8 byte.
8815 assert((imm & 7) == 0);
8820 assert(opSize == EA_4BYTE);
8821 // Low 2 bits should be 0 -- 4 byte aligned data.
8822 assert((imm & 3) == 0);
8826 code |= insEncodeReg_Rt(reg); // ttttt
8827 code |= insEncodeReg_Rn(reg); // nnnnn
8832 assert(!"Unknown fmt for emitOutputShortConstant");
8835 dst += emitOutput_Instr(dst, code);
8839 /*****************************************************************************
8841 * Output a call instruction.
8844 unsigned emitter::emitOutputCall(insGroup* ig, BYTE* dst, instrDesc* id, code_t code)
8846 const unsigned char callInstrSize = sizeof(code_t); // 4 bytes
8847 regMaskTP gcrefRegs;
8848 regMaskTP byrefRegs;
8850 VARSET_TP GCvars(VarSetOps::UninitVal());
8852 // Is this a "fat" call descriptor?
8853 if (id->idIsLargeCall())
8855 instrDescCGCA* idCall = (instrDescCGCA*)id;
8856 gcrefRegs = idCall->idcGcrefRegs;
8857 byrefRegs = idCall->idcByrefRegs;
8858 VarSetOps::Assign(emitComp, GCvars, idCall->idcGCvars);
8862 assert(!id->idIsLargeDsp());
8863 assert(!id->idIsLargeCns());
8865 gcrefRegs = emitDecodeCallGCregs(id);
8867 VarSetOps::AssignNoCopy(emitComp, GCvars, VarSetOps::MakeEmpty(emitComp));
8870 /* We update the GC info before the call as the variables cannot be
8871 used by the call. Killing variables before the call helps with
8872 boundary conditions if the call is CORINFO_HELP_THROW - see bug 50029.
8873 If we ever track aliased variables (which could be used by the
8874 call), we would have to keep them alive past the call. */
8876 emitUpdateLiveGCvars(GCvars, dst);
8878 // Now output the call instruction and update the 'dst' pointer
8880 unsigned outputInstrSize = emitOutput_Instr(dst, code);
8881 dst += outputInstrSize;
8883 // All call instructions are 4-byte in size on ARM64
8885 assert(outputInstrSize == callInstrSize);
8887 // If the method returns a GC ref, mark INTRET (R0) appropriately.
8888 if (id->idGCref() == GCT_GCREF)
8890 gcrefRegs |= RBM_INTRET;
8892 else if (id->idGCref() == GCT_BYREF)
8894 byrefRegs |= RBM_INTRET;
8897 // If is a multi-register return method is called, mark INTRET_1 (X1) appropriately
8898 if (id->idIsLargeCall())
8900 instrDescCGCA* idCall = (instrDescCGCA*)id;
8901 if (idCall->idSecondGCref() == GCT_GCREF)
8903 gcrefRegs |= RBM_INTRET_1;
8905 else if (idCall->idSecondGCref() == GCT_BYREF)
8907 byrefRegs |= RBM_INTRET_1;
8911 // If the GC register set has changed, report the new set.
8912 if (gcrefRegs != emitThisGCrefRegs)
8914 emitUpdateLiveGCregs(GCT_GCREF, gcrefRegs, dst);
8916 // If the Byref register set has changed, report the new set.
8917 if (byrefRegs != emitThisByrefRegs)
8919 emitUpdateLiveGCregs(GCT_BYREF, byrefRegs, dst);
8922 // Some helper calls may be marked as not requiring GC info to be recorded.
8923 if ((!id->idIsNoGC()))
8925 // On ARM64, as on AMD64, we don't change the stack pointer to push/pop args.
8926 // So we're not really doing a "stack pop" here (note that "args" is 0), but we use this mechanism
8927 // to record the call for GC info purposes. (It might be best to use an alternate call,
8928 // and protect "emitStackPop" under the EMIT_TRACK_STACK_DEPTH preprocessor variable.)
8929 emitStackPop(dst, /*isCall*/ true, callInstrSize, /*args*/ 0);
8931 // Do we need to record a call location for GC purposes?
8933 if (!emitFullGCinfo)
8935 emitRecordGCcall(dst, callInstrSize);
8938 return callInstrSize;
8941 /*****************************************************************************
8943 * Emit a 32-bit Arm64 instruction
8946 /*static*/ unsigned emitter::emitOutput_Instr(BYTE* dst, code_t code)
8948 assert(sizeof(code_t) == 4);
8949 *((code_t*)dst) = code;
8951 return sizeof(code_t);
8954 /*****************************************************************************
8956 * Append the machine code corresponding to the given instruction descriptor
8957 * to the code block at '*dp'; the base of the code block is 'bp', and 'ig'
8958 * is the instruction group that contains the instruction. Updates '*dp' to
8959 * point past the generated code, and returns the size of the instruction
8960 * descriptor in bytes.
8963 size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
8968 size_t sz = emitGetInstrDescSize(id); // TODO-ARM64-Cleanup: on ARM, this is set in each case. why?
8969 instruction ins = id->idIns();
8970 insFormat fmt = id->idInsFmt();
8971 emitAttr size = id->idOpSize();
8972 unsigned char callInstrSize = 0;
8977 bool dspOffs = emitComp->opts.dspGCtbls;
8979 bool dspOffs = !emitComp->opts.disDiffable;
8983 assert(REG_NA == (int)REG_NA);
8985 VARSET_TP GCvars(VarSetOps::UninitVal());
8987 /* What instruction format have we got? */
9002 case IF_BI_0A: // BI_0A ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
9003 case IF_BI_0B: // BI_0B ......iiiiiiiiii iiiiiiiiiii..... simm19:00
9005 assert(id->idGCref() == GCT_NONE);
9006 assert(id->idIsBound());
9007 dst = emitOutputLJ(ig, dst, id);
9008 sz = sizeof(instrDescJmp);
9011 case IF_BI_0C: // BI_0C ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
9012 code = emitInsCode(ins, fmt);
9013 sz = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
9014 dst += emitOutputCall(ig, dst, id, code);
9015 // Always call RecordRelocation so that we wire in a JumpStub when we don't reach
9016 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_BRANCH26);
9019 case IF_BI_1A: // BI_1A ......iiiiiiiiii iiiiiiiiiiittttt Rt simm19:00
9020 assert(insOptsNone(id->idInsOpt()));
9021 assert(id->idIsBound());
9023 dst = emitOutputLJ(ig, dst, id);
9024 sz = sizeof(instrDescJmp);
9027 case IF_BI_1B: // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
9028 assert(insOptsNone(id->idInsOpt()));
9029 assert(id->idIsBound());
9031 dst = emitOutputLJ(ig, dst, id);
9032 sz = sizeof(instrDescJmp);
9035 case IF_BR_1A: // BR_1A ................ ......nnnnn..... Rn
9036 assert(insOptsNone(id->idInsOpt()));
9037 assert((ins == INS_ret) || (ins == INS_br));
9038 code = emitInsCode(ins, fmt);
9039 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9041 dst += emitOutput_Instr(dst, code);
9044 case IF_BR_1B: // BR_1B ................ ......nnnnn..... Rn
9045 assert(insOptsNone(id->idInsOpt()));
9046 assert((ins == INS_br_tail) || (ins == INS_blr));
9047 code = emitInsCode(ins, fmt);
9048 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9050 sz = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
9051 dst += emitOutputCall(ig, dst, id, code);
9054 case IF_LS_1A: // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB)
9056 assert(insOptsNone(id->idInsOpt()));
9057 assert(id->idIsBound());
9059 dst = emitOutputLJ(ig, dst, id);
9060 sz = sizeof(instrDescJmp);
9063 case IF_LS_2A: // LS_2A .X.......X...... ......nnnnnttttt Rt Rn
9064 assert(insOptsNone(id->idInsOpt()));
9065 code = emitInsCode(ins, fmt);
9066 // Is the target a vector register?
9067 if (isVectorRegister(id->idReg1()))
9069 code &= 0x3FFFFFFF; // clear the size bits
9070 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9071 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9075 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9076 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9078 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9079 dst += emitOutput_Instr(dst, code);
9082 case IF_LS_2B: // LS_2B .X.......Xiiiiii iiiiiinnnnnttttt Rt Rn imm(0-4095)
9083 assert(insOptsNone(id->idInsOpt()));
9084 imm = emitGetInsSC(id);
9085 assert(isValidUimm12(imm));
9086 code = emitInsCode(ins, fmt);
9087 // Is the target a vector register?
9088 if (isVectorRegister(id->idReg1()))
9090 code &= 0x3FFFFFFF; // clear the size bits
9091 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9092 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9096 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9097 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9099 code |= ((code_t)imm << 10); // iiiiiiiiiiii
9100 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9101 dst += emitOutput_Instr(dst, code);
9104 case IF_LS_2C: // LS_2C .X.......X.iiiii iiiiPPnnnnnttttt Rt Rn imm(-256..+255) no/pre/post inc
9105 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9106 imm = emitGetInsSC(id);
9107 assert((imm >= -256) && (imm <= 255)); // signed 9 bits
9108 imm &= 0x1ff; // force into unsigned 9 bit representation
9109 code = emitInsCode(ins, fmt);
9110 // Is the target a vector register?
9111 if (isVectorRegister(id->idReg1()))
9113 code &= 0x3FFFFFFF; // clear the size bits
9114 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9115 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9119 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9120 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9122 code |= insEncodeIndexedOpt(id->idInsOpt()); // PP
9123 code |= ((code_t)imm << 12); // iiiiiiiii
9124 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9125 dst += emitOutput_Instr(dst, code);
9128 case IF_LS_3A: // LS_3A .X.......X.mmmmm oooS..nnnnnttttt Rt Rn Rm ext(Rm) LSL {}
9129 assert(insOptsLSExtend(id->idInsOpt()));
9130 code = emitInsCode(ins, fmt);
9131 // Is the target a vector register?
9132 if (isVectorRegister(id->idReg1()))
9134 code &= 0x3FFFFFFF; // clear the size bits
9135 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9136 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9140 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9141 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9143 code |= insEncodeExtend(id->idInsOpt()); // ooo
9144 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9145 if (id->idIsLclVar())
9147 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9151 code |= insEncodeReg3Scale(id->idReg3Scaled()); // S
9152 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9154 dst += emitOutput_Instr(dst, code);
9157 case IF_LS_3B: // LS_3B X............... .aaaaannnnnddddd Rd Ra Rn
9158 assert(insOptsNone(id->idInsOpt()));
9159 code = emitInsCode(ins, fmt);
9160 // Is the target a vector register?
9161 if (isVectorRegister(id->idReg1()))
9163 code &= 0x3FFFFFFF; // clear the size bits
9164 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9165 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9166 code |= insEncodeReg_Va(id->idReg2()); // aaaaa
9170 code |= insEncodeDatasize(id->idOpSize()); // X
9171 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9172 code |= insEncodeReg_Ra(id->idReg2()); // aaaaa
9174 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9175 dst += emitOutput_Instr(dst, code);
9178 case IF_LS_3C: // LS_3C X......PP.iiiiii iaaaaannnnnddddd Rd Ra Rn imm(im7,sh)
9179 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9180 imm = emitGetInsSC(id);
9181 assert((imm >= -64) && (imm <= 63)); // signed 7 bits
9182 imm &= 0x7f; // force into unsigned 7 bit representation
9183 code = emitInsCode(ins, fmt);
9184 // Is the target a vector register?
9185 if (isVectorRegister(id->idReg1()))
9187 code &= 0x3FFFFFFF; // clear the size bits
9188 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9189 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9190 code |= insEncodeReg_Va(id->idReg2()); // aaaaa
9194 code |= insEncodeDatasize(id->idOpSize()); // X
9195 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9196 code |= insEncodeReg_Ra(id->idReg2()); // aaaaa
9198 code |= insEncodePairIndexedOpt(ins, id->idInsOpt()); // PP
9199 code |= ((code_t)imm << 15); // iiiiiiiii
9200 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9201 dst += emitOutput_Instr(dst, code);
9204 case IF_LS_3D: // LS_3D .X.......X.mmmmm ......nnnnnttttt Wm Rt Rn
9205 code = emitInsCode(ins, fmt);
9206 // Arm64 store exclusive unpredictable cases
9207 assert(id->idReg1() != id->idReg2());
9208 assert(id->idReg1() != id->idReg3());
9209 code |= insEncodeDatasizeLS(code, id->idOpSize()); // X
9210 code |= insEncodeReg_Rm(id->idReg1()); // mmmmm
9211 code |= insEncodeReg_Rt(id->idReg2()); // ttttt
9212 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9213 dst += emitOutput_Instr(dst, code);
9216 case IF_DI_1A: // DI_1A X.......shiiiiii iiiiiinnnnn..... Rn imm(i12,sh)
9217 assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9218 imm = emitGetInsSC(id);
9219 assert(isValidUimm12(imm));
9220 code = emitInsCode(ins, fmt);
9221 code |= insEncodeDatasize(id->idOpSize()); // X
9222 code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9223 code |= ((code_t)imm << 10); // iiiiiiiiiiii
9224 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9225 dst += emitOutput_Instr(dst, code);
9228 case IF_DI_1B: // DI_1B X........hwiiiii iiiiiiiiiiiddddd Rd imm(i16,hw)
9229 imm = emitGetInsSC(id);
9230 assert(isValidImmHWVal(imm, id->idOpSize()));
9231 code = emitInsCode(ins, fmt);
9232 code |= insEncodeDatasize(id->idOpSize()); // X
9233 code |= ((code_t)imm << 5); // hwiiiii iiiiiiiiiii
9234 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9235 dst += emitOutput_Instr(dst, code);
9238 case IF_DI_1C: // DI_1C X........Nrrrrrr ssssssnnnnn..... Rn imm(N,r,s)
9239 imm = emitGetInsSC(id);
9240 assert(isValidImmNRS(imm, id->idOpSize()));
9241 code = emitInsCode(ins, fmt);
9242 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9243 code |= insEncodeDatasize(id->idOpSize()); // X
9244 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9245 dst += emitOutput_Instr(dst, code);
9248 case IF_DI_1D: // DI_1D X........Nrrrrrr ssssss.....ddddd Rd imm(N,r,s)
9249 imm = emitGetInsSC(id);
9250 assert(isValidImmNRS(imm, id->idOpSize()));
9251 code = emitInsCode(ins, fmt);
9252 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9253 code |= insEncodeDatasize(id->idOpSize()); // X
9254 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9255 dst += emitOutput_Instr(dst, code);
9258 case IF_DI_1E: // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
9260 assert(insOptsNone(id->idInsOpt()));
9261 if (id->idIsReloc())
9263 code = emitInsCode(ins, fmt);
9264 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9265 dst += emitOutput_Instr(dst, code);
9266 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEBASE_REL21);
9270 // Local jmp/load case which does not need a relocation.
9271 assert(id->idIsBound());
9272 dst = emitOutputLJ(ig, dst, id);
9274 sz = sizeof(instrDescJmp);
9277 case IF_DI_1F: // DI_1F X..........iiiii cccc..nnnnn.nzcv Rn imm5 nzcv cond
9278 imm = emitGetInsSC(id);
9279 assert(isValidImmCondFlagsImm5(imm));
9282 cfi.immCFVal = (unsigned)imm;
9283 code = emitInsCode(ins, fmt);
9284 code |= insEncodeDatasize(id->idOpSize()); // X
9285 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9286 code |= ((code_t)cfi.imm5 << 16); // iiiii
9287 code |= insEncodeFlags(cfi.flags); // nzcv
9288 code |= insEncodeCond(cfi.cond); // cccc
9289 dst += emitOutput_Instr(dst, code);
9293 case IF_DI_2A: // DI_2A X.......shiiiiii iiiiiinnnnnddddd Rd Rn imm(i12,sh)
9294 assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9295 imm = emitGetInsSC(id);
9296 assert(isValidUimm12(imm));
9297 code = emitInsCode(ins, fmt);
9298 code |= insEncodeDatasize(id->idOpSize()); // X
9299 code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9300 code |= ((code_t)imm << 10); // iiiiiiiiiiii
9301 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9302 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9303 dst += emitOutput_Instr(dst, code);
9305 if (id->idIsReloc())
9307 assert(sz == sizeof(instrDesc));
9308 assert(id->idAddr()->iiaAddr != nullptr);
9309 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEOFFSET_12A);
9313 case IF_DI_2B: // DI_2B X.........Xnnnnn ssssssnnnnnddddd Rd Rn imm(0-63)
9314 code = emitInsCode(ins, fmt);
9315 imm = emitGetInsSC(id);
9316 assert(isValidImmShift(imm, id->idOpSize()));
9317 code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9318 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9319 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9320 code |= insEncodeReg_Rm(id->idReg2()); // Reg2 also in mmmmm
9321 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9322 dst += emitOutput_Instr(dst, code);
9325 case IF_DI_2C: // DI_2C X........Nrrrrrr ssssssnnnnnddddd Rd Rn imm(N,r,s)
9326 imm = emitGetInsSC(id);
9327 assert(isValidImmNRS(imm, id->idOpSize()));
9328 code = emitInsCode(ins, fmt);
9329 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9330 code |= insEncodeDatasize(id->idOpSize()); // X
9331 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9332 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9333 dst += emitOutput_Instr(dst, code);
9336 case IF_DI_2D: // DI_2D X........Nrrrrrr ssssssnnnnnddddd Rd Rn imr, imms (N,r,s)
9337 if (ins == INS_asr || ins == INS_lsl || ins == INS_lsr)
9339 imm = emitGetInsSC(id);
9340 assert(isValidImmShift(imm, id->idOpSize()));
9342 // Shift immediates are aliases of the SBFM/UBFM instructions
9343 // that actually take 2 registers and 2 constants,
9344 // Since we stored the shift immediate value
9345 // we need to calculate the N,R and S values here.
9350 bmi.immN = (size == EA_8BYTE) ? 1 : 0;
9352 bmi.immS = (size == EA_8BYTE) ? 0x3f : 0x1f;
9354 // immR and immS are now set correctly for INS_asr and INS_lsr
9355 // but for INS_lsl we have to adjust the values for immR and immS
9359 bmi.immR = -imm & bmi.immS;
9360 bmi.immS = bmi.immS - imm;
9363 // setup imm with the proper 13 bit value N:R:S
9369 // The other instructions have already have encoded N,R and S values
9370 imm = emitGetInsSC(id);
9372 assert(isValidImmNRS(imm, id->idOpSize()));
9374 code = emitInsCode(ins, fmt);
9375 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9376 code |= insEncodeDatasize(id->idOpSize()); // X
9377 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9378 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9379 dst += emitOutput_Instr(dst, code);
9382 case IF_DR_1D: // DR_1D X............... cccc.......ddddd Rd cond
9383 imm = emitGetInsSC(id);
9384 assert(isValidImmCond(imm));
9387 cfi.immCFVal = (unsigned)imm;
9388 code = emitInsCode(ins, fmt);
9389 code |= insEncodeDatasize(id->idOpSize()); // X
9390 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9391 code |= insEncodeInvertedCond(cfi.cond); // cccc
9392 dst += emitOutput_Instr(dst, code);
9396 case IF_DR_2A: // DR_2A X..........mmmmm ......nnnnn..... Rn Rm
9397 assert(insOptsNone(id->idInsOpt()));
9398 code = emitInsCode(ins, fmt);
9399 code |= insEncodeDatasize(id->idOpSize()); // X
9400 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9401 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9402 dst += emitOutput_Instr(dst, code);
9405 case IF_DR_2B: // DR_2B X.......sh.mmmmm ssssssnnnnn..... Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
9406 code = emitInsCode(ins, fmt);
9407 imm = emitGetInsSC(id);
9408 assert(isValidImmShift(imm, id->idOpSize()));
9409 code |= insEncodeDatasize(id->idOpSize()); // X
9410 code |= insEncodeShiftType(id->idInsOpt()); // sh
9411 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9412 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9413 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9414 dst += emitOutput_Instr(dst, code);
9417 case IF_DR_2C: // DR_2C X..........mmmmm ooosssnnnnn..... Rn Rm ext(Rm) LSL imm(0-4)
9418 code = emitInsCode(ins, fmt);
9419 imm = emitGetInsSC(id);
9420 assert((imm >= 0) && (imm <= 4)); // imm [0..4]
9421 code |= insEncodeDatasize(id->idOpSize()); // X
9422 code |= insEncodeExtend(id->idInsOpt()); // ooo
9423 code |= insEncodeExtendScale(imm); // sss
9424 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9425 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9426 dst += emitOutput_Instr(dst, code);
9429 case IF_DR_2D: // DR_2D X..........nnnnn cccc..nnnnnddddd Rd Rn cond
9430 imm = emitGetInsSC(id);
9431 assert(isValidImmCond(imm));
9434 cfi.immCFVal = (unsigned)imm;
9435 code = emitInsCode(ins, fmt);
9436 code |= insEncodeDatasize(id->idOpSize()); // X
9437 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9438 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9439 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9440 code |= insEncodeInvertedCond(cfi.cond); // cccc
9441 dst += emitOutput_Instr(dst, code);
9445 case IF_DR_2E: // DR_2E X..........mmmmm ...........ddddd Rd Rm
9446 code = emitInsCode(ins, fmt);
9447 code |= insEncodeDatasize(id->idOpSize()); // X
9448 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9449 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9450 dst += emitOutput_Instr(dst, code);
9453 case IF_DR_2F: // DR_2F X.......sh.mmmmm ssssss.....ddddd Rd Rm {LSL,LSR,ASR} imm(0-63)
9454 code = emitInsCode(ins, fmt);
9455 imm = emitGetInsSC(id);
9456 assert(isValidImmShift(imm, id->idOpSize()));
9457 code |= insEncodeDatasize(id->idOpSize()); // X
9458 code |= insEncodeShiftType(id->idInsOpt()); // sh
9459 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9460 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9461 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9462 dst += emitOutput_Instr(dst, code);
9465 case IF_DR_2G: // DR_2G X............... .....xnnnnnddddd Rd Rn
9466 code = emitInsCode(ins, fmt);
9467 code |= insEncodeDatasize(id->idOpSize()); // X
9470 if (size == EA_8BYTE)
9472 code |= 0x00000400; // x - bit at location 10
9475 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9476 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9477 dst += emitOutput_Instr(dst, code);
9480 case IF_DR_2H: // DR_2H X........X...... ......nnnnnddddd Rd Rn
9481 code = emitInsCode(ins, fmt);
9482 code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9483 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9484 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9485 dst += emitOutput_Instr(dst, code);
9488 case IF_DR_2I: // DR_2I X..........mmmmm cccc..nnnnn.nzcv Rn Rm nzcv cond
9489 imm = emitGetInsSC(id);
9490 assert(isValidImmCondFlags(imm));
9493 cfi.immCFVal = (unsigned)imm;
9494 code = emitInsCode(ins, fmt);
9495 code |= insEncodeDatasize(id->idOpSize()); // X
9496 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9497 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9498 code |= insEncodeFlags(cfi.flags); // nzcv
9499 code |= insEncodeCond(cfi.cond); // cccc
9500 dst += emitOutput_Instr(dst, code);
9504 case IF_DR_3A: // DR_3A X..........mmmmm ......nnnnnmmmmm Rd Rn Rm
9505 code = emitInsCode(ins, fmt);
9506 code |= insEncodeDatasize(id->idOpSize()); // X
9507 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9508 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9509 if (id->idIsLclVar())
9511 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9515 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9517 dst += emitOutput_Instr(dst, code);
9520 case IF_DR_3B: // DR_3B X.......sh.mmmmm ssssssnnnnnddddd Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
9521 code = emitInsCode(ins, fmt);
9522 imm = emitGetInsSC(id);
9523 assert(isValidImmShift(imm, id->idOpSize()));
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 |= insEncodeShiftType(id->idInsOpt()); // sh
9529 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9530 dst += emitOutput_Instr(dst, code);
9533 case IF_DR_3C: // DR_3C X..........mmmmm ooosssnnnnnddddd Rd Rn Rm ext(Rm) LSL imm(0-4)
9534 code = emitInsCode(ins, fmt);
9535 imm = emitGetInsSC(id);
9536 assert((imm >= 0) && (imm <= 4)); // imm [0..4]
9537 code |= insEncodeDatasize(id->idOpSize()); // X
9538 code |= insEncodeExtend(id->idInsOpt()); // ooo
9539 code |= insEncodeExtendScale(imm); // sss
9540 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9541 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9542 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9543 dst += emitOutput_Instr(dst, code);
9546 case IF_DR_3D: // DR_3D X..........mmmmm cccc..nnnnnddddd Rd Rn Rm cond
9547 imm = emitGetInsSC(id);
9548 assert(isValidImmCond(imm));
9551 cfi.immCFVal = (unsigned)imm;
9552 code = emitInsCode(ins, fmt);
9553 code |= insEncodeDatasize(id->idOpSize()); // X
9554 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9555 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9556 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9557 code |= insEncodeCond(cfi.cond); // cccc
9558 dst += emitOutput_Instr(dst, code);
9562 case IF_DR_3E: // DR_3E X........X.mmmmm ssssssnnnnnddddd Rd Rn Rm imm(0-63)
9563 code = emitInsCode(ins, fmt);
9564 imm = emitGetInsSC(id);
9565 assert(isValidImmShift(imm, id->idOpSize()));
9566 code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9567 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9568 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9569 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9570 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9571 dst += emitOutput_Instr(dst, code);
9574 case IF_DR_4A: // DR_4A X..........mmmmm .aaaaannnnnmmmmm Rd Rn Rm Ra
9575 code = emitInsCode(ins, fmt);
9576 code |= insEncodeDatasize(id->idOpSize()); // X
9577 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9578 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9579 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9580 code |= insEncodeReg_Ra(id->idReg4()); // aaaaa
9581 dst += emitOutput_Instr(dst, code);
9584 case IF_DV_1A: // DV_1A .........X.iiiii iii........ddddd Vd imm8 (fmov - immediate scalar)
9585 imm = emitGetInsSC(id);
9586 elemsize = id->idOpSize();
9587 code = emitInsCode(ins, fmt);
9588 code |= insEncodeFloatElemsize(elemsize); // X
9589 code |= ((code_t)imm << 13); // iiiii iii
9590 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9591 dst += emitOutput_Instr(dst, code);
9594 case IF_DV_1B: // DV_1B .QX..........iii cmod..iiiiiddddd Vd imm8 (immediate vector)
9595 imm = emitGetInsSC(id) & 0x0ff;
9596 immShift = (emitGetInsSC(id) & 0x700) >> 8;
9597 elemsize = optGetElemsize(id->idInsOpt());
9602 cmode = 0xE; // 1110
9606 cmode |= (immShift << 1); // 10x0
9612 cmode |= (immShift << 1); // 0xx0
9622 cmode = 0xE; // 1110
9629 code = emitInsCode(ins, fmt);
9630 code |= insEncodeVectorsize(id->idOpSize()); // Q
9631 if ((ins == INS_fmov) || (ins == INS_movi))
9633 if (elemsize == EA_8BYTE)
9635 code |= 0x20000000; // X
9638 if (ins != INS_fmov)
9640 assert((cmode >= 0) && (cmode <= 0xF));
9641 code |= (cmode << 12); // cmod
9643 code |= (((code_t)imm >> 5) << 16); // iii
9644 code |= (((code_t)imm & 0x1f) << 5); // iiiii
9645 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9646 dst += emitOutput_Instr(dst, code);
9649 case IF_DV_1C: // DV_1C .........X...... ......nnnnn..... Vn #0.0 (fcmp - with zero)
9650 elemsize = id->idOpSize();
9651 code = emitInsCode(ins, fmt);
9652 code |= insEncodeFloatElemsize(elemsize); // X
9653 code |= insEncodeReg_Vn(id->idReg1()); // nnnnn
9654 dst += emitOutput_Instr(dst, code);
9657 case IF_DV_2A: // DV_2A .Q.......X...... ......nnnnnddddd Vd Vn (fabs, fcvt - vector)
9658 elemsize = optGetElemsize(id->idInsOpt());
9659 code = emitInsCode(ins, fmt);
9660 code |= insEncodeVectorsize(id->idOpSize()); // Q
9661 code |= insEncodeFloatElemsize(elemsize); // X
9662 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9663 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9664 dst += emitOutput_Instr(dst, code);
9667 case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov/smov - to general)
9668 elemsize = id->idOpSize();
9669 index = emitGetInsSC(id);
9670 datasize = (elemsize == EA_8BYTE) ? EA_16BYTE : EA_8BYTE;
9671 if (ins == INS_smov)
9673 datasize = EA_16BYTE;
9675 code = emitInsCode(ins, fmt);
9676 code |= insEncodeVectorsize(datasize); // Q
9677 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9678 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9679 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9680 dst += emitOutput_Instr(dst, code);
9683 case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
9686 datasize = id->idOpSize();
9687 elemsize = optGetElemsize(id->idInsOpt());
9692 datasize = EA_16BYTE;
9693 elemsize = id->idOpSize();
9694 index = emitGetInsSC(id);
9696 code = emitInsCode(ins, fmt);
9697 code |= insEncodeVectorsize(datasize); // Q
9698 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9699 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9700 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9701 dst += emitOutput_Instr(dst, code);
9704 case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
9705 index = emitGetInsSC(id);
9706 elemsize = optGetElemsize(id->idInsOpt());
9707 code = emitInsCode(ins, fmt);
9708 code |= insEncodeVectorsize(id->idOpSize()); // Q
9709 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9710 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9711 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9712 dst += emitOutput_Instr(dst, code);
9715 case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
9716 index = emitGetInsSC(id);
9717 elemsize = id->idOpSize();
9718 code = emitInsCode(ins, fmt);
9719 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9720 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9721 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9722 dst += emitOutput_Instr(dst, code);
9725 case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
9726 elemsize = id->idOpSize();
9727 imm = emitGetInsSC(id);
9728 index = (imm >> 4) & 0xf;
9730 code = emitInsCode(ins, fmt);
9731 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9732 code |= insEncodeVectorIndex2(elemsize, index2); // jjjj
9733 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9734 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9735 dst += emitOutput_Instr(dst, code);
9738 case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov,fcvtXX - register)
9739 elemsize = id->idOpSize();
9740 code = emitInsCode(ins, fmt);
9741 code |= insEncodeFloatElemsize(elemsize); // X
9742 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9743 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9744 dst += emitOutput_Instr(dst, code);
9747 case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov - to general)
9748 elemsize = id->idOpSize();
9749 code = emitInsCode(ins, fmt);
9750 code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X X
9751 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9752 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9753 dst += emitOutput_Instr(dst, code);
9756 case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov - from general)
9757 elemsize = id->idOpSize();
9758 code = emitInsCode(ins, fmt);
9759 code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X X
9760 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9761 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9762 dst += emitOutput_Instr(dst, code);
9765 case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
9766 code = emitInsCode(ins, fmt);
9767 code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // SS DD
9768 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9769 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9770 dst += emitOutput_Instr(dst, code);
9773 case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
9774 elemsize = id->idOpSize();
9775 code = emitInsCode(ins, fmt);
9776 code |= insEncodeFloatElemsize(elemsize); // X
9777 code |= insEncodeReg_Vn(id->idReg1()); // nnnnn
9778 code |= insEncodeReg_Vm(id->idReg2()); // mmmmm
9779 dst += emitOutput_Instr(dst, code);
9782 case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
9783 elemsize = id->idOpSize();
9784 code = emitInsCode(ins, fmt);
9785 code |= insEncodeElemsize(elemsize); // XX
9786 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9787 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9788 dst += emitOutput_Instr(dst, code);
9791 case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
9792 elemsize = optGetElemsize(id->idInsOpt());
9793 code = emitInsCode(ins, fmt);
9794 code |= insEncodeVectorsize(id->idOpSize()); // Q
9795 code |= insEncodeElemsize(elemsize); // XX
9796 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9797 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9798 dst += emitOutput_Instr(dst, code);
9801 case IF_DV_2N: // DV_2N .........iiiiiii ......nnnnnddddd Vd Vn imm (shift - scalar)
9802 imm = emitGetInsSC(id);
9803 code = emitInsCode(ins, fmt);
9804 code |= insEncodeVectorShift(EA_8BYTE, imm); // iiiiiii
9805 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9806 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9807 dst += emitOutput_Instr(dst, code);
9810 case IF_DV_2O: // DV_2O .Q.......iiiiiii ......nnnnnddddd Vd Vn imm (shift - vector)
9811 imm = emitGetInsSC(id);
9812 elemsize = optGetElemsize(id->idInsOpt());
9813 code = emitInsCode(ins, fmt);
9814 code |= insEncodeVectorsize(id->idOpSize()); // Q
9815 code |= insEncodeVectorShift(elemsize, imm); // iiiiiii
9816 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9817 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9818 dst += emitOutput_Instr(dst, code);
9821 case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
9822 code = emitInsCode(ins, fmt);
9823 elemsize = optGetElemsize(id->idInsOpt());
9824 code |= insEncodeVectorsize(id->idOpSize()); // Q
9825 code |= insEncodeElemsize(elemsize); // XX
9826 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9827 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9828 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9829 dst += emitOutput_Instr(dst, code);
9832 case IF_DV_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector)
9833 code = emitInsCode(ins, fmt);
9834 imm = emitGetInsSC(id);
9835 elemsize = optGetElemsize(id->idInsOpt());
9836 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
9837 code |= insEncodeVectorsize(id->idOpSize()); // Q
9838 code |= insEncodeElemsize(elemsize); // XX
9839 code |= insEncodeVectorIndexLMH(elemsize, imm); // LM H
9840 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9841 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9842 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9843 dst += emitOutput_Instr(dst, code);
9846 case IF_DV_3B: // DV_3B .Q.......X.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
9847 code = emitInsCode(ins, fmt);
9848 elemsize = optGetElemsize(id->idInsOpt());
9849 code |= insEncodeVectorsize(id->idOpSize()); // Q
9850 code |= insEncodeFloatElemsize(elemsize); // X
9851 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9852 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9853 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9854 dst += emitOutput_Instr(dst, code);
9857 case IF_DV_3BI: // DV_3BI .Q.......XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
9858 code = emitInsCode(ins, fmt);
9859 imm = emitGetInsSC(id);
9860 elemsize = optGetElemsize(id->idInsOpt());
9861 assert(isValidVectorIndex(id->idOpSize(), elemsize, imm));
9862 code |= insEncodeVectorsize(id->idOpSize()); // Q
9863 code |= insEncodeFloatElemsize(elemsize); // X
9864 code |= insEncodeFloatIndex(elemsize, imm); // L H
9865 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9866 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9867 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9868 dst += emitOutput_Instr(dst, code);
9871 case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
9872 code = emitInsCode(ins, fmt);
9873 code |= insEncodeVectorsize(id->idOpSize()); // Q
9874 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9875 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9876 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9877 dst += emitOutput_Instr(dst, code);
9880 case IF_DV_3D: // DV_3D .........X.mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
9881 code = emitInsCode(ins, fmt);
9882 code |= insEncodeFloatElemsize(id->idOpSize()); // X
9883 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9884 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9885 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9886 dst += emitOutput_Instr(dst, code);
9889 case IF_DV_3DI: // DV_3DI .........XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (scalar by elem)
9890 code = emitInsCode(ins, fmt);
9891 imm = emitGetInsSC(id);
9892 elemsize = id->idOpSize();
9893 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
9894 code |= insEncodeFloatElemsize(elemsize); // X
9895 code |= insEncodeFloatIndex(elemsize, imm); // L H
9896 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9897 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9898 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9899 dst += emitOutput_Instr(dst, code);
9902 case IF_DV_3E: // DV_3E ...........mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
9903 code = emitInsCode(ins, fmt);
9904 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9905 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9906 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9907 dst += emitOutput_Instr(dst, code);
9910 case IF_DV_4A: // DV_4A .........X.mmmmm .aaaaannnnnddddd Vd Va Vn Vm (scalar)
9911 code = emitInsCode(ins, fmt);
9912 elemsize = id->idOpSize();
9913 code |= insEncodeFloatElemsize(elemsize); // X
9914 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9915 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9916 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9917 code |= insEncodeReg_Va(id->idReg4()); // aaaaa
9918 dst += emitOutput_Instr(dst, code);
9921 case IF_SN_0A: // SN_0A ................ ................
9922 code = emitInsCode(ins, fmt);
9923 dst += emitOutput_Instr(dst, code);
9926 case IF_SI_0A: // SI_0A ...........iiiii iiiiiiiiiii..... imm16
9927 imm = emitGetInsSC(id);
9928 assert(isValidUimm16(imm));
9929 code = emitInsCode(ins, fmt);
9930 code |= ((code_t)imm << 5); // iiiii iiiiiiiiiii
9931 dst += emitOutput_Instr(dst, code);
9934 case IF_SI_0B: // SI_0B ................ ....bbbb........ imm4 - barrier
9935 imm = emitGetInsSC(id);
9936 assert((imm >= 0) && (imm <= 15));
9937 code = emitInsCode(ins, fmt);
9938 code |= ((code_t)imm << 8); // bbbb
9939 dst += emitOutput_Instr(dst, code);
9943 assert(!"Unexpected format");
9947 // Determine if any registers now hold GC refs, or whether a register that was overwritten held a GC ref.
9948 // We assume here that "id->idGCref()" is not GC_NONE only if the instruction described by "id" writes a
9949 // GC ref to register "id->idReg1()". (It may, apparently, also not be GC_NONE in other cases, such as
9950 // for stores, but we ignore those cases here.)
9951 if (emitInsMayWriteToGCReg(id)) // True if "id->idIns()" writes to a register than can hold GC ref.
9953 // We assume that "idReg1" is the primary destination register for all instructions
9954 if (id->idGCref() != GCT_NONE)
9956 emitGCregLiveUpd(id->idGCref(), id->idReg1(), dst);
9960 emitGCregDeadUpd(id->idReg1(), dst);
9963 if (emitInsMayWriteMultipleRegs(id))
9966 // "idReg2" is the secondary destination register
9967 if (id->idGCrefReg2() != GCT_NONE)
9969 emitGCregLiveUpd(id->idGCrefReg2(), id->idReg2(), dst);
9973 emitGCregDeadUpd(id->idReg2(), dst);
9978 // Now we determine if the instruction has written to a (local variable) stack location, and either written a GC
9979 // ref or overwritten one.
9980 if (emitInsWritesToLclVarStackLoc(id) || emitInsWritesToLclVarStackLocPair(id))
9982 int varNum = id->idAddr()->iiaLclVar.lvaVarNum();
9983 unsigned ofs = AlignDown(id->idAddr()->iiaLclVar.lvaOffset(), TARGET_POINTER_SIZE);
9985 int adr = emitComp->lvaFrameAddress(varNum, &FPbased);
9986 if (id->idGCref() != GCT_NONE)
9988 emitGCvarLiveUpd(adr + ofs, varNum, id->idGCref(), dst);
9992 // If the type of the local is a gc ref type, update the liveness.
9996 // "Regular" (non-spill-temp) local.
9997 vt = var_types(emitComp->lvaTable[varNum].lvType);
10001 TempDsc* tmpDsc = emitComp->tmpFindNum(varNum);
10002 vt = tmpDsc->tdTempType();
10004 if (vt == TYP_REF || vt == TYP_BYREF)
10005 emitGCvarDeadUpd(adr + ofs, dst);
10007 if (emitInsWritesToLclVarStackLocPair(id))
10009 unsigned ofs2 = ofs + TARGET_POINTER_SIZE;
10010 if (id->idGCrefReg2() != GCT_NONE)
10012 emitGCvarLiveUpd(adr + ofs2, varNum, id->idGCrefReg2(), dst);
10016 // If the type of the local is a gc ref type, update the liveness.
10020 // "Regular" (non-spill-temp) local.
10021 vt = var_types(emitComp->lvaTable[varNum].lvType);
10025 TempDsc* tmpDsc = emitComp->tmpFindNum(varNum);
10026 vt = tmpDsc->tdTempType();
10028 if (vt == TYP_REF || vt == TYP_BYREF)
10029 emitGCvarDeadUpd(adr + ofs2, dst);
10035 /* Make sure we set the instruction descriptor size correctly */
10037 size_t expected = emitSizeOfInsDsc(id);
10038 assert(sz == expected);
10040 if (emitComp->opts.disAsm || emitComp->opts.dspEmit || emitComp->verbose)
10042 emitDispIns(id, false, dspOffs, true, emitCurCodeOffs(odst), *dp, (dst - *dp), ig);
10045 if (emitComp->compDebugBreak)
10047 // For example, set JitBreakEmitOutputInstr=a6 will break when this method is called for
10048 // emitting instruction a6, (i.e. IN00a6 in jitdump).
10049 if ((unsigned)JitConfig.JitBreakEmitOutputInstr() == id->idDebugOnlyInfo()->idNum)
10051 assert(!"JitBreakEmitOutputInstr reached");
10056 /* All instructions are expected to generate code */
10058 assert(*dp != dst);
10065 /*****************************************************************************/
10066 /*****************************************************************************/
10070 /*****************************************************************************
10072 * Display the instruction name
10074 void emitter::emitDispInst(instruction ins)
10076 const char* insstr = codeGen->genInsName(ins);
10077 size_t len = strlen(insstr);
10079 /* Display the instruction name */
10081 printf("%s", insstr);
10084 // Add at least one space after the instruction name
10085 // and add spaces until we have reach the normal size of 8
10093 /*****************************************************************************
10095 * Display an reloc value
10096 * If we are formatting for an assembly listing don't print the hex value
10097 * since it will prevent us from doing assembly diffs
10099 void emitter::emitDispReloc(int value, bool addComma)
10101 if (emitComp->opts.disAsm)
10107 printf("(reloc 0x%x)", dspPtr(value));
10114 /*****************************************************************************
10116 * Display an immediate value
10118 void emitter::emitDispImm(ssize_t imm, bool addComma, bool alwaysHex /* =false */)
10125 // Munge any pointers if we want diff-able disassembly.
10126 // Since some may be emitted as partial words, print as diffable anything that has
10127 // significant bits beyond the lowest 8-bits.
10128 if (emitComp->opts.disDiffable)
10130 ssize_t top56bits = (imm >> 8);
10131 if ((top56bits != 0) && (top56bits != -1))
10135 if (!alwaysHex && (imm > -1000) && (imm < 1000))
10141 if ((imm < 0) && ((imm & 0xFFFFFFFF00000000LL) == 0xFFFFFFFF00000000LL))
10147 if ((imm & 0xFFFFFFFF00000000LL) != 0)
10149 printf("0x%llx", imm);
10153 printf("0x%02x", imm);
10161 /*****************************************************************************
10163 * Display a float zero constant
10165 void emitter::emitDispFloatZero()
10174 /*****************************************************************************
10176 * Display an encoded float constant value
10178 void emitter::emitDispFloatImm(ssize_t imm8)
10180 assert((0 <= imm8) && (imm8 <= 0x0ff));
10187 fpImm.immFPIVal = (unsigned)imm8;
10188 double result = emitDecodeFloatImm8(fpImm);
10190 printf("%.4f", result);
10193 /*****************************************************************************
10195 * Display an immediate that is optionally LSL12.
10197 void emitter::emitDispImmOptsLSL12(ssize_t imm, insOpts opt)
10199 if (!strictArmAsm && insOptsLSL12(opt))
10203 emitDispImm(imm, false);
10204 if (strictArmAsm && insOptsLSL12(opt))
10206 printf(", LSL #12");
10210 /*****************************************************************************
10212 * Display an ARM64 condition code for the conditional instructions
10214 void emitter::emitDispCond(insCond cond)
10216 const static char* armCond[16] = {"eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc",
10217 "hi", "ls", "ge", "lt", "gt", "le", "AL", "NV"}; // The last two are invalid
10218 unsigned imm = (unsigned)cond;
10219 assert((0 <= imm) && (imm < ArrLen(armCond)));
10220 printf(armCond[imm]);
10223 /*****************************************************************************
10225 * Display an ARM64 flags for the conditional instructions
10227 void emitter::emitDispFlags(insCflags flags)
10229 const static char* armFlags[16] = {"0", "v", "c", "cv", "z", "zv", "zc", "zcv",
10230 "n", "nv", "nc", "ncv", "nz", "nzv", "nzc", "nzcv"};
10231 unsigned imm = (unsigned)flags;
10232 assert((0 <= imm) && (imm < ArrLen(armFlags)));
10233 printf(armFlags[imm]);
10236 /*****************************************************************************
10238 * Display an ARM64 'barrier' for the memory barrier instructions
10240 void emitter::emitDispBarrier(insBarrier barrier)
10242 const static char* armBarriers[16] = {"#0", "oshld", "oshst", "osh", "#4", "nshld", "nshst", "nsh",
10243 "#8", "ishld", "ishst", "ish", "#12", "ld", "st", "sy"};
10244 unsigned imm = (unsigned)barrier;
10245 assert((0 <= imm) && (imm < ArrLen(armBarriers)));
10246 printf(armBarriers[imm]);
10249 /*****************************************************************************
10251 * Prints the encoding for the Shift Type encoding
10254 void emitter::emitDispShiftOpts(insOpts opt)
10256 if (opt == INS_OPTS_LSL)
10258 else if (opt == INS_OPTS_LSR)
10260 else if (opt == INS_OPTS_ASR)
10262 else if (opt == INS_OPTS_ROR)
10264 else if (opt == INS_OPTS_MSL)
10267 assert(!"Bad value");
10270 /*****************************************************************************
10272 * Prints the encoding for the Extend Type encoding
10275 void emitter::emitDispExtendOpts(insOpts opt)
10277 if (opt == INS_OPTS_UXTB)
10279 else if (opt == INS_OPTS_UXTH)
10281 else if (opt == INS_OPTS_UXTW)
10283 else if (opt == INS_OPTS_UXTX)
10285 else if (opt == INS_OPTS_SXTB)
10287 else if (opt == INS_OPTS_SXTH)
10289 else if (opt == INS_OPTS_SXTW)
10291 else if (opt == INS_OPTS_SXTX)
10294 assert(!"Bad value");
10297 /*****************************************************************************
10299 * Prints the encoding for the Extend Type encoding in loads/stores
10302 void emitter::emitDispLSExtendOpts(insOpts opt)
10304 if (opt == INS_OPTS_LSL)
10306 else if (opt == INS_OPTS_UXTW)
10308 else if (opt == INS_OPTS_UXTX)
10310 else if (opt == INS_OPTS_SXTW)
10312 else if (opt == INS_OPTS_SXTX)
10315 assert(!"Bad value");
10318 /*****************************************************************************
10320 * Display a register
10322 void emitter::emitDispReg(regNumber reg, emitAttr attr, bool addComma)
10324 emitAttr size = EA_SIZE(attr);
10325 printf(emitRegName(reg, size));
10331 /*****************************************************************************
10333 * Display a vector register with an arrangement suffix
10335 void emitter::emitDispVectorReg(regNumber reg, insOpts opt, bool addComma)
10337 assert(isVectorRegister(reg));
10338 printf(emitVectorRegName(reg));
10339 emitDispArrangement(opt);
10345 /*****************************************************************************
10347 * Display an vector register index suffix
10349 void emitter::emitDispVectorRegIndex(regNumber reg, emitAttr elemsize, ssize_t index, bool addComma)
10351 assert(isVectorRegister(reg));
10352 printf(emitVectorRegName(reg));
10369 assert(!"invalid elemsize");
10373 printf("[%d]", index);
10379 /*****************************************************************************
10381 * Display an arrangement suffix
10383 void emitter::emitDispArrangement(insOpts opt)
10385 const char* str = "???";
10415 assert(!"Invalid insOpt for vector register");
10421 /*****************************************************************************
10423 * Display a register with an optional shift operation
10425 void emitter::emitDispShiftedReg(regNumber reg, insOpts opt, ssize_t imm, emitAttr attr)
10427 emitAttr size = EA_SIZE(attr);
10428 assert((imm & 0x003F) == imm);
10429 assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
10431 printf(emitRegName(reg, size));
10439 emitDispShiftOpts(opt);
10440 emitDispImm(imm, false);
10444 /*****************************************************************************
10446 * Display a register with an optional extend and scale operations
10448 void emitter::emitDispExtendReg(regNumber reg, insOpts opt, ssize_t imm)
10450 assert((imm >= 0) && (imm <= 4));
10451 assert(insOptsNone(opt) || insOptsAnyExtend(opt) || (opt == INS_OPTS_LSL));
10453 // size is based on the extend option, not the instr size.
10454 emitAttr size = insOpts32BitExtend(opt) ? EA_4BYTE : EA_8BYTE;
10458 if (insOptsNone(opt))
10460 emitDispReg(reg, size, false);
10464 emitDispReg(reg, size, true);
10465 if (opt == INS_OPTS_LSL)
10468 emitDispExtendOpts(opt);
10469 if ((imm > 0) || (opt == INS_OPTS_LSL))
10472 emitDispImm(imm, false);
10476 else // !strictArmAsm
10478 if (insOptsNone(opt))
10480 emitDispReg(reg, size, false);
10484 if (opt != INS_OPTS_LSL)
10486 emitDispExtendOpts(opt);
10488 emitDispReg(reg, size, false);
10495 emitDispImm(1 << imm, false);
10500 /*****************************************************************************
10502 * Display an addressing operand [reg + imm]
10504 void emitter::emitDispAddrRI(regNumber reg, insOpts opt, ssize_t imm)
10506 reg = encodingZRtoSP(reg); // ZR (R31) encodes the SP register
10512 emitDispReg(reg, EA_8BYTE, false);
10514 if (!insOptsPostIndex(opt) && (imm != 0))
10517 emitDispImm(imm, false);
10521 if (insOptsPreIndex(opt))
10525 else if (insOptsPostIndex(opt))
10528 emitDispImm(imm, false);
10531 else // !strictArmAsm
10535 const char* operStr = "++";
10542 if (insOptsPreIndex(opt))
10547 emitDispReg(reg, EA_8BYTE, false);
10549 if (insOptsPostIndex(opt))
10554 if (insOptsIndexed(opt))
10560 printf("%c", operStr[1]);
10562 emitDispImm(imm, false);
10567 /*****************************************************************************
10569 * Display an addressing operand [reg + extended reg]
10571 void emitter::emitDispAddrRRExt(regNumber reg1, regNumber reg2, insOpts opt, bool isScaled, emitAttr size)
10573 reg1 = encodingZRtoSP(reg1); // ZR (R31) encodes the SP register
10575 unsigned scale = 0;
10578 scale = NaturalScale_helper(size);
10585 emitDispReg(reg1, EA_8BYTE, true);
10586 emitDispExtendReg(reg2, opt, scale);
10588 else // !strictArmAsm
10590 emitDispReg(reg1, EA_8BYTE, false);
10592 emitDispExtendReg(reg2, opt, scale);
10598 /*****************************************************************************
10600 * Display (optionally) the instruction encoding in hex
10603 void emitter::emitDispInsHex(BYTE* code, size_t sz)
10605 // We do not display the instruction hex if we want diff-able disassembly
10606 if (!emitComp->opts.disDiffable)
10610 printf(" %08X ", (*((code_t*)code)));
10619 /****************************************************************************
10621 * Display the given instruction.
10624 void emitter::emitDispIns(
10625 instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* pCode, size_t sz, insGroup* ig)
10630 id->idDebugOnlyInfo()->idNum; // Do not remove this! It is needed for VisualStudio conditional breakpoints
10632 printf("IN%04x: ", idNum);
10638 if (!emitComp->opts.dspEmit && !isNew && !asmfm && sz)
10641 /* Display the instruction offset */
10643 emitDispInsOffs(offset, doffs);
10645 /* Display the instruction hex code */
10647 emitDispInsHex(pCode, sz);
10651 /* Get the instruction and format */
10653 instruction ins = id->idIns();
10654 insFormat fmt = id->idInsFmt();
10658 /* If this instruction has just been added, check its size */
10660 assert(isNew == false || (int)emitSizeOfInsDsc(id) == emitCurIGfreeNext - (BYTE*)id);
10662 /* Figure out the operand size */
10663 emitAttr size = id->idOpSize();
10664 emitAttr attr = size;
10665 if (id->idGCref() == GCT_GCREF)
10667 else if (id->idGCref() == GCT_BYREF)
10675 bool isExtendAlias;
10684 const char* methodName;
10692 case IF_BI_0A: // BI_0A ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
10693 case IF_BI_0B: // BI_0B ......iiiiiiiiii iiiiiiiiiii..... simm19:00
10696 if (fmt == IF_LARGEJMP)
10698 printf("(LARGEJMP)");
10700 if (id->idAddr()->iiaHasInstrCount())
10702 int instrCount = id->idAddr()->iiaGetInstrCount();
10706 printf("pc%s%d instructions", (instrCount >= 0) ? "+" : "", instrCount);
10710 unsigned insNum = emitFindInsNum(ig, id);
10711 UNATIVE_OFFSET srcOffs = ig->igOffs + emitFindOffset(ig, insNum + 1);
10712 UNATIVE_OFFSET dstOffs = ig->igOffs + emitFindOffset(ig, insNum + 1 + instrCount);
10713 ssize_t relOffs = (ssize_t)(emitOffsetToPtr(dstOffs) - emitOffsetToPtr(srcOffs));
10714 printf("pc%s%d (%d instructions)", (relOffs >= 0) ? "+" : "", relOffs, instrCount);
10717 else if (id->idIsBound())
10719 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10723 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10728 case IF_BI_0C: // BI_0C ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
10729 if (id->idIsCallAddr())
10731 offs = (ssize_t)id->idAddr()->iiaAddr;
10737 methodName = emitComp->eeGetMethodFullName((CORINFO_METHOD_HANDLE)id->idDebugOnlyInfo()->idMemCookie);
10742 if (id->idIsDspReloc())
10744 printf("%08X", offs);
10748 printf("%s", methodName);
10752 case IF_BI_1A: // BI_1A ......iiiiiiiiii iiiiiiiiiiittttt Rt simm19:00
10753 assert(insOptsNone(id->idInsOpt()));
10754 emitDispReg(id->idReg1(), size, true);
10755 if (id->idIsBound())
10757 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10761 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10765 case IF_BI_1B: // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
10766 assert(insOptsNone(id->idInsOpt()));
10767 emitDispReg(id->idReg1(), size, true);
10768 emitDispImm(emitGetInsSC(id), true);
10769 if (id->idIsBound())
10771 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10775 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10779 case IF_BR_1A: // BR_1A ................ ......nnnnn..... Rn
10780 assert(insOptsNone(id->idInsOpt()));
10781 emitDispReg(id->idReg1(), size, false);
10784 case IF_BR_1B: // BR_1B ................ ......nnnnn..... Rn
10785 assert(insOptsNone(id->idInsOpt()));
10786 emitDispReg(id->idReg3(), size, false);
10789 case IF_LS_1A: // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB)
10790 case IF_DI_1E: // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
10793 assert(insOptsNone(id->idInsOpt()));
10794 emitDispReg(id->idReg1(), size, true);
10795 imm = emitGetInsSC(id);
10797 /* Is this actually a reference to a data section? */
10798 if (fmt == IF_LARGEADR)
10800 printf("(LARGEADR)");
10802 else if (fmt == IF_LARGELDC)
10804 printf("(LARGELDC)");
10808 if (id->idAddr()->iiaIsJitDataOffset())
10810 doffs = Compiler::eeGetJitDataOffs(id->idAddr()->iiaFieldHnd);
10811 /* Display a data section reference */
10814 printf("@CNS%02u", doffs - 1);
10816 printf("@RWD%02u", doffs);
10819 printf("%+Id", imm);
10824 if (id->idIsReloc())
10827 emitDispImm((ssize_t)id->idAddr()->iiaAddr, false);
10829 else if (id->idIsBound())
10831 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10835 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10841 case IF_LS_2A: // LS_2A .X.......X...... ......nnnnnttttt Rt Rn
10842 assert(insOptsNone(id->idInsOpt()));
10843 assert(emitGetInsSC(id) == 0);
10844 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10845 emitDispAddrRI(id->idReg2(), id->idInsOpt(), 0);
10848 case IF_LS_2B: // LS_2B .X.......Xiiiiii iiiiiinnnnnttttt Rt Rn imm(0-4095)
10849 assert(insOptsNone(id->idInsOpt()));
10850 imm = emitGetInsSC(id);
10851 scale = NaturalScale_helper(emitInsLoadStoreSize(id));
10852 imm <<= scale; // The immediate is scaled by the size of the ld/st
10853 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10854 emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
10857 case IF_LS_2C: // LS_2C .X.......X.iiiii iiiiPPnnnnnttttt Rt Rn imm(-256..+255) no/pre/post inc
10858 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
10859 imm = emitGetInsSC(id);
10860 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10861 emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
10864 case IF_LS_3A: // LS_3A .X.......X.mmmmm oooS..nnnnnttttt Rt Rn Rm ext(Rm) LSL {}
10865 assert(insOptsLSExtend(id->idInsOpt()));
10866 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10867 if (id->idIsLclVar())
10869 emitDispAddrRRExt(id->idReg2(), codeGen->rsGetRsvdReg(), id->idInsOpt(), false, size);
10873 emitDispAddrRRExt(id->idReg2(), id->idReg3(), id->idInsOpt(), id->idReg3Scaled(), size);
10877 case IF_LS_3B: // LS_3B X............... .aaaaannnnnddddd Rt Ra Rn
10878 assert(insOptsNone(id->idInsOpt()));
10879 assert(emitGetInsSC(id) == 0);
10880 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10881 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10882 emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
10885 case IF_LS_3C: // LS_3C X.........iiiiii iaaaaannnnnddddd Rt Ra Rn imm(im7,sh)
10886 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
10887 imm = emitGetInsSC(id);
10888 scale = NaturalScale_helper(emitInsLoadStoreSize(id));
10890 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10891 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10892 emitDispAddrRI(id->idReg3(), id->idInsOpt(), imm);
10895 case IF_LS_3D: // LS_3D .X.......X.mmmmm ......nnnnnttttt Wm Rt Rn
10896 assert(insOptsNone(id->idInsOpt()));
10897 emitDispReg(id->idReg1(), EA_4BYTE, true);
10898 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10899 emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
10902 case IF_DI_1A: // DI_1A X.......shiiiiii iiiiiinnnnn..... Rn imm(i12,sh)
10903 emitDispReg(id->idReg1(), size, true);
10904 emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
10907 case IF_DI_1B: // DI_1B X........hwiiiii iiiiiiiiiiiddddd Rd imm(i16,hw)
10908 emitDispReg(id->idReg1(), size, true);
10909 hwi.immHWVal = (unsigned)emitGetInsSC(id);
10910 if (ins == INS_mov)
10912 emitDispImm(emitDecodeHalfwordImm(hwi, size), false);
10914 else // movz, movn, movk
10916 emitDispImm(hwi.immVal, false);
10917 if (hwi.immHW != 0)
10919 emitDispShiftOpts(INS_OPTS_LSL);
10920 emitDispImm(hwi.immHW * 16, false);
10925 case IF_DI_1C: // DI_1C X........Nrrrrrr ssssssnnnnn..... Rn imm(N,r,s)
10926 emitDispReg(id->idReg1(), size, true);
10927 bmi.immNRS = (unsigned)emitGetInsSC(id);
10928 emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
10931 case IF_DI_1D: // DI_1D X........Nrrrrrr ssssss.....ddddd Rd imm(N,r,s)
10932 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
10933 bmi.immNRS = (unsigned)emitGetInsSC(id);
10934 emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
10937 case IF_DI_2A: // DI_2A X.......shiiiiii iiiiiinnnnnddddd Rd Rn imm(i12,sh)
10938 if ((ins == INS_add) || (ins == INS_sub))
10940 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
10941 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
10945 emitDispReg(id->idReg1(), size, true);
10946 emitDispReg(id->idReg2(), size, true);
10948 emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
10951 case IF_DI_2B: // DI_2B X........X.nnnnn ssssssnnnnnddddd Rd Rn imm(0-63)
10952 emitDispReg(id->idReg1(), size, true);
10953 emitDispReg(id->idReg2(), size, true);
10954 emitDispImm(emitGetInsSC(id), false);
10957 case IF_DI_2C: // DI_2C X........Nrrrrrr ssssssnnnnnddddd Rd Rn imm(N,r,s)
10958 if (ins == INS_ands)
10960 emitDispReg(id->idReg1(), size, true);
10964 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
10966 emitDispReg(id->idReg2(), size, true);
10967 bmi.immNRS = (unsigned)emitGetInsSC(id);
10968 emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
10971 case IF_DI_2D: // DI_2D X........Nrrrrrr ssssssnnnnnddddd Rd Rn imr, ims (N,r,s)
10972 emitDispReg(id->idReg1(), size, true);
10973 emitDispReg(id->idReg2(), size, true);
10975 imm = emitGetInsSC(id);
10976 bmi.immNRS = (unsigned)imm;
10983 emitDispImm(bmi.immR, true);
10984 emitDispImm(bmi.immS, false);
10990 emitDispImm(getBitWidth(size) - bmi.immR, true);
10991 emitDispImm(bmi.immS + 1, false);
10997 emitDispImm(bmi.immR, true);
10998 emitDispImm(bmi.immS - bmi.immR + 1, false);
11004 emitDispImm(imm, false);
11008 assert(!"Unexpected instruction in IF_DI_2D");
11013 case IF_DI_1F: // DI_1F X..........iiiii cccc..nnnnn.nzcv Rn imm5 nzcv cond
11014 emitDispReg(id->idReg1(), size, true);
11015 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11016 emitDispImm(cfi.imm5, true);
11017 emitDispFlags(cfi.flags);
11019 emitDispCond(cfi.cond);
11022 case IF_DR_1D: // DR_1D X............... cccc.......mmmmm Rd cond
11023 emitDispReg(id->idReg1(), size, true);
11024 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11025 emitDispCond(cfi.cond);
11028 case IF_DR_2A: // DR_2A X..........mmmmm ......nnnnn..... Rn Rm
11029 emitDispReg(id->idReg1(), size, true);
11030 emitDispReg(id->idReg2(), size, false);
11033 case IF_DR_2B: // DR_2B X.......sh.mmmmm ssssssnnnnn..... Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
11034 emitDispReg(id->idReg1(), size, true);
11035 emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
11038 case IF_DR_2C: // DR_2C X..........mmmmm ooosssnnnnn..... Rn Rm ext(Rm) LSL imm(0-4)
11039 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11040 imm = emitGetInsSC(id);
11041 emitDispExtendReg(id->idReg2(), id->idInsOpt(), imm);
11044 case IF_DR_2D: // DR_2D X..........nnnnn cccc..nnnnnddddd Rd Rn cond
11045 emitDispReg(id->idReg1(), size, true);
11046 emitDispReg(id->idReg2(), size, true);
11047 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11048 emitDispCond(cfi.cond);
11051 case IF_DR_2E: // DR_2E X..........mmmmm ...........ddddd Rd Rm
11052 emitDispReg(id->idReg1(), size, true);
11053 emitDispReg(id->idReg2(), size, false);
11056 case IF_DR_2F: // DR_2F X.......sh.mmmmm ssssss.....ddddd Rd Rm {LSL,LSR,ASR} imm(0-63)
11057 emitDispReg(id->idReg1(), size, true);
11058 emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
11061 case IF_DR_2G: // DR_2G X............... ......nnnnnddddd Rd Rn
11062 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11063 emitDispReg(encodingZRtoSP(id->idReg2()), size, false);
11066 case IF_DR_2H: // DR_2H X........X...... ......nnnnnddddd Rd Rn
11067 emitDispReg(id->idReg1(), size, true);
11068 emitDispReg(id->idReg2(), size, false);
11071 case IF_DR_2I: // DR_2I X..........mmmmm cccc..nnnnn.nzcv Rn Rm nzcv cond
11072 emitDispReg(id->idReg1(), size, true);
11073 emitDispReg(id->idReg2(), size, true);
11074 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11075 emitDispFlags(cfi.flags);
11077 emitDispCond(cfi.cond);
11080 case IF_DR_3A: // DR_3A X..........mmmmm ......nnnnnmmmmm Rd Rn Rm
11081 if ((ins == INS_add) || (ins == INS_sub))
11083 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11084 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11086 else if ((ins == INS_smull) || (ins == INS_smulh))
11088 // Rd is always 8 bytes
11089 emitDispReg(id->idReg1(), EA_8BYTE, true);
11091 // Rn, Rm effective size depends on instruction type
11092 size = (ins == INS_smulh) ? EA_8BYTE : EA_4BYTE;
11093 emitDispReg(id->idReg2(), size, true);
11097 emitDispReg(id->idReg1(), size, true);
11098 emitDispReg(id->idReg2(), size, true);
11100 if (id->idIsLclVar())
11102 emitDispReg(codeGen->rsGetRsvdReg(), size, false);
11106 emitDispReg(id->idReg3(), size, false);
11111 case IF_DR_3B: // DR_3B X.......sh.mmmmm ssssssnnnnnddddd Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
11112 emitDispReg(id->idReg1(), size, true);
11113 emitDispReg(id->idReg2(), size, true);
11114 emitDispShiftedReg(id->idReg3(), id->idInsOpt(), emitGetInsSC(id), size);
11117 case IF_DR_3C: // DR_3C X..........mmmmm ooosssnnnnnddddd Rd Rn Rm ext(Rm) LSL imm(0-4)
11118 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11119 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11120 imm = emitGetInsSC(id);
11121 emitDispExtendReg(id->idReg3(), id->idInsOpt(), imm);
11124 case IF_DR_3D: // DR_3D X..........mmmmm cccc..nnnnnmmmmm Rd Rn Rm cond
11125 emitDispReg(id->idReg1(), size, true);
11126 emitDispReg(id->idReg2(), size, true);
11127 emitDispReg(id->idReg3(), size, true);
11128 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11129 emitDispCond(cfi.cond);
11132 case IF_DR_3E: // DR_3E X........X.mmmmm ssssssnnnnnddddd Rd Rn Rm imm(0-63)
11133 emitDispReg(id->idReg1(), size, true);
11134 emitDispReg(id->idReg2(), size, true);
11135 emitDispReg(id->idReg3(), size, true);
11136 emitDispImm(emitGetInsSC(id), false);
11139 case IF_DR_4A: // DR_4A X..........mmmmm .aaaaannnnnmmmmm Rd Rn Rm Ra
11140 emitDispReg(id->idReg1(), size, true);
11141 emitDispReg(id->idReg2(), size, true);
11142 emitDispReg(id->idReg3(), size, true);
11143 emitDispReg(id->idReg4(), size, false);
11146 case IF_DV_1A: // DV_1A .........X.iiiii iii........ddddd Vd imm8 (fmov - immediate scalar)
11147 elemsize = id->idOpSize();
11148 emitDispReg(id->idReg1(), elemsize, true);
11149 emitDispFloatImm(emitGetInsSC(id));
11152 case IF_DV_1B: // DV_1B .QX..........iii cmod..iiiiiddddd Vd imm8 (immediate vector)
11153 imm = emitGetInsSC(id) & 0x0ff;
11154 immShift = (emitGetInsSC(id) & 0x700) >> 8;
11155 hasShift = (immShift != 0);
11156 elemsize = optGetElemsize(id->idInsOpt());
11157 if (id->idInsOpt() == INS_OPTS_1D)
11159 assert(elemsize == size);
11160 emitDispReg(id->idReg1(), size, true);
11164 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11166 if (ins == INS_fmov)
11168 emitDispFloatImm(imm);
11169 assert(hasShift == false);
11173 if (elemsize == EA_8BYTE)
11175 assert(ins == INS_movi);
11177 const ssize_t mask8 = 0xFF;
11178 for (unsigned b = 0; b < 8; b++)
11180 if (imm & (1 << b))
11182 imm64 |= (mask8 << (b * 8));
11185 emitDispImm(imm64, hasShift, true);
11189 emitDispImm(imm, hasShift, true);
11193 insOpts opt = (immShift & 0x4) ? INS_OPTS_MSL : INS_OPTS_LSL;
11194 unsigned shift = (immShift & 0x3) * 8;
11195 emitDispShiftOpts(opt);
11196 emitDispImm(shift, false);
11201 case IF_DV_1C: // DV_1C .........X...... ......nnnnn..... Vn #0.0 (fcmp - with zero)
11202 elemsize = id->idOpSize();
11203 emitDispReg(id->idReg1(), elemsize, true);
11204 emitDispFloatZero();
11207 case IF_DV_2A: // DV_2A .Q.......X...... ......nnnnnddddd Vd Vn (fabs, fcvt - vector)
11208 case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
11209 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11210 emitDispVectorReg(id->idReg2(), id->idInsOpt(), false);
11213 case IF_DV_2N: // DV_2N .........iiiiiii ......nnnnnddddd Vd Vn imm (shift - scalar)
11214 elemsize = id->idOpSize();
11215 emitDispReg(id->idReg1(), elemsize, true);
11216 emitDispReg(id->idReg2(), elemsize, true);
11217 emitDispImm(emitGetInsSC(id), false);
11220 case IF_DV_2O: // DV_2O .Q.......iiiiiii ......nnnnnddddd Vd Vn imm (shift - vector)
11221 imm = emitGetInsSC(id);
11222 // Do we have a sxtl or uxtl instruction?
11223 isExtendAlias = ((ins == INS_sxtl) || (ins == INS_sxtl2) || (ins == INS_uxtl) || (ins == INS_uxtl2));
11224 code = emitInsCode(ins, fmt);
11225 if (code & 0x00008000) // widen/narrow opcodes
11227 if (code & 0x00002000) // SHL opcodes
11229 emitDispVectorReg(id->idReg1(), optWidenElemsize(id->idInsOpt()), true);
11230 emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11232 else // SHR opcodes
11234 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11235 emitDispVectorReg(id->idReg2(), optWidenElemsize(id->idInsOpt()), !isExtendAlias);
11240 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11241 emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11243 // Print the immediate unless we have a sxtl or uxtl instruction
11244 if (!isExtendAlias)
11246 emitDispImm(imm, false);
11250 case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov/smov - to general)
11251 srcsize = id->idOpSize();
11252 index = emitGetInsSC(id);
11253 if (ins == INS_smov)
11255 dstsize = EA_8BYTE;
11257 else // INS_umov or INS_mov
11259 dstsize = (srcsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE;
11261 emitDispReg(id->idReg1(), dstsize, true);
11262 emitDispVectorRegIndex(id->idReg2(), srcsize, index, false);
11265 case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
11266 if (ins == INS_dup)
11268 datasize = id->idOpSize();
11269 assert(isValidVectorDatasize(datasize));
11270 assert(isValidArrangement(datasize, id->idInsOpt()));
11271 elemsize = optGetElemsize(id->idInsOpt());
11272 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11276 elemsize = id->idOpSize();
11277 index = emitGetInsSC(id);
11278 assert(isValidVectorElemsize(elemsize));
11279 emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11281 emitDispReg(id->idReg2(), (elemsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE, false);
11284 case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
11285 datasize = id->idOpSize();
11286 assert(isValidVectorDatasize(datasize));
11287 assert(isValidArrangement(datasize, id->idInsOpt()));
11288 elemsize = optGetElemsize(id->idInsOpt());
11289 index = emitGetInsSC(id);
11290 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11291 emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11294 case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
11295 elemsize = id->idOpSize();
11296 index = emitGetInsSC(id);
11297 emitDispReg(id->idReg1(), elemsize, true);
11298 emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11301 case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
11302 imm = emitGetInsSC(id);
11303 index = (imm >> 4) & 0xf;
11304 index2 = imm & 0xf;
11305 elemsize = id->idOpSize();
11306 emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11307 emitDispVectorRegIndex(id->idReg2(), elemsize, index2, false);
11310 case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov, fcvtXX - register)
11311 case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
11312 case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
11313 elemsize = id->idOpSize();
11314 emitDispReg(id->idReg1(), elemsize, true);
11315 emitDispReg(id->idReg2(), elemsize, false);
11318 case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov, fcvtXX - to general)
11319 case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov, Xcvtf - from general)
11320 case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
11321 dstsize = optGetDstsize(id->idInsOpt());
11322 srcsize = optGetSrcsize(id->idInsOpt());
11324 emitDispReg(id->idReg1(), dstsize, true);
11325 emitDispReg(id->idReg2(), srcsize, false);
11328 case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11329 case IF_DV_3B: // DV_3B .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11330 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11331 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11332 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11335 case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11336 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11337 if (ins != INS_mov)
11339 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11341 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11344 case IF_DV_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
11345 case IF_DV_3BI: // DV_3BI .Q........Lmmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
11346 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11347 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11348 elemsize = optGetElemsize(id->idInsOpt());
11349 emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11352 case IF_DV_3D: // DV_3D .........X.mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
11353 case IF_DV_3E: // DV_3E ...........mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
11354 emitDispReg(id->idReg1(), size, true);
11355 emitDispReg(id->idReg2(), size, true);
11356 emitDispReg(id->idReg3(), size, false);
11359 case IF_DV_3DI: // DV_3DI .........XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (scalar by elem)
11360 emitDispReg(id->idReg1(), size, true);
11361 emitDispReg(id->idReg2(), size, true);
11363 emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11366 case IF_DV_4A: // DV_4A .........X.mmmmm .aaaaannnnnddddd Vd Va Vn Vm (scalar)
11367 emitDispReg(id->idReg1(), size, true);
11368 emitDispReg(id->idReg2(), size, true);
11369 emitDispReg(id->idReg3(), size, true);
11370 emitDispReg(id->idReg4(), size, false);
11373 case IF_SN_0A: // SN_0A ................ ................
11376 case IF_SI_0A: // SI_0A ...........iiiii iiiiiiiiiii..... imm16
11377 emitDispImm(emitGetInsSC(id), false);
11380 case IF_SI_0B: // SI_0B ................ ....bbbb........ imm4 - barrier
11381 emitDispBarrier((insBarrier)emitGetInsSC(id));
11385 printf("unexpected format %s", emitIfName(id->idInsFmt()));
11386 assert(!"unexpectedFormat");
11390 if (id->idDebugOnlyInfo()->idVarRefOffs)
11393 emitDispFrameRef(id->idAddr()->iiaLclVar.lvaVarNum(), id->idAddr()->iiaLclVar.lvaOffset(),
11394 id->idDebugOnlyInfo()->idVarRefOffs, asmfm);
11400 /*****************************************************************************
11402 * Display a stack frame reference.
11405 void emitter::emitDispFrameRef(int varx, int disp, int offs, bool asmfm)
11410 printf("TEMP_%02u", -varx);
11412 emitComp->gtDispLclVar(+varx, false);
11415 printf("-0x%02x", -disp);
11417 printf("+0x%02x", +disp);
11421 if (varx >= 0 && emitComp->opts.varNames)
11424 const char* varName;
11426 assert((unsigned)varx < emitComp->lvaCount);
11427 varDsc = emitComp->lvaTable + varx;
11428 varName = emitComp->compLocalVarName(varx, offs);
11432 printf("'%s", varName);
11435 printf("-%d", -disp);
11437 printf("+%d", +disp);
11446 // Generate code for a load or store operation with a potentially complex addressing mode
11447 // This method handles the case of a GT_IND with contained GT_LEA op1 of the x86 form [base + index*sccale + offset]
11448 // Since Arm64 does not directly support this complex of an addressing mode
11449 // we may generates up to three instructions for this for Arm64
11451 void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataReg, GenTreeIndir* indir)
11453 emitAttr ldstAttr = isVectorRegister(dataReg) ? attr : emitInsAdjustLoadStoreAttr(ins, attr);
11455 GenTree* addr = indir->Addr();
11457 if (addr->isContained())
11459 assert(addr->OperGet() == GT_LCL_VAR_ADDR || addr->OperGet() == GT_LEA);
11464 if (addr->OperGet() == GT_LEA)
11466 offset = addr->AsAddrMode()->Offset();
11467 if (addr->AsAddrMode()->gtScale > 0)
11469 assert(isPow2(addr->AsAddrMode()->gtScale));
11470 BitScanForward(&lsl, addr->AsAddrMode()->gtScale);
11474 GenTree* memBase = indir->Base();
11476 if (indir->HasIndex())
11478 GenTree* index = indir->Index();
11482 regNumber tmpReg = indir->GetSingleTempReg();
11484 emitAttr addType = varTypeIsGC(memBase) ? EA_BYREF : EA_PTRSIZE;
11486 if (emitIns_valid_imm_for_add(offset, EA_8BYTE))
11490 // Generate code to set tmpReg = base + index*scale
11491 emitIns_R_R_R_I(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum, lsl,
11496 // Generate code to set tmpReg = base + index
11497 emitIns_R_R_R(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum);
11500 noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11502 // Then load/store dataReg from/to [tmpReg + offset]
11503 emitIns_R_R_I(ins, ldstAttr, dataReg, tmpReg, offset);
11505 else // large offset
11507 // First load/store tmpReg with the large offset constant
11508 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11509 // Then add the base register
11511 emitIns_R_R_R(INS_add, addType, tmpReg, tmpReg, memBase->gtRegNum);
11513 noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11514 noway_assert(tmpReg != index->gtRegNum);
11516 // Then load/store dataReg from/to [tmpReg + index*scale]
11517 emitIns_R_R_R_I(ins, ldstAttr, dataReg, tmpReg, index->gtRegNum, lsl, INS_OPTS_LSL);
11520 else // (offset == 0)
11524 // Then load/store dataReg from/to [memBase + index*scale]
11525 emitIns_R_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum, lsl, INS_OPTS_LSL);
11529 // Then load/store dataReg from/to [memBase + index]
11530 emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum);
11534 else // no Index register
11536 if (emitIns_valid_imm_for_ldst_offset(offset, EA_SIZE(attr)))
11538 // Then load/store dataReg from/to [memBase + offset]
11539 emitIns_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, offset);
11543 // We require a tmpReg to hold the offset
11544 regNumber tmpReg = indir->GetSingleTempReg();
11546 // First load/store tmpReg with the large offset constant
11547 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11549 // Then load/store dataReg from/to [memBase + tmpReg]
11550 emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, tmpReg);
11554 else // addr is not contained, so we evaluate it into a register
11556 // Then load/store dataReg from/to [addrReg]
11557 emitIns_R_R(ins, ldstAttr, dataReg, addr->gtRegNum);
11561 // The callee must call genConsumeReg() for any non-contained srcs
11562 // and genProduceReg() for any non-contained dsts.
11564 regNumber emitter::emitInsBinary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src)
11566 regNumber result = REG_NA;
11568 // dst can only be a reg
11569 assert(!dst->isContained());
11571 // src can be immed or reg
11572 assert(!src->isContained() || src->isContainedIntOrIImmed());
11574 // find immed (if any) - it cannot be a dst
11575 GenTreeIntConCommon* intConst = nullptr;
11576 if (src->isContainedIntOrIImmed())
11578 intConst = src->AsIntConCommon();
11583 emitIns_R_I(ins, attr, dst->gtRegNum, intConst->IconValue());
11584 return dst->gtRegNum;
11588 emitIns_R_R(ins, attr, dst->gtRegNum, src->gtRegNum);
11589 return dst->gtRegNum;
11593 // The callee must call genConsumeReg() for any non-contained srcs
11594 // and genProduceReg() for any non-contained dsts.
11596 regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src1, GenTree* src2)
11598 regNumber result = REG_NA;
11600 // dst can only be a reg
11601 assert(!dst->isContained());
11603 // find immed (if any) - it cannot be a dst
11604 // Only one src can be an int.
11605 GenTreeIntConCommon* intConst = nullptr;
11606 GenTree* nonIntReg = nullptr;
11608 if (varTypeIsFloating(dst))
11610 // src1 can only be a reg
11611 assert(!src1->isContained());
11612 // src2 can only be a reg
11613 assert(!src2->isContained());
11615 else // not floating point
11617 // src2 can be immed or reg
11618 assert(!src2->isContained() || src2->isContainedIntOrIImmed());
11620 // Check src2 first as we can always allow it to be a contained immediate
11621 if (src2->isContainedIntOrIImmed())
11623 intConst = src2->AsIntConCommon();
11626 // Only for commutative operations do we check src1 and allow it to be a contained immediate
11627 else if (dst->OperIsCommutative())
11629 // src1 can be immed or reg
11630 assert(!src1->isContained() || src1->isContainedIntOrIImmed());
11632 // Check src1 and allow it to be a contained immediate
11633 if (src1->isContainedIntOrIImmed())
11635 assert(!src2->isContainedIntOrIImmed());
11636 intConst = src1->AsIntConCommon();
11642 // src1 can only be a reg
11643 assert(!src1->isContained());
11647 bool isMulOverflow = false;
11648 if (dst->gtOverflowEx())
11650 if ((ins == INS_add) || (ins == INS_adds))
11654 else if ((ins == INS_sub) || (ins == INS_subs))
11658 else if (ins == INS_mul)
11660 isMulOverflow = true;
11661 assert(intConst == nullptr); // overflow format doesn't support an int constant operand
11665 assert(!"Invalid ins for overflow check");
11668 if (intConst != nullptr)
11670 emitIns_R_R_I(ins, attr, dst->gtRegNum, nonIntReg->gtRegNum, intConst->IconValue());
11676 regNumber extraReg = dst->GetSingleTempReg();
11677 assert(extraReg != dst->gtRegNum);
11679 if ((dst->gtFlags & GTF_UNSIGNED) != 0)
11681 if (attr == EA_4BYTE)
11683 // Compute 8 byte results from 4 byte by 4 byte multiplication.
11684 emitIns_R_R_R(INS_umull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11686 // Get the high result by shifting dst.
11687 emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11691 assert(attr == EA_8BYTE);
11692 // Compute the high result.
11693 emitIns_R_R_R(INS_umulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11695 // Now multiply without skewing the high result.
11696 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11699 // zero-sign bit comparison to detect overflow.
11700 emitIns_R_I(INS_cmp, attr, extraReg, 0);
11705 if (attr == EA_4BYTE)
11707 // Compute 8 byte results from 4 byte by 4 byte multiplication.
11708 emitIns_R_R_R(INS_smull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11710 // Get the high result by shifting dst.
11711 emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11717 assert(attr == EA_8BYTE);
11718 // Save the high result in a temporary register.
11719 emitIns_R_R_R(INS_smulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11721 // Now multiply without skewing the high result.
11722 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11727 // Sign bit comparison to detect overflow.
11728 emitIns_R_R_I(INS_cmp, attr, extraReg, dst->gtRegNum, bitShift, INS_OPTS_ASR);
11733 // We can just multiply.
11734 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11738 if (dst->gtOverflowEx())
11740 assert(!varTypeIsFloating(dst));
11741 codeGen->genCheckOverflow(dst);
11744 return dst->gtRegNum;
11747 #endif // defined(_TARGET_ARM64_)