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 case IF_DV_2P: // DV_2P ................ ......nnnnnddddd Vd Vn (aes*)
552 assert(isValidVectorDatasize(id->idOpSize()));
553 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
554 assert(isVectorRegister(id->idReg1()));
555 assert(isVectorRegister(id->idReg2()));
558 case IF_DV_2N: // DV_2N .........iiiiiii ......nnnnnddddd Vd Vn imm (shift - scalar)
559 assert(id->idOpSize() == EA_8BYTE);
560 assert(insOptsNone(id->idInsOpt()));
561 assert(isVectorRegister(id->idReg1()));
562 assert(isVectorRegister(id->idReg2()));
563 assert(isValidImmShift(emitGetInsSC(id), EA_8BYTE));
566 case IF_DV_2O: // DV_2O .Q.......iiiiiii ......nnnnnddddd Vd Vn imm (shift - vector)
567 assert(isValidVectorDatasize(id->idOpSize()));
568 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
569 assert(isVectorRegister(id->idReg1()));
570 assert(isVectorRegister(id->idReg2()));
571 elemsize = optGetElemsize(id->idInsOpt());
572 assert(isValidImmShift(emitGetInsSC(id), elemsize));
575 case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov/smov - to general)
576 elemsize = id->idOpSize();
577 index = emitGetInsSC(id);
578 assert(insOptsNone(id->idInsOpt()));
579 assert(isValidVectorIndex(EA_16BYTE, elemsize, index));
580 assert(isValidVectorElemsize(elemsize));
581 assert(isGeneralRegister(id->idReg1()));
582 assert(isVectorRegister(id->idReg2()));
585 case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
586 if (id->idIns() == INS_dup)
588 datasize = id->idOpSize();
589 assert(isValidVectorDatasize(datasize));
590 assert(isValidArrangement(datasize, id->idInsOpt()));
591 elemsize = optGetElemsize(id->idInsOpt());
595 datasize = EA_16BYTE;
596 elemsize = id->idOpSize();
597 assert(isValidVectorElemsize(elemsize));
599 assert(isVectorRegister(id->idReg1()));
600 assert(isGeneralRegisterOrZR(id->idReg2()));
603 case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
604 datasize = id->idOpSize();
605 assert(isValidVectorDatasize(datasize));
606 assert(isValidArrangement(datasize, id->idInsOpt()));
607 elemsize = optGetElemsize(id->idInsOpt());
608 index = emitGetInsSC(id);
609 assert(isValidVectorIndex(datasize, elemsize, index));
610 assert(isVectorRegister(id->idReg1()));
611 assert(isVectorRegister(id->idReg2()));
614 case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
615 elemsize = id->idOpSize();
616 index = emitGetInsSC(id);
617 assert(isValidVectorIndex(EA_16BYTE, elemsize, index));
618 assert(isValidVectorElemsize(elemsize));
619 assert(isVectorRegister(id->idReg1()));
620 assert(isVectorRegister(id->idReg2()));
623 case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
624 imm = emitGetInsSC(id);
625 index = (imm >> 4) & 0xf;
627 elemsize = id->idOpSize();
628 assert(isValidVectorElemsize(elemsize));
629 assert(isValidVectorIndex(EA_16BYTE, elemsize, index));
630 assert(isValidVectorIndex(EA_16BYTE, elemsize, index2));
631 assert(isVectorRegister(id->idReg1()));
632 assert(isVectorRegister(id->idReg2()));
635 case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
636 assert(id->idOpSize() == EA_8BYTE); // only type D is supported
639 case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov, fcvtXX - register)
640 case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
641 assert(insOptsNone(id->idInsOpt()));
642 assert(isValidVectorElemsizeFloat(id->idOpSize()));
643 assert(isVectorRegister(id->idReg1()));
644 assert(isVectorRegister(id->idReg2()));
647 case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov/fcvtXX - to general)
648 assert(insOptsConvertFloatToInt(id->idInsOpt()));
649 dstsize = optGetDstsize(id->idInsOpt());
650 srcsize = optGetSrcsize(id->idInsOpt());
651 assert(isValidGeneralDatasize(dstsize));
652 assert(isValidVectorElemsizeFloat(srcsize));
653 assert(dstsize == id->idOpSize());
654 assert(isGeneralRegister(id->idReg1()));
655 assert(isVectorRegister(id->idReg2()));
658 case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov/Xcvtf - from general)
659 assert(insOptsConvertIntToFloat(id->idInsOpt()));
660 dstsize = optGetDstsize(id->idInsOpt());
661 srcsize = optGetSrcsize(id->idInsOpt());
662 assert(isValidGeneralDatasize(srcsize));
663 assert(isValidVectorElemsizeFloat(dstsize));
664 assert(dstsize == id->idOpSize());
665 assert(isVectorRegister(id->idReg1()));
666 assert(isGeneralRegister(id->idReg2()));
669 case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
670 assert(insOptsConvertFloatToFloat(id->idInsOpt()));
671 dstsize = optGetDstsize(id->idInsOpt());
672 srcsize = optGetSrcsize(id->idInsOpt());
673 assert(isValidVectorFcvtsize(srcsize));
674 assert(isValidVectorFcvtsize(dstsize));
675 assert(dstsize == id->idOpSize());
676 assert(isVectorRegister(id->idReg1()));
677 assert(isVectorRegister(id->idReg2()));
680 case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
681 assert(isValidVectorDatasize(id->idOpSize()));
682 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
683 assert(isVectorRegister(id->idReg1()));
684 assert(isVectorRegister(id->idReg2()));
685 assert(isVectorRegister(id->idReg3()));
686 elemsize = optGetElemsize(id->idInsOpt());
690 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
692 else if (ins == INS_pmul)
694 assert(elemsize == EA_1BYTE); // only supports 8B or 16B
698 case IF_DV_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
699 assert(isValidVectorDatasize(id->idOpSize()));
700 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
701 assert(isVectorRegister(id->idReg1()));
702 assert(isVectorRegister(id->idReg2()));
703 assert(isVectorRegister(id->idReg3()));
704 elemsize = optGetElemsize(id->idInsOpt());
705 assert(isValidVectorIndex(EA_16BYTE, elemsize, emitGetInsSC(id)));
706 // Only has encodings for H or S elemsize
707 assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE));
710 case IF_DV_3B: // DV_3B .Q.......X.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
711 assert(isValidVectorDatasize(id->idOpSize()));
712 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
713 assert(isVectorRegister(id->idReg1()));
714 assert(isVectorRegister(id->idReg2()));
715 assert(isVectorRegister(id->idReg3()));
718 case IF_DV_3BI: // DV_3BI .Q.......XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
719 assert(isValidVectorDatasize(id->idOpSize()));
720 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
721 assert(isVectorRegister(id->idReg1()));
722 assert(isVectorRegister(id->idReg2()));
723 assert(isVectorRegister(id->idReg3()));
724 elemsize = optGetElemsize(id->idInsOpt());
725 assert(isValidVectorIndex(id->idOpSize(), elemsize, emitGetInsSC(id)));
728 case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
729 assert(isValidVectorDatasize(id->idOpSize()));
730 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
731 assert(isVectorRegister(id->idReg1()));
732 assert(isVectorRegister(id->idReg2()));
733 assert(isVectorRegister(id->idReg3()));
736 case IF_DV_3D: // DV_3D .........X.mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
737 assert(isValidScalarDatasize(id->idOpSize()));
738 assert(insOptsNone(id->idInsOpt()));
739 assert(isVectorRegister(id->idReg1()));
740 assert(isVectorRegister(id->idReg2()));
741 assert(isVectorRegister(id->idReg3()));
744 case IF_DV_3DI: // DV_3DI .........XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (scalar by elem)
745 assert(isValidScalarDatasize(id->idOpSize()));
746 assert(insOptsNone(id->idInsOpt()));
747 assert(isVectorRegister(id->idReg1()));
748 assert(isVectorRegister(id->idReg2()));
749 assert(isVectorRegister(id->idReg3()));
750 elemsize = id->idOpSize();
751 assert(isValidVectorIndex(EA_16BYTE, elemsize, emitGetInsSC(id)));
754 case IF_DV_3E: // DV_3E ...........mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
755 assert(insOptsNone(id->idInsOpt()));
756 assert(id->idOpSize() == EA_8BYTE);
757 assert(isVectorRegister(id->idReg1()));
758 assert(isVectorRegister(id->idReg2()));
759 assert(isVectorRegister(id->idReg3()));
762 case IF_DV_4A: // DR_4A .........X.mmmmm .aaaaannnnnddddd Rd Rn Rm Ra (scalar)
763 assert(isValidGeneralDatasize(id->idOpSize()));
764 assert(isVectorRegister(id->idReg1()));
765 assert(isVectorRegister(id->idReg2()));
766 assert(isVectorRegister(id->idReg3()));
767 assert(isVectorRegister(id->idReg4()));
770 case IF_SN_0A: // SN_0A ................ ................
771 case IF_SI_0A: // SI_0A ...........iiiii iiiiiiiiiii..... imm16
772 case IF_SI_0B: // SI_0B ................ ....bbbb........ imm4 - barrier
776 printf("unexpected format %s\n", emitIfName(id->idInsFmt()));
777 assert(!"Unexpected format");
783 bool emitter::emitInsMayWriteToGCReg(instrDesc* id)
785 instruction ins = id->idIns();
786 insFormat fmt = id->idInsFmt();
791 // These are the formats with "destination" registers:
793 case IF_DI_1B: // DI_1B X........hwiiiii iiiiiiiiiiiddddd Rd imm(i16,hw)
794 case IF_DI_1D: // DI_1D X........Nrrrrrr ssssss.....ddddd Rd imm(N,r,s)
795 case IF_DI_1E: // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
797 case IF_DI_2A: // DI_2A X.......shiiiiii iiiiiinnnnnddddd Rd Rn imm(i12,sh)
798 case IF_DI_2B: // DI_2B X.........Xnnnnn ssssssnnnnnddddd Rd Rn imm(0-63)
799 case IF_DI_2C: // DI_2C X........Nrrrrrr ssssssnnnnnddddd Rd Rn imm(N,r,s)
800 case IF_DI_2D: // DI_2D X........Nrrrrrr ssssssnnnnnddddd Rd Rn imr, imms (N,r,s)
802 case IF_DR_1D: // DR_1D X............... cccc.......ddddd Rd cond
804 case IF_DR_2D: // DR_2D X..........nnnnn cccc..nnnnnddddd Rd Rn cond
805 case IF_DR_2E: // DR_2E X..........mmmmm ...........ddddd Rd Rm
806 case IF_DR_2F: // DR_2F X.......sh.mmmmm ssssss.....ddddd Rd Rm {LSL,LSR,ASR} imm(0-63)
807 case IF_DR_2G: // DR_2G X............... ......nnnnnddddd Rd Rn
808 case IF_DR_2H: // DR_2H X........X...... ......nnnnnddddd Rd Rn
810 case IF_DR_3A: // DR_3A X..........mmmmm ......nnnnnddddd Rd Rn Rm
811 case IF_DR_3B: // DR_3B X.......sh.mmmmm ssssssnnnnnddddd Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
812 case IF_DR_3C: // DR_3C X..........mmmmm xxxsssnnnnnddddd Rd Rn Rm ext(Rm) LSL imm(0-4)
813 case IF_DR_3D: // DR_3D X..........mmmmm cccc..nnnnnddddd Rd Rn Rm cond
814 case IF_DR_3E: // DR_3E X........X.mmmmm ssssssnnnnnddddd Rd Rn Rm imm(0-63)
816 case IF_DR_4A: // DR_4A X..........mmmmm .aaaaannnnnddddd Rd Rn Rm Ra
818 case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov - to general)
819 case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov - to general)
823 case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
824 case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
825 case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
826 case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
827 case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov, fcvtXX - register)
828 case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov - from general)
829 case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
830 case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
831 case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
832 case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
833 case IF_DV_2P: // DV_2P ................ ......nnnnnddddd Vd Vn (aes*) - Vd both source and dest
834 case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
835 case IF_DV_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector)
836 case IF_DV_3B: // DV_3B .Q.......X.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
837 case IF_DV_3BI: // DV_3BI .Q.......XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
838 case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
839 case IF_DV_3D: // DV_3D .........X.mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
840 case IF_DV_3DI: // DV_3DI .........XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (scalar by elem)
841 case IF_DV_3E: // DV_3E ...........mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
842 case IF_DV_4A: // DV_4A .........X.mmmmm .aaaaannnnnddddd Vd Va Vn Vm (scalar)
843 // Tracked GC pointers cannot be placed into the SIMD registers.
846 // These are the load/store formats with "target" registers:
848 case IF_LS_1A: // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB)
849 case IF_LS_2A: // LS_2A .X.......X...... ......nnnnnttttt Rt Rn
850 case IF_LS_2B: // LS_2B .X.......Xiiiiii iiiiiinnnnnttttt Rt Rn imm(0-4095)
851 case IF_LS_2C: // LS_2C .X.......X.iiiii iiiiP.nnnnnttttt Rt Rn imm(-256..+255) pre/post inc
852 case IF_LS_3A: // LS_3A .X.......X.mmmmm xxxS..nnnnnttttt Rt Rn Rm ext(Rm) LSL {}
853 case IF_LS_3B: // LS_3B X............... .aaaaannnnnttttt Rt Ra Rn
854 case IF_LS_3C: // LS_3C X.........iiiiii iaaaaannnnnttttt Rt Ra Rn imm(im7,sh)
855 case IF_LS_3D: // LS_3D .X.......X.mmmmm ......nnnnnttttt Wm Rt Rn
857 // For the Store instructions the "target" register is actually a "source" value
859 if (emitInsIsStore(ins))
865 assert(emitInsIsLoad(ins));
874 bool emitter::emitInsWritesToLclVarStackLoc(instrDesc* id)
876 if (!id->idIsLclVar())
879 instruction ins = id->idIns();
881 // This list is related to the list of instructions used to store local vars in emitIns_S_R().
882 // We don't accept writing to float local vars.
898 bool emitter::emitInsWritesToLclVarStackLocPair(instrDesc* id)
900 if (!id->idIsLclVar())
903 instruction ins = id->idIns();
905 // This list is related to the list of instructions used to store local vars in emitIns_S_S_R_R().
906 // We don't accept writing to float local vars.
918 bool emitter::emitInsMayWriteMultipleRegs(instrDesc* id)
920 instruction ins = id->idIns();
933 // For the small loads/store instruction we adjust the size 'attr'
934 // depending upon whether we have a load or a store
936 emitAttr emitter::emitInsAdjustLoadStoreAttr(instruction ins, emitAttr attr)
938 if (EA_SIZE(attr) <= EA_4BYTE)
940 if (emitInsIsLoad(ins))
942 // The value of 'ins' encodes the size to load
943 // we use EA_8BYTE here because it is the size we will write (into dataReg)
944 // it is also required when ins is INS_ldrsw
950 assert(emitInsIsStore(ins));
952 // The value of 'ins' encodes the size to store
953 // we use EA_4BYTE here because it is the size of the register
954 // that we want to display when storing small values
962 // Takes an instrDesc 'id' and uses the instruction 'ins' to determine the
963 // size of the target register that is written or read by the instruction.
964 // Note that even if EA_4BYTE is returned a load instruction will still
965 // always zero the upper 4 bytes of the target register.
966 // This method is required so that we can distinguish between loads that are
967 // sign-extending as they can have two different sizes for their target register.
968 // Additionally for instructions like 'ldr' and 'str' these can load/store
969 // either 4 byte or 8 bytes to/from the target register.
970 // By convention the small unsigned load instructions are considered to write
971 // a 4 byte sized target register, though since these also zero the upper 4 bytes
972 // they could equally be considered to write the unsigned value to full 8 byte register.
974 emitAttr emitter::emitInsTargetRegSize(instrDesc* id)
976 instruction ins = id->idIns();
977 emitAttr result = EA_UNKNOWN;
979 // This is used to determine the size of the target registers for a load/store instruction
1013 if (id->idOpSize() == EA_8BYTE)
1029 result = id->idOpSize();
1042 result = id->idOpSize();
1046 NO_WAY("unexpected instruction");
1052 // Takes an instrDesc and uses the instruction to determine the 'size' of the
1053 // data that is loaded from memory.
1055 emitAttr emitter::emitInsLoadStoreSize(instrDesc* id)
1057 instruction ins = id->idIns();
1058 emitAttr result = EA_UNKNOWN;
1060 // The 'result' returned is the 'size' of the data that is loaded from memory.
1096 result = id->idOpSize();
1105 result = id->idOpSize();
1109 NO_WAY("unexpected instruction");
1115 /*****************************************************************************/
1119 static const char * const xRegNames[] =
1121 #define REGDEF(name, rnum, mask, xname, wname) xname,
1122 #include "register.h"
1125 static const char * const wRegNames[] =
1127 #define REGDEF(name, rnum, mask, xname, wname) wname,
1128 #include "register.h"
1131 static const char * const vRegNames[] =
1133 "v0", "v1", "v2", "v3", "v4",
1134 "v5", "v6", "v7", "v8", "v9",
1135 "v10", "v11", "v12", "v13", "v14",
1136 "v15", "v16", "v17", "v18", "v19",
1137 "v20", "v21", "v22", "v23", "v24",
1138 "v25", "v26", "v27", "v28", "v29",
1142 static const char * const qRegNames[] =
1144 "q0", "q1", "q2", "q3", "q4",
1145 "q5", "q6", "q7", "q8", "q9",
1146 "q10", "q11", "q12", "q13", "q14",
1147 "q15", "q16", "q17", "q18", "q19",
1148 "q20", "q21", "q22", "q23", "q24",
1149 "q25", "q26", "q27", "q28", "q29",
1153 static const char * const hRegNames[] =
1155 "h0", "h1", "h2", "h3", "h4",
1156 "h5", "h6", "h7", "h8", "h9",
1157 "h10", "h11", "h12", "h13", "h14",
1158 "h15", "h16", "h17", "h18", "h19",
1159 "h20", "h21", "h22", "h23", "h24",
1160 "h25", "h26", "h27", "h28", "h29",
1163 static const char * const bRegNames[] =
1165 "b0", "b1", "b2", "b3", "b4",
1166 "b5", "b6", "b7", "b8", "b9",
1167 "b10", "b11", "b12", "b13", "b14",
1168 "b15", "b16", "b17", "b18", "b19",
1169 "b20", "b21", "b22", "b23", "b24",
1170 "b25", "b26", "b27", "b28", "b29",
1175 /*****************************************************************************
1177 * Return a string that represents the given register.
1180 const char* emitter::emitRegName(regNumber reg, emitAttr size, bool varName)
1182 assert(reg < REG_COUNT);
1184 const char* rn = nullptr;
1186 if (size == EA_8BYTE)
1188 rn = xRegNames[reg];
1190 else if (size == EA_4BYTE)
1192 rn = wRegNames[reg];
1194 else if (isVectorRegister(reg))
1196 if (size == EA_16BYTE)
1198 rn = qRegNames[reg - REG_V0];
1200 else if (size == EA_2BYTE)
1202 rn = hRegNames[reg - REG_V0];
1204 else if (size == EA_1BYTE)
1206 rn = bRegNames[reg - REG_V0];
1210 assert(rn != nullptr);
1215 /*****************************************************************************
1217 * Return a string that represents the given register.
1220 const char* emitter::emitVectorRegName(regNumber reg)
1222 assert((reg >= REG_V0) && (reg <= REG_V31));
1224 int index = (int)reg - (int)REG_V0;
1226 return vRegNames[index];
1230 /*****************************************************************************
1232 * Returns the base encoding of the given CPU instruction.
1235 emitter::insFormat emitter::emitInsFormat(instruction ins)
1238 const static insFormat insFormats[] =
1240 #define INST1(id, nm, fp, ldst, fmt, e1 ) fmt,
1241 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) fmt,
1242 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) fmt,
1243 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) fmt,
1244 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) fmt,
1245 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) fmt,
1246 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) fmt,
1251 assert(ins < ArrLen(insFormats));
1252 assert((insFormats[ins] != IF_NONE));
1254 return insFormats[ins];
1263 /*static*/ const BYTE CodeGenInterface::instInfo[] =
1265 #define INST1(id, nm, fp, ldst, fmt, e1 ) ldst | INST_FP*fp,
1266 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) ldst | INST_FP*fp,
1267 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) ldst | INST_FP*fp,
1268 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) ldst | INST_FP*fp,
1269 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) ldst | INST_FP*fp,
1270 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) ldst | INST_FP*fp,
1271 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) ldst | INST_FP*fp,
1276 /*****************************************************************************
1278 * Returns true if the instruction is some kind of compare or test instruction
1281 bool emitter::emitInsIsCompare(instruction ins)
1283 // We have pseudo ins like lea which are not included in emitInsLdStTab.
1284 if (ins < ArrLen(CodeGenInterface::instInfo))
1285 return (CodeGenInterface::instInfo[ins] & CMP) ? true : false;
1290 /*****************************************************************************
1292 * Returns true if the instruction is some kind of load instruction
1295 bool emitter::emitInsIsLoad(instruction ins)
1297 // We have pseudo ins like lea which are not included in emitInsLdStTab.
1298 if (ins < ArrLen(CodeGenInterface::instInfo))
1299 return (CodeGenInterface::instInfo[ins] & LD) ? true : false;
1303 /*****************************************************************************
1305 * Returns true if the instruction is some kind of store instruction
1308 bool emitter::emitInsIsStore(instruction ins)
1310 // We have pseudo ins like lea which are not included in emitInsLdStTab.
1311 if (ins < ArrLen(CodeGenInterface::instInfo))
1312 return (CodeGenInterface::instInfo[ins] & ST) ? true : false;
1317 /*****************************************************************************
1319 * Returns true if the instruction is some kind of load/store instruction
1322 bool emitter::emitInsIsLoadOrStore(instruction ins)
1324 // We have pseudo ins like lea which are not included in emitInsLdStTab.
1325 if (ins < ArrLen(CodeGenInterface::instInfo))
1326 return (CodeGenInterface::instInfo[ins] & (LD | ST)) ? true : false;
1335 /*****************************************************************************
1337 * Returns the specific encoding of the given CPU instruction and format
1340 emitter::code_t emitter::emitInsCode(instruction ins, insFormat fmt)
1343 const static code_t insCodes1[] =
1345 #define INST1(id, nm, fp, ldst, fmt, e1 ) e1,
1346 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) e1,
1347 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) e1,
1348 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e1,
1349 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e1,
1350 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e1,
1351 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e1,
1354 const static code_t insCodes2[] =
1356 #define INST1(id, nm, fp, ldst, fmt, e1 )
1357 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) e2,
1358 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) e2,
1359 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e2,
1360 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e2,
1361 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e2,
1362 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e2,
1365 const static code_t insCodes3[] =
1367 #define INST1(id, nm, fp, ldst, fmt, e1 )
1368 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1369 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) e3,
1370 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e3,
1371 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e3,
1372 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e3,
1373 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e3,
1376 const static code_t insCodes4[] =
1378 #define INST1(id, nm, fp, ldst, fmt, e1 )
1379 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1380 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
1381 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e4,
1382 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e4,
1383 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e4,
1384 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e4,
1387 const static code_t insCodes5[] =
1389 #define INST1(id, nm, fp, ldst, fmt, e1 )
1390 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1391 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
1392 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
1393 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e5,
1394 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e5,
1395 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e5,
1398 const static code_t insCodes6[] =
1400 #define INST1(id, nm, fp, ldst, fmt, e1 )
1401 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1402 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
1403 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
1404 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
1405 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e6,
1406 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e6,
1409 const static code_t insCodes7[] =
1411 #define INST1(id, nm, fp, ldst, fmt, e1 )
1412 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1413 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
1414 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
1415 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
1416 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 )
1417 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e7,
1420 const static code_t insCodes8[] =
1422 #define INST1(id, nm, fp, ldst, fmt, e1 )
1423 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1424 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
1425 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
1426 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
1427 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 )
1428 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e8,
1431 const static code_t insCodes9[] =
1433 #define INST1(id, nm, fp, ldst, fmt, e1 )
1434 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1435 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
1436 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
1437 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
1438 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 )
1439 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e9,
1444 const static insFormat formatEncode9[9] = {IF_DR_2E, IF_DR_2G, IF_DI_1B, IF_DI_1D, IF_DV_3C,
1445 IF_DV_2B, IF_DV_2C, IF_DV_2E, IF_DV_2F};
1446 const static insFormat formatEncode6A[6] = {IF_DR_3A, IF_DR_3B, IF_DR_3C, IF_DI_2A, IF_DV_3A, IF_DV_3E};
1447 const static insFormat formatEncode5A[5] = {IF_LS_2A, IF_LS_2B, IF_LS_2C, IF_LS_3A, IF_LS_1A};
1448 const static insFormat formatEncode5B[5] = {IF_DV_2G, IF_DV_2H, IF_DV_2I, IF_DV_1A, IF_DV_1B};
1449 const static insFormat formatEncode5C[5] = {IF_DR_3A, IF_DR_3B, IF_DI_2C, IF_DV_3C, IF_DV_1B};
1450 const static insFormat formatEncode4A[4] = {IF_LS_2A, IF_LS_2B, IF_LS_2C, IF_LS_3A};
1451 const static insFormat formatEncode4B[4] = {IF_DR_3A, IF_DR_3B, IF_DR_3C, IF_DI_2A};
1452 const static insFormat formatEncode4C[4] = {IF_DR_2A, IF_DR_2B, IF_DR_2C, IF_DI_1A};
1453 const static insFormat formatEncode4D[4] = {IF_DV_3B, IF_DV_3D, IF_DV_3BI, IF_DV_3DI};
1454 const static insFormat formatEncode4E[4] = {IF_DR_3A, IF_DR_3B, IF_DI_2C, IF_DV_3C};
1455 const static insFormat formatEncode4F[4] = {IF_DR_3A, IF_DR_3B, IF_DV_3C, IF_DV_1B};
1456 const static insFormat formatEncode4G[4] = {IF_DR_2E, IF_DR_2F, IF_DV_2M, IF_DV_2L};
1457 const static insFormat formatEncode4H[4] = {IF_DV_3E, IF_DV_3A, IF_DV_2L, IF_DV_2M};
1458 const static insFormat formatEncode4I[4] = {IF_DV_3D, IF_DV_3B, IF_DV_2G, IF_DV_2A};
1459 const static insFormat formatEncode3A[3] = {IF_DR_3A, IF_DR_3B, IF_DI_2C};
1460 const static insFormat formatEncode3B[3] = {IF_DR_2A, IF_DR_2B, IF_DI_1C};
1461 const static insFormat formatEncode3C[3] = {IF_DR_3A, IF_DR_3B, IF_DV_3C};
1462 const static insFormat formatEncode3D[3] = {IF_DV_2C, IF_DV_2D, IF_DV_2E};
1463 const static insFormat formatEncode3E[3] = {IF_DV_3B, IF_DV_3BI, IF_DV_3DI};
1464 const static insFormat formatEncode3F[3] = {IF_DV_2A, IF_DV_2G, IF_DV_2H};
1465 const static insFormat formatEncode3G[3] = {IF_DV_2A, IF_DV_2G, IF_DV_2I};
1466 const static insFormat formatEncode3H[3] = {IF_DR_3A, IF_DV_3A, IF_DV_3AI};
1467 const static insFormat formatEncode3I[3] = {IF_DR_2E, IF_DR_2F, IF_DV_2M};
1468 const static insFormat formatEncode2A[2] = {IF_DR_2E, IF_DR_2F};
1469 const static insFormat formatEncode2B[2] = {IF_DR_3A, IF_DR_3B};
1470 const static insFormat formatEncode2C[2] = {IF_DR_3A, IF_DI_2D};
1471 const static insFormat formatEncode2D[2] = {IF_DR_3A, IF_DI_2B};
1472 const static insFormat formatEncode2E[2] = {IF_LS_3B, IF_LS_3C};
1473 const static insFormat formatEncode2F[2] = {IF_DR_2I, IF_DI_1F};
1474 const static insFormat formatEncode2G[2] = {IF_DV_3B, IF_DV_3D};
1475 const static insFormat formatEncode2H[2] = {IF_DV_2C, IF_DV_2F};
1476 const static insFormat formatEncode2I[2] = {IF_DV_2K, IF_DV_1C};
1477 const static insFormat formatEncode2J[2] = {IF_DV_2A, IF_DV_2G};
1478 const static insFormat formatEncode2K[2] = {IF_DV_2M, IF_DV_2L};
1479 const static insFormat formatEncode2L[2] = {IF_DV_2G, IF_DV_2M};
1480 const static insFormat formatEncode2M[2] = {IF_DV_3A, IF_DV_3AI};
1481 const static insFormat formatEncode2N[2] = {IF_DV_2N, IF_DV_2O};
1482 const static insFormat formatEncode2O[2] = {IF_DV_3E, IF_DV_3A};
1483 const static insFormat formatEncode2P[2] = {IF_DV_2G, IF_DV_3B};
1485 code_t code = BAD_CODE;
1486 insFormat insFmt = emitInsFormat(ins);
1487 bool encoding_found = false;
1493 for (index = 0; index < 9; index++)
1495 if (fmt == formatEncode9[index])
1497 encoding_found = true;
1504 for (index = 0; index < 6; index++)
1506 if (fmt == formatEncode6A[index])
1508 encoding_found = true;
1515 for (index = 0; index < 5; index++)
1517 if (fmt == formatEncode5A[index])
1519 encoding_found = true;
1526 for (index = 0; index < 5; index++)
1528 if (fmt == formatEncode5B[index])
1530 encoding_found = true;
1537 for (index = 0; index < 5; index++)
1539 if (fmt == formatEncode5C[index])
1541 encoding_found = true;
1548 for (index = 0; index < 4; index++)
1550 if (fmt == formatEncode4A[index])
1552 encoding_found = true;
1559 for (index = 0; index < 4; index++)
1561 if (fmt == formatEncode4B[index])
1563 encoding_found = true;
1570 for (index = 0; index < 4; index++)
1572 if (fmt == formatEncode4C[index])
1574 encoding_found = true;
1581 for (index = 0; index < 4; index++)
1583 if (fmt == formatEncode4D[index])
1585 encoding_found = true;
1592 for (index = 0; index < 4; index++)
1594 if (fmt == formatEncode4E[index])
1596 encoding_found = true;
1603 for (index = 0; index < 4; index++)
1605 if (fmt == formatEncode4F[index])
1607 encoding_found = true;
1614 for (index = 0; index < 4; index++)
1616 if (fmt == formatEncode4G[index])
1618 encoding_found = true;
1625 for (index = 0; index < 4; index++)
1627 if (fmt == formatEncode4H[index])
1629 encoding_found = true;
1636 for (index = 0; index < 4; index++)
1638 if (fmt == formatEncode4I[index])
1640 encoding_found = true;
1647 for (index = 0; index < 3; index++)
1649 if (fmt == formatEncode3A[index])
1651 encoding_found = true;
1658 for (index = 0; index < 3; index++)
1660 if (fmt == formatEncode3B[index])
1662 encoding_found = true;
1669 for (index = 0; index < 3; index++)
1671 if (fmt == formatEncode3C[index])
1673 encoding_found = true;
1680 for (index = 0; index < 3; index++)
1682 if (fmt == formatEncode3D[index])
1684 encoding_found = true;
1691 for (index = 0; index < 3; index++)
1693 if (fmt == formatEncode3E[index])
1695 encoding_found = true;
1702 for (index = 0; index < 3; index++)
1704 if (fmt == formatEncode3F[index])
1706 encoding_found = true;
1713 for (index = 0; index < 3; index++)
1715 if (fmt == formatEncode3G[index])
1717 encoding_found = true;
1724 for (index = 0; index < 3; index++)
1726 if (fmt == formatEncode3H[index])
1728 encoding_found = true;
1735 for (index = 0; index < 3; index++)
1737 if (fmt == formatEncode3I[index])
1739 encoding_found = true;
1746 for (index = 0; index < 2; index++)
1748 if (fmt == formatEncode2A[index])
1750 encoding_found = true;
1757 for (index = 0; index < 2; index++)
1759 if (fmt == formatEncode2B[index])
1761 encoding_found = true;
1768 for (index = 0; index < 2; index++)
1770 if (fmt == formatEncode2C[index])
1772 encoding_found = true;
1779 for (index = 0; index < 2; index++)
1781 if (fmt == formatEncode2D[index])
1783 encoding_found = true;
1790 for (index = 0; index < 2; index++)
1792 if (fmt == formatEncode2E[index])
1794 encoding_found = true;
1801 for (index = 0; index < 2; index++)
1803 if (fmt == formatEncode2F[index])
1805 encoding_found = true;
1812 for (index = 0; index < 2; index++)
1814 if (fmt == formatEncode2G[index])
1816 encoding_found = true;
1823 for (index = 0; index < 2; index++)
1825 if (fmt == formatEncode2H[index])
1827 encoding_found = true;
1834 for (index = 0; index < 2; index++)
1836 if (fmt == formatEncode2I[index])
1838 encoding_found = true;
1845 for (index = 0; index < 2; index++)
1847 if (fmt == formatEncode2J[index])
1849 encoding_found = true;
1856 for (index = 0; index < 2; index++)
1858 if (fmt == formatEncode2K[index])
1860 encoding_found = true;
1867 for (index = 0; index < 2; index++)
1869 if (fmt == formatEncode2L[index])
1871 encoding_found = true;
1878 for (index = 0; index < 2; index++)
1880 if (fmt == formatEncode2M[index])
1882 encoding_found = true;
1889 for (index = 0; index < 2; index++)
1891 if (fmt == formatEncode2N[index])
1893 encoding_found = true;
1900 for (index = 0; index < 2; index++)
1902 if (fmt == formatEncode2O[index])
1904 encoding_found = true;
1911 for (index = 0; index < 2; index++)
1913 if (fmt == formatEncode2P[index])
1915 encoding_found = true;
1995 encoding_found = true;
2000 encoding_found = false;
2004 assert(encoding_found);
2009 assert(ins < ArrLen(insCodes1));
2010 code = insCodes1[ins];
2013 assert(ins < ArrLen(insCodes2));
2014 code = insCodes2[ins];
2017 assert(ins < ArrLen(insCodes3));
2018 code = insCodes3[ins];
2021 assert(ins < ArrLen(insCodes4));
2022 code = insCodes4[ins];
2025 assert(ins < ArrLen(insCodes5));
2026 code = insCodes5[ins];
2029 assert(ins < ArrLen(insCodes6));
2030 code = insCodes6[ins];
2033 assert(ins < ArrLen(insCodes7));
2034 code = insCodes7[ins];
2037 assert(ins < ArrLen(insCodes8));
2038 code = insCodes8[ins];
2041 assert(ins < ArrLen(insCodes9));
2042 code = insCodes9[ins];
2046 assert((code != BAD_CODE));
2051 // true if this 'imm' can be encoded as a input operand to a mov instruction
2052 /*static*/ bool emitter::emitIns_valid_imm_for_mov(INT64 imm, emitAttr size)
2054 // Check for "MOV (wide immediate)".
2055 if (canEncodeHalfwordImm(imm, size))
2058 // Next try the ones-complement form of 'halfword immediate' imm(i16,hw),
2059 // namely "MOV (inverted wide immediate)".
2060 ssize_t notOfImm = NOT_helper(imm, getBitWidth(size));
2061 if (canEncodeHalfwordImm(notOfImm, size))
2064 // Finally try "MOV (bitmask immediate)" imm(N,r,s)
2065 if (canEncodeBitMaskImm(imm, size))
2071 // true if this 'imm' can be encoded as a input operand to a vector movi instruction
2072 /*static*/ bool emitter::emitIns_valid_imm_for_movi(INT64 imm, emitAttr elemsize)
2074 if (elemsize == EA_8BYTE)
2079 INT64 loByte = uimm & 0xFF;
2080 if ((loByte == 0) || (loByte == 0xFF))
2094 // First try the standard 'byteShifted immediate' imm(i8,bySh)
2095 if (canEncodeByteShiftedImm(imm, elemsize, true))
2098 // Next try the ones-complement form of the 'immediate' imm(i8,bySh)
2099 ssize_t notOfImm = NOT_helper(imm, getBitWidth(elemsize));
2100 if (canEncodeByteShiftedImm(notOfImm, elemsize, true))
2106 // true if this 'imm' can be encoded as a input operand to a fmov instruction
2107 /*static*/ bool emitter::emitIns_valid_imm_for_fmov(double immDbl)
2109 if (canEncodeFloatImm8(immDbl))
2115 // true if this 'imm' can be encoded as a input operand to an add instruction
2116 /*static*/ bool emitter::emitIns_valid_imm_for_add(INT64 imm, emitAttr size)
2118 if (unsigned_abs(imm) <= 0x0fff)
2120 else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
2126 // true if this 'imm' can be encoded as a input operand to an non-add/sub alu instruction
2127 /*static*/ bool emitter::emitIns_valid_imm_for_cmp(INT64 imm, emitAttr size)
2129 return emitIns_valid_imm_for_add(imm, size);
2132 // true if this 'imm' can be encoded as a input operand to an non-add/sub alu instruction
2133 /*static*/ bool emitter::emitIns_valid_imm_for_alu(INT64 imm, emitAttr size)
2135 if (canEncodeBitMaskImm(imm, size))
2141 // true if this 'imm' can be encoded as the offset in a ldr/str instruction
2142 /*static*/ bool emitter::emitIns_valid_imm_for_ldst_offset(INT64 imm, emitAttr attr)
2145 return true; // Encodable using IF_LS_2A
2147 if ((imm >= -256) && (imm <= 255))
2148 return true; // Encodable using IF_LS_2C (or possibly IF_LS_2B)
2151 return false; // not encodable
2153 emitAttr size = EA_SIZE(attr);
2154 unsigned scale = NaturalScale_helper(size);
2155 ssize_t mask = size - 1; // the mask of low bits that must be zero to encode the immediate
2157 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
2158 return true; // Encodable using IF_LS_2B
2160 return false; // not encodable
2163 /************************************************************************
2165 * A helper method to return the natural scale for an EA 'size'
2168 /*static*/ unsigned emitter::NaturalScale_helper(emitAttr size)
2170 assert(size == EA_1BYTE || size == EA_2BYTE || size == EA_4BYTE || size == EA_8BYTE || size == EA_16BYTE);
2172 unsigned result = 0;
2173 unsigned utemp = (unsigned)size;
2175 // Compute log base 2 of utemp (aka 'size')
2185 /************************************************************************
2187 * A helper method to perform a Rotate-Right shift operation
2188 * the source is 'value' and it is rotated right by 'sh' bits
2189 * 'value' is considered to be a fixed size 'width' set of bits.
2192 * value is '00001111', sh is 2 and width is 8
2193 * result is '11000011'
2196 /*static*/ UINT64 emitter::ROR_helper(UINT64 value, unsigned sh, unsigned width)
2198 assert(width <= 64);
2199 // Check that 'value' fits in 'width' bits
2200 assert((width == 64) || (value < (1ULL << width)));
2201 // We don't support shifts >= width
2207 unsigned lsh = width - rsh;
2209 result = (value >> rsh);
2210 result |= (value << lsh);
2214 // mask off any extra bits that we got from the left shift
2215 result &= ((1ULL << width) - 1);
2219 /************************************************************************
2221 * A helper method to perform a 'NOT' bitwise complement operation.
2222 * 'value' is considered to be a fixed size 'width' set of bits.
2225 * value is '01001011', and width is 8
2226 * result is '10110100'
2229 /*static*/ UINT64 emitter::NOT_helper(UINT64 value, unsigned width)
2231 assert(width <= 64);
2233 UINT64 result = ~value;
2237 // Check that 'value' fits in 'width' bits. Don't consider "sign" bits above width.
2238 UINT64 maxVal = 1ULL << width;
2239 UINT64 lowBitsMask = maxVal - 1;
2240 UINT64 signBitsMask = ~lowBitsMask | (1ULL << (width - 1)); // The high bits must be set, and the top bit
2241 // (sign bit) must be set.
2242 assert((value < maxVal) || ((value & signBitsMask) == signBitsMask));
2244 // mask off any extra bits that we got from the complement operation
2245 result &= lowBitsMask;
2251 /************************************************************************
2253 * A helper method to perform a bit Replicate operation
2254 * the source is 'value' with a fixed size 'width' set of bits.
2255 * value is replicated to fill out 32 or 64 bits as determined by 'size'.
2258 * value is '11000011' (0xE3), width is 8 and size is EA_8BYTE
2259 * result is '11000011 11000011 11000011 11000011 11000011 11000011 11000011 11000011'
2260 * 0xE3E3E3E3E3E3E3E3
2263 /*static*/ UINT64 emitter::Replicate_helper(UINT64 value, unsigned width, emitAttr size)
2265 assert(emitter::isValidGeneralDatasize(size));
2267 unsigned immWidth = (size == EA_8BYTE) ? 64 : 32;
2268 assert(width <= immWidth);
2270 UINT64 result = value;
2271 unsigned filledBits = width;
2273 while (filledBits < immWidth)
2277 filledBits += width;
2282 /************************************************************************
2284 * Convert an imm(N,r,s) into a 64-bit immediate
2285 * inputs 'bmImm' a bitMaskImm struct
2286 * 'size' specifies the size of the result (64 or 32 bits)
2289 /*static*/ INT64 emitter::emitDecodeBitMaskImm(const emitter::bitMaskImm bmImm, emitAttr size)
2291 assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2293 unsigned N = bmImm.immN; // read the N,R and S values from the 'bitMaskImm' encoding
2294 unsigned R = bmImm.immR;
2295 unsigned S = bmImm.immS;
2297 unsigned elemWidth = 64; // used when immN == 1
2299 if (bmImm.immN == 0) // find the smaller elemWidth when immN == 0
2301 // Scan S for the highest bit not set
2303 for (unsigned bitNum = 5; bitNum > 0; bitNum--)
2305 unsigned oneBit = elemWidth;
2306 if ((S & oneBit) == 0)
2313 assert(size == EA_8BYTE);
2316 unsigned maskSR = elemWidth - 1;
2321 // encoding for S is one less than the number of consecutive one bits
2322 S++; // Number of consecutive ones to generate in 'welem'
2326 // 'elemWidth' is the number of bits that we will use for the ROR and Replicate operations
2327 // 'S' is the number of consecutive 1 bits for the immediate
2328 // 'R' is the number of bits that we will Rotate Right the immediate
2329 // 'size' selects the final size of the immedate that we return (64 or 32 bits)
2331 assert(S < elemWidth); // 'elemWidth' consecutive one's is a reserved encoding
2336 welem = (1ULL << S) - 1;
2338 wmask = ROR_helper(welem, R, elemWidth);
2339 wmask = Replicate_helper(wmask, elemWidth, size);
2344 /*****************************************************************************
2346 * Check if an immediate can use the left shifted by 12 bits encoding
2349 /*static*/ bool emitter::canEncodeWithShiftImmBy12(INT64 imm)
2353 imm = -imm; // convert to unsigned
2358 return false; // Must be MIN_INT64
2361 if ((imm & 0xfff) != 0) // Now the low 12 bits all have to be zero
2366 imm >>= 12; // shift right by 12 bits
2368 return (imm <= 0x0fff); // Does it fit in 12 bits
2371 /*****************************************************************************
2373 * Normalize the 'imm' so that the upper bits, as defined by 'size' are zero
2376 /*static*/ INT64 emitter::normalizeImm64(INT64 imm, emitAttr size)
2378 unsigned immWidth = getBitWidth(size);
2383 // Check that 'imm' fits in 'immWidth' bits. Don't consider "sign" bits above width.
2384 INT64 maxVal = 1LL << immWidth;
2385 INT64 lowBitsMask = maxVal - 1;
2386 INT64 hiBitsMask = ~lowBitsMask;
2387 INT64 signBitsMask =
2388 hiBitsMask | (1LL << (immWidth - 1)); // The high bits must be set, and the top bit (sign bit) must be set.
2389 assert((imm < maxVal) || ((imm & signBitsMask) == signBitsMask));
2391 // mask off the hiBits
2392 result &= lowBitsMask;
2397 /*****************************************************************************
2399 * Normalize the 'imm' so that the upper bits, as defined by 'size' are zero
2402 /*static*/ INT32 emitter::normalizeImm32(INT32 imm, emitAttr size)
2404 unsigned immWidth = getBitWidth(size);
2409 // Check that 'imm' fits in 'immWidth' bits. Don't consider "sign" bits above width.
2410 INT32 maxVal = 1 << immWidth;
2411 INT32 lowBitsMask = maxVal - 1;
2412 INT32 hiBitsMask = ~lowBitsMask;
2413 INT32 signBitsMask = hiBitsMask | (1 << (immWidth - 1)); // The high bits must be set, and the top bit
2414 // (sign bit) must be set.
2415 assert((imm < maxVal) || ((imm & signBitsMask) == signBitsMask));
2417 // mask off the hiBits
2418 result &= lowBitsMask;
2423 /************************************************************************
2425 * returns true if 'imm' of 'size bits (32/64) can be encoded
2426 * using the ARM64 'bitmask immediate' form.
2427 * When a non-null value is passed for 'wbBMI' then this method
2428 * writes back the 'N','S' and 'R' values use to encode this immediate
2432 /*static*/ bool emitter::canEncodeBitMaskImm(INT64 imm, emitAttr size, emitter::bitMaskImm* wbBMI)
2434 assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2436 unsigned immWidth = (size == EA_8BYTE) ? 64 : 32;
2437 unsigned maxLen = (size == EA_8BYTE) ? 6 : 5;
2439 imm = normalizeImm64(imm, size);
2441 // Starting with len=1, elemWidth is 2 bits
2442 // len=2, elemWidth is 4 bits
2443 // len=3, elemWidth is 8 bits
2444 // len=4, elemWidth is 16 bits
2445 // len=5, elemWidth is 32 bits
2446 // (optionally) len=6, elemWidth is 64 bits
2448 for (unsigned len = 1; (len <= maxLen); len++)
2450 unsigned elemWidth = 1 << len;
2451 UINT64 elemMask = ((UINT64)-1) >> (64 - elemWidth);
2452 UINT64 tempImm = (UINT64)imm; // A working copy of 'imm' that we can mutate
2453 UINT64 elemVal = tempImm & elemMask; // The low 'elemWidth' bits of 'imm'
2455 // Check for all 1's or 0's as these can't be encoded
2456 if ((elemVal == 0) || (elemVal == elemMask))
2459 // 'checkedBits' is the count of bits that are known to match 'elemVal' when replicated
2460 unsigned checkedBits = elemWidth; // by definition the first 'elemWidth' bits match
2462 // Now check to see if each of the next bits match...
2464 while (checkedBits < immWidth)
2466 tempImm >>= elemWidth;
2468 UINT64 nextElem = tempImm & elemMask;
2469 if (nextElem != elemVal)
2471 // Not matching, exit this loop and checkedBits will not be equal to immWidth
2475 // The 'nextElem' is matching, so increment 'checkedBits'
2476 checkedBits += elemWidth;
2479 // Did the full immediate contain bits that can be formed by repeating 'elemVal'?
2480 if (checkedBits == immWidth)
2482 // We are not quite done, since the only values that we can encode as a
2483 // 'bitmask immediate' are those that can be formed by starting with a
2484 // bit string of 0*1* that is rotated by some number of bits.
2486 // We check to see if 'elemVal' can be formed using these restrictions.
2489 // Rotating by one bit any value that passes these restrictions
2490 // can be xor-ed with the original value and will result it a string
2491 // of bits that have exactly two 1 bits: 'elemRorXor'
2492 // Further the distance between the two one bits tells us the value
2493 // of S and the location of the 1 bits tells us the value of R
2495 // Some examples: (immWidth is 8)
2497 // S=4,R=0 S=5,R=3 S=3,R=6
2498 // elemVal: 00001111 11100011 00011100
2499 // elemRor: 10000111 11110001 00001110
2500 // elemRorXor: 10001000 00010010 00010010
2501 // compute S 45678--- ---5678- ---3210-
2502 // compute R 01234567 ---34567 ------67
2504 UINT64 elemRor = ROR_helper(elemVal, 1, elemWidth); // Rotate 'elemVal' Right by one bit
2505 UINT64 elemRorXor = elemVal ^ elemRor; // Xor elemVal and elemRor
2507 // If we only have a two-bit change in elemROR then we can form a mask for this value
2508 unsigned bitCount = 0;
2509 UINT64 oneBit = 0x1;
2510 unsigned R = elemWidth; // R is shift count for ROR (rotate right shift)
2511 unsigned S = 0; // S is number of consecutive one bits
2514 // Loop over the 'elemWidth' bits in 'elemRorXor'
2516 for (unsigned bitNum = 0; bitNum < elemWidth; bitNum++)
2520 R--; // We decrement R by one whenever incr is -1
2524 S += incr; // We incr/decr S, after we find the first one bit in 'elemRorXor'
2527 // Is this bit position a 1 bit in 'elemRorXor'?
2529 if (oneBit & elemRorXor)
2532 // Is this the first 1 bit that we found in 'elemRorXor'?
2535 // Does this 1 bit represent a transition to zero bits?
2536 bool toZeros = ((oneBit & elemVal) != 0);
2539 // S :: Count down from elemWidth
2543 else // this 1 bit represent a transition to one bits.
2545 // S :: Count up from zero
2550 else // bitCount > 1
2552 // We found the second (or third...) 1 bit in 'elemRorXor'
2553 incr = 0; // stop decrementing 'R'
2557 // More than 2 transitions from 0/1 in 'elemVal'
2558 // This means that 'elemVal' can't be encoded
2559 // using a 'bitmask immediate'.
2561 // Furthermore, it will continue to fail
2562 // with any larger 'len' that we try.
2563 // so just return false.
2570 // shift oneBit left by one bit to test the next position
2574 // We expect that bitCount will always be two at this point
2575 // but just in case return false for any bad cases.
2577 assert(bitCount == 2);
2581 // Perform some sanity checks on the values of 'S' and 'R'
2583 assert(S < elemWidth);
2584 assert(R < elemWidth);
2586 // Does the caller want us to return the N,R,S encoding values?
2588 if (wbBMI != nullptr)
2591 // The encoding used for S is one less than the
2592 // number of consecutive one bits
2602 // The encoding used for 'S' here is a bit peculiar.
2604 // The upper bits need to be complemented, followed by a zero bit
2605 // then the value of 'S-1'
2607 unsigned upperBitsOfS = 64 - (1 << (len + 1));
2613 // Verify that what we are returning is correct.
2614 assert(imm == emitDecodeBitMaskImm(*wbBMI, size));
2616 // Tell the caller that we can successfully encode this immediate
2617 // using a 'bitmask immediate'.
2625 /************************************************************************
2627 * Convert a 64-bit immediate into its 'bitmask immediate' representation imm(N,r,s)
2630 /*static*/ emitter::bitMaskImm emitter::emitEncodeBitMaskImm(INT64 imm, emitAttr size)
2632 emitter::bitMaskImm result;
2635 bool canEncode = canEncodeBitMaskImm(imm, size, &result);
2641 /************************************************************************
2643 * Convert an imm(i16,hw) into a 32/64-bit immediate
2644 * inputs 'hwImm' a halfwordImm struct
2645 * 'size' specifies the size of the result (64 or 32 bits)
2648 /*static*/ INT64 emitter::emitDecodeHalfwordImm(const emitter::halfwordImm hwImm, emitAttr size)
2650 assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2652 unsigned hw = hwImm.immHW;
2653 INT64 val = (INT64)hwImm.immVal;
2655 assert((hw <= 1) || (size == EA_8BYTE));
2657 INT64 result = val << (16 * hw);
2661 /************************************************************************
2663 * returns true if 'imm' of 'size' bits (32/64) can be encoded
2664 * using the ARM64 'halfword immediate' form.
2665 * When a non-null value is passed for 'wbHWI' then this method
2666 * writes back the 'immHW' and 'immVal' values use to encode this immediate
2670 /*static*/ bool emitter::canEncodeHalfwordImm(INT64 imm, emitAttr size, emitter::halfwordImm* wbHWI)
2672 assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2674 unsigned immWidth = (size == EA_8BYTE) ? 64 : 32;
2675 unsigned maxHW = (size == EA_8BYTE) ? 4 : 2;
2677 // setup immMask to a (EA_4BYTE) 0x00000000_FFFFFFFF or (EA_8BYTE) 0xFFFFFFFF_FFFFFFFF
2678 const UINT64 immMask = ((UINT64)-1) >> (64 - immWidth);
2679 const INT64 mask16 = (INT64)0xFFFF;
2681 imm = normalizeImm64(imm, size);
2683 // Try each of the valid hw shift sizes
2684 for (unsigned hw = 0; (hw < maxHW); hw++)
2686 INT64 curMask = mask16 << (hw * 16); // Represents the mask of the bits in the current halfword
2687 INT64 checkBits = immMask & ~curMask;
2689 // Excluding the current halfword (using ~curMask)
2690 // does the immediate have zero bits in every other bit that we care about?
2691 // note we care about all 64-bits for EA_8BYTE
2692 // and we care about the lowest 32 bits for EA_4BYTE
2694 if ((imm & checkBits) == 0)
2696 // Does the caller want us to return the imm(i16,hw) encoding values?
2698 if (wbHWI != nullptr)
2700 INT64 val = ((imm & curMask) >> (hw * 16)) & mask16;
2702 wbHWI->immVal = val;
2704 // Verify that what we are returning is correct.
2705 assert(imm == emitDecodeHalfwordImm(*wbHWI, size));
2707 // Tell the caller that we can successfully encode this immediate
2708 // using a 'halfword immediate'.
2716 /************************************************************************
2718 * Convert a 64-bit immediate into its 'halfword immediate' representation imm(i16,hw)
2721 /*static*/ emitter::halfwordImm emitter::emitEncodeHalfwordImm(INT64 imm, emitAttr size)
2723 emitter::halfwordImm result;
2724 result.immHWVal = 0;
2726 bool canEncode = canEncodeHalfwordImm(imm, size, &result);
2732 /************************************************************************
2734 * Convert an imm(i8,sh) into a 16/32-bit immediate
2735 * inputs 'bsImm' a byteShiftedImm struct
2736 * 'size' specifies the size of the result (16 or 32 bits)
2739 /*static*/ INT32 emitter::emitDecodeByteShiftedImm(const emitter::byteShiftedImm bsImm, emitAttr size)
2741 bool onesShift = (bsImm.immOnes == 1);
2742 unsigned bySh = bsImm.immBY; // Num Bytes to shift 0,1,2,3
2743 INT32 val = (INT32)bsImm.immVal; // 8-bit immediate
2748 assert((size == EA_2BYTE) || (size == EA_4BYTE)); // Only EA_2BYTE or EA_4BYTE forms
2749 if (size == EA_2BYTE)
2758 result <<= (8 * bySh);
2762 result |= ((1 << (8 * bySh)) - 1);
2768 /************************************************************************
2770 * returns true if 'imm' of 'size' bits (16/32) can be encoded
2771 * using the ARM64 'byteShifted immediate' form.
2772 * When a non-null value is passed for 'wbBSI' then this method
2773 * writes back the 'immBY' and 'immVal' values use to encode this immediate
2777 /*static*/ bool emitter::canEncodeByteShiftedImm(INT64 imm,
2780 emitter::byteShiftedImm* wbBSI)
2782 bool canEncode = false;
2783 bool onesShift = false; // true if we use the shifting ones variant
2784 unsigned bySh = 0; // number of bytes to shift: 0, 1, 2, 3
2785 unsigned imm8 = 0; // immediate to use in the encoding
2787 imm = normalizeImm64(imm, size);
2789 if (size == EA_1BYTE)
2791 imm8 = (unsigned)imm;
2792 assert(imm8 < 0x100);
2795 else if (size == EA_8BYTE)
2797 imm8 = (unsigned)imm;
2798 assert(imm8 < 0x100);
2803 assert((size == EA_2BYTE) || (size == EA_4BYTE)); // Only EA_2BYTE or EA_4BYTE forms
2805 unsigned immWidth = (size == EA_4BYTE) ? 32 : 16;
2806 unsigned maxBY = (size == EA_4BYTE) ? 4 : 2;
2808 // setup immMask to a (EA_2BYTE) 0x0000FFFF or (EA_4BYTE) 0xFFFFFFFF
2809 const UINT32 immMask = ((UINT32)-1) >> (32 - immWidth);
2810 const INT32 mask8 = (INT32)0xFF;
2812 // Try each of the valid by shift sizes
2813 for (bySh = 0; (bySh < maxBY); bySh++)
2815 INT32 curMask = mask8 << (bySh * 8); // Represents the mask of the bits in the current byteShifted
2816 INT32 checkBits = immMask & ~curMask;
2817 INT32 immCheck = (imm & checkBits);
2819 // Excluding the current byte (using ~curMask)
2820 // does the immediate have zero bits in every other bit that we care about?
2821 // or can be use the shifted one variant?
2822 // note we care about all 32-bits for EA_4BYTE
2823 // and we care about the lowest 16 bits for EA_2BYTE
2831 if ((bySh == 1) && (immCheck == 0xFF))
2836 else if ((bySh == 2) && (immCheck == 0xFFFF))
2844 imm8 = (unsigned)(((imm & curMask) >> (bySh * 8)) & mask8);
2852 // Does the caller want us to return the imm(i8,bySh) encoding values?
2854 if (wbBSI != nullptr)
2856 wbBSI->immOnes = onesShift;
2857 wbBSI->immBY = bySh;
2858 wbBSI->immVal = imm8;
2860 // Verify that what we are returning is correct.
2861 assert(imm == emitDecodeByteShiftedImm(*wbBSI, size));
2863 // Tell the caller that we can successfully encode this immediate
2864 // using a 'byteShifted immediate'.
2871 /************************************************************************
2873 * Convert a 32-bit immediate into its 'byteShifted immediate' representation imm(i8,by)
2876 /*static*/ emitter::byteShiftedImm emitter::emitEncodeByteShiftedImm(INT64 imm, emitAttr size, bool allow_MSL)
2878 emitter::byteShiftedImm result;
2879 result.immBSVal = 0;
2881 bool canEncode = canEncodeByteShiftedImm(imm, size, allow_MSL, &result);
2887 /************************************************************************
2889 * Convert a 'float 8-bit immediate' into a double.
2890 * inputs 'fpImm' a floatImm8 struct
2893 /*static*/ double emitter::emitDecodeFloatImm8(const emitter::floatImm8 fpImm)
2895 unsigned sign = fpImm.immSign;
2896 unsigned exp = fpImm.immExp ^ 0x4;
2897 unsigned mant = fpImm.immMant + 16;
2898 unsigned scale = 16 * 8;
2906 double result = ((double)mant) / ((double)scale);
2915 /************************************************************************
2917 * returns true if the 'immDbl' can be encoded using the 'float 8-bit immediate' form.
2918 * also returns the encoding if wbFPI is non-null
2922 /*static*/ bool emitter::canEncodeFloatImm8(double immDbl, emitter::floatImm8* wbFPI)
2924 bool canEncode = false;
2925 double val = immDbl;
2935 while ((val < 1.0) && (exp >= -4))
2940 while ((val >= 2.0) && (exp <= 5))
2947 int ival = (int)val;
2949 if ((exp >= 0) && (exp <= 7))
2951 if (val == (double)ival)
2955 if (wbFPI != nullptr)
2958 assert((ival >= 0) && (ival <= 15));
2960 wbFPI->immSign = sign;
2961 wbFPI->immExp = exp ^ 0x4;
2962 wbFPI->immMant = ival;
2963 unsigned imm8 = wbFPI->immFPIVal;
2964 assert((imm8 >= 0) && (imm8 <= 0xff));
2972 /************************************************************************
2974 * Convert a double into its 'float 8-bit immediate' representation
2977 /*static*/ emitter::floatImm8 emitter::emitEncodeFloatImm8(double immDbl)
2979 emitter::floatImm8 result;
2980 result.immFPIVal = 0;
2982 bool canEncode = canEncodeFloatImm8(immDbl, &result);
2988 /*****************************************************************************
2990 * For the given 'ins' returns the reverse instruction
2991 * if one exists, otherwise returns INS_INVALID
2994 /*static*/ instruction emitter::insReverse(instruction ins)
3023 /*****************************************************************************
3025 * For the given 'datasize' and 'elemsize', make the proper arrangement option
3026 * returns the insOpts that specifies the vector register arrangement
3027 * if one does not exist returns INS_OPTS_NONE
3030 /*static*/ insOpts emitter::optMakeArrangement(emitAttr datasize, emitAttr elemsize)
3032 insOpts result = INS_OPTS_NONE;
3034 if (datasize == EA_8BYTE)
3039 result = INS_OPTS_8B;
3042 result = INS_OPTS_4H;
3045 result = INS_OPTS_2S;
3048 result = INS_OPTS_1D;
3055 else if (datasize == EA_16BYTE)
3060 result = INS_OPTS_16B;
3063 result = INS_OPTS_8H;
3066 result = INS_OPTS_4S;
3069 result = INS_OPTS_2D;
3079 /*****************************************************************************
3081 * For the given 'datasize' and arrangement 'opts'
3082 * returns true is the pair spcifies a valid arrangement
3084 /*static*/ bool emitter::isValidArrangement(emitAttr datasize, insOpts opt)
3086 if (datasize == EA_8BYTE)
3088 if ((opt == INS_OPTS_8B) || (opt == INS_OPTS_4H) || (opt == INS_OPTS_2S) || (opt == INS_OPTS_1D))
3093 else if (datasize == EA_16BYTE)
3095 if ((opt == INS_OPTS_16B) || (opt == INS_OPTS_8H) || (opt == INS_OPTS_4S) || (opt == INS_OPTS_2D))
3103 // For the given 'arrangement' returns the 'datasize' specified by the vector register arrangement
3104 // asserts and returns EA_UNKNOWN if an invalid 'arrangement' value is passed
3106 /*static*/ emitAttr emitter::optGetDatasize(insOpts arrangement)
3108 if ((arrangement == INS_OPTS_8B) || (arrangement == INS_OPTS_4H) || (arrangement == INS_OPTS_2S) ||
3109 (arrangement == INS_OPTS_1D))
3113 else if ((arrangement == INS_OPTS_16B) || (arrangement == INS_OPTS_8H) || (arrangement == INS_OPTS_4S) ||
3114 (arrangement == INS_OPTS_2D))
3120 assert(!" invalid 'arrangement' value");
3125 // For the given 'arrangement' returns the 'elemsize' specified by the vector register arrangement
3126 // asserts and returns EA_UNKNOWN if an invalid 'arrangement' value is passed
3128 /*static*/ emitAttr emitter::optGetElemsize(insOpts arrangement)
3130 if ((arrangement == INS_OPTS_8B) || (arrangement == INS_OPTS_16B))
3134 else if ((arrangement == INS_OPTS_4H) || (arrangement == INS_OPTS_8H))
3138 else if ((arrangement == INS_OPTS_2S) || (arrangement == INS_OPTS_4S))
3142 else if ((arrangement == INS_OPTS_1D) || (arrangement == INS_OPTS_2D))
3148 assert(!" invalid 'arrangement' value");
3153 // For the given 'arrangement' returns the 'widen-arrangement' specified by the vector register arrangement
3154 // asserts and returns INS_OPTS_NONE if an invalid 'arrangement' value is passed
3156 /*static*/ insOpts emitter::optWidenElemsize(insOpts arrangement)
3158 if ((arrangement == INS_OPTS_8B) || (arrangement == INS_OPTS_16B))
3162 else if ((arrangement == INS_OPTS_4H) || (arrangement == INS_OPTS_8H))
3166 else if ((arrangement == INS_OPTS_2S) || (arrangement == INS_OPTS_4S))
3172 assert(!" invalid 'arrangement' value");
3173 return INS_OPTS_NONE;
3177 // For the given 'conversion' returns the 'dstsize' specified by the conversion option
3178 /*static*/ emitAttr emitter::optGetDstsize(insOpts conversion)
3182 case INS_OPTS_S_TO_8BYTE:
3183 case INS_OPTS_D_TO_8BYTE:
3184 case INS_OPTS_4BYTE_TO_D:
3185 case INS_OPTS_8BYTE_TO_D:
3186 case INS_OPTS_S_TO_D:
3187 case INS_OPTS_H_TO_D:
3191 case INS_OPTS_S_TO_4BYTE:
3192 case INS_OPTS_D_TO_4BYTE:
3193 case INS_OPTS_4BYTE_TO_S:
3194 case INS_OPTS_8BYTE_TO_S:
3195 case INS_OPTS_D_TO_S:
3196 case INS_OPTS_H_TO_S:
3200 case INS_OPTS_S_TO_H:
3201 case INS_OPTS_D_TO_H:
3206 assert(!" invalid 'conversion' value");
3211 // For the given 'conversion' returns the 'srcsize' specified by the conversion option
3212 /*static*/ emitAttr emitter::optGetSrcsize(insOpts conversion)
3216 case INS_OPTS_D_TO_8BYTE:
3217 case INS_OPTS_D_TO_4BYTE:
3218 case INS_OPTS_8BYTE_TO_D:
3219 case INS_OPTS_8BYTE_TO_S:
3220 case INS_OPTS_D_TO_S:
3221 case INS_OPTS_D_TO_H:
3225 case INS_OPTS_S_TO_8BYTE:
3226 case INS_OPTS_S_TO_4BYTE:
3227 case INS_OPTS_4BYTE_TO_S:
3228 case INS_OPTS_4BYTE_TO_D:
3229 case INS_OPTS_S_TO_D:
3230 case INS_OPTS_S_TO_H:
3234 case INS_OPTS_H_TO_S:
3235 case INS_OPTS_H_TO_D:
3240 assert(!" invalid 'conversion' value");
3245 // For the given 'size' and 'index' returns true if it specifies a valid index for a vector register of 'size'
3246 /*static*/ bool emitter::isValidVectorIndex(emitAttr datasize, emitAttr elemsize, ssize_t index)
3248 assert(isValidVectorDatasize(datasize));
3249 assert(isValidVectorElemsize(elemsize));
3251 bool result = false;
3254 if (datasize == EA_8BYTE)
3259 result = (index < 8);
3262 result = (index < 4);
3265 result = (index < 2);
3268 result = (index < 1);
3275 else if (datasize == EA_16BYTE)
3280 result = (index < 16);
3283 result = (index < 8);
3286 result = (index < 4);
3289 result = (index < 2);
3300 /*****************************************************************************
3302 * Add an instruction with no operands.
3305 void emitter::emitIns(instruction ins)
3307 instrDesc* id = emitNewInstrSmall(EA_8BYTE);
3308 insFormat fmt = emitInsFormat(ins);
3310 assert(fmt == IF_SN_0A);
3319 /*****************************************************************************
3321 * Add an instruction with a single immediate value.
3324 void emitter::emitIns_I(instruction ins, emitAttr attr, ssize_t imm)
3326 insFormat fmt = IF_NONE;
3328 /* Figure out the encoding format of the instruction */
3332 if ((imm & 0x0000ffff) == imm)
3338 assert(!"Instruction cannot be encoded: IF_SI_0A");
3345 assert(fmt != IF_NONE);
3347 instrDesc* id = emitNewInstrSC(attr, imm);
3356 /*****************************************************************************
3358 * Add an instruction referencing a single register.
3361 void emitter::emitIns_R(instruction ins, emitAttr attr, regNumber reg)
3363 emitAttr size = EA_SIZE(attr);
3364 insFormat fmt = IF_NONE;
3365 instrDesc* id = nullptr;
3367 /* Figure out the encoding format of the instruction */
3372 assert(isGeneralRegister(reg));
3373 id = emitNewInstrSmall(attr);
3382 assert(fmt != IF_NONE);
3391 /*****************************************************************************
3393 * Add an instruction referencing a register and a constant.
3396 void emitter::emitIns_R_I(instruction ins, emitAttr attr, regNumber reg, ssize_t imm, insOpts opt /* = INS_OPTS_NONE */)
3398 emitAttr size = EA_SIZE(attr);
3399 emitAttr elemsize = EA_UNKNOWN;
3400 insFormat fmt = IF_NONE;
3401 bool canEncode = false;
3403 /* Figure out the encoding format of the instruction */
3412 assert(insOptsNone(opt));
3413 assert(isGeneralRegister(reg));
3415 canEncode = canEncodeBitMaskImm(imm, size, &bmi);
3419 assert(isValidImmNRS(imm, size));
3427 assert(isValidGeneralDatasize(size));
3428 assert(insOptsNone(opt)); // No LSL here (you must use emitIns_R_I_I if a shift is needed)
3429 assert(isGeneralRegister(reg));
3430 assert(isValidUimm16(imm));
3434 assert(imm == emitDecodeHalfwordImm(hwi, size));
3442 assert(isValidGeneralDatasize(size));
3443 assert(insOptsNone(opt)); // No explicit LSL here
3444 // We will automatically determine the shift based upon the imm
3446 // First try the standard 'halfword immediate' imm(i16,hw)
3448 canEncode = canEncodeHalfwordImm(imm, size, &hwi);
3451 // uses a movz encoding
3452 assert(isGeneralRegister(reg));
3454 assert(isValidImmHWVal(imm, size));
3459 // Next try the ones-complement form of 'halfword immediate' imm(i16,hw)
3460 notOfImm = NOT_helper(imm, getBitWidth(size));
3461 canEncode = canEncodeHalfwordImm(notOfImm, size, &hwi);
3464 assert(isGeneralRegister(reg));
3466 ins = INS_movn; // uses a movn encoding
3467 assert(isValidImmHWVal(imm, size));
3472 // Finally try the 'bitmask immediate' imm(N,r,s)
3474 canEncode = canEncodeBitMaskImm(imm, size, &bmi);
3477 assert(isGeneralRegisterOrSP(reg));
3478 reg = encodingSPtoZR(reg);
3480 assert(isValidImmNRS(imm, size));
3486 assert(!"Instruction cannot be encoded: mov imm");
3492 assert(isValidVectorDatasize(size));
3493 assert(isVectorRegister(reg));
3494 if (insOptsNone(opt) && (size == EA_8BYTE))
3498 assert(isValidArrangement(size, opt));
3499 elemsize = optGetElemsize(opt);
3501 if (elemsize == EA_8BYTE)
3507 bool failed = false;
3510 INT64 loByte = uimm & 0xFF;
3511 if (((loByte == 0) || (loByte == 0xFF)) && (pos < 8))
3527 assert(isValidUimm8(imm));
3535 // No explicit LSL/MSL is used for the immediate
3536 // We will automatically determine the shift based upon the value of imm
3538 // First try the standard 'byteShifted immediate' imm(i8,bySh)
3540 canEncode = canEncodeByteShiftedImm(imm, elemsize, true, &bsi);
3544 assert(isValidImmBSVal(imm, size));
3549 // Next try the ones-complement form of the 'immediate' imm(i8,bySh)
3550 if ((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE)) // Only EA_2BYTE or EA_4BYTE forms
3552 notOfImm = NOT_helper(imm, getBitWidth(elemsize));
3553 canEncode = canEncodeByteShiftedImm(notOfImm, elemsize, true, &bsi);
3557 ins = INS_mvni; // uses a mvni encoding
3558 assert(isValidImmBSVal(imm, size));
3569 assert(isValidVectorDatasize(size));
3570 assert(isVectorRegister(reg));
3571 assert(isValidArrangement(size, opt));
3572 elemsize = optGetElemsize(opt);
3573 assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE)); // Only EA_2BYTE or EA_4BYTE forms
3577 // No explicit LSL/MSL is used for the immediate
3578 // We will automatically determine the shift based upon the value of imm
3580 // First try the standard 'byteShifted immediate' imm(i8,bySh)
3582 canEncode = canEncodeByteShiftedImm(imm, elemsize,
3583 (ins == INS_mvni), // mvni supports the ones shifting variant (aka MSL)
3588 assert(isValidImmBSVal(imm, size));
3596 assert(insOptsNone(opt));
3597 assert(isGeneralRegister(reg));
3599 if (unsigned_abs(imm) <= 0x0fff)
3603 ins = insReverse(ins);
3606 assert(isValidUimm12(imm));
3610 else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
3612 // Encoding will use a 12-bit left shift of the immediate
3613 opt = INS_OPTS_LSL12;
3616 ins = insReverse(ins);
3619 assert((imm & 0xfff) == 0);
3621 assert(isValidUimm12(imm));
3627 assert(!"Instruction cannot be encoded: IF_DI_1A");
3635 } // end switch (ins)
3638 assert(fmt != IF_NONE);
3640 instrDesc* id = emitNewInstrSC(attr, imm);
3652 /*****************************************************************************
3654 * Add an instruction referencing a register and a floating point constant.
3657 void emitter::emitIns_R_F(
3658 instruction ins, emitAttr attr, regNumber reg, double immDbl, insOpts opt /* = INS_OPTS_NONE */)
3661 emitAttr size = EA_SIZE(attr);
3662 emitAttr elemsize = EA_UNKNOWN;
3663 insFormat fmt = IF_NONE;
3665 bool canEncode = false;
3667 /* Figure out the encoding format of the instruction */
3674 assert(insOptsNone(opt));
3675 assert(isValidVectorElemsizeFloat(size));
3676 assert(isVectorRegister(reg));
3685 assert(isVectorRegister(reg));
3687 canEncode = canEncodeFloatImm8(immDbl, &fpi);
3689 if (insOptsAnyArrangement(opt))
3692 assert(isValidVectorDatasize(size));
3693 assert(isValidArrangement(size, opt));
3694 elemsize = optGetElemsize(opt);
3695 assert(isValidVectorElemsizeFloat(elemsize));
3696 assert(opt != INS_OPTS_1D); // Reserved encoding
3700 imm = fpi.immFPIVal;
3701 assert((imm >= 0) && (imm <= 0xff));
3708 assert(insOptsNone(opt));
3709 assert(isValidVectorElemsizeFloat(size));
3713 imm = fpi.immFPIVal;
3714 assert((imm >= 0) && (imm <= 0xff));
3724 } // end switch (ins)
3727 assert(fmt != IF_NONE);
3729 instrDesc* id = emitNewInstrSC(attr, imm);
3741 /*****************************************************************************
3743 * Add an instruction referencing two registers
3746 void emitter::emitIns_R_R(
3747 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insOpts opt /* = INS_OPTS_NONE */)
3749 emitAttr size = EA_SIZE(attr);
3750 emitAttr elemsize = EA_UNKNOWN;
3751 insFormat fmt = IF_NONE;
3753 /* Figure out the encoding format of the instruction */
3757 assert(insOptsNone(opt));
3758 // Is the mov even necessary?
3761 // A mov with a EA_4BYTE has the side-effect of clearing the upper bits
3762 // So only eliminate mov instructions that are not clearing the upper bits
3764 if (isGeneralRegisterOrSP(reg1) && (size == EA_8BYTE))
3768 else if (isVectorRegister(reg1) && (size == EA_16BYTE))
3774 // Check for the 'mov' aliases for the vector registers
3775 if (isVectorRegister(reg1))
3777 if (isVectorRegister(reg2) && isValidVectorDatasize(size))
3779 return emitIns_R_R_R(INS_mov, size, reg1, reg2, reg2);
3783 return emitIns_R_R_I(INS_mov, size, reg1, reg2, 0);
3788 if (isVectorRegister(reg2))
3790 assert(isGeneralRegister(reg1));
3791 return emitIns_R_R_I(INS_mov, size, reg1, reg2, 0);
3795 // Is this a MOV to/from SP instruction?
3796 if ((reg1 == REG_SP) || (reg2 == REG_SP))
3798 assert(isGeneralRegisterOrSP(reg1));
3799 assert(isGeneralRegisterOrSP(reg2));
3800 reg1 = encodingSPtoZR(reg1);
3801 reg2 = encodingSPtoZR(reg2);
3806 assert(insOptsNone(opt));
3807 assert(isGeneralRegister(reg1));
3808 assert(isGeneralRegisterOrZR(reg2));
3815 assert(insOptsAnyArrangement(opt));
3816 assert(isVectorRegister(reg1));
3817 assert(isGeneralRegisterOrZR(reg2));
3818 assert(isValidVectorDatasize(size));
3819 assert(isValidArrangement(size, opt));
3825 assert(isVectorRegister(reg1));
3826 assert(isVectorRegister(reg2));
3829 assert(isValidVectorDatasize(size));
3830 // Bitwise behavior is independent of element size, but is always encoded as 1 Byte
3831 opt = optMakeArrangement(size, EA_1BYTE);
3833 if (insOptsNone(opt))
3836 assert(size == EA_8BYTE); // Only type D is supported
3842 assert(insOptsAnyArrangement(opt));
3843 assert(isValidVectorDatasize(size));
3844 assert(isValidArrangement(size, opt));
3845 elemsize = optGetElemsize(opt);
3852 if (isVectorRegister(reg1))
3854 assert(isVectorRegister(reg2));
3857 assert(isValidVectorDatasize(size));
3858 // Bitwise behavior is independent of element size, but is always encoded as 1 Byte
3859 opt = optMakeArrangement(size, EA_1BYTE);
3861 if (insOptsNone(opt))
3864 assert(size == EA_8BYTE); // Only type D is supported
3870 assert(isValidVectorDatasize(size));
3871 assert(isValidArrangement(size, opt));
3872 elemsize = optGetElemsize(opt);
3880 assert(insOptsNone(opt));
3881 assert(isGeneralRegister(reg1));
3882 assert(isGeneralRegisterOrZR(reg2));
3887 assert(size == EA_8BYTE);
3894 assert(insOptsNone(opt));
3895 assert(isValidGeneralDatasize(size));
3896 assert(isGeneralRegister(reg1));
3897 assert(isGeneralRegister(reg2));
3905 return emitIns_R_R_I(ins, size, reg1, reg2, 0, opt);
3913 if (isVectorRegister(reg1))
3915 assert(isVectorRegister(reg2));
3916 assert(isValidVectorDatasize(size));
3917 assert(isValidArrangement(size, opt));
3918 elemsize = optGetElemsize(opt);
3919 if ((ins == INS_cls) || (ins == INS_clz))
3921 assert(elemsize != EA_8BYTE); // No encoding for type D
3923 else if (ins == INS_rev32)
3925 assert((elemsize == EA_2BYTE) || (elemsize == EA_1BYTE));
3929 assert(elemsize == EA_1BYTE); // Only supports 8B or 16B
3936 // Doesn't have general register version(s)
3943 assert(insOptsNone(opt));
3944 assert(isGeneralRegister(reg1));
3945 assert(isGeneralRegister(reg2));
3946 if (ins == INS_rev32)
3948 assert(size == EA_8BYTE);
3952 assert(isValidGeneralDatasize(size));
3965 assert(isVectorRegister(reg1));
3966 assert(isVectorRegister(reg2));
3967 assert(isValidVectorDatasize(size));
3968 assert(isValidArrangement(size, opt));
3969 elemsize = optGetElemsize(opt);
3970 assert(elemsize != EA_8BYTE); // No encoding for type D
3976 assert(isVectorRegister(reg1));
3977 assert(isVectorRegister(reg2));
3978 assert(isValidVectorDatasize(size));
3979 assert(isValidArrangement(size, opt));
3980 elemsize = optGetElemsize(opt);
3981 // size is determined by instruction
3984 assert(size == EA_8BYTE);
3986 else // ins == INS_xtn2
3988 assert(size == EA_16BYTE);
3990 assert(elemsize != EA_8BYTE); // Narrowing must not end with 8 byte data
3998 assert(isValidGeneralDatasize(size));
4010 assert(isValidGeneralLSDatasize(size));
4011 assert(isGeneralRegisterOrZR(reg1));
4012 assert(isGeneralRegisterOrSP(reg2));
4013 assert(insOptsNone(opt));
4015 reg2 = encodingSPtoZR(reg2);
4033 assert(insOptsNone(opt));
4034 emitIns_R_R_I(ins, attr, reg1, reg2, 0, INS_OPTS_NONE);
4038 assert(isValidVectorElemsizeFloat(size));
4040 // Is the mov even necessary?
4046 if (isVectorRegister(reg1))
4048 if (isVectorRegister(reg2))
4050 assert(insOptsNone(opt));
4055 assert(isGeneralRegister(reg2));
4057 // if the optional conversion specifier is not present we calculate it
4058 if (opt == INS_OPTS_NONE)
4060 opt = (size == EA_4BYTE) ? INS_OPTS_4BYTE_TO_S : INS_OPTS_8BYTE_TO_D;
4062 assert(insOptsConvertIntToFloat(opt));
4069 assert(isGeneralRegister(reg1));
4070 assert(isVectorRegister(reg2));
4072 // if the optional conversion specifier is not present we calculate it
4073 if (opt == INS_OPTS_NONE)
4075 opt = (size == EA_4BYTE) ? INS_OPTS_S_TO_4BYTE : INS_OPTS_D_TO_8BYTE;
4077 assert(insOptsConvertFloatToInt(opt));
4085 assert(insOptsNone(opt));
4086 assert(isValidVectorElemsizeFloat(size));
4087 assert(isVectorRegister(reg1));
4088 assert(isVectorRegister(reg2));
4102 if (insOptsAnyArrangement(opt))
4105 assert(isVectorRegister(reg1));
4106 assert(isVectorRegister(reg2));
4107 assert(isValidVectorDatasize(size));
4108 assert(isValidArrangement(size, opt));
4109 elemsize = optGetElemsize(opt);
4110 assert(isValidVectorElemsizeFloat(elemsize));
4111 assert(opt != INS_OPTS_1D); // Reserved encoding
4117 assert(isVectorRegister(reg2));
4118 if (isVectorRegister(reg1))
4120 assert(insOptsNone(opt));
4121 assert(isValidVectorElemsizeFloat(size));
4126 assert(isGeneralRegister(reg1));
4127 assert(insOptsConvertFloatToInt(opt));
4128 assert(isValidVectorElemsizeFloat(size));
4138 assert(isVectorRegister(reg1));
4139 assert(isVectorRegister(reg2));
4140 assert(isValidVectorDatasize(size));
4141 assert(insOptsNone(opt));
4142 assert(size == EA_8BYTE); // Narrowing from Double or Widening to Double (Half not supported)
4148 if (insOptsAnyArrangement(opt))
4151 assert(isVectorRegister(reg1));
4152 assert(isVectorRegister(reg2));
4153 assert(isValidVectorDatasize(size));
4154 assert(isValidArrangement(size, opt));
4155 elemsize = optGetElemsize(opt);
4156 assert(isValidVectorElemsizeFloat(elemsize));
4157 assert(opt != INS_OPTS_1D); // Reserved encoding
4163 assert(isVectorRegister(reg1));
4164 if (isVectorRegister(reg2))
4166 assert(insOptsNone(opt));
4167 assert(isValidVectorElemsizeFloat(size));
4172 assert(isGeneralRegister(reg2));
4173 assert(insOptsConvertIntToFloat(opt));
4174 assert(isValidVectorElemsizeFloat(size));
4190 if (insOptsAnyArrangement(opt))
4193 assert(isVectorRegister(reg1));
4194 assert(isVectorRegister(reg2));
4195 assert(isValidVectorDatasize(size));
4196 assert(isValidArrangement(size, opt));
4197 elemsize = optGetElemsize(opt);
4198 assert(isValidVectorElemsizeFloat(elemsize));
4199 assert(opt != INS_OPTS_1D); // Reserved encoding
4205 assert(insOptsNone(opt));
4206 assert(isValidVectorElemsizeFloat(size));
4207 assert(isVectorRegister(reg1));
4208 assert(isVectorRegister(reg2));
4215 assert(insOptsNone(opt));
4216 assert(isValidVectorElemsizeFloat(size));
4217 assert(isVectorRegister(reg1));
4218 assert(isVectorRegister(reg2));
4223 assert(insOptsConvertFloatToFloat(opt));
4224 assert(isValidVectorFcvtsize(size));
4225 assert(isVectorRegister(reg1));
4226 assert(isVectorRegister(reg2));
4235 assert(isVectorRegister(reg1));
4236 assert(isVectorRegister(reg2));
4238 if (isValidVectorDatasize(size))
4241 assert(insOptsAnyArrangement(opt));
4242 assert(isValidArrangement(size, opt));
4243 elemsize = optGetElemsize(opt);
4250 assert(size == EA_8BYTE); // Only Double supported
4260 assert(isVectorRegister(reg1));
4261 assert(isVectorRegister(reg2));
4263 if (isValidVectorDatasize(size))
4266 assert(insOptsAnyArrangement(opt));
4267 assert(isValidArrangement(size, opt));
4268 elemsize = optGetElemsize(opt);
4269 assert((elemsize == EA_8BYTE) || (elemsize == EA_4BYTE)); // Only Double/Float supported
4270 assert(opt != INS_OPTS_1D); // Reserved encoding
4277 assert((size == EA_8BYTE) || (size == EA_4BYTE)); // Only Double/Float supported
4285 assert(isVectorRegister(reg1));
4286 assert(isVectorRegister(reg2));
4287 assert(isValidVectorDatasize(size));
4288 elemsize = optGetElemsize(opt);
4289 assert(elemsize == EA_1BYTE);
4297 } // end switch (ins)
4299 assert(fmt != IF_NONE);
4301 instrDesc* id = emitNewInstrSmall(attr);
4314 /*****************************************************************************
4316 * Add an instruction referencing a register and two constants.
4319 void emitter::emitIns_R_I_I(
4320 instruction ins, emitAttr attr, regNumber reg, ssize_t imm1, ssize_t imm2, insOpts opt /* = INS_OPTS_NONE */)
4322 emitAttr size = EA_SIZE(attr);
4323 insFormat fmt = IF_NONE;
4324 size_t immOut = 0; // composed from imm1 and imm2 and stored in the instrDesc
4326 /* Figure out the encoding format of the instruction */
4333 ins = INS_movz; // INS_mov with LSL is an alias for INS_movz LSL
4339 assert(isValidGeneralDatasize(size));
4340 assert(isGeneralRegister(reg));
4341 assert(isValidUimm16(imm1));
4342 assert(insOptsLSL(opt)); // Must be INS_OPTS_LSL
4344 if (size == EA_8BYTE)
4346 assert((imm2 == 0) || (imm2 == 16) || // shift amount: 0, 16, 32 or 48
4347 (imm2 == 32) || (imm2 == 48));
4351 assert((imm2 == 0) || (imm2 == 16)); // shift amount: 0 or 16
4386 immOut = hwi.immHWVal;
4387 assert(isValidImmHWVal(immOut, size));
4396 } // end switch (ins)
4398 assert(fmt != IF_NONE);
4400 instrDesc* id = emitNewInstrSC(attr, immOut);
4411 /*****************************************************************************
4413 * Add an instruction referencing two registers and a constant.
4416 void emitter::emitIns_R_R_I(
4417 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm, insOpts opt /* = INS_OPTS_NONE */)
4419 emitAttr size = EA_SIZE(attr);
4420 emitAttr elemsize = EA_UNKNOWN;
4421 insFormat fmt = IF_NONE;
4422 bool isLdSt = false;
4423 bool isSIMD = false;
4424 bool isAddSub = false;
4425 bool setFlags = false;
4427 bool unscaledOp = false;
4429 /* Figure out the encoding format of the instruction */
4436 // Check for the 'mov' aliases for the vector registers
4437 assert(insOptsNone(opt));
4438 assert(isValidVectorElemsize(size));
4440 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4442 if (isVectorRegister(reg1))
4444 if (isGeneralRegisterOrZR(reg2))
4446 fmt = IF_DV_2C; // Alias for 'ins'
4449 else if (isVectorRegister(reg2))
4451 fmt = IF_DV_2E; // Alias for 'dup'
4455 else // isGeneralRegister(reg1)
4457 assert(isGeneralRegister(reg1));
4458 if (isVectorRegister(reg2))
4460 fmt = IF_DV_2B; // Alias for 'umov'
4464 assert(!" invalid INS_mov operands");
4470 assert(insOptsNone(opt));
4471 assert(isValidGeneralDatasize(size));
4472 assert(isGeneralRegister(reg1));
4473 assert(isGeneralRegister(reg2));
4474 assert(isValidImmShift(imm, size));
4479 assert(insOptsNone(opt));
4480 assert(isValidGeneralDatasize(size));
4481 assert(isGeneralRegister(reg1));
4482 assert(isGeneralRegister(reg2));
4483 assert(isValidImmShift(imm, size));
4498 assert(isVectorRegister(reg1));
4499 assert(isVectorRegister(reg2));
4500 if (insOptsAnyArrangement(opt))
4503 assert(isValidVectorDatasize(size));
4504 assert(isValidArrangement(size, opt));
4505 elemsize = optGetElemsize(opt);
4506 assert(isValidVectorElemsize(elemsize));
4507 assert(isValidImmShift(imm, elemsize));
4508 assert(opt != INS_OPTS_1D); // Reserved encoding
4515 assert(insOptsNone(opt));
4516 assert(size == EA_8BYTE); // only supported size
4517 assert(isValidImmShift(imm, size));
4531 assert(isVectorRegister(reg1));
4532 assert(isVectorRegister(reg2));
4534 assert(size == EA_8BYTE);
4535 assert(isValidArrangement(size, opt));
4536 elemsize = optGetElemsize(opt);
4537 assert(elemsize != EA_8BYTE); // Reserved encodings
4538 assert(isValidVectorElemsize(elemsize));
4539 assert(isValidImmShift(imm, elemsize));
4552 assert(isVectorRegister(reg1));
4553 assert(isVectorRegister(reg2));
4555 assert(size == EA_16BYTE);
4556 assert(isValidArrangement(size, opt));
4557 elemsize = optGetElemsize(opt);
4558 assert(elemsize != EA_8BYTE); // Reserved encodings
4559 assert(isValidVectorElemsize(elemsize));
4560 assert(isValidImmShift(imm, elemsize));
4567 assert(isValidGeneralDatasize(size));
4568 assert(isGeneralRegister(reg1));
4569 assert(isGeneralRegisterOrZR(reg2));
4573 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4581 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
4585 assert(insOptsAluShift(opt)); // a non-zero imm, must select shift kind, can't use ROR
4587 assert(isValidImmShift(imm, size));
4593 assert(isValidGeneralDatasize(size));
4594 assert(isGeneralRegisterOrZR(reg1));
4595 assert(isGeneralRegister(reg2));
4597 if (insOptsAnyShift(opt))
4599 assert(isValidImmShift(imm, size) && (imm != 0));
4604 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4612 assert(isValidGeneralDatasize(size));
4613 assert(isGeneralRegisterOrSP(reg1));
4614 assert(isGeneralRegister(reg2));
4616 reg1 = encodingSPtoZR(reg1);
4617 if (insOptsAnyExtend(opt))
4619 assert((imm >= 0) && (imm <= 4));
4625 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4631 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
4632 assert(isValidImmShift(imm, size));
4641 assert(insOptsNone(opt));
4642 assert(isGeneralRegister(reg2));
4643 if (ins == INS_ands)
4645 assert(isGeneralRegister(reg1));
4649 assert(isGeneralRegisterOrSP(reg1));
4650 reg1 = encodingSPtoZR(reg1);
4654 canEncode = canEncodeBitMaskImm(imm, size, &bmi);
4658 assert(isValidImmNRS(imm, size));
4663 case INS_dup: // by element, imm selects the element of reg2
4664 assert(isVectorRegister(reg1));
4665 if (isVectorRegister(reg2))
4667 if (insOptsAnyArrangement(opt))
4670 assert(isValidVectorDatasize(size));
4671 assert(isValidArrangement(size, opt));
4672 elemsize = optGetElemsize(opt);
4673 assert(isValidVectorElemsize(elemsize));
4674 assert(isValidVectorIndex(size, elemsize, imm));
4675 assert(opt != INS_OPTS_1D); // Reserved encoding
4682 assert(insOptsNone(opt));
4684 assert(isValidVectorElemsize(elemsize));
4685 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4692 case INS_ins: // (MOV from general)
4693 assert(insOptsNone(opt));
4694 assert(isValidVectorElemsize(size));
4695 assert(isVectorRegister(reg1));
4696 assert(isGeneralRegisterOrZR(reg2));
4698 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4702 case INS_umov: // (MOV to general)
4703 assert(insOptsNone(opt));
4704 assert(isValidVectorElemsize(size));
4705 assert(isGeneralRegister(reg1));
4706 assert(isVectorRegister(reg2));
4708 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4713 assert(insOptsNone(opt));
4714 assert(isValidVectorElemsize(size));
4715 assert(size != EA_8BYTE); // no encoding, use INS_umov
4716 assert(isGeneralRegister(reg1));
4717 assert(isVectorRegister(reg2));
4719 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4737 // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4738 assert(isValidGeneralDatasize(size));
4739 unscaledOp = (ins == INS_ldursb);
4746 // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4747 assert(isValidGeneralDatasize(size));
4748 unscaledOp = (ins == INS_ldursh);
4755 // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4756 assert(size == EA_8BYTE);
4757 unscaledOp = (ins == INS_ldursw);
4796 // Is the target a vector register?
4797 if (isVectorRegister(reg1))
4799 assert(isValidVectorLSDatasize(size));
4800 assert(isGeneralRegisterOrSP(reg2));
4805 assert(isValidGeneralDatasize(size));
4808 scale = NaturalScale_helper(size);
4814 // Is the target a vector register?
4815 if (isVectorRegister(reg1))
4817 assert(isValidVectorLSDatasize(size));
4818 assert(isGeneralRegisterOrSP(reg2));
4823 assert(isValidGeneralDatasize(size));
4834 } // end switch (ins)
4842 assert(isValidVectorLSDatasize(size));
4843 assert(isVectorRegister(reg1));
4844 assert((scale >= 0) && (scale <= 4));
4848 assert(isValidGeneralLSDatasize(size));
4849 assert(isGeneralRegisterOrZR(reg1));
4850 assert((scale >= 0) && (scale <= 3));
4853 assert(isGeneralRegisterOrSP(reg2));
4855 // Load/Store reserved encodings:
4856 if (insOptsIndexed(opt))
4858 assert(reg1 != reg2);
4861 reg2 = encodingSPtoZR(reg2);
4863 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
4866 assert(insOptsNone(opt)); // PRE/POST Index doesn't make sense with an immediate of zero
4870 else if (insOptsIndexed(opt) || unscaledOp || (imm < 0) || ((imm & mask) != 0))
4872 if ((imm >= -256) && (imm <= 255))
4878 assert(!"Instruction cannot be encoded: IF_LS_2C");
4883 assert(insOptsNone(opt));
4884 assert(!unscaledOp);
4886 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
4888 imm >>= scale; // The immediate is scaled by the size of the ld/st
4894 assert(!"Instruction cannot be encoded: IF_LS_2B");
4901 assert(insOptsNone(opt));
4903 if (setFlags) // Can't encode SP with setFlags
4905 assert(isGeneralRegister(reg1));
4906 assert(isGeneralRegister(reg2));
4910 assert(isGeneralRegisterOrSP(reg1));
4911 assert(isGeneralRegisterOrSP(reg2));
4913 // Is it just a mov?
4916 // Is the mov even necessary?
4919 emitIns_R_R(INS_mov, attr, reg1, reg2);
4924 reg1 = encodingSPtoZR(reg1);
4925 reg2 = encodingSPtoZR(reg2);
4928 if (unsigned_abs(imm) <= 0x0fff)
4932 ins = insReverse(ins);
4935 assert(isValidUimm12(imm));
4938 else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
4940 // Encoding will use a 12-bit left shift of the immediate
4941 opt = INS_OPTS_LSL12;
4944 ins = insReverse(ins);
4947 assert((imm & 0xfff) == 0);
4949 assert(isValidUimm12(imm));
4954 assert(!"Instruction cannot be encoded: IF_DI_2A");
4958 assert(fmt != IF_NONE);
4960 instrDesc* id = emitNewInstrSC(attr, imm);
4973 /*****************************************************************************
4975 * Add an instruction referencing two registers and a constant.
4976 * Also checks for a large immediate that needs a second instruction
4977 * and will load it in reg1
4979 * - Supports instructions: add, adds, sub, subs, and, ands, eor and orr
4980 * - Requires that reg1 is a general register and not SP or ZR
4981 * - Requires that reg1 != reg2
4983 void emitter::emitIns_R_R_Imm(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm)
4985 assert(isGeneralRegister(reg1));
4986 assert(reg1 != reg2);
4988 bool immFits = true;
4996 immFits = emitter::emitIns_valid_imm_for_add(imm, attr);
5003 immFits = emitter::emitIns_valid_imm_for_alu(imm, attr);
5007 assert(!"Unsupported instruction in emitIns_R_R_Imm");
5012 emitIns_R_R_I(ins, attr, reg1, reg2, imm);
5016 // Load 'imm' into the reg1 register
5017 // then issue: 'ins' reg1, reg2, reg1
5019 codeGen->instGen_Set_Reg_To_Imm(attr, reg1, imm);
5020 emitIns_R_R_R(ins, attr, reg1, reg2, reg1);
5024 /*****************************************************************************
5026 * Add an instruction referencing three registers.
5029 void emitter::emitIns_R_R_R(
5030 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insOpts opt) /* = INS_OPTS_NONE */
5032 emitAttr size = EA_SIZE(attr);
5033 emitAttr elemsize = EA_UNKNOWN;
5034 insFormat fmt = IF_NONE;
5036 /* Figure out the encoding format of the instruction */
5060 assert(insOptsNone(opt));
5061 assert(isValidGeneralDatasize(size));
5062 assert(isGeneralRegister(reg1));
5063 assert(isGeneralRegister(reg2));
5064 assert(isGeneralRegister(reg3));
5069 if (insOptsNone(opt))
5072 assert(isValidGeneralDatasize(size));
5073 assert(isGeneralRegister(reg1));
5074 assert(isGeneralRegister(reg2));
5075 assert(isGeneralRegister(reg3));
5084 assert(insOptsAnyArrangement(opt));
5085 assert(isVectorRegister(reg1));
5086 assert(isVectorRegister(reg2));
5087 assert(isVectorRegister(reg3));
5088 assert(isValidVectorDatasize(size));
5089 assert(isValidArrangement(size, opt));
5090 elemsize = optGetElemsize(opt);
5091 if (ins == INS_pmul)
5093 assert(elemsize == EA_1BYTE); // only supports 8B or 16B
5095 else // INS_mul, INS_mla, INS_mls
5097 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
5104 if (isVectorRegister(reg1))
5106 assert(isVectorRegister(reg2));
5107 assert(isVectorRegister(reg3));
5109 if (insOptsAnyArrangement(opt))
5112 assert(opt != INS_OPTS_1D); // Reserved encoding
5113 assert(isValidVectorDatasize(size));
5114 assert(isValidArrangement(size, opt));
5120 assert(insOptsNone(opt));
5121 assert(size == EA_8BYTE);
5130 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, INS_OPTS_NONE);
5139 assert(isVectorRegister(reg1));
5140 assert(isVectorRegister(reg2));
5141 assert(isVectorRegister(reg3));
5143 if (isValidVectorDatasize(size))
5146 assert(insOptsAnyArrangement(opt));
5147 assert(isValidArrangement(size, opt));
5148 elemsize = optGetElemsize(opt);
5155 assert(size == EA_8BYTE); // Only Double supported
5163 assert(isVectorRegister(reg1));
5164 assert(isVectorRegister(reg2));
5165 assert(isVectorRegister(reg3));
5167 if (isValidVectorDatasize(size))
5170 assert(insOptsAnyArrangement(opt));
5171 assert(isValidArrangement(size, opt));
5172 elemsize = optGetElemsize(opt);
5173 assert((elemsize == EA_8BYTE) || (elemsize == EA_4BYTE)); // Only Double/Float supported
5174 assert(opt != INS_OPTS_1D); // Reserved encoding
5181 assert((size == EA_8BYTE) || (size == EA_4BYTE)); // Only Double/Float supported
5194 assert(isVectorRegister(reg1));
5195 assert(isVectorRegister(reg2));
5196 assert(isVectorRegister(reg3));
5197 assert(insOptsAnyArrangement(opt));
5200 assert(isValidVectorDatasize(size));
5201 assert(isValidArrangement(size, opt));
5202 elemsize = optGetElemsize(opt);
5203 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
5209 assert(isVectorRegister(reg1));
5210 assert(isVectorRegister(reg2));
5211 assert(reg2 == reg3);
5212 assert(isValidVectorDatasize(size));
5213 // INS_mov is an alias for INS_orr (vector register)
5214 if (opt == INS_OPTS_NONE)
5216 elemsize = EA_1BYTE;
5217 opt = optMakeArrangement(size, elemsize);
5219 assert(isValidArrangement(size, opt));
5228 if (isVectorRegister(reg1))
5230 assert(isValidVectorDatasize(size));
5231 assert(isVectorRegister(reg2));
5232 assert(isVectorRegister(reg3));
5233 if (opt == INS_OPTS_NONE)
5235 elemsize = EA_1BYTE;
5236 opt = optMakeArrangement(size, elemsize);
5238 assert(isValidArrangement(size, opt));
5247 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, INS_OPTS_NONE);
5253 assert(isValidVectorDatasize(size));
5254 assert(isVectorRegister(reg1));
5255 assert(isVectorRegister(reg2));
5256 assert(isVectorRegister(reg3));
5257 if (opt == INS_OPTS_NONE)
5259 elemsize = EA_1BYTE;
5260 opt = optMakeArrangement(size, elemsize);
5262 assert(isValidArrangement(size, opt));
5274 assert(isVectorRegister(reg1));
5275 assert(isVectorRegister(reg2));
5276 assert(isVectorRegister(reg3));
5277 if (insOptsAnyArrangement(opt))
5280 assert(isValidVectorDatasize(size));
5281 assert(isValidArrangement(size, opt));
5282 elemsize = optGetElemsize(opt);
5283 assert(isValidVectorElemsizeFloat(elemsize));
5284 assert(opt != INS_OPTS_1D); // Reserved encoding
5290 assert(insOptsNone(opt));
5291 assert(isValidScalarDatasize(size));
5298 assert(insOptsNone(opt));
5299 assert(isVectorRegister(reg1));
5300 assert(isVectorRegister(reg2));
5301 assert(isVectorRegister(reg3));
5302 assert(isValidScalarDatasize(size));
5309 assert(isVectorRegister(reg1));
5310 assert(isVectorRegister(reg2));
5311 assert(isVectorRegister(reg3));
5312 assert(insOptsAnyArrangement(opt)); // no scalar encoding, use 4-operand 'fmadd' or 'fmsub'
5315 assert(isValidVectorDatasize(size));
5316 assert(isValidArrangement(size, opt));
5317 elemsize = optGetElemsize(opt);
5318 assert(isValidVectorElemsizeFloat(elemsize));
5319 assert(opt != INS_OPTS_1D); // Reserved encoding
5332 emitIns_R_R_R_Ext(ins, attr, reg1, reg2, reg3, opt);
5340 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0);
5349 assert(isGeneralRegisterOrZR(reg1));
5350 assert(isGeneralRegisterOrZR(reg2));
5351 assert(isGeneralRegisterOrSP(reg3));
5359 } // end switch (ins)
5361 assert(fmt != IF_NONE);
5363 instrDesc* id = emitNewInstr(attr);
5377 /*****************************************************************************
5379 * Add an instruction referencing three registers and a constant.
5382 void emitter::emitIns_R_R_R_I(instruction ins,
5388 insOpts opt /* = INS_OPTS_NONE */,
5389 emitAttr attrReg2 /* = EA_UNKNOWN */)
5391 emitAttr size = EA_SIZE(attr);
5392 emitAttr elemsize = EA_UNKNOWN;
5393 insFormat fmt = IF_NONE;
5394 bool isLdSt = false;
5395 bool isSIMD = false;
5396 bool isAddSub = false;
5397 bool setFlags = false;
5400 /* Figure out the encoding format of the instruction */
5404 assert(insOptsNone(opt));
5405 assert(isValidGeneralDatasize(size));
5406 assert(isGeneralRegister(reg1));
5407 assert(isGeneralRegister(reg2));
5408 assert(isGeneralRegister(reg3));
5409 assert(isValidImmShift(imm, size));
5421 assert(isValidGeneralDatasize(size));
5422 assert(isGeneralRegister(reg1));
5423 assert(isGeneralRegister(reg2));
5424 assert(isGeneralRegister(reg3));
5425 assert(isValidImmShift(imm, size));
5428 assert(insOptsNone(opt)); // a zero imm, means no shift kind
5433 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
5438 case INS_fmul: // by element, imm[0..3] selects the element of reg3
5442 assert(isVectorRegister(reg1));
5443 assert(isVectorRegister(reg2));
5444 assert(isVectorRegister(reg3));
5445 if (insOptsAnyArrangement(opt))
5448 assert(isValidVectorDatasize(size));
5449 assert(isValidArrangement(size, opt));
5450 elemsize = optGetElemsize(opt);
5451 assert(isValidVectorElemsizeFloat(elemsize));
5452 assert(isValidVectorIndex(size, elemsize, imm));
5453 assert(opt != INS_OPTS_1D); // Reserved encoding
5459 assert(insOptsNone(opt));
5460 assert(isValidScalarDatasize(size));
5462 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
5467 case INS_mul: // by element, imm[0..7] selects the element of reg3
5470 assert(isVectorRegister(reg1));
5471 assert(isVectorRegister(reg2));
5472 assert(isVectorRegister(reg3));
5474 assert(insOptsAnyArrangement(opt));
5475 assert(isValidVectorDatasize(size));
5476 assert(isValidArrangement(size, opt));
5477 elemsize = optGetElemsize(opt);
5478 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
5479 // Only has encodings for H or S elemsize
5480 assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE));
5481 // Only has encodings for V0..V15
5482 if ((elemsize == EA_2BYTE) && (reg3 >= REG_V16))
5484 noway_assert(!"Invalid reg3");
5508 assert(insOptsNone(opt)); // Can't use Pre/Post index on these two instructions
5513 // Is the target a vector register?
5514 if (isVectorRegister(reg1))
5516 scale = NaturalScale_helper(size);
5521 scale = (size == EA_8BYTE) ? 3 : 2;
5530 } // end switch (ins)
5535 assert(isGeneralRegisterOrSP(reg3));
5536 assert(insOptsNone(opt) || insOptsIndexed(opt));
5540 assert(isValidVectorLSPDatasize(size));
5541 assert(isVectorRegister(reg1));
5542 assert(isVectorRegister(reg2));
5543 assert((scale >= 2) && (scale <= 4));
5547 assert(isValidGeneralDatasize(size));
5548 assert(isGeneralRegisterOrZR(reg1));
5549 assert(isGeneralRegisterOrZR(reg2));
5550 assert((scale == 2) || (scale == 3));
5553 // Load/Store Pair reserved encodings:
5554 if (emitInsIsLoad(ins))
5556 assert(reg1 != reg2);
5558 if (insOptsIndexed(opt))
5560 assert(reg1 != reg3);
5561 assert(reg2 != reg3);
5564 reg3 = encodingSPtoZR(reg3);
5566 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
5569 assert(insOptsNone(opt)); // PRE/POST Index doesn't make sense with an immediate of zero
5575 if ((imm & mask) == 0)
5577 imm >>= scale; // The immediate is scaled by the size of the ld/st
5579 if ((imm >= -64) && (imm <= 63))
5585 if (fmt != IF_LS_3C)
5587 assert(!"Instruction cannot be encoded: IF_LS_3C");
5594 bool reg2IsSP = (reg2 == REG_SP);
5596 assert(isValidGeneralDatasize(size));
5597 assert(isGeneralRegister(reg3));
5599 if (setFlags || insOptsAluShift(opt)) // Can't encode SP in reg1 with setFlags or AluShift option
5601 assert(isGeneralRegisterOrZR(reg1));
5605 assert(isGeneralRegisterOrSP(reg1));
5606 reg1 = encodingSPtoZR(reg1);
5609 if (insOptsAluShift(opt)) // Can't encode SP in reg2 with AluShift option
5611 assert(isGeneralRegister(reg2));
5615 assert(isGeneralRegisterOrSP(reg2));
5616 reg2 = encodingSPtoZR(reg2);
5619 if (insOptsAnyExtend(opt))
5621 assert((imm >= 0) && (imm <= 4));
5625 else if (insOptsAluShift(opt))
5627 // imm should be non-zero and in [1..63]
5628 assert(isValidImmShift(imm, size) && (imm != 0));
5633 assert(insOptsNone(opt));
5637 // To encode the SP register as reg2 we must use the IF_DR_3C encoding
5638 // and also specify a LSL of zero (imm == 0)
5649 assert(!"Instruction cannot be encoded: Add/Sub IF_DR_3A");
5652 assert(fmt != IF_NONE);
5654 instrDesc* id = emitNewInstrCns(attr, imm);
5664 // Record the attribute for the second register in the pair
5665 id->idGCrefReg2(GCT_NONE);
5666 if (attrReg2 != EA_UNKNOWN)
5668 // Record the attribute for the second register in the pair
5669 assert((fmt == IF_LS_3B) || (fmt == IF_LS_3C));
5670 if (EA_IS_GCREF(attrReg2))
5672 id->idGCrefReg2(GCT_GCREF);
5674 else if (EA_IS_BYREF(attrReg2))
5676 id->idGCrefReg2(GCT_BYREF);
5684 /*****************************************************************************
5686 * Add an instruction referencing three registers, with an extend option
5689 void emitter::emitIns_R_R_R_Ext(instruction ins,
5694 insOpts opt, /* = INS_OPTS_NONE */
5695 int shiftAmount) /* = -1 -- unset */
5697 emitAttr size = EA_SIZE(attr);
5698 insFormat fmt = IF_NONE;
5699 bool isSIMD = false;
5702 /* Figure out the encoding format of the instruction */
5723 // Is the target a vector register?
5724 if (isVectorRegister(reg1))
5726 assert(isValidVectorLSDatasize(size));
5727 scale = NaturalScale_helper(size);
5732 assert(isValidGeneralDatasize(size));
5733 scale = (size == EA_8BYTE) ? 3 : 2;
5742 } // end switch (ins)
5744 assert(scale != -1);
5745 assert(insOptsLSExtend(opt));
5749 assert(isValidVectorLSDatasize(size));
5750 assert(isVectorRegister(reg1));
5754 assert(isValidGeneralLSDatasize(size));
5755 assert(isGeneralRegisterOrZR(reg1));
5758 assert(isGeneralRegisterOrSP(reg2));
5759 assert(isGeneralRegister(reg3));
5761 // Load/Store reserved encodings:
5762 if (insOptsIndexed(opt))
5764 assert(reg1 != reg2);
5767 if (shiftAmount == -1)
5769 shiftAmount = insOptsLSL(opt) ? scale : 0;
5771 assert((shiftAmount == scale) || (shiftAmount == 0));
5773 reg2 = encodingSPtoZR(reg2);
5776 instrDesc* id = emitNewInstr(attr);
5785 id->idReg3Scaled(shiftAmount == scale);
5791 /*****************************************************************************
5793 * Add an instruction referencing two registers and two constants.
5796 void emitter::emitIns_R_R_I_I(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, int imm1, int imm2)
5798 emitAttr size = EA_SIZE(attr);
5799 emitAttr elemsize = EA_UNKNOWN;
5800 insFormat fmt = IF_NONE;
5801 size_t immOut = 0; // composed from imm1 and imm2 and stored in the instrDesc
5803 /* Figure out the encoding format of the instruction */
5813 assert(isGeneralRegister(reg1));
5814 assert(isGeneralRegister(reg2));
5815 assert(isValidImmShift(imm1, size));
5816 assert(isValidImmShift(imm2, size));
5818 bmi.immN = (size == EA_8BYTE);
5821 immOut = bmi.immNRS;
5828 assert(isGeneralRegister(reg1));
5829 assert(isGeneralRegister(reg2));
5830 lsb = getBitWidth(size) - imm1;
5832 assert(isValidImmShift(lsb, size));
5833 assert(isValidImmShift(width, size));
5835 bmi.immN = (size == EA_8BYTE);
5838 immOut = bmi.immNRS;
5845 assert(isGeneralRegister(reg1));
5846 assert(isGeneralRegister(reg2));
5848 width = imm2 + imm1 - 1;
5849 assert(isValidImmShift(lsb, size));
5850 assert(isValidImmShift(width, size));
5852 bmi.immN = (size == EA_8BYTE);
5854 bmi.immS = imm2 + imm1 - 1;
5855 immOut = bmi.immNRS;
5861 assert(isVectorRegister(reg1));
5862 assert(isVectorRegister(reg2));
5864 assert(isValidVectorElemsize(elemsize));
5865 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm1));
5866 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm2));
5867 immOut = (imm1 << 4) + imm2;
5875 assert(fmt != IF_NONE);
5877 instrDesc* id = emitNewInstrSC(attr, immOut);
5889 /*****************************************************************************
5891 * Add an instruction referencing four registers.
5894 void emitter::emitIns_R_R_R_R(
5895 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, regNumber reg4)
5897 emitAttr size = EA_SIZE(attr);
5898 insFormat fmt = IF_NONE;
5900 /* Figure out the encoding format of the instruction */
5909 assert(isValidGeneralDatasize(size));
5910 assert(isGeneralRegister(reg1));
5911 assert(isGeneralRegister(reg2));
5912 assert(isGeneralRegister(reg3));
5913 assert(isGeneralRegister(reg4));
5922 assert(isValidScalarDatasize(size));
5923 assert(isVectorRegister(reg1));
5924 assert(isVectorRegister(reg2));
5925 assert(isVectorRegister(reg3));
5926 assert(isVectorRegister(reg4));
5938 assert(fmt != IF_NONE);
5940 instrDesc* id = emitNewInstr(attr);
5954 /*****************************************************************************
5956 * Add an instruction referencing a register and a condition code
5959 void emitter::emitIns_R_COND(instruction ins, emitAttr attr, regNumber reg, insCond cond)
5961 emitAttr size = EA_SIZE(attr);
5962 insFormat fmt = IF_NONE;
5966 /* Figure out the encoding format of the instruction */
5971 assert(isGeneralRegister(reg));
5980 } // end switch (ins)
5982 assert(fmt != IF_NONE);
5983 assert(isValidImmCond(cfi.immCFVal));
5985 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
5989 id->idInsOpt(INS_OPTS_NONE);
5997 /*****************************************************************************
5999 * Add an instruction referencing two registers and a condition code
6002 void emitter::emitIns_R_R_COND(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insCond cond)
6004 emitAttr size = EA_SIZE(attr);
6005 insFormat fmt = IF_NONE;
6009 /* Figure out the encoding format of the instruction */
6015 assert(isGeneralRegister(reg1));
6016 assert(isGeneralRegister(reg2));
6024 } // end switch (ins)
6026 assert(fmt != IF_NONE);
6027 assert(isValidImmCond(cfi.immCFVal));
6029 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6033 id->idInsOpt(INS_OPTS_NONE);
6042 /*****************************************************************************
6044 * Add an instruction referencing two registers and a condition code
6047 void emitter::emitIns_R_R_R_COND(
6048 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insCond cond)
6050 emitAttr size = EA_SIZE(attr);
6051 insFormat fmt = IF_NONE;
6055 /* Figure out the encoding format of the instruction */
6062 assert(isGeneralRegister(reg1));
6063 assert(isGeneralRegister(reg2));
6064 assert(isGeneralRegister(reg3));
6073 } // end switch (ins)
6075 assert(fmt != IF_NONE);
6076 assert(isValidImmCond(cfi.immCFVal));
6078 instrDesc* id = emitNewInstr(attr);
6082 id->idInsOpt(INS_OPTS_NONE);
6087 id->idSmallCns(cfi.immCFVal);
6093 /*****************************************************************************
6095 * Add an instruction referencing two registers the flags and a condition code
6098 void emitter::emitIns_R_R_FLAGS_COND(
6099 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insCflags flags, insCond cond)
6101 emitAttr size = EA_SIZE(attr);
6102 insFormat fmt = IF_NONE;
6106 /* Figure out the encoding format of the instruction */
6111 assert(isGeneralRegister(reg1));
6112 assert(isGeneralRegister(reg2));
6120 } // end switch (ins)
6122 assert(fmt != IF_NONE);
6123 assert(isValidImmCondFlags(cfi.immCFVal));
6125 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6129 id->idInsOpt(INS_OPTS_NONE);
6138 /*****************************************************************************
6140 * Add an instruction referencing a register, an immediate, the flags and a condition code
6143 void emitter::emitIns_R_I_FLAGS_COND(
6144 instruction ins, emitAttr attr, regNumber reg, int imm, insCflags flags, insCond cond)
6146 emitAttr size = EA_SIZE(attr);
6147 insFormat fmt = IF_NONE;
6151 /* Figure out the encoding format of the instruction */
6156 assert(isGeneralRegister(reg));
6159 ins = insReverse(ins);
6162 if ((imm >= 0) && (imm <= 31))
6171 assert(!"Instruction cannot be encoded: ccmp/ccmn imm5");
6177 } // end switch (ins)
6179 assert(fmt != IF_NONE);
6180 assert(isValidImmCondFlagsImm5(cfi.immCFVal));
6182 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6186 id->idInsOpt(INS_OPTS_NONE);
6194 /*****************************************************************************
6196 * Add a memory barrier instruction with a 'barrier' immediate
6199 void emitter::emitIns_BARR(instruction ins, insBarrier barrier)
6201 insFormat fmt = IF_NONE;
6204 /* Figure out the encoding format of the instruction */
6212 imm = (ssize_t)barrier;
6217 } // end switch (ins)
6219 assert(fmt != IF_NONE);
6221 instrDesc* id = emitNewInstrSC(EA_8BYTE, imm);
6225 id->idInsOpt(INS_OPTS_NONE);
6231 /*****************************************************************************
6233 * Add an instruction with a static data member operand. If 'size' is 0, the
6234 * instruction operates on the address of the static member instead of its
6235 * value (e.g. "push offset clsvar", rather than "push dword ptr [clsvar]").
6238 void emitter::emitIns_C(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, int offs)
6243 /*****************************************************************************
6245 * Add an instruction referencing stack-based local variable.
6248 void emitter::emitIns_S(instruction ins, emitAttr attr, int varx, int offs)
6253 /*****************************************************************************
6255 * Add an instruction referencing a register and a stack-based local variable.
6257 void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
6259 emitAttr size = EA_SIZE(attr);
6260 insFormat fmt = IF_NONE;
6266 // TODO-ARM64-CQ: use unscaled loads?
6267 /* Figure out the encoding format of the instruction */
6288 assert(isValidGeneralDatasize(size) || isValidVectorDatasize(size));
6289 scale = genLog2(EA_SIZE_IN_BYTES(size));
6293 assert(size == EA_8BYTE);
6298 NYI("emitIns_R_S"); // FP locals?
6301 } // end switch (ins)
6303 /* Figure out the variable's frame position */
6308 base = emitComp->lvaFrameAddress(varx, &FPbased);
6310 assert((scale >= 0) && (scale <= 4));
6312 regNumber reg2 = FPbased ? REG_FPBASE : REG_SPBASE;
6313 reg2 = encodingSPtoZR(reg2);
6330 fmt = IF_DI_2A; // add reg1,reg2,#disp
6334 regNumber rsvdReg = codeGen->rsGetRsvdReg();
6335 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6336 fmt = IF_DR_3A; // add reg1,reg2,rsvdReg
6341 bool useRegForImm = false;
6342 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6349 else if ((imm < 0) || ((imm & mask) != 0))
6351 if ((imm >= -256) && (imm <= 255))
6357 useRegForImm = true;
6362 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
6364 imm >>= scale; // The immediate is scaled by the size of the ld/st
6370 useRegForImm = true;
6376 regNumber rsvdReg = codeGen->rsGetRsvdReg();
6377 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6382 assert(fmt != IF_NONE);
6384 instrDesc* id = emitNewInstrCns(attr, imm);
6388 id->idInsOpt(INS_OPTS_NONE);
6392 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6393 id->idSetIsLclVar();
6396 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6403 /*****************************************************************************
6405 * Add an instruction referencing two register and consectutive stack-based local variable slots.
6407 void emitter::emitIns_R_R_S_S(
6408 instruction ins, emitAttr attr1, emitAttr attr2, regNumber reg1, regNumber reg2, int varx, int offs)
6410 assert((ins == INS_ldp) || (ins == INS_ldnp));
6411 assert(EA_8BYTE == EA_SIZE(attr1));
6412 assert(EA_8BYTE == EA_SIZE(attr2));
6413 assert(isGeneralRegisterOrZR(reg1));
6414 assert(isGeneralRegisterOrZR(reg2));
6417 insFormat fmt = IF_LS_3B;
6419 const unsigned scale = 3;
6421 /* Figure out the variable's frame position */
6425 base = emitComp->lvaFrameAddress(varx, &FPbased);
6428 // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6429 regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE;
6430 reg3 = encodingSPtoZR(reg3);
6432 bool useRegForAdr = true;
6434 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6437 useRegForAdr = false;
6441 if ((imm & mask) == 0)
6443 ssize_t immShift = imm >> scale; // The immediate is scaled by the size of the ld/st
6445 if ((immShift >= -64) && (immShift <= 63))
6448 useRegForAdr = false;
6456 regNumber rsvd = codeGen->rsGetRsvdReg();
6457 emitIns_R_R_Imm(INS_add, EA_PTRSIZE, rsvd, reg3, imm);
6462 assert(fmt != IF_NONE);
6464 instrDesc* id = emitNewInstrCns(attr1, imm);
6468 id->idInsOpt(INS_OPTS_NONE);
6470 // Record the attribute for the second register in the pair
6471 if (EA_IS_GCREF(attr2))
6473 id->idGCrefReg2(GCT_GCREF);
6475 else if (EA_IS_BYREF(attr2))
6477 id->idGCrefReg2(GCT_BYREF);
6481 id->idGCrefReg2(GCT_NONE);
6487 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6488 id->idSetIsLclVar();
6491 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6498 /*****************************************************************************
6500 * Add an instruction referencing a stack-based local variable and a register
6502 void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
6505 emitAttr size = EA_SIZE(attr);
6506 insFormat fmt = IF_NONE;
6509 bool isVectorStore = false;
6511 // TODO-ARM64-CQ: use unscaled loads?
6512 /* Figure out the encoding format of the instruction */
6517 assert(isGeneralRegisterOrZR(reg1));
6522 assert(isGeneralRegisterOrZR(reg1));
6526 if (isGeneralRegisterOrZR(reg1))
6528 assert(isValidGeneralDatasize(size));
6529 scale = (size == EA_8BYTE) ? 3 : 2;
6533 assert(isVectorRegister(reg1));
6534 assert(isValidVectorLSDatasize(size));
6535 scale = NaturalScale_helper(size);
6536 isVectorStore = true;
6541 NYI("emitIns_S_R"); // FP locals?
6544 } // end switch (ins)
6546 /* Figure out the variable's frame position */
6550 base = emitComp->lvaFrameAddress(varx, &FPbased);
6562 // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6563 regNumber reg2 = FPbased ? REG_FPBASE : REG_SPBASE;
6564 reg2 = encodingSPtoZR(reg2);
6566 bool useRegForImm = false;
6568 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6573 else if ((imm < 0) || ((imm & mask) != 0))
6575 if ((imm >= -256) && (imm <= 255))
6581 useRegForImm = true;
6586 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
6588 imm >>= scale; // The immediate is scaled by the size of the ld/st
6594 useRegForImm = true;
6600 // The reserved register is not stored in idReg3() since that field overlaps with iiaLclVar.
6601 // It is instead implicit when idSetIsLclVar() is set, with this encoding format.
6602 regNumber rsvdReg = codeGen->rsGetRsvdReg();
6603 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6607 assert(fmt != IF_NONE);
6609 instrDesc* id = emitNewInstrCns(attr, imm);
6613 id->idInsOpt(INS_OPTS_NONE);
6617 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6618 id->idSetIsLclVar();
6621 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6628 /*****************************************************************************
6630 * Add an instruction referencing consecutive stack-based local variable slots and two registers
6632 void emitter::emitIns_S_S_R_R(
6633 instruction ins, emitAttr attr1, emitAttr attr2, regNumber reg1, regNumber reg2, int varx, int offs)
6635 assert((ins == INS_stp) || (ins == INS_stnp));
6636 assert(EA_8BYTE == EA_SIZE(attr1));
6637 assert(EA_8BYTE == EA_SIZE(attr2));
6638 assert(isGeneralRegisterOrZR(reg1));
6639 assert(isGeneralRegisterOrZR(reg2));
6642 insFormat fmt = IF_LS_3B;
6644 const unsigned scale = 3;
6646 /* Figure out the variable's frame position */
6650 base = emitComp->lvaFrameAddress(varx, &FPbased);
6653 // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6654 regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE;
6655 reg3 = encodingSPtoZR(reg3);
6657 bool useRegForAdr = true;
6659 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6662 useRegForAdr = false;
6666 if ((imm & mask) == 0)
6668 ssize_t immShift = imm >> scale; // The immediate is scaled by the size of the ld/st
6670 if ((immShift >= -64) && (immShift <= 63))
6673 useRegForAdr = false;
6681 regNumber rsvd = codeGen->rsGetRsvdReg();
6682 emitIns_R_R_Imm(INS_add, EA_PTRSIZE, rsvd, reg3, imm);
6687 assert(fmt != IF_NONE);
6689 instrDesc* id = emitNewInstrCns(attr1, imm);
6693 id->idInsOpt(INS_OPTS_NONE);
6695 // Record the attribute for the second register in the pair
6696 if (EA_IS_GCREF(attr2))
6698 id->idGCrefReg2(GCT_GCREF);
6700 else if (EA_IS_BYREF(attr2))
6702 id->idGCrefReg2(GCT_BYREF);
6706 id->idGCrefReg2(GCT_NONE);
6712 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6713 id->idSetIsLclVar();
6716 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6723 /*****************************************************************************
6725 * Add an instruction referencing stack-based local variable and an immediate
6727 void emitter::emitIns_S_I(instruction ins, emitAttr attr, int varx, int offs, int val)
6732 /*****************************************************************************
6734 * Add an instruction with a register + static member operands.
6735 * Constant is stored into JIT data which is adjacent to code.
6736 * No relocation is needed. PC-relative offset will be encoded directly into instruction.
6739 void emitter::emitIns_R_C(
6740 instruction ins, emitAttr attr, regNumber reg, regNumber addrReg, CORINFO_FIELD_HANDLE fldHnd, int offs)
6743 assert(instrDesc::fitsInSmallCns(offs));
6745 emitAttr size = EA_SIZE(attr);
6746 insFormat fmt = IF_NONE;
6748 instrDescJmp* id = emitNewInstrJmp();
6753 // This is case to get address to the constant data.
6755 assert(isGeneralRegister(reg));
6756 assert(isValidGeneralDatasize(size));
6761 if (isVectorRegister(reg))
6763 assert(isValidScalarDatasize(size));
6764 // For vector (float/double) register, we should have an integer address reg to
6765 // compute long address which consists of page address and page offset.
6766 // For integer constant, this is not needed since the dest reg can be used to
6767 // compute address as well as contain the final contents.
6768 assert(isGeneralRegister(reg) || (addrReg != REG_NA));
6772 assert(isGeneralRegister(reg));
6773 assert(isValidGeneralDatasize(size));
6780 assert(fmt != IF_NONE);
6784 id->idInsOpt(INS_OPTS_NONE);
6785 id->idSmallCns(offs);
6787 id->idAddr()->iiaFieldHnd = fldHnd;
6788 id->idSetIsBound(); // We won't patch address since we will know the exact distance once JIT code and data are
6789 // allocated together.
6791 id->idReg1(reg); // destination register that will get the constant value.
6792 if (addrReg != REG_NA)
6794 id->idReg2(addrReg); // integer register to compute long address (used for vector dest when we end up with long
6797 id->idjShort = false; // Assume loading constant from long address
6799 // Keep it long if it's in cold code.
6800 id->idjKeepLong = emitComp->fgIsBlockCold(emitComp->compCurBB);
6803 if (emitComp->opts.compLongAddress)
6804 id->idjKeepLong = 1;
6807 // If it's possible to be shortened, then put it in jump list
6808 // to be revisited by emitJumpDistBind.
6809 if (!id->idjKeepLong)
6811 /* Record the jump's IG and offset within it */
6812 id->idjIG = emitCurIG;
6813 id->idjOffs = emitCurIGsize;
6815 /* Append this jump to this IG's jump list */
6816 id->idjNext = emitCurIGjmpList;
6817 emitCurIGjmpList = id;
6828 /*****************************************************************************
6830 * Add an instruction with a static member + constant.
6833 void emitter::emitIns_C_I(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, ssize_t offs, ssize_t val)
6838 /*****************************************************************************
6840 * Add an instruction with a static member + register operands.
6843 void emitter::emitIns_C_R(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, regNumber reg, int offs)
6845 assert(!"emitIns_C_R not supported for RyuJIT backend");
6848 void emitter::emitIns_R_AR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
6850 NYI("emitIns_R_AR");
6853 // This computes address from the immediate which is relocatable.
6854 void emitter::emitIns_R_AI(instruction ins, emitAttr attr, regNumber ireg, ssize_t addr)
6856 assert(EA_IS_RELOC(attr));
6857 emitAttr size = EA_SIZE(attr);
6858 insFormat fmt = IF_DI_1E;
6859 bool needAdd = false;
6860 instrDescJmp* id = emitNewInstrJmp();
6865 // This computes page address.
6866 // page offset is needed using add.
6877 id->idInsOpt(INS_OPTS_NONE);
6879 id->idAddr()->iiaAddr = (BYTE*)addr;
6881 id->idSetIsDspReloc();
6888 // add reg, reg, imm
6891 instrDesc* id = emitAllocInstr(attr);
6892 assert(id->idIsReloc());
6896 id->idInsOpt(INS_OPTS_NONE);
6898 id->idAddr()->iiaAddr = (BYTE*)addr;
6907 void emitter::emitIns_AR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
6909 NYI("emitIns_AR_R");
6912 void emitter::emitIns_R_ARR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
6914 NYI("emitIns_R_ARR");
6917 void emitter::emitIns_ARR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
6919 NYI("emitIns_R_ARR");
6922 void emitter::emitIns_R_ARX(
6923 instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, unsigned mul, int disp)
6925 NYI("emitIns_R_ARR");
6928 /*****************************************************************************
6930 * Record that a jump instruction uses the short encoding
6933 void emitter::emitSetShortJump(instrDescJmp* id)
6935 if (id->idjKeepLong)
6938 insFormat fmt = IF_NONE;
6939 if (emitIsCondJump(id))
6941 switch (id->idIns())
6956 else if (emitIsLoadLabel(id))
6960 else if (emitIsLoadConstant(id))
6970 id->idjShort = true;
6973 /*****************************************************************************
6975 * Add a label instruction.
6978 void emitter::emitIns_R_L(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
6980 assert(dst->bbFlags & BBF_JMP_TARGET);
6982 insFormat fmt = IF_NONE;
6993 instrDescJmp* id = emitNewInstrJmp();
6997 id->idjShort = false;
6998 id->idAddr()->iiaBBlabel = dst;
7000 id->idOpSize(EA_PTRSIZE);
7003 // Mark the catch return
7004 if (emitComp->compCurBB->bbJumpKind == BBJ_EHCATCHRET)
7006 id->idDebugOnlyInfo()->idCatchRet = true;
7010 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7013 if (emitComp->opts.compLongAddress)
7014 id->idjKeepLong = 1;
7017 /* Record the jump's IG and offset within it */
7019 id->idjIG = emitCurIG;
7020 id->idjOffs = emitCurIGsize;
7022 /* Append this jump to this IG's jump list */
7024 id->idjNext = emitCurIGjmpList;
7025 emitCurIGjmpList = id;
7035 /*****************************************************************************
7037 * Add a data label instruction.
7040 void emitter::emitIns_R_D(instruction ins, emitAttr attr, unsigned offs, regNumber reg)
7045 void emitter::emitIns_J_R(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
7047 assert((ins == INS_cbz) || (ins == INS_cbnz));
7049 assert(dst != nullptr);
7050 assert((dst->bbFlags & BBF_JMP_TARGET) != 0);
7052 insFormat fmt = IF_LARGEJMP;
7054 instrDescJmp* id = emitNewInstrJmp();
7059 id->idjShort = false;
7060 id->idOpSize(EA_SIZE(attr));
7062 id->idAddr()->iiaBBlabel = dst;
7063 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7065 /* Record the jump's IG and offset within it */
7067 id->idjIG = emitCurIG;
7068 id->idjOffs = emitCurIGsize;
7070 /* Append this jump to this IG's jump list */
7072 id->idjNext = emitCurIGjmpList;
7073 emitCurIGjmpList = id;
7083 void emitter::emitIns_J_R_I(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg, int imm)
7085 assert((ins == INS_tbz) || (ins == INS_tbnz));
7087 assert(dst != nullptr);
7088 assert((dst->bbFlags & BBF_JMP_TARGET) != 0);
7089 assert((EA_SIZE(attr) == EA_4BYTE) || (EA_SIZE(attr) == EA_8BYTE));
7090 assert(imm < ((EA_SIZE(attr) == EA_4BYTE) ? 32 : 64));
7092 insFormat fmt = IF_LARGEJMP;
7094 instrDescJmp* id = emitNewInstrJmp();
7099 id->idjShort = false;
7100 id->idSmallCns(imm);
7101 id->idOpSize(EA_SIZE(attr));
7103 id->idAddr()->iiaBBlabel = dst;
7104 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7106 /* Record the jump's IG and offset within it */
7108 id->idjIG = emitCurIG;
7109 id->idjOffs = emitCurIGsize;
7111 /* Append this jump to this IG's jump list */
7113 id->idjNext = emitCurIGjmpList;
7114 emitCurIGjmpList = id;
7124 void emitter::emitIns_J(instruction ins, BasicBlock* dst, int instrCount)
7126 insFormat fmt = IF_NONE;
7130 assert(dst->bbFlags & BBF_JMP_TARGET);
7134 assert(instrCount != 0);
7137 /* Figure out the encoding format of the instruction */
7139 bool idjShort = false;
7144 // Unconditional jump is a single form.
7163 // Assume conditional jump is long.
7172 instrDescJmp* id = emitNewInstrJmp();
7176 id->idjShort = idjShort;
7179 // Mark the finally call
7180 if (ins == INS_bl_local && emitComp->compCurBB->bbJumpKind == BBJ_CALLFINALLY)
7182 id->idDebugOnlyInfo()->idFinallyCall = true;
7188 id->idAddr()->iiaBBlabel = dst;
7190 // Skip unconditional jump that has a single form.
7191 // TODO-ARM64-NYI: enable hot/cold splittingNYI.
7192 // The target needs to be relocated.
7195 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7198 if (emitComp->opts.compLongAddress) // Force long branches
7199 id->idjKeepLong = 1;
7205 id->idAddr()->iiaSetInstrCount(instrCount);
7206 id->idjKeepLong = false;
7207 /* This jump must be short */
7208 emitSetShortJump(id);
7212 /* Record the jump's IG and offset within it */
7214 id->idjIG = emitCurIG;
7215 id->idjOffs = emitCurIGsize;
7217 /* Append this jump to this IG's jump list */
7219 id->idjNext = emitCurIGjmpList;
7220 emitCurIGjmpList = id;
7230 /*****************************************************************************
7232 * Add a call instruction (direct or indirect).
7233 * argSize<0 means that the caller will pop the arguments
7235 * The other arguments are interpreted depending on callType as shown:
7236 * Unless otherwise specified, ireg,xreg,xmul,disp should have default values.
7238 * EC_FUNC_TOKEN : addr is the method address
7239 * EC_FUNC_ADDR : addr is the absolute address of the function
7241 * If callType is one of these emitCallTypes, addr has to be NULL.
7242 * EC_INDIR_R : "call ireg".
7244 * For ARM xreg, xmul and disp are never used and should always be 0/REG_NA.
7246 * Please consult the "debugger team notification" comment in genFnProlog().
7249 void emitter::emitIns_Call(EmitCallType callType,
7250 CORINFO_METHOD_HANDLE methHnd,
7251 INDEBUG_LDISASM_COMMA(CORINFO_SIG_INFO* sigInfo) // used to report call sites to the EE
7255 emitAttr secondRetSize,
7256 VARSET_VALARG_TP ptrVars,
7257 regMaskTP gcrefRegs,
7258 regMaskTP byrefRegs,
7259 IL_OFFSETX ilOffset /* = BAD_IL_OFFSET */,
7260 regNumber ireg /* = REG_NA */,
7261 regNumber xreg /* = REG_NA */,
7262 unsigned xmul /* = 0 */,
7263 ssize_t disp /* = 0 */,
7264 bool isJump /* = false */,
7265 bool isNoGC /* = false */,
7266 bool isProfLeaveCB /* = false */)
7268 /* Sanity check the arguments depending on callType */
7270 assert(callType < EC_COUNT);
7271 assert((callType != EC_FUNC_TOKEN && callType != EC_FUNC_ADDR) ||
7272 (ireg == REG_NA && xreg == REG_NA && xmul == 0 && disp == 0));
7273 assert(callType < EC_INDIR_R || addr == NULL);
7274 assert(callType != EC_INDIR_R || (ireg < REG_COUNT && xreg == REG_NA && xmul == 0 && disp == 0));
7276 // ARM never uses these
7277 assert(xreg == REG_NA && xmul == 0 && disp == 0);
7279 // Our stack level should be always greater than the bytes of arguments we push. Just
7281 assert((unsigned)abs(argSize) <= codeGen->genStackLevel);
7286 /* This is the saved set of registers after a normal call */
7287 regMaskTP savedSet = RBM_CALLEE_SAVED;
7289 /* some special helper calls have a different saved set registers */
7293 assert(emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
7295 // Get the set of registers that this call kills and remove it from the saved set.
7296 savedSet = RBM_ALLINT & ~emitComp->compNoGCHelperCallKillSet(Compiler::eeGetHelperNum(methHnd));
7298 // In case of Leave profiler callback, we need to preserve liveness of REG_PROFILER_RET_SCRATCH
7301 savedSet |= RBM_PROFILER_RET_SCRATCH;
7306 assert(!emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
7309 /* Trim out any callee-trashed registers from the live set */
7311 gcrefRegs &= savedSet;
7312 byrefRegs &= savedSet;
7315 if (EMIT_GC_VERBOSE)
7317 printf("Call: GCvars=%s ", VarSetOps::ToString(emitComp, ptrVars));
7318 dumpConvertedVarSet(emitComp, ptrVars);
7319 printf(", gcrefRegs=");
7320 printRegMaskInt(gcrefRegs);
7321 emitDispRegSet(gcrefRegs);
7322 printf(", byrefRegs=");
7323 printRegMaskInt(byrefRegs);
7324 emitDispRegSet(byrefRegs);
7329 assert(argSize % REGSIZE_BYTES == 0);
7330 argCnt = (int)(argSize / (int)REGSIZE_BYTES);
7332 /* Managed RetVal: emit sequence point for the call */
7333 if (emitComp->opts.compDbgInfo && ilOffset != BAD_IL_OFFSET)
7335 codeGen->genIPmappingAdd(ilOffset, false);
7339 We need to allocate the appropriate instruction descriptor based
7340 on whether this is a direct/indirect call, and whether we need to
7341 record an updated set of live GC variables.
7344 if (callType >= EC_INDIR_R)
7346 /* Indirect call, virtual calls */
7348 assert(callType == EC_INDIR_R);
7350 id = emitNewInstrCallInd(argCnt, disp, ptrVars, gcrefRegs, byrefRegs, retSize, secondRetSize);
7354 /* Helper/static/nonvirtual/function calls (direct or through handle),
7355 and calls to an absolute addr. */
7357 assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
7359 id = emitNewInstrCallDir(argCnt, ptrVars, gcrefRegs, byrefRegs, retSize, secondRetSize);
7362 /* Update the emitter's live GC ref sets */
7364 VarSetOps::Assign(emitComp, emitThisGCrefVars, ptrVars);
7365 emitThisGCrefRegs = gcrefRegs;
7366 emitThisByrefRegs = byrefRegs;
7368 /* Set the instruction - special case jumping a function */
7370 insFormat fmt = IF_NONE;
7372 id->idSetIsNoGC(isNoGC);
7374 /* Record the address: method, indirection, or funcptr */
7376 if (callType > EC_FUNC_ADDR)
7378 /* This is an indirect call (either a virtual call or func ptr call) */
7382 case EC_INDIR_R: // the address is in a register
7384 id->idSetIsCallRegPtr();
7388 ins = INS_br_tail; // INS_br_tail Reg
7392 ins = INS_blr; // INS_blr Reg
7400 assert(xreg == REG_NA);
7404 NO_WAY("unexpected instruction");
7410 /* This is a simple direct call: "call helper/method/addr" */
7412 assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
7414 assert(addr != NULL);
7418 ins = INS_b_tail; // INS_b_tail imm28
7422 ins = INS_bl; // INS_bl imm28
7429 id->idAddr()->iiaAddr = (BYTE*)addr;
7431 if (callType == EC_FUNC_ADDR)
7433 id->idSetIsCallAddr();
7436 if (emitComp->opts.compReloc)
7438 id->idSetIsDspReloc();
7443 if (EMIT_GC_VERBOSE)
7445 if (id->idIsLargeCall())
7447 printf("[%02u] Rec call GC vars = %s\n", id->idDebugOnlyInfo()->idNum,
7448 VarSetOps::ToString(emitComp, ((instrDescCGCA*)id)->idcGCvars));
7452 id->idDebugOnlyInfo()->idMemCookie = (size_t)methHnd; // method token
7453 id->idDebugOnlyInfo()->idCallSig = sigInfo;
7457 if (addr != nullptr)
7459 codeGen->getDisAssembler().disSetMethod((size_t)addr, methHnd);
7461 #endif // LATE_DISASM
7467 /*****************************************************************************
7469 * Returns true if 'imm' is valid Cond encoding
7472 /*static*/ bool emitter::isValidImmCond(ssize_t imm)
7474 // range check the ssize_t value, to make sure it is a small unsigned value
7475 // and that only the bits in the cfi.cond are set
7476 if ((imm < 0) || (imm > 0xF))
7480 cfi.immCFVal = (unsigned)imm;
7482 return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7485 /*****************************************************************************
7487 * Returns true if 'imm' is valid Cond/Flags encoding
7490 /*static*/ bool emitter::isValidImmCondFlags(ssize_t imm)
7492 // range check the ssize_t value, to make sure it is a small unsigned value
7493 // and that only the bits in the cfi.cond or cfi.flags are set
7494 if ((imm < 0) || (imm > 0xFF))
7498 cfi.immCFVal = (unsigned)imm;
7500 return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7503 /*****************************************************************************
7505 * Returns true if 'imm' is valid Cond/Flags/Imm5 encoding
7508 /*static*/ bool emitter::isValidImmCondFlagsImm5(ssize_t imm)
7510 // range check the ssize_t value, to make sure it is a small unsigned value
7511 // and that only the bits in the cfi.cond, cfi.flags or cfi.imm5 are set
7512 if ((imm < 0) || (imm > 0x1FFF))
7516 cfi.immCFVal = (unsigned)imm;
7518 return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7521 /*****************************************************************************
7523 * Returns an encoding for the specified register used in the 'Rd' position
7526 /*static*/ emitter::code_t emitter::insEncodeReg_Rd(regNumber reg)
7528 assert(isIntegerRegister(reg));
7529 emitter::code_t ureg = (emitter::code_t)reg;
7530 assert((ureg >= 0) && (ureg <= 31));
7534 /*****************************************************************************
7536 * Returns an encoding for the specified register used in the 'Rt' position
7539 /*static*/ emitter::code_t emitter::insEncodeReg_Rt(regNumber reg)
7541 assert(isIntegerRegister(reg));
7542 emitter::code_t ureg = (emitter::code_t)reg;
7543 assert((ureg >= 0) && (ureg <= 31));
7547 /*****************************************************************************
7549 * Returns an encoding for the specified register used in the 'Rn' position
7552 /*static*/ emitter::code_t emitter::insEncodeReg_Rn(regNumber reg)
7554 assert(isIntegerRegister(reg));
7555 emitter::code_t ureg = (emitter::code_t)reg;
7556 assert((ureg >= 0) && (ureg <= 31));
7560 /*****************************************************************************
7562 * Returns an encoding for the specified register used in the 'Rm' position
7565 /*static*/ emitter::code_t emitter::insEncodeReg_Rm(regNumber reg)
7567 assert(isIntegerRegister(reg));
7568 emitter::code_t ureg = (emitter::code_t)reg;
7569 assert((ureg >= 0) && (ureg <= 31));
7573 /*****************************************************************************
7575 * Returns an encoding for the specified register used in the 'Ra' position
7578 /*static*/ emitter::code_t emitter::insEncodeReg_Ra(regNumber reg)
7580 assert(isIntegerRegister(reg));
7581 emitter::code_t ureg = (emitter::code_t)reg;
7582 assert((ureg >= 0) && (ureg <= 31));
7586 /*****************************************************************************
7588 * Returns an encoding for the specified register used in the 'Vd' position
7591 /*static*/ emitter::code_t emitter::insEncodeReg_Vd(regNumber reg)
7593 assert(emitter::isVectorRegister(reg));
7594 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7595 assert((ureg >= 0) && (ureg <= 31));
7599 /*****************************************************************************
7601 * Returns an encoding for the specified register used in the 'Vt' position
7604 /*static*/ emitter::code_t emitter::insEncodeReg_Vt(regNumber reg)
7606 assert(emitter::isVectorRegister(reg));
7607 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7608 assert((ureg >= 0) && (ureg <= 31));
7612 /*****************************************************************************
7614 * Returns an encoding for the specified register used in the 'Vn' position
7617 /*static*/ emitter::code_t emitter::insEncodeReg_Vn(regNumber reg)
7619 assert(emitter::isVectorRegister(reg));
7620 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7621 assert((ureg >= 0) && (ureg <= 31));
7625 /*****************************************************************************
7627 * Returns an encoding for the specified register used in the 'Vm' position
7630 /*static*/ emitter::code_t emitter::insEncodeReg_Vm(regNumber reg)
7632 assert(emitter::isVectorRegister(reg));
7633 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7634 assert((ureg >= 0) && (ureg <= 31));
7638 /*****************************************************************************
7640 * Returns an encoding for the specified register used in the 'Va' position
7643 /*static*/ emitter::code_t emitter::insEncodeReg_Va(regNumber reg)
7645 assert(emitter::isVectorRegister(reg));
7646 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7647 assert((ureg >= 0) && (ureg <= 31));
7651 /*****************************************************************************
7653 * Returns an encoding for the specified condition code.
7656 /*static*/ emitter::code_t emitter::insEncodeCond(insCond cond)
7658 emitter::code_t uimm = (emitter::code_t)cond;
7662 /*****************************************************************************
7664 * Returns an encoding for the condition code with the lowest bit inverted (marked by invert(<cond>) in the
7665 * architecture manual).
7668 /*static*/ emitter::code_t emitter::insEncodeInvertedCond(insCond cond)
7670 emitter::code_t uimm = (emitter::code_t)cond;
7671 uimm ^= 1; // invert the lowest bit
7675 /*****************************************************************************
7677 * Returns an encoding for the specified flags.
7680 /*static*/ emitter::code_t emitter::insEncodeFlags(insCflags flags)
7682 emitter::code_t uimm = (emitter::code_t)flags;
7686 /*****************************************************************************
7688 * Returns the encoding for the Shift Count bits to be used for Arm64 encodings
7691 /*static*/ emitter::code_t emitter::insEncodeShiftCount(ssize_t imm, emitAttr size)
7693 assert((imm & 0x003F) == imm);
7694 assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
7696 return (emitter::code_t)imm << 10;
7699 /*****************************************************************************
7701 * Returns the encoding to select a 64-bit datasize for an Arm64 instruction
7704 /*static*/ emitter::code_t emitter::insEncodeDatasize(emitAttr size)
7706 if (size == EA_8BYTE)
7708 return 0x80000000; // set the bit at location 31
7712 assert(size == EA_4BYTE);
7717 /*****************************************************************************
7719 * Returns the encoding to select the datasize for the general load/store Arm64 instructions
7723 /*static*/ emitter::code_t emitter::insEncodeDatasizeLS(emitter::code_t code, emitAttr size)
7725 bool exclusive = ((code & 0x35000000) == 0);
7727 if ((code & 0x00800000) && !exclusive) // Is this a sign-extending opcode? (i.e. ldrsw, ldrsh, ldrsb)
7729 if ((code & 0x80000000) == 0) // Is it a ldrsh or ldrsb and not ldrsw ?
7731 if (EA_SIZE(size) != EA_8BYTE) // Do we need to encode the 32-bit Rt size bit?
7733 return 0x00400000; // set the bit at location 22
7737 else if (code & 0x80000000) // Is this a ldr/str/ldur/stur opcode?
7739 if (EA_SIZE(size) == EA_8BYTE) // Do we need to encode the 64-bit size bit?
7741 return 0x40000000; // set the bit at location 30
7747 /*****************************************************************************
7749 * Returns the encoding to select the datasize for the vector load/store Arm64 instructions
7753 /*static*/ emitter::code_t emitter::insEncodeDatasizeVLS(emitter::code_t code, emitAttr size)
7758 if ((code & 0x20000000) == 0)
7762 if (size == EA_16BYTE)
7764 // set the operation size in bit 31
7765 result = 0x80000000;
7767 else if (size == EA_8BYTE)
7769 // set the operation size in bit 30
7770 result = 0x40000000;
7774 assert(size == EA_4BYTE);
7776 result = 0x00000000;
7783 if (size == EA_16BYTE)
7785 // The operation size in bits 31 and 30 are zero
7786 // Bit 23 specifies a 128-bit Load/Store
7787 result = 0x00800000;
7789 else if (size == EA_8BYTE)
7791 // set the operation size in bits 31 and 30
7792 result = 0xC0000000;
7794 else if (size == EA_4BYTE)
7796 // set the operation size in bit 31
7797 result = 0x80000000;
7799 else if (size == EA_2BYTE)
7801 // set the operation size in bit 30
7802 result = 0x40000000;
7806 assert(size == EA_1BYTE);
7807 // The operation size in bits 31 and 30 are zero
7808 result = 0x00000000;
7812 // Or in bit 26 to indicate a Vector register is used as 'target'
7813 result |= 0x04000000;
7818 /*****************************************************************************
7820 * Returns the encoding to select the datasize for the vector load/store Arm64 instructions
7824 /*static*/ emitter::code_t emitter::insEncodeDatasizeVPLS(emitter::code_t code, emitAttr size)
7828 if (size == EA_16BYTE)
7830 // The operation size in bits 31 and 30 are zero
7831 // Bit 23 specifies a 128-bit Load/Store
7832 result = 0x80000000;
7834 else if (size == EA_8BYTE)
7836 // set the operation size in bits 31 and 30
7837 result = 0x40000000;
7839 else if (size == EA_4BYTE)
7841 // set the operation size in bit 31
7842 result = 0x00000000;
7845 // Or in bit 26 to indicate a Vector register is used as 'target'
7846 result |= 0x04000000;
7851 /*****************************************************************************
7853 * Returns the encoding to set the size bit and the N bits for a 'bitfield' instruction
7857 /*static*/ emitter::code_t emitter::insEncodeDatasizeBF(emitter::code_t code, emitAttr size)
7859 // is bit 30 equal to 0?
7860 if ((code & 0x40000000) == 0) // is the opcode one of extr, sxtb, sxth or sxtw
7862 if (size == EA_8BYTE) // Do we need to set the sf and N bits?
7864 return 0x80400000; // set the sf-bit at location 31 and the N-bit at location 22
7867 return 0; // don't set any bits
7870 /*****************************************************************************
7872 * Returns the encoding to select the 64/128-bit datasize for an Arm64 vector instruction
7875 /*static*/ emitter::code_t emitter::insEncodeVectorsize(emitAttr size)
7877 if (size == EA_16BYTE)
7879 return 0x40000000; // set the bit at location 30
7883 assert(size == EA_8BYTE);
7888 /*****************************************************************************
7890 * Returns the encoding to select 'index' for an Arm64 vector elem instruction
7892 /*static*/ emitter::code_t emitter::insEncodeVectorIndex(emitAttr elemsize, ssize_t index)
7894 code_t bits = (code_t)index;
7895 if (elemsize == EA_1BYTE)
7900 else if (elemsize == EA_2BYTE)
7905 else if (elemsize == EA_4BYTE)
7912 assert(elemsize == EA_8BYTE);
7916 assert((bits >= 1) && (bits <= 0x1f));
7918 return (bits << 16); // bits at locations [20,19,18,17,16]
7921 /*****************************************************************************
7923 * Returns the encoding to select 'index2' for an Arm64 'ins' elem instruction
7925 /*static*/ emitter::code_t emitter::insEncodeVectorIndex2(emitAttr elemsize, ssize_t index2)
7927 code_t bits = (code_t)index2;
7928 if (elemsize == EA_1BYTE)
7932 else if (elemsize == EA_2BYTE)
7936 else if (elemsize == EA_4BYTE)
7942 assert(elemsize == EA_8BYTE);
7945 assert((bits >= 0) && (bits <= 0xf));
7947 return (bits << 11); // bits at locations [14,13,12,11]
7950 /*****************************************************************************
7952 * Returns the encoding to select the 'index' for an Arm64 'mul' by elem instruction
7954 /*static*/ emitter::code_t emitter::insEncodeVectorIndexLMH(emitAttr elemsize, ssize_t index)
7958 if (elemsize == EA_2BYTE)
7960 assert((index >= 0) && (index <= 7));
7963 bits |= (1 << 11); // set bit 11 'H'
7967 bits |= (1 << 21); // set bit 21 'L'
7971 bits |= (1 << 20); // set bit 20 'M'
7974 else if (elemsize == EA_4BYTE)
7976 assert((index >= 0) && (index <= 3));
7979 bits |= (1 << 11); // set bit 11 'H'
7983 bits |= (1 << 21); // set bit 21 'L'
7988 assert(!"Invalid 'elemsize' value");
7994 /*****************************************************************************
7996 * Returns the encoding to shift by 'shift' for an Arm64 vector or scalar instruction
7999 /*static*/ emitter::code_t emitter::insEncodeVectorShift(emitAttr size, ssize_t shift)
8001 assert(shift < getBitWidth(size));
8003 code_t imm = (code_t)(getBitWidth(size) + shift);
8008 /*****************************************************************************
8010 * Returns the encoding to select the 1/2/4/8 byte elemsize for an Arm64 vector instruction
8013 /*static*/ emitter::code_t emitter::insEncodeElemsize(emitAttr size)
8015 if (size == EA_8BYTE)
8017 return 0x00C00000; // set the bit at location 23 and 22
8019 else if (size == EA_4BYTE)
8021 return 0x00800000; // set the bit at location 23
8023 else if (size == EA_2BYTE)
8025 return 0x00400000; // set the bit at location 22
8027 assert(size == EA_1BYTE);
8031 /*****************************************************************************
8033 * Returns the encoding to select the 4/8 byte elemsize for an Arm64 float vector instruction
8036 /*static*/ emitter::code_t emitter::insEncodeFloatElemsize(emitAttr size)
8038 if (size == EA_8BYTE)
8040 return 0x00400000; // set the bit at location 22
8042 assert(size == EA_4BYTE);
8046 // Returns the encoding to select the index for an Arm64 float vector by elem instruction
8047 /*static*/ emitter::code_t emitter::insEncodeFloatIndex(emitAttr elemsize, ssize_t index)
8049 code_t result = 0x00000000;
8050 if (elemsize == EA_8BYTE)
8052 assert((index >= 0) && (index <= 1));
8055 result |= 0x00000800; // 'H' - set the bit at location 11
8060 assert(elemsize == EA_4BYTE);
8061 assert((index >= 0) && (index <= 3));
8064 result |= 0x00000800; // 'H' - set the bit at location 11
8068 result |= 0x00200000; // 'L' - set the bit at location 21
8074 /*****************************************************************************
8076 * Returns the encoding to select the fcvt operation for Arm64 instructions
8078 /*static*/ emitter::code_t emitter::insEncodeConvertOpt(insFormat fmt, insOpts conversion)
8083 case INS_OPTS_S_TO_D: // Single to Double
8084 assert(fmt == IF_DV_2J);
8085 result = 0x00008000; // type=00, opc=01
8088 case INS_OPTS_D_TO_S: // Double to Single
8089 assert(fmt == IF_DV_2J);
8090 result = 0x00400000; // type=01, opc=00
8093 case INS_OPTS_H_TO_S: // Half to Single
8094 assert(fmt == IF_DV_2J);
8095 result = 0x00C00000; // type=11, opc=00
8098 case INS_OPTS_H_TO_D: // Half to Double
8099 assert(fmt == IF_DV_2J);
8100 result = 0x00C08000; // type=11, opc=01
8103 case INS_OPTS_S_TO_H: // Single to Half
8104 assert(fmt == IF_DV_2J);
8105 result = 0x00018000; // type=00, opc=11
8108 case INS_OPTS_D_TO_H: // Double to Half
8109 assert(fmt == IF_DV_2J);
8110 result = 0x00418000; // type=01, opc=11
8113 case INS_OPTS_S_TO_4BYTE: // Single to INT32
8114 assert(fmt == IF_DV_2H);
8115 result = 0x00000000; // sf=0, type=00
8118 case INS_OPTS_D_TO_4BYTE: // Double to INT32
8119 assert(fmt == IF_DV_2H);
8120 result = 0x00400000; // sf=0, type=01
8123 case INS_OPTS_S_TO_8BYTE: // Single to INT64
8124 assert(fmt == IF_DV_2H);
8125 result = 0x80000000; // sf=1, type=00
8128 case INS_OPTS_D_TO_8BYTE: // Double to INT64
8129 assert(fmt == IF_DV_2H);
8130 result = 0x80400000; // sf=1, type=01
8133 case INS_OPTS_4BYTE_TO_S: // INT32 to Single
8134 assert(fmt == IF_DV_2I);
8135 result = 0x00000000; // sf=0, type=00
8138 case INS_OPTS_4BYTE_TO_D: // INT32 to Double
8139 assert(fmt == IF_DV_2I);
8140 result = 0x00400000; // sf=0, type=01
8143 case INS_OPTS_8BYTE_TO_S: // INT64 to Single
8144 assert(fmt == IF_DV_2I);
8145 result = 0x80000000; // sf=1, type=00
8148 case INS_OPTS_8BYTE_TO_D: // INT64 to Double
8149 assert(fmt == IF_DV_2I);
8150 result = 0x80400000; // sf=1, type=01
8154 assert(!"Invalid 'conversion' value");
8160 /*****************************************************************************
8162 * Returns the encoding to have the Rn register be updated Pre/Post indexed
8166 /*static*/ emitter::code_t emitter::insEncodeIndexedOpt(insOpts opt)
8168 assert(emitter::insOptsNone(opt) || emitter::insOptsIndexed(opt));
8170 if (emitter::insOptsIndexed(opt))
8172 if (emitter::insOptsPostIndex(opt))
8174 return 0x00000400; // set the bit at location 10
8178 assert(emitter::insOptsPreIndex(opt));
8179 return 0x00000C00; // set the bit at location 10 and 11
8184 assert(emitter::insOptsNone(opt));
8185 return 0; // bits 10 and 11 are zero
8189 /*****************************************************************************
8191 * Returns the encoding for a ldp/stp instruction to have the Rn register
8192 * be updated Pre/Post indexed or not updated
8195 /*static*/ emitter::code_t emitter::insEncodePairIndexedOpt(instruction ins, insOpts opt)
8197 assert(emitter::insOptsNone(opt) || emitter::insOptsIndexed(opt));
8199 if ((ins == INS_ldnp) || (ins == INS_stnp))
8201 assert(emitter::insOptsNone(opt));
8202 return 0; // bits 23 and 24 are zero
8206 if (emitter::insOptsIndexed(opt))
8208 if (emitter::insOptsPostIndex(opt))
8210 return 0x00800000; // set the bit at location 23
8214 assert(emitter::insOptsPreIndex(opt));
8215 return 0x01800000; // set the bit at location 24 and 23
8220 assert(emitter::insOptsNone(opt));
8221 return 0x01000000; // set the bit at location 24
8226 /*****************************************************************************
8228 * Returns the encoding to apply a Shift Type on the Rm register
8231 /*static*/ emitter::code_t emitter::insEncodeShiftType(insOpts opt)
8233 if (emitter::insOptsNone(opt))
8235 // None implies the we encode LSL (with a zero immediate)
8238 assert(emitter::insOptsAnyShift(opt));
8240 emitter::code_t option = (emitter::code_t)opt - (emitter::code_t)INS_OPTS_LSL;
8241 assert(option <= 3);
8243 return option << 22; // bits 23, 22
8246 /*****************************************************************************
8248 * Returns the encoding to apply a 12 bit left shift to the immediate
8251 /*static*/ emitter::code_t emitter::insEncodeShiftImm12(insOpts opt)
8253 if (emitter::insOptsLSL12(opt))
8255 return 0x00400000; // set the bit at location 22
8260 /*****************************************************************************
8262 * Returns the encoding to have the Rm register use an extend operation
8265 /*static*/ emitter::code_t emitter::insEncodeExtend(insOpts opt)
8267 if (emitter::insOptsNone(opt) || (opt == INS_OPTS_LSL))
8269 // None or LSL implies the we encode UXTX
8270 opt = INS_OPTS_UXTX;
8272 assert(emitter::insOptsAnyExtend(opt));
8274 emitter::code_t option = (emitter::code_t)opt - (emitter::code_t)INS_OPTS_UXTB;
8275 assert(option <= 7);
8277 return option << 13; // bits 15,14,13
8280 /*****************************************************************************
8282 * Returns the encoding to scale the Rm register by {0,1,2,3,4}
8283 * when using an extend operation
8286 /*static*/ emitter::code_t emitter::insEncodeExtendScale(ssize_t imm)
8288 assert((imm >= 0) && (imm <= 4));
8290 return (emitter::code_t)imm << 10; // bits 12,11,10
8293 /*****************************************************************************
8295 * Returns the encoding to have the Rm register be auto scaled by the ld/st size
8298 /*static*/ emitter::code_t emitter::insEncodeReg3Scale(bool isScaled)
8302 return 0x00001000; // set the bit at location 12
8310 BYTE* emitter::emitOutputLoadLabel(BYTE* dst, BYTE* srcAddr, BYTE* dstAddr, instrDescJmp* id)
8312 instruction ins = id->idIns();
8313 insFormat fmt = id->idInsFmt();
8314 regNumber dstReg = id->idReg1();
8317 // adr x, [rel addr] -- compute address: current addr(ip) + rel addr.
8318 assert(ins == INS_adr);
8319 assert(fmt == IF_DI_1E);
8320 ssize_t distVal = (ssize_t)(dstAddr - srcAddr);
8321 dst = emitOutputShortAddress(dst, ins, fmt, distVal, dstReg);
8325 // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8326 assert(fmt == IF_LARGEADR);
8327 ssize_t relPageAddr =
8328 (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8329 dst = emitOutputShortAddress(dst, INS_adrp, IF_DI_1E, relPageAddr, dstReg);
8331 // add x, x, page offs -- compute address = page addr + page offs
8332 ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8333 assert(isValidUimm12(imm12));
8335 emitInsCode(INS_add, IF_DI_2A); // DI_2A X0010001shiiiiii iiiiiinnnnnddddd 1100 0000 imm(i12, sh)
8336 code |= insEncodeDatasize(EA_8BYTE); // X
8337 code |= ((code_t)imm12 << 10); // iiiiiiiiiiii
8338 code |= insEncodeReg_Rd(dstReg); // ddddd
8339 code |= insEncodeReg_Rn(dstReg); // nnnnn
8340 dst += emitOutput_Instr(dst, code);
8345 /*****************************************************************************
8347 * Output a local jump or other instruction with a pc-relative immediate.
8348 * Note that this may be invoked to overwrite an existing jump instruction at 'dst'
8349 * to handle forward branch patching.
8352 BYTE* emitter::emitOutputLJ(insGroup* ig, BYTE* dst, instrDesc* i)
8354 instrDescJmp* id = (instrDescJmp*)i;
8363 // Set default ins/fmt from id.
8364 instruction ins = id->idIns();
8365 insFormat fmt = id->idInsFmt();
8367 bool loadLabel = false;
8368 bool isJump = false;
8369 bool loadConstant = false;
8386 loadConstant = true;
8395 /* Figure out the distance to the target */
8397 srcOffs = emitCurCodeOffs(dst);
8398 srcAddr = emitOffsetToPtr(srcOffs);
8400 if (id->idAddr()->iiaIsJitDataOffset())
8402 assert(loadConstant || loadLabel);
8403 int doff = id->idAddr()->iiaGetJitDataOffset();
8405 ssize_t imm = emitGetInsSC(id);
8406 assert((imm >= 0) && (imm < 0x1000)); // 0x1000 is arbitrary, currently 'imm' is always 0
8408 unsigned dataOffs = (unsigned)(doff + imm);
8409 assert(dataOffs < emitDataSize());
8410 dstAddr = emitDataOffsetToPtr(dataOffs);
8412 regNumber dstReg = id->idReg1();
8413 regNumber addrReg = dstReg; // an integer register to compute long address.
8414 emitAttr opSize = id->idOpSize();
8420 // ldr x/v, [rel addr] -- load constant from current addr(ip) + rel addr.
8421 assert(ins == INS_ldr);
8422 assert(fmt == IF_LS_1A);
8423 distVal = (ssize_t)(dstAddr - srcAddr);
8424 dst = emitOutputShortConstant(dst, ins, fmt, distVal, dstReg, opSize);
8428 // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8429 assert(fmt == IF_LARGELDC);
8430 ssize_t relPageAddr =
8431 (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8432 if (isVectorRegister(dstReg))
8434 // Update addrReg with the reserved integer register
8435 // since we cannot use dstReg (vector) to load constant directly from memory.
8436 addrReg = id->idReg2();
8437 assert(isGeneralRegister(addrReg));
8441 dst = emitOutputShortAddress(dst, ins, fmt, relPageAddr, addrReg);
8443 // ldr x, [x, page offs] -- load constant from page address + page offset into integer register.
8444 ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8445 assert(isValidUimm12(imm12));
8448 dst = emitOutputShortConstant(dst, ins, fmt, imm12, addrReg, opSize);
8450 // fmov v, d -- copy constant in integer register to vector register.
8451 // This is needed only for vector constant.
8452 if (addrReg != dstReg)
8454 // fmov Vd,Rn DV_2I X00111100X100111 000000nnnnnddddd 1E27 0000 Vd,Rn
8455 // (scalar, from general)
8456 assert(isVectorRegister(dstReg) && isGeneralRegister(addrReg));
8459 code_t code = emitInsCode(ins, fmt);
8461 code |= insEncodeReg_Vd(dstReg); // ddddd
8462 code |= insEncodeReg_Rn(addrReg); // nnnnn
8463 if (id->idOpSize() == EA_8BYTE)
8465 code |= 0x80400000; // X ... X
8467 dst += emitOutput_Instr(dst, code);
8474 dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8480 assert(loadLabel || isJump);
8482 if (id->idAddr()->iiaHasInstrCount())
8485 int instrCount = id->idAddr()->iiaGetInstrCount();
8486 unsigned insNum = emitFindInsNum(ig, id);
8489 // Backward branches using instruction count must be within the same instruction group.
8490 assert(insNum + 1 >= (unsigned)(-instrCount));
8492 dstOffs = ig->igOffs + emitFindOffset(ig, (insNum + 1 + instrCount));
8493 dstAddr = emitOffsetToPtr(dstOffs);
8497 dstOffs = id->idAddr()->iiaIGlabel->igOffs;
8498 dstAddr = emitOffsetToPtr(dstOffs);
8501 distVal = (ssize_t)(dstAddr - srcAddr);
8503 if (dstOffs <= srcOffs)
8506 /* This is a backward jump - distance is known at this point */
8508 if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8510 size_t blkOffs = id->idjIG->igOffs;
8512 if (INTERESTING_JUMP_NUM == 0)
8513 printf("[3] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8514 printf("[3] Jump block is at %08X - %02X = %08X\n", blkOffs, emitOffsAdj, blkOffs - emitOffsAdj);
8515 printf("[3] Jump is at %08X - %02X = %08X\n", srcOffs, emitOffsAdj, srcOffs - emitOffsAdj);
8516 printf("[3] Label block is at %08X - %02X = %08X\n", dstOffs, emitOffsAdj, dstOffs - emitOffsAdj);
8522 /* This is a forward jump - distance will be an upper limit */
8524 emitFwdJumps = true;
8526 /* The target offset will be closer by at least 'emitOffsAdj', but only if this
8527 jump doesn't cross the hot-cold boundary. */
8529 if (!emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8531 dstOffs -= emitOffsAdj;
8532 distVal -= emitOffsAdj;
8535 /* Record the location of the jump for later patching */
8537 id->idjOffs = dstOffs;
8539 /* Are we overflowing the id->idjOffs bitfield? */
8540 if (id->idjOffs != dstOffs)
8541 IMPL_LIMITATION("Method is too large");
8544 if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8546 size_t blkOffs = id->idjIG->igOffs;
8548 if (INTERESTING_JUMP_NUM == 0)
8549 printf("[4] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8550 printf("[4] Jump block is at %08X\n", blkOffs);
8551 printf("[4] Jump is at %08X\n", srcOffs);
8552 printf("[4] Label block is at %08X - %02X = %08X\n", dstOffs + emitOffsAdj, emitOffsAdj, dstOffs);
8558 if (0 && emitComp->verbose)
8561 int distValSize = id->idjShort ? 4 : 8;
8562 printf("; %s jump [%08X/%03u] from %0*X to %0*X: dist = %08XH\n", (dstOffs <= srcOffs) ? "Fwd" : "Bwd",
8563 dspPtr(id), id->idDebugOnlyInfo()->idNum, distValSize, srcOffs + sz, distValSize, dstOffs, distVal);
8567 /* For forward jumps, record the address of the distance value */
8568 id->idjTemp.idjAddr = (distVal > 0) ? dst : NULL;
8570 if (emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8572 assert(!id->idjShort);
8573 NYI_ARM64("Relocation Support for long address");
8576 assert(insOptsNone(id->idInsOpt()));
8582 // Short conditional/unconditional jump
8583 assert(!id->idjKeepLong);
8584 assert(emitJumpCrossHotColdBoundary(srcOffs, dstOffs) == false);
8585 assert((fmt == IF_BI_0A) || (fmt == IF_BI_0B) || (fmt == IF_BI_1A) || (fmt == IF_BI_1B));
8589 // Long conditional jump
8590 assert(fmt == IF_LARGEJMP);
8591 // This is a pseudo-instruction format representing a large conditional branch, to allow
8592 // us to get a greater branch target range than we can get by using a straightforward conditional
8593 // branch. It is encoded as a short conditional branch that branches around a long unconditional
8596 // Conceptually, we have:
8600 // The code we emit is:
8602 // b<!cond> L_not // 4 bytes. Note that we reverse the condition.
8603 // b L_target // 4 bytes
8606 // Note that we don't actually insert any blocks: we simply encode "b <!cond> L_not" as a branch with
8607 // the correct offset. Note also that this works for both integer and floating-point conditions, because
8608 // the condition inversion takes ordered/unordered into account, preserving NaN behavior. For example,
8609 // "GT" (greater than) is inverted to "LE" (less than, equal, or unordered).
8611 instruction reverseIns;
8612 insFormat reverseFmt;
8617 reverseIns = INS_cbnz;
8618 reverseFmt = IF_BI_1A;
8621 reverseIns = INS_cbz;
8622 reverseFmt = IF_BI_1A;
8625 reverseIns = INS_tbnz;
8626 reverseFmt = IF_BI_1B;
8629 reverseIns = INS_tbz;
8630 reverseFmt = IF_BI_1B;
8633 reverseIns = emitJumpKindToIns(emitReverseJumpKind(emitInsToJumpKind(ins)));
8634 reverseFmt = IF_BI_0B;
8638 emitOutputShortBranch(dst,
8639 reverseIns, // reverse the conditional instruction
8641 8, /* 8 bytes from start of this large conditional pseudo-instruction to L_not. */
8644 // Now, pretend we've got a normal unconditional branch, and fall through to the code to emit that.
8648 // The distVal was computed based on the beginning of the pseudo-instruction,
8649 // So subtract the size of the conditional branch so that it is relative to the
8650 // unconditional branch.
8654 dst = emitOutputShortBranch(dst, ins, fmt, distVal, id);
8658 dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8664 /*****************************************************************************
8666 * Output a short branch instruction.
8668 BYTE* emitter::emitOutputShortBranch(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, instrDescJmp* id)
8670 code_t code = emitInsCode(ins, fmt);
8672 ssize_t loBits = (distVal & 3);
8673 noway_assert(loBits == 0);
8674 distVal >>= 2; // branch offset encodings are scaled by 4.
8676 if (fmt == IF_BI_0A)
8678 // INS_b or INS_bl_local
8679 noway_assert(isValidSimm26(distVal));
8680 distVal &= 0x3FFFFFFLL;
8683 else if (fmt == IF_BI_0B) // BI_0B 01010100iiiiiiii iiiiiiiiiiiXXXXX simm19:00
8685 // INS_beq, INS_bne, etc...
8686 noway_assert(isValidSimm19(distVal));
8687 distVal &= 0x7FFFFLL;
8688 code |= distVal << 5;
8690 else if (fmt == IF_BI_1A) // BI_1A X.......iiiiiiii iiiiiiiiiiittttt Rt simm19:00
8692 // INS_cbz or INS_cbnz
8693 assert(id != nullptr);
8694 code |= insEncodeDatasize(id->idOpSize()); // X
8695 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
8697 noway_assert(isValidSimm19(distVal));
8698 distVal &= 0x7FFFFLL; // 19 bits
8699 code |= distVal << 5;
8701 else if (fmt == IF_BI_1B) // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
8703 // INS_tbz or INS_tbnz
8704 assert(id != nullptr);
8705 ssize_t imm = emitGetInsSC(id);
8706 assert(isValidImmShift(imm, id->idOpSize()));
8708 if (imm & 0x20) // test bit 32-63 ?
8710 code |= 0x80000000; // B
8712 code |= ((imm & 0x1F) << 19); // bbbbb
8713 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
8715 noway_assert(isValidSimm14(distVal));
8716 distVal &= 0x3FFFLL; // 14 bits
8717 code |= distVal << 5;
8721 assert(!"Unknown fmt for emitOutputShortBranch");
8724 dst += emitOutput_Instr(dst, code);
8729 /*****************************************************************************
8731 * Output a short address instruction.
8733 BYTE* emitter::emitOutputShortAddress(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, regNumber reg)
8735 ssize_t loBits = (distVal & 3);
8738 code_t code = emitInsCode(ins, fmt);
8739 if (fmt == IF_DI_1E) // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
8741 // INS_adr or INS_adrp
8742 code |= insEncodeReg_Rd(reg); // ddddd
8744 noway_assert(isValidSimm19(distVal));
8745 distVal &= 0x7FFFFLL; // 19 bits
8746 code |= distVal << 5;
8747 code |= loBits << 29; // 2 bits
8751 assert(!"Unknown fmt for emitOutputShortAddress");
8754 dst += emitOutput_Instr(dst, code);
8759 /*****************************************************************************
8761 * Output a short constant instruction.
8763 BYTE* emitter::emitOutputShortConstant(
8764 BYTE* dst, instruction ins, insFormat fmt, ssize_t imm, regNumber reg, emitAttr opSize)
8766 code_t code = emitInsCode(ins, fmt);
8768 if (fmt == IF_LS_1A)
8770 // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt simm21
8771 // INS_ldr or INS_ldrsw (PC-Relative)
8773 ssize_t loBits = (imm & 3);
8774 noway_assert(loBits == 0);
8775 ssize_t distVal = imm >>= 2; // load offset encodings are scaled by 4.
8777 noway_assert(isValidSimm19(distVal));
8779 // Is the target a vector register?
8780 if (isVectorRegister(reg))
8782 code |= insEncodeDatasizeVLS(code, opSize); // XX V
8783 code |= insEncodeReg_Vt(reg); // ttttt
8787 assert(isGeneralRegister(reg));
8788 // insEncodeDatasizeLS is not quite right for this case.
8789 // So just specialize it.
8790 if ((ins == INS_ldr) && (opSize == EA_8BYTE))
8792 // set the operation size in bit 30
8796 code |= insEncodeReg_Rt(reg); // ttttt
8799 distVal &= 0x7FFFFLL; // 19 bits
8800 code |= distVal << 5;
8802 else if (fmt == IF_LS_2B)
8804 // ldr Rt,[Xn+pimm12] LS_2B 1X11100101iiiiii iiiiiinnnnnttttt B940 0000 imm(0-4095<<{2,3})
8805 // INS_ldr or INS_ldrsw (PC-Relative)
8806 noway_assert(isValidUimm12(imm));
8807 assert(isGeneralRegister(reg));
8809 if (opSize == EA_8BYTE)
8811 // insEncodeDatasizeLS is not quite right for this case.
8812 // So just specialize it.
8815 // set the operation size in bit 30
8818 // Low 3 bits should be 0 -- 8 byte JIT data should be aligned on 8 byte.
8819 assert((imm & 7) == 0);
8824 assert(opSize == EA_4BYTE);
8825 // Low 2 bits should be 0 -- 4 byte aligned data.
8826 assert((imm & 3) == 0);
8830 code |= insEncodeReg_Rt(reg); // ttttt
8831 code |= insEncodeReg_Rn(reg); // nnnnn
8836 assert(!"Unknown fmt for emitOutputShortConstant");
8839 dst += emitOutput_Instr(dst, code);
8843 /*****************************************************************************
8845 * Output a call instruction.
8848 unsigned emitter::emitOutputCall(insGroup* ig, BYTE* dst, instrDesc* id, code_t code)
8850 const unsigned char callInstrSize = sizeof(code_t); // 4 bytes
8851 regMaskTP gcrefRegs;
8852 regMaskTP byrefRegs;
8854 VARSET_TP GCvars(VarSetOps::UninitVal());
8856 // Is this a "fat" call descriptor?
8857 if (id->idIsLargeCall())
8859 instrDescCGCA* idCall = (instrDescCGCA*)id;
8860 gcrefRegs = idCall->idcGcrefRegs;
8861 byrefRegs = idCall->idcByrefRegs;
8862 VarSetOps::Assign(emitComp, GCvars, idCall->idcGCvars);
8866 assert(!id->idIsLargeDsp());
8867 assert(!id->idIsLargeCns());
8869 gcrefRegs = emitDecodeCallGCregs(id);
8871 VarSetOps::AssignNoCopy(emitComp, GCvars, VarSetOps::MakeEmpty(emitComp));
8874 /* We update the GC info before the call as the variables cannot be
8875 used by the call. Killing variables before the call helps with
8876 boundary conditions if the call is CORINFO_HELP_THROW - see bug 50029.
8877 If we ever track aliased variables (which could be used by the
8878 call), we would have to keep them alive past the call. */
8880 emitUpdateLiveGCvars(GCvars, dst);
8882 // Now output the call instruction and update the 'dst' pointer
8884 unsigned outputInstrSize = emitOutput_Instr(dst, code);
8885 dst += outputInstrSize;
8887 // All call instructions are 4-byte in size on ARM64
8889 assert(outputInstrSize == callInstrSize);
8891 // If the method returns a GC ref, mark INTRET (R0) appropriately.
8892 if (id->idGCref() == GCT_GCREF)
8894 gcrefRegs |= RBM_INTRET;
8896 else if (id->idGCref() == GCT_BYREF)
8898 byrefRegs |= RBM_INTRET;
8901 // If is a multi-register return method is called, mark INTRET_1 (X1) appropriately
8902 if (id->idIsLargeCall())
8904 instrDescCGCA* idCall = (instrDescCGCA*)id;
8905 if (idCall->idSecondGCref() == GCT_GCREF)
8907 gcrefRegs |= RBM_INTRET_1;
8909 else if (idCall->idSecondGCref() == GCT_BYREF)
8911 byrefRegs |= RBM_INTRET_1;
8915 // If the GC register set has changed, report the new set.
8916 if (gcrefRegs != emitThisGCrefRegs)
8918 emitUpdateLiveGCregs(GCT_GCREF, gcrefRegs, dst);
8920 // If the Byref register set has changed, report the new set.
8921 if (byrefRegs != emitThisByrefRegs)
8923 emitUpdateLiveGCregs(GCT_BYREF, byrefRegs, dst);
8926 // Some helper calls may be marked as not requiring GC info to be recorded.
8927 if ((!id->idIsNoGC()))
8929 // On ARM64, as on AMD64, we don't change the stack pointer to push/pop args.
8930 // So we're not really doing a "stack pop" here (note that "args" is 0), but we use this mechanism
8931 // to record the call for GC info purposes. (It might be best to use an alternate call,
8932 // and protect "emitStackPop" under the EMIT_TRACK_STACK_DEPTH preprocessor variable.)
8933 emitStackPop(dst, /*isCall*/ true, callInstrSize, /*args*/ 0);
8935 // Do we need to record a call location for GC purposes?
8937 if (!emitFullGCinfo)
8939 emitRecordGCcall(dst, callInstrSize);
8942 return callInstrSize;
8945 /*****************************************************************************
8947 * Emit a 32-bit Arm64 instruction
8950 /*static*/ unsigned emitter::emitOutput_Instr(BYTE* dst, code_t code)
8952 assert(sizeof(code_t) == 4);
8953 *((code_t*)dst) = code;
8955 return sizeof(code_t);
8958 /*****************************************************************************
8960 * Append the machine code corresponding to the given instruction descriptor
8961 * to the code block at '*dp'; the base of the code block is 'bp', and 'ig'
8962 * is the instruction group that contains the instruction. Updates '*dp' to
8963 * point past the generated code, and returns the size of the instruction
8964 * descriptor in bytes.
8967 size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
8972 size_t sz = emitGetInstrDescSize(id); // TODO-ARM64-Cleanup: on ARM, this is set in each case. why?
8973 instruction ins = id->idIns();
8974 insFormat fmt = id->idInsFmt();
8975 emitAttr size = id->idOpSize();
8976 unsigned char callInstrSize = 0;
8981 bool dspOffs = emitComp->opts.dspGCtbls;
8983 bool dspOffs = !emitComp->opts.disDiffable;
8987 assert(REG_NA == (int)REG_NA);
8989 VARSET_TP GCvars(VarSetOps::UninitVal());
8991 /* What instruction format have we got? */
9006 case IF_BI_0A: // BI_0A ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
9007 case IF_BI_0B: // BI_0B ......iiiiiiiiii iiiiiiiiiii..... simm19:00
9009 assert(id->idGCref() == GCT_NONE);
9010 assert(id->idIsBound());
9011 dst = emitOutputLJ(ig, dst, id);
9012 sz = sizeof(instrDescJmp);
9015 case IF_BI_0C: // BI_0C ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
9016 code = emitInsCode(ins, fmt);
9017 sz = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
9018 dst += emitOutputCall(ig, dst, id, code);
9019 // Always call RecordRelocation so that we wire in a JumpStub when we don't reach
9020 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_BRANCH26);
9023 case IF_BI_1A: // BI_1A ......iiiiiiiiii iiiiiiiiiiittttt Rt simm19:00
9024 assert(insOptsNone(id->idInsOpt()));
9025 assert(id->idIsBound());
9027 dst = emitOutputLJ(ig, dst, id);
9028 sz = sizeof(instrDescJmp);
9031 case IF_BI_1B: // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
9032 assert(insOptsNone(id->idInsOpt()));
9033 assert(id->idIsBound());
9035 dst = emitOutputLJ(ig, dst, id);
9036 sz = sizeof(instrDescJmp);
9039 case IF_BR_1A: // BR_1A ................ ......nnnnn..... Rn
9040 assert(insOptsNone(id->idInsOpt()));
9041 assert((ins == INS_ret) || (ins == INS_br));
9042 code = emitInsCode(ins, fmt);
9043 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9045 dst += emitOutput_Instr(dst, code);
9048 case IF_BR_1B: // BR_1B ................ ......nnnnn..... Rn
9049 assert(insOptsNone(id->idInsOpt()));
9050 assert((ins == INS_br_tail) || (ins == INS_blr));
9051 code = emitInsCode(ins, fmt);
9052 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9054 sz = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
9055 dst += emitOutputCall(ig, dst, id, code);
9058 case IF_LS_1A: // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB)
9060 assert(insOptsNone(id->idInsOpt()));
9061 assert(id->idIsBound());
9063 dst = emitOutputLJ(ig, dst, id);
9064 sz = sizeof(instrDescJmp);
9067 case IF_LS_2A: // LS_2A .X.......X...... ......nnnnnttttt Rt Rn
9068 assert(insOptsNone(id->idInsOpt()));
9069 code = emitInsCode(ins, fmt);
9070 // Is the target a vector register?
9071 if (isVectorRegister(id->idReg1()))
9073 code &= 0x3FFFFFFF; // clear the size bits
9074 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9075 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9079 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9080 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9082 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9083 dst += emitOutput_Instr(dst, code);
9086 case IF_LS_2B: // LS_2B .X.......Xiiiiii iiiiiinnnnnttttt Rt Rn imm(0-4095)
9087 assert(insOptsNone(id->idInsOpt()));
9088 imm = emitGetInsSC(id);
9089 assert(isValidUimm12(imm));
9090 code = emitInsCode(ins, fmt);
9091 // Is the target a vector register?
9092 if (isVectorRegister(id->idReg1()))
9094 code &= 0x3FFFFFFF; // clear the size bits
9095 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9096 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9100 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9101 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9103 code |= ((code_t)imm << 10); // iiiiiiiiiiii
9104 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9105 dst += emitOutput_Instr(dst, code);
9108 case IF_LS_2C: // LS_2C .X.......X.iiiii iiiiPPnnnnnttttt Rt Rn imm(-256..+255) no/pre/post inc
9109 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9110 imm = emitGetInsSC(id);
9111 assert((imm >= -256) && (imm <= 255)); // signed 9 bits
9112 imm &= 0x1ff; // force into unsigned 9 bit representation
9113 code = emitInsCode(ins, fmt);
9114 // Is the target a vector register?
9115 if (isVectorRegister(id->idReg1()))
9117 code &= 0x3FFFFFFF; // clear the size bits
9118 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9119 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9123 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9124 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9126 code |= insEncodeIndexedOpt(id->idInsOpt()); // PP
9127 code |= ((code_t)imm << 12); // iiiiiiiii
9128 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9129 dst += emitOutput_Instr(dst, code);
9132 case IF_LS_3A: // LS_3A .X.......X.mmmmm oooS..nnnnnttttt Rt Rn Rm ext(Rm) LSL {}
9133 assert(insOptsLSExtend(id->idInsOpt()));
9134 code = emitInsCode(ins, fmt);
9135 // Is the target a vector register?
9136 if (isVectorRegister(id->idReg1()))
9138 code &= 0x3FFFFFFF; // clear the size bits
9139 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9140 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9144 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9145 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9147 code |= insEncodeExtend(id->idInsOpt()); // ooo
9148 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9149 if (id->idIsLclVar())
9151 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9155 code |= insEncodeReg3Scale(id->idReg3Scaled()); // S
9156 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9158 dst += emitOutput_Instr(dst, code);
9161 case IF_LS_3B: // LS_3B X............... .aaaaannnnnddddd Rd Ra Rn
9162 assert(insOptsNone(id->idInsOpt()));
9163 code = emitInsCode(ins, fmt);
9164 // Is the target a vector register?
9165 if (isVectorRegister(id->idReg1()))
9167 code &= 0x3FFFFFFF; // clear the size bits
9168 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9169 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9170 code |= insEncodeReg_Va(id->idReg2()); // aaaaa
9174 code |= insEncodeDatasize(id->idOpSize()); // X
9175 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9176 code |= insEncodeReg_Ra(id->idReg2()); // aaaaa
9178 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9179 dst += emitOutput_Instr(dst, code);
9182 case IF_LS_3C: // LS_3C X......PP.iiiiii iaaaaannnnnddddd Rd Ra Rn imm(im7,sh)
9183 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9184 imm = emitGetInsSC(id);
9185 assert((imm >= -64) && (imm <= 63)); // signed 7 bits
9186 imm &= 0x7f; // force into unsigned 7 bit representation
9187 code = emitInsCode(ins, fmt);
9188 // Is the target a vector register?
9189 if (isVectorRegister(id->idReg1()))
9191 code &= 0x3FFFFFFF; // clear the size bits
9192 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9193 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9194 code |= insEncodeReg_Va(id->idReg2()); // aaaaa
9198 code |= insEncodeDatasize(id->idOpSize()); // X
9199 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9200 code |= insEncodeReg_Ra(id->idReg2()); // aaaaa
9202 code |= insEncodePairIndexedOpt(ins, id->idInsOpt()); // PP
9203 code |= ((code_t)imm << 15); // iiiiiiiii
9204 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9205 dst += emitOutput_Instr(dst, code);
9208 case IF_LS_3D: // LS_3D .X.......X.mmmmm ......nnnnnttttt Wm Rt Rn
9209 code = emitInsCode(ins, fmt);
9210 // Arm64 store exclusive unpredictable cases
9211 assert(id->idReg1() != id->idReg2());
9212 assert(id->idReg1() != id->idReg3());
9213 code |= insEncodeDatasizeLS(code, id->idOpSize()); // X
9214 code |= insEncodeReg_Rm(id->idReg1()); // mmmmm
9215 code |= insEncodeReg_Rt(id->idReg2()); // ttttt
9216 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9217 dst += emitOutput_Instr(dst, code);
9220 case IF_DI_1A: // DI_1A X.......shiiiiii iiiiiinnnnn..... Rn imm(i12,sh)
9221 assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9222 imm = emitGetInsSC(id);
9223 assert(isValidUimm12(imm));
9224 code = emitInsCode(ins, fmt);
9225 code |= insEncodeDatasize(id->idOpSize()); // X
9226 code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9227 code |= ((code_t)imm << 10); // iiiiiiiiiiii
9228 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9229 dst += emitOutput_Instr(dst, code);
9232 case IF_DI_1B: // DI_1B X........hwiiiii iiiiiiiiiiiddddd Rd imm(i16,hw)
9233 imm = emitGetInsSC(id);
9234 assert(isValidImmHWVal(imm, id->idOpSize()));
9235 code = emitInsCode(ins, fmt);
9236 code |= insEncodeDatasize(id->idOpSize()); // X
9237 code |= ((code_t)imm << 5); // hwiiiii iiiiiiiiiii
9238 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9239 dst += emitOutput_Instr(dst, code);
9242 case IF_DI_1C: // DI_1C X........Nrrrrrr ssssssnnnnn..... Rn imm(N,r,s)
9243 imm = emitGetInsSC(id);
9244 assert(isValidImmNRS(imm, id->idOpSize()));
9245 code = emitInsCode(ins, fmt);
9246 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9247 code |= insEncodeDatasize(id->idOpSize()); // X
9248 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9249 dst += emitOutput_Instr(dst, code);
9252 case IF_DI_1D: // DI_1D X........Nrrrrrr ssssss.....ddddd Rd imm(N,r,s)
9253 imm = emitGetInsSC(id);
9254 assert(isValidImmNRS(imm, id->idOpSize()));
9255 code = emitInsCode(ins, fmt);
9256 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9257 code |= insEncodeDatasize(id->idOpSize()); // X
9258 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9259 dst += emitOutput_Instr(dst, code);
9262 case IF_DI_1E: // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
9264 assert(insOptsNone(id->idInsOpt()));
9265 if (id->idIsReloc())
9267 code = emitInsCode(ins, fmt);
9268 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9269 dst += emitOutput_Instr(dst, code);
9270 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEBASE_REL21);
9274 // Local jmp/load case which does not need a relocation.
9275 assert(id->idIsBound());
9276 dst = emitOutputLJ(ig, dst, id);
9278 sz = sizeof(instrDescJmp);
9281 case IF_DI_1F: // DI_1F X..........iiiii cccc..nnnnn.nzcv Rn imm5 nzcv cond
9282 imm = emitGetInsSC(id);
9283 assert(isValidImmCondFlagsImm5(imm));
9286 cfi.immCFVal = (unsigned)imm;
9287 code = emitInsCode(ins, fmt);
9288 code |= insEncodeDatasize(id->idOpSize()); // X
9289 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9290 code |= ((code_t)cfi.imm5 << 16); // iiiii
9291 code |= insEncodeFlags(cfi.flags); // nzcv
9292 code |= insEncodeCond(cfi.cond); // cccc
9293 dst += emitOutput_Instr(dst, code);
9297 case IF_DI_2A: // DI_2A X.......shiiiiii iiiiiinnnnnddddd Rd Rn imm(i12,sh)
9298 assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9299 imm = emitGetInsSC(id);
9300 assert(isValidUimm12(imm));
9301 code = emitInsCode(ins, fmt);
9302 code |= insEncodeDatasize(id->idOpSize()); // X
9303 code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9304 code |= ((code_t)imm << 10); // iiiiiiiiiiii
9305 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9306 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9307 dst += emitOutput_Instr(dst, code);
9309 if (id->idIsReloc())
9311 assert(sz == sizeof(instrDesc));
9312 assert(id->idAddr()->iiaAddr != nullptr);
9313 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEOFFSET_12A);
9317 case IF_DI_2B: // DI_2B X.........Xnnnnn ssssssnnnnnddddd Rd Rn imm(0-63)
9318 code = emitInsCode(ins, fmt);
9319 imm = emitGetInsSC(id);
9320 assert(isValidImmShift(imm, id->idOpSize()));
9321 code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9322 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9323 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9324 code |= insEncodeReg_Rm(id->idReg2()); // Reg2 also in mmmmm
9325 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9326 dst += emitOutput_Instr(dst, code);
9329 case IF_DI_2C: // DI_2C X........Nrrrrrr ssssssnnnnnddddd Rd Rn imm(N,r,s)
9330 imm = emitGetInsSC(id);
9331 assert(isValidImmNRS(imm, id->idOpSize()));
9332 code = emitInsCode(ins, fmt);
9333 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9334 code |= insEncodeDatasize(id->idOpSize()); // X
9335 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9336 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9337 dst += emitOutput_Instr(dst, code);
9340 case IF_DI_2D: // DI_2D X........Nrrrrrr ssssssnnnnnddddd Rd Rn imr, imms (N,r,s)
9341 if (ins == INS_asr || ins == INS_lsl || ins == INS_lsr)
9343 imm = emitGetInsSC(id);
9344 assert(isValidImmShift(imm, id->idOpSize()));
9346 // Shift immediates are aliases of the SBFM/UBFM instructions
9347 // that actually take 2 registers and 2 constants,
9348 // Since we stored the shift immediate value
9349 // we need to calculate the N,R and S values here.
9354 bmi.immN = (size == EA_8BYTE) ? 1 : 0;
9356 bmi.immS = (size == EA_8BYTE) ? 0x3f : 0x1f;
9358 // immR and immS are now set correctly for INS_asr and INS_lsr
9359 // but for INS_lsl we have to adjust the values for immR and immS
9363 bmi.immR = -imm & bmi.immS;
9364 bmi.immS = bmi.immS - imm;
9367 // setup imm with the proper 13 bit value N:R:S
9373 // The other instructions have already have encoded N,R and S values
9374 imm = emitGetInsSC(id);
9376 assert(isValidImmNRS(imm, id->idOpSize()));
9378 code = emitInsCode(ins, fmt);
9379 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9380 code |= insEncodeDatasize(id->idOpSize()); // X
9381 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9382 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9383 dst += emitOutput_Instr(dst, code);
9386 case IF_DR_1D: // DR_1D X............... cccc.......ddddd Rd cond
9387 imm = emitGetInsSC(id);
9388 assert(isValidImmCond(imm));
9391 cfi.immCFVal = (unsigned)imm;
9392 code = emitInsCode(ins, fmt);
9393 code |= insEncodeDatasize(id->idOpSize()); // X
9394 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9395 code |= insEncodeInvertedCond(cfi.cond); // cccc
9396 dst += emitOutput_Instr(dst, code);
9400 case IF_DR_2A: // DR_2A X..........mmmmm ......nnnnn..... Rn Rm
9401 assert(insOptsNone(id->idInsOpt()));
9402 code = emitInsCode(ins, fmt);
9403 code |= insEncodeDatasize(id->idOpSize()); // X
9404 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9405 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9406 dst += emitOutput_Instr(dst, code);
9409 case IF_DR_2B: // DR_2B X.......sh.mmmmm ssssssnnnnn..... Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
9410 code = emitInsCode(ins, fmt);
9411 imm = emitGetInsSC(id);
9412 assert(isValidImmShift(imm, id->idOpSize()));
9413 code |= insEncodeDatasize(id->idOpSize()); // X
9414 code |= insEncodeShiftType(id->idInsOpt()); // sh
9415 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9416 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9417 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9418 dst += emitOutput_Instr(dst, code);
9421 case IF_DR_2C: // DR_2C X..........mmmmm ooosssnnnnn..... Rn Rm ext(Rm) LSL imm(0-4)
9422 code = emitInsCode(ins, fmt);
9423 imm = emitGetInsSC(id);
9424 assert((imm >= 0) && (imm <= 4)); // imm [0..4]
9425 code |= insEncodeDatasize(id->idOpSize()); // X
9426 code |= insEncodeExtend(id->idInsOpt()); // ooo
9427 code |= insEncodeExtendScale(imm); // sss
9428 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9429 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9430 dst += emitOutput_Instr(dst, code);
9433 case IF_DR_2D: // DR_2D X..........nnnnn cccc..nnnnnddddd Rd Rn cond
9434 imm = emitGetInsSC(id);
9435 assert(isValidImmCond(imm));
9438 cfi.immCFVal = (unsigned)imm;
9439 code = emitInsCode(ins, fmt);
9440 code |= insEncodeDatasize(id->idOpSize()); // X
9441 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9442 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9443 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9444 code |= insEncodeInvertedCond(cfi.cond); // cccc
9445 dst += emitOutput_Instr(dst, code);
9449 case IF_DR_2E: // DR_2E X..........mmmmm ...........ddddd Rd Rm
9450 code = emitInsCode(ins, fmt);
9451 code |= insEncodeDatasize(id->idOpSize()); // X
9452 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9453 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9454 dst += emitOutput_Instr(dst, code);
9457 case IF_DR_2F: // DR_2F X.......sh.mmmmm ssssss.....ddddd Rd Rm {LSL,LSR,ASR} imm(0-63)
9458 code = emitInsCode(ins, fmt);
9459 imm = emitGetInsSC(id);
9460 assert(isValidImmShift(imm, id->idOpSize()));
9461 code |= insEncodeDatasize(id->idOpSize()); // X
9462 code |= insEncodeShiftType(id->idInsOpt()); // sh
9463 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9464 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9465 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9466 dst += emitOutput_Instr(dst, code);
9469 case IF_DR_2G: // DR_2G X............... .....xnnnnnddddd Rd Rn
9470 code = emitInsCode(ins, fmt);
9471 code |= insEncodeDatasize(id->idOpSize()); // X
9474 if (size == EA_8BYTE)
9476 code |= 0x00000400; // x - bit at location 10
9479 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9480 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9481 dst += emitOutput_Instr(dst, code);
9484 case IF_DR_2H: // DR_2H X........X...... ......nnnnnddddd Rd Rn
9485 code = emitInsCode(ins, fmt);
9486 code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9487 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9488 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9489 dst += emitOutput_Instr(dst, code);
9492 case IF_DR_2I: // DR_2I X..........mmmmm cccc..nnnnn.nzcv Rn Rm nzcv cond
9493 imm = emitGetInsSC(id);
9494 assert(isValidImmCondFlags(imm));
9497 cfi.immCFVal = (unsigned)imm;
9498 code = emitInsCode(ins, fmt);
9499 code |= insEncodeDatasize(id->idOpSize()); // X
9500 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9501 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9502 code |= insEncodeFlags(cfi.flags); // nzcv
9503 code |= insEncodeCond(cfi.cond); // cccc
9504 dst += emitOutput_Instr(dst, code);
9508 case IF_DR_3A: // DR_3A X..........mmmmm ......nnnnnmmmmm Rd Rn Rm
9509 code = emitInsCode(ins, fmt);
9510 code |= insEncodeDatasize(id->idOpSize()); // X
9511 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9512 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9513 if (id->idIsLclVar())
9515 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9519 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9521 dst += emitOutput_Instr(dst, code);
9524 case IF_DR_3B: // DR_3B X.......sh.mmmmm ssssssnnnnnddddd Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
9525 code = emitInsCode(ins, fmt);
9526 imm = emitGetInsSC(id);
9527 assert(isValidImmShift(imm, id->idOpSize()));
9528 code |= insEncodeDatasize(id->idOpSize()); // X
9529 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9530 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9531 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9532 code |= insEncodeShiftType(id->idInsOpt()); // sh
9533 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9534 dst += emitOutput_Instr(dst, code);
9537 case IF_DR_3C: // DR_3C X..........mmmmm ooosssnnnnnddddd Rd Rn Rm ext(Rm) LSL imm(0-4)
9538 code = emitInsCode(ins, fmt);
9539 imm = emitGetInsSC(id);
9540 assert((imm >= 0) && (imm <= 4)); // imm [0..4]
9541 code |= insEncodeDatasize(id->idOpSize()); // X
9542 code |= insEncodeExtend(id->idInsOpt()); // ooo
9543 code |= insEncodeExtendScale(imm); // sss
9544 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9545 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9546 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9547 dst += emitOutput_Instr(dst, code);
9550 case IF_DR_3D: // DR_3D X..........mmmmm cccc..nnnnnddddd Rd Rn Rm cond
9551 imm = emitGetInsSC(id);
9552 assert(isValidImmCond(imm));
9555 cfi.immCFVal = (unsigned)imm;
9556 code = emitInsCode(ins, fmt);
9557 code |= insEncodeDatasize(id->idOpSize()); // X
9558 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9559 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9560 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9561 code |= insEncodeCond(cfi.cond); // cccc
9562 dst += emitOutput_Instr(dst, code);
9566 case IF_DR_3E: // DR_3E X........X.mmmmm ssssssnnnnnddddd Rd Rn Rm imm(0-63)
9567 code = emitInsCode(ins, fmt);
9568 imm = emitGetInsSC(id);
9569 assert(isValidImmShift(imm, id->idOpSize()));
9570 code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9571 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9572 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9573 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9574 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9575 dst += emitOutput_Instr(dst, code);
9578 case IF_DR_4A: // DR_4A X..........mmmmm .aaaaannnnnmmmmm Rd Rn Rm Ra
9579 code = emitInsCode(ins, fmt);
9580 code |= insEncodeDatasize(id->idOpSize()); // X
9581 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9582 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9583 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9584 code |= insEncodeReg_Ra(id->idReg4()); // aaaaa
9585 dst += emitOutput_Instr(dst, code);
9588 case IF_DV_1A: // DV_1A .........X.iiiii iii........ddddd Vd imm8 (fmov - immediate scalar)
9589 imm = emitGetInsSC(id);
9590 elemsize = id->idOpSize();
9591 code = emitInsCode(ins, fmt);
9592 code |= insEncodeFloatElemsize(elemsize); // X
9593 code |= ((code_t)imm << 13); // iiiii iii
9594 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9595 dst += emitOutput_Instr(dst, code);
9598 case IF_DV_1B: // DV_1B .QX..........iii cmod..iiiiiddddd Vd imm8 (immediate vector)
9599 imm = emitGetInsSC(id) & 0x0ff;
9600 immShift = (emitGetInsSC(id) & 0x700) >> 8;
9601 elemsize = optGetElemsize(id->idInsOpt());
9606 cmode = 0xE; // 1110
9610 cmode |= (immShift << 1); // 10x0
9616 cmode |= (immShift << 1); // 0xx0
9626 cmode = 0xE; // 1110
9633 code = emitInsCode(ins, fmt);
9634 code |= insEncodeVectorsize(id->idOpSize()); // Q
9635 if ((ins == INS_fmov) || (ins == INS_movi))
9637 if (elemsize == EA_8BYTE)
9639 code |= 0x20000000; // X
9642 if (ins != INS_fmov)
9644 assert((cmode >= 0) && (cmode <= 0xF));
9645 code |= (cmode << 12); // cmod
9647 code |= (((code_t)imm >> 5) << 16); // iii
9648 code |= (((code_t)imm & 0x1f) << 5); // iiiii
9649 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9650 dst += emitOutput_Instr(dst, code);
9653 case IF_DV_1C: // DV_1C .........X...... ......nnnnn..... Vn #0.0 (fcmp - with zero)
9654 elemsize = id->idOpSize();
9655 code = emitInsCode(ins, fmt);
9656 code |= insEncodeFloatElemsize(elemsize); // X
9657 code |= insEncodeReg_Vn(id->idReg1()); // nnnnn
9658 dst += emitOutput_Instr(dst, code);
9661 case IF_DV_2A: // DV_2A .Q.......X...... ......nnnnnddddd Vd Vn (fabs, fcvt - vector)
9662 elemsize = optGetElemsize(id->idInsOpt());
9663 code = emitInsCode(ins, fmt);
9664 code |= insEncodeVectorsize(id->idOpSize()); // Q
9665 code |= insEncodeFloatElemsize(elemsize); // X
9666 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9667 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9668 dst += emitOutput_Instr(dst, code);
9671 case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov/smov - to general)
9672 elemsize = id->idOpSize();
9673 index = emitGetInsSC(id);
9674 datasize = (elemsize == EA_8BYTE) ? EA_16BYTE : EA_8BYTE;
9675 if (ins == INS_smov)
9677 datasize = EA_16BYTE;
9679 code = emitInsCode(ins, fmt);
9680 code |= insEncodeVectorsize(datasize); // Q
9681 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9682 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9683 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9684 dst += emitOutput_Instr(dst, code);
9687 case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
9690 datasize = id->idOpSize();
9691 elemsize = optGetElemsize(id->idInsOpt());
9696 datasize = EA_16BYTE;
9697 elemsize = id->idOpSize();
9698 index = emitGetInsSC(id);
9700 code = emitInsCode(ins, fmt);
9701 code |= insEncodeVectorsize(datasize); // Q
9702 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9703 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9704 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9705 dst += emitOutput_Instr(dst, code);
9708 case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
9709 index = emitGetInsSC(id);
9710 elemsize = optGetElemsize(id->idInsOpt());
9711 code = emitInsCode(ins, fmt);
9712 code |= insEncodeVectorsize(id->idOpSize()); // Q
9713 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9714 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9715 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9716 dst += emitOutput_Instr(dst, code);
9719 case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
9720 index = emitGetInsSC(id);
9721 elemsize = id->idOpSize();
9722 code = emitInsCode(ins, fmt);
9723 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9724 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9725 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9726 dst += emitOutput_Instr(dst, code);
9729 case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
9730 elemsize = id->idOpSize();
9731 imm = emitGetInsSC(id);
9732 index = (imm >> 4) & 0xf;
9734 code = emitInsCode(ins, fmt);
9735 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9736 code |= insEncodeVectorIndex2(elemsize, index2); // jjjj
9737 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9738 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9739 dst += emitOutput_Instr(dst, code);
9742 case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov,fcvtXX - register)
9743 elemsize = id->idOpSize();
9744 code = emitInsCode(ins, fmt);
9745 code |= insEncodeFloatElemsize(elemsize); // X
9746 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9747 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9748 dst += emitOutput_Instr(dst, code);
9751 case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov - to general)
9752 elemsize = id->idOpSize();
9753 code = emitInsCode(ins, fmt);
9754 code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X X
9755 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9756 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9757 dst += emitOutput_Instr(dst, code);
9760 case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov - from general)
9761 elemsize = id->idOpSize();
9762 code = emitInsCode(ins, fmt);
9763 code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X X
9764 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9765 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9766 dst += emitOutput_Instr(dst, code);
9769 case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
9770 code = emitInsCode(ins, fmt);
9771 code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // SS DD
9772 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9773 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9774 dst += emitOutput_Instr(dst, code);
9777 case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
9778 elemsize = id->idOpSize();
9779 code = emitInsCode(ins, fmt);
9780 code |= insEncodeFloatElemsize(elemsize); // X
9781 code |= insEncodeReg_Vn(id->idReg1()); // nnnnn
9782 code |= insEncodeReg_Vm(id->idReg2()); // mmmmm
9783 dst += emitOutput_Instr(dst, code);
9786 case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
9787 elemsize = id->idOpSize();
9788 code = emitInsCode(ins, fmt);
9789 code |= insEncodeElemsize(elemsize); // XX
9790 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9791 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9792 dst += emitOutput_Instr(dst, code);
9795 case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
9796 elemsize = optGetElemsize(id->idInsOpt());
9797 code = emitInsCode(ins, fmt);
9798 code |= insEncodeVectorsize(id->idOpSize()); // Q
9799 code |= insEncodeElemsize(elemsize); // XX
9800 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9801 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9802 dst += emitOutput_Instr(dst, code);
9805 case IF_DV_2N: // DV_2N .........iiiiiii ......nnnnnddddd Vd Vn imm (shift - scalar)
9806 imm = emitGetInsSC(id);
9807 code = emitInsCode(ins, fmt);
9808 code |= insEncodeVectorShift(EA_8BYTE, imm); // iiiiiii
9809 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9810 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9811 dst += emitOutput_Instr(dst, code);
9814 case IF_DV_2O: // DV_2O .Q.......iiiiiii ......nnnnnddddd Vd Vn imm (shift - vector)
9815 imm = emitGetInsSC(id);
9816 elemsize = optGetElemsize(id->idInsOpt());
9817 code = emitInsCode(ins, fmt);
9818 code |= insEncodeVectorsize(id->idOpSize()); // Q
9819 code |= insEncodeVectorShift(elemsize, imm); // iiiiiii
9820 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9821 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9822 dst += emitOutput_Instr(dst, code);
9825 case IF_DV_2P: // DV_2P ............... ......nnnnnddddd Vd Vn (aes*)
9826 elemsize = optGetElemsize(id->idInsOpt());
9827 code = emitInsCode(ins, fmt);
9828 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9829 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9830 dst += emitOutput_Instr(dst, code);
9833 case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
9834 code = emitInsCode(ins, fmt);
9835 elemsize = optGetElemsize(id->idInsOpt());
9836 code |= insEncodeVectorsize(id->idOpSize()); // Q
9837 code |= insEncodeElemsize(elemsize); // XX
9838 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9839 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9840 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9841 dst += emitOutput_Instr(dst, code);
9844 case IF_DV_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector)
9845 code = emitInsCode(ins, fmt);
9846 imm = emitGetInsSC(id);
9847 elemsize = optGetElemsize(id->idInsOpt());
9848 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
9849 code |= insEncodeVectorsize(id->idOpSize()); // Q
9850 code |= insEncodeElemsize(elemsize); // XX
9851 code |= insEncodeVectorIndexLMH(elemsize, imm); // LM H
9852 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9853 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9854 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9855 dst += emitOutput_Instr(dst, code);
9858 case IF_DV_3B: // DV_3B .Q.......X.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
9859 code = emitInsCode(ins, fmt);
9860 elemsize = optGetElemsize(id->idInsOpt());
9861 code |= insEncodeVectorsize(id->idOpSize()); // Q
9862 code |= insEncodeFloatElemsize(elemsize); // X
9863 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9864 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9865 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9866 dst += emitOutput_Instr(dst, code);
9869 case IF_DV_3BI: // DV_3BI .Q.......XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
9870 code = emitInsCode(ins, fmt);
9871 imm = emitGetInsSC(id);
9872 elemsize = optGetElemsize(id->idInsOpt());
9873 assert(isValidVectorIndex(id->idOpSize(), elemsize, imm));
9874 code |= insEncodeVectorsize(id->idOpSize()); // Q
9875 code |= insEncodeFloatElemsize(elemsize); // X
9876 code |= insEncodeFloatIndex(elemsize, imm); // L H
9877 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9878 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9879 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9880 dst += emitOutput_Instr(dst, code);
9883 case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
9884 code = emitInsCode(ins, fmt);
9885 code |= insEncodeVectorsize(id->idOpSize()); // Q
9886 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9887 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9888 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9889 dst += emitOutput_Instr(dst, code);
9892 case IF_DV_3D: // DV_3D .........X.mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
9893 code = emitInsCode(ins, fmt);
9894 code |= insEncodeFloatElemsize(id->idOpSize()); // X
9895 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9896 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9897 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9898 dst += emitOutput_Instr(dst, code);
9901 case IF_DV_3DI: // DV_3DI .........XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (scalar by elem)
9902 code = emitInsCode(ins, fmt);
9903 imm = emitGetInsSC(id);
9904 elemsize = id->idOpSize();
9905 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
9906 code |= insEncodeFloatElemsize(elemsize); // X
9907 code |= insEncodeFloatIndex(elemsize, imm); // L H
9908 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9909 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9910 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9911 dst += emitOutput_Instr(dst, code);
9914 case IF_DV_3E: // DV_3E ...........mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
9915 code = emitInsCode(ins, fmt);
9916 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9917 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9918 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9919 dst += emitOutput_Instr(dst, code);
9922 case IF_DV_4A: // DV_4A .........X.mmmmm .aaaaannnnnddddd Vd Va Vn Vm (scalar)
9923 code = emitInsCode(ins, fmt);
9924 elemsize = id->idOpSize();
9925 code |= insEncodeFloatElemsize(elemsize); // X
9926 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9927 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9928 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9929 code |= insEncodeReg_Va(id->idReg4()); // aaaaa
9930 dst += emitOutput_Instr(dst, code);
9933 case IF_SN_0A: // SN_0A ................ ................
9934 code = emitInsCode(ins, fmt);
9935 dst += emitOutput_Instr(dst, code);
9938 case IF_SI_0A: // SI_0A ...........iiiii iiiiiiiiiii..... imm16
9939 imm = emitGetInsSC(id);
9940 assert(isValidUimm16(imm));
9941 code = emitInsCode(ins, fmt);
9942 code |= ((code_t)imm << 5); // iiiii iiiiiiiiiii
9943 dst += emitOutput_Instr(dst, code);
9946 case IF_SI_0B: // SI_0B ................ ....bbbb........ imm4 - barrier
9947 imm = emitGetInsSC(id);
9948 assert((imm >= 0) && (imm <= 15));
9949 code = emitInsCode(ins, fmt);
9950 code |= ((code_t)imm << 8); // bbbb
9951 dst += emitOutput_Instr(dst, code);
9955 assert(!"Unexpected format");
9959 // Determine if any registers now hold GC refs, or whether a register that was overwritten held a GC ref.
9960 // We assume here that "id->idGCref()" is not GC_NONE only if the instruction described by "id" writes a
9961 // GC ref to register "id->idReg1()". (It may, apparently, also not be GC_NONE in other cases, such as
9962 // for stores, but we ignore those cases here.)
9963 if (emitInsMayWriteToGCReg(id)) // True if "id->idIns()" writes to a register than can hold GC ref.
9965 // We assume that "idReg1" is the primary destination register for all instructions
9966 if (id->idGCref() != GCT_NONE)
9968 emitGCregLiveUpd(id->idGCref(), id->idReg1(), dst);
9972 emitGCregDeadUpd(id->idReg1(), dst);
9975 if (emitInsMayWriteMultipleRegs(id))
9978 // "idReg2" is the secondary destination register
9979 if (id->idGCrefReg2() != GCT_NONE)
9981 emitGCregLiveUpd(id->idGCrefReg2(), id->idReg2(), dst);
9985 emitGCregDeadUpd(id->idReg2(), dst);
9990 // Now we determine if the instruction has written to a (local variable) stack location, and either written a GC
9991 // ref or overwritten one.
9992 if (emitInsWritesToLclVarStackLoc(id) || emitInsWritesToLclVarStackLocPair(id))
9994 int varNum = id->idAddr()->iiaLclVar.lvaVarNum();
9995 unsigned ofs = AlignDown(id->idAddr()->iiaLclVar.lvaOffset(), TARGET_POINTER_SIZE);
9997 int adr = emitComp->lvaFrameAddress(varNum, &FPbased);
9998 if (id->idGCref() != GCT_NONE)
10000 emitGCvarLiveUpd(adr + ofs, varNum, id->idGCref(), dst);
10004 // If the type of the local is a gc ref type, update the liveness.
10008 // "Regular" (non-spill-temp) local.
10009 vt = var_types(emitComp->lvaTable[varNum].lvType);
10013 TempDsc* tmpDsc = emitComp->tmpFindNum(varNum);
10014 vt = tmpDsc->tdTempType();
10016 if (vt == TYP_REF || vt == TYP_BYREF)
10017 emitGCvarDeadUpd(adr + ofs, dst);
10019 if (emitInsWritesToLclVarStackLocPair(id))
10021 unsigned ofs2 = ofs + TARGET_POINTER_SIZE;
10022 if (id->idGCrefReg2() != GCT_NONE)
10024 emitGCvarLiveUpd(adr + ofs2, varNum, id->idGCrefReg2(), dst);
10028 // If the type of the local is a gc ref type, update the liveness.
10032 // "Regular" (non-spill-temp) local.
10033 vt = var_types(emitComp->lvaTable[varNum].lvType);
10037 TempDsc* tmpDsc = emitComp->tmpFindNum(varNum);
10038 vt = tmpDsc->tdTempType();
10040 if (vt == TYP_REF || vt == TYP_BYREF)
10041 emitGCvarDeadUpd(adr + ofs2, dst);
10047 /* Make sure we set the instruction descriptor size correctly */
10049 size_t expected = emitSizeOfInsDsc(id);
10050 assert(sz == expected);
10052 if (emitComp->opts.disAsm || emitComp->opts.dspEmit || emitComp->verbose)
10054 emitDispIns(id, false, dspOffs, true, emitCurCodeOffs(odst), *dp, (dst - *dp), ig);
10057 if (emitComp->compDebugBreak)
10059 // For example, set JitBreakEmitOutputInstr=a6 will break when this method is called for
10060 // emitting instruction a6, (i.e. IN00a6 in jitdump).
10061 if ((unsigned)JitConfig.JitBreakEmitOutputInstr() == id->idDebugOnlyInfo()->idNum)
10063 assert(!"JitBreakEmitOutputInstr reached");
10068 /* All instructions are expected to generate code */
10070 assert(*dp != dst);
10077 /*****************************************************************************/
10078 /*****************************************************************************/
10082 /*****************************************************************************
10084 * Display the instruction name
10086 void emitter::emitDispInst(instruction ins)
10088 const char* insstr = codeGen->genInsName(ins);
10089 size_t len = strlen(insstr);
10091 /* Display the instruction name */
10093 printf("%s", insstr);
10096 // Add at least one space after the instruction name
10097 // and add spaces until we have reach the normal size of 8
10105 /*****************************************************************************
10107 * Display an reloc value
10108 * If we are formatting for an assembly listing don't print the hex value
10109 * since it will prevent us from doing assembly diffs
10111 void emitter::emitDispReloc(int value, bool addComma)
10113 if (emitComp->opts.disAsm)
10119 printf("(reloc 0x%x)", dspPtr(value));
10126 /*****************************************************************************
10128 * Display an immediate value
10130 void emitter::emitDispImm(ssize_t imm, bool addComma, bool alwaysHex /* =false */)
10137 // Munge any pointers if we want diff-able disassembly.
10138 // Since some may be emitted as partial words, print as diffable anything that has
10139 // significant bits beyond the lowest 8-bits.
10140 if (emitComp->opts.disDiffable)
10142 ssize_t top56bits = (imm >> 8);
10143 if ((top56bits != 0) && (top56bits != -1))
10147 if (!alwaysHex && (imm > -1000) && (imm < 1000))
10153 if ((imm < 0) && ((imm & 0xFFFFFFFF00000000LL) == 0xFFFFFFFF00000000LL))
10159 if ((imm & 0xFFFFFFFF00000000LL) != 0)
10161 printf("0x%llx", imm);
10165 printf("0x%02x", imm);
10173 /*****************************************************************************
10175 * Display a float zero constant
10177 void emitter::emitDispFloatZero()
10186 /*****************************************************************************
10188 * Display an encoded float constant value
10190 void emitter::emitDispFloatImm(ssize_t imm8)
10192 assert((0 <= imm8) && (imm8 <= 0x0ff));
10199 fpImm.immFPIVal = (unsigned)imm8;
10200 double result = emitDecodeFloatImm8(fpImm);
10202 printf("%.4f", result);
10205 /*****************************************************************************
10207 * Display an immediate that is optionally LSL12.
10209 void emitter::emitDispImmOptsLSL12(ssize_t imm, insOpts opt)
10211 if (!strictArmAsm && insOptsLSL12(opt))
10215 emitDispImm(imm, false);
10216 if (strictArmAsm && insOptsLSL12(opt))
10218 printf(", LSL #12");
10222 /*****************************************************************************
10224 * Display an ARM64 condition code for the conditional instructions
10226 void emitter::emitDispCond(insCond cond)
10228 const static char* armCond[16] = {"eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc",
10229 "hi", "ls", "ge", "lt", "gt", "le", "AL", "NV"}; // The last two are invalid
10230 unsigned imm = (unsigned)cond;
10231 assert((0 <= imm) && (imm < ArrLen(armCond)));
10232 printf(armCond[imm]);
10235 /*****************************************************************************
10237 * Display an ARM64 flags for the conditional instructions
10239 void emitter::emitDispFlags(insCflags flags)
10241 const static char* armFlags[16] = {"0", "v", "c", "cv", "z", "zv", "zc", "zcv",
10242 "n", "nv", "nc", "ncv", "nz", "nzv", "nzc", "nzcv"};
10243 unsigned imm = (unsigned)flags;
10244 assert((0 <= imm) && (imm < ArrLen(armFlags)));
10245 printf(armFlags[imm]);
10248 /*****************************************************************************
10250 * Display an ARM64 'barrier' for the memory barrier instructions
10252 void emitter::emitDispBarrier(insBarrier barrier)
10254 const static char* armBarriers[16] = {"#0", "oshld", "oshst", "osh", "#4", "nshld", "nshst", "nsh",
10255 "#8", "ishld", "ishst", "ish", "#12", "ld", "st", "sy"};
10256 unsigned imm = (unsigned)barrier;
10257 assert((0 <= imm) && (imm < ArrLen(armBarriers)));
10258 printf(armBarriers[imm]);
10261 /*****************************************************************************
10263 * Prints the encoding for the Shift Type encoding
10266 void emitter::emitDispShiftOpts(insOpts opt)
10268 if (opt == INS_OPTS_LSL)
10270 else if (opt == INS_OPTS_LSR)
10272 else if (opt == INS_OPTS_ASR)
10274 else if (opt == INS_OPTS_ROR)
10276 else if (opt == INS_OPTS_MSL)
10279 assert(!"Bad value");
10282 /*****************************************************************************
10284 * Prints the encoding for the Extend Type encoding
10287 void emitter::emitDispExtendOpts(insOpts opt)
10289 if (opt == INS_OPTS_UXTB)
10291 else if (opt == INS_OPTS_UXTH)
10293 else if (opt == INS_OPTS_UXTW)
10295 else if (opt == INS_OPTS_UXTX)
10297 else if (opt == INS_OPTS_SXTB)
10299 else if (opt == INS_OPTS_SXTH)
10301 else if (opt == INS_OPTS_SXTW)
10303 else if (opt == INS_OPTS_SXTX)
10306 assert(!"Bad value");
10309 /*****************************************************************************
10311 * Prints the encoding for the Extend Type encoding in loads/stores
10314 void emitter::emitDispLSExtendOpts(insOpts opt)
10316 if (opt == INS_OPTS_LSL)
10318 else if (opt == INS_OPTS_UXTW)
10320 else if (opt == INS_OPTS_UXTX)
10322 else if (opt == INS_OPTS_SXTW)
10324 else if (opt == INS_OPTS_SXTX)
10327 assert(!"Bad value");
10330 /*****************************************************************************
10332 * Display a register
10334 void emitter::emitDispReg(regNumber reg, emitAttr attr, bool addComma)
10336 emitAttr size = EA_SIZE(attr);
10337 printf(emitRegName(reg, size));
10343 /*****************************************************************************
10345 * Display a vector register with an arrangement suffix
10347 void emitter::emitDispVectorReg(regNumber reg, insOpts opt, bool addComma)
10349 assert(isVectorRegister(reg));
10350 printf(emitVectorRegName(reg));
10351 emitDispArrangement(opt);
10357 /*****************************************************************************
10359 * Display an vector register index suffix
10361 void emitter::emitDispVectorRegIndex(regNumber reg, emitAttr elemsize, ssize_t index, bool addComma)
10363 assert(isVectorRegister(reg));
10364 printf(emitVectorRegName(reg));
10381 assert(!"invalid elemsize");
10385 printf("[%d]", index);
10391 /*****************************************************************************
10393 * Display an arrangement suffix
10395 void emitter::emitDispArrangement(insOpts opt)
10397 const char* str = "???";
10427 assert(!"Invalid insOpt for vector register");
10433 /*****************************************************************************
10435 * Display a register with an optional shift operation
10437 void emitter::emitDispShiftedReg(regNumber reg, insOpts opt, ssize_t imm, emitAttr attr)
10439 emitAttr size = EA_SIZE(attr);
10440 assert((imm & 0x003F) == imm);
10441 assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
10443 printf(emitRegName(reg, size));
10451 emitDispShiftOpts(opt);
10452 emitDispImm(imm, false);
10456 /*****************************************************************************
10458 * Display a register with an optional extend and scale operations
10460 void emitter::emitDispExtendReg(regNumber reg, insOpts opt, ssize_t imm)
10462 assert((imm >= 0) && (imm <= 4));
10463 assert(insOptsNone(opt) || insOptsAnyExtend(opt) || (opt == INS_OPTS_LSL));
10465 // size is based on the extend option, not the instr size.
10466 emitAttr size = insOpts32BitExtend(opt) ? EA_4BYTE : EA_8BYTE;
10470 if (insOptsNone(opt))
10472 emitDispReg(reg, size, false);
10476 emitDispReg(reg, size, true);
10477 if (opt == INS_OPTS_LSL)
10480 emitDispExtendOpts(opt);
10481 if ((imm > 0) || (opt == INS_OPTS_LSL))
10484 emitDispImm(imm, false);
10488 else // !strictArmAsm
10490 if (insOptsNone(opt))
10492 emitDispReg(reg, size, false);
10496 if (opt != INS_OPTS_LSL)
10498 emitDispExtendOpts(opt);
10500 emitDispReg(reg, size, false);
10507 emitDispImm(1 << imm, false);
10512 /*****************************************************************************
10514 * Display an addressing operand [reg + imm]
10516 void emitter::emitDispAddrRI(regNumber reg, insOpts opt, ssize_t imm)
10518 reg = encodingZRtoSP(reg); // ZR (R31) encodes the SP register
10524 emitDispReg(reg, EA_8BYTE, false);
10526 if (!insOptsPostIndex(opt) && (imm != 0))
10529 emitDispImm(imm, false);
10533 if (insOptsPreIndex(opt))
10537 else if (insOptsPostIndex(opt))
10540 emitDispImm(imm, false);
10543 else // !strictArmAsm
10547 const char* operStr = "++";
10554 if (insOptsPreIndex(opt))
10559 emitDispReg(reg, EA_8BYTE, false);
10561 if (insOptsPostIndex(opt))
10566 if (insOptsIndexed(opt))
10572 printf("%c", operStr[1]);
10574 emitDispImm(imm, false);
10579 /*****************************************************************************
10581 * Display an addressing operand [reg + extended reg]
10583 void emitter::emitDispAddrRRExt(regNumber reg1, regNumber reg2, insOpts opt, bool isScaled, emitAttr size)
10585 reg1 = encodingZRtoSP(reg1); // ZR (R31) encodes the SP register
10587 unsigned scale = 0;
10590 scale = NaturalScale_helper(size);
10597 emitDispReg(reg1, EA_8BYTE, true);
10598 emitDispExtendReg(reg2, opt, scale);
10600 else // !strictArmAsm
10602 emitDispReg(reg1, EA_8BYTE, false);
10604 emitDispExtendReg(reg2, opt, scale);
10610 /*****************************************************************************
10612 * Display (optionally) the instruction encoding in hex
10615 void emitter::emitDispInsHex(BYTE* code, size_t sz)
10617 // We do not display the instruction hex if we want diff-able disassembly
10618 if (!emitComp->opts.disDiffable)
10622 printf(" %08X ", (*((code_t*)code)));
10631 /****************************************************************************
10633 * Display the given instruction.
10636 void emitter::emitDispIns(
10637 instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* pCode, size_t sz, insGroup* ig)
10642 id->idDebugOnlyInfo()->idNum; // Do not remove this! It is needed for VisualStudio conditional breakpoints
10644 printf("IN%04x: ", idNum);
10650 if (!emitComp->opts.dspEmit && !isNew && !asmfm && sz)
10653 /* Display the instruction offset */
10655 emitDispInsOffs(offset, doffs);
10657 /* Display the instruction hex code */
10659 emitDispInsHex(pCode, sz);
10663 /* Get the instruction and format */
10665 instruction ins = id->idIns();
10666 insFormat fmt = id->idInsFmt();
10670 /* If this instruction has just been added, check its size */
10672 assert(isNew == false || (int)emitSizeOfInsDsc(id) == emitCurIGfreeNext - (BYTE*)id);
10674 /* Figure out the operand size */
10675 emitAttr size = id->idOpSize();
10676 emitAttr attr = size;
10677 if (id->idGCref() == GCT_GCREF)
10679 else if (id->idGCref() == GCT_BYREF)
10687 bool isExtendAlias;
10696 const char* methodName;
10704 case IF_BI_0A: // BI_0A ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
10705 case IF_BI_0B: // BI_0B ......iiiiiiiiii iiiiiiiiiii..... simm19:00
10708 if (fmt == IF_LARGEJMP)
10710 printf("(LARGEJMP)");
10712 if (id->idAddr()->iiaHasInstrCount())
10714 int instrCount = id->idAddr()->iiaGetInstrCount();
10718 printf("pc%s%d instructions", (instrCount >= 0) ? "+" : "", instrCount);
10722 unsigned insNum = emitFindInsNum(ig, id);
10723 UNATIVE_OFFSET srcOffs = ig->igOffs + emitFindOffset(ig, insNum + 1);
10724 UNATIVE_OFFSET dstOffs = ig->igOffs + emitFindOffset(ig, insNum + 1 + instrCount);
10725 ssize_t relOffs = (ssize_t)(emitOffsetToPtr(dstOffs) - emitOffsetToPtr(srcOffs));
10726 printf("pc%s%d (%d instructions)", (relOffs >= 0) ? "+" : "", relOffs, instrCount);
10729 else if (id->idIsBound())
10731 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10735 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10740 case IF_BI_0C: // BI_0C ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
10741 if (id->idIsCallAddr())
10743 offs = (ssize_t)id->idAddr()->iiaAddr;
10749 methodName = emitComp->eeGetMethodFullName((CORINFO_METHOD_HANDLE)id->idDebugOnlyInfo()->idMemCookie);
10754 if (id->idIsDspReloc())
10756 printf("%08X", offs);
10760 printf("%s", methodName);
10764 case IF_BI_1A: // BI_1A ......iiiiiiiiii iiiiiiiiiiittttt Rt simm19:00
10765 assert(insOptsNone(id->idInsOpt()));
10766 emitDispReg(id->idReg1(), size, true);
10767 if (id->idIsBound())
10769 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10773 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10777 case IF_BI_1B: // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
10778 assert(insOptsNone(id->idInsOpt()));
10779 emitDispReg(id->idReg1(), size, true);
10780 emitDispImm(emitGetInsSC(id), true);
10781 if (id->idIsBound())
10783 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10787 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10791 case IF_BR_1A: // BR_1A ................ ......nnnnn..... Rn
10792 assert(insOptsNone(id->idInsOpt()));
10793 emitDispReg(id->idReg1(), size, false);
10796 case IF_BR_1B: // BR_1B ................ ......nnnnn..... Rn
10797 assert(insOptsNone(id->idInsOpt()));
10798 emitDispReg(id->idReg3(), size, false);
10801 case IF_LS_1A: // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB)
10802 case IF_DI_1E: // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
10805 assert(insOptsNone(id->idInsOpt()));
10806 emitDispReg(id->idReg1(), size, true);
10807 imm = emitGetInsSC(id);
10809 /* Is this actually a reference to a data section? */
10810 if (fmt == IF_LARGEADR)
10812 printf("(LARGEADR)");
10814 else if (fmt == IF_LARGELDC)
10816 printf("(LARGELDC)");
10820 if (id->idAddr()->iiaIsJitDataOffset())
10822 doffs = Compiler::eeGetJitDataOffs(id->idAddr()->iiaFieldHnd);
10823 /* Display a data section reference */
10826 printf("@CNS%02u", doffs - 1);
10828 printf("@RWD%02u", doffs);
10831 printf("%+Id", imm);
10836 if (id->idIsReloc())
10839 emitDispImm((ssize_t)id->idAddr()->iiaAddr, false);
10841 else if (id->idIsBound())
10843 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10847 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10853 case IF_LS_2A: // LS_2A .X.......X...... ......nnnnnttttt Rt Rn
10854 assert(insOptsNone(id->idInsOpt()));
10855 assert(emitGetInsSC(id) == 0);
10856 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10857 emitDispAddrRI(id->idReg2(), id->idInsOpt(), 0);
10860 case IF_LS_2B: // LS_2B .X.......Xiiiiii iiiiiinnnnnttttt Rt Rn imm(0-4095)
10861 assert(insOptsNone(id->idInsOpt()));
10862 imm = emitGetInsSC(id);
10863 scale = NaturalScale_helper(emitInsLoadStoreSize(id));
10864 imm <<= scale; // The immediate is scaled by the size of the ld/st
10865 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10866 emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
10869 case IF_LS_2C: // LS_2C .X.......X.iiiii iiiiPPnnnnnttttt Rt Rn imm(-256..+255) no/pre/post inc
10870 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
10871 imm = emitGetInsSC(id);
10872 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10873 emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
10876 case IF_LS_3A: // LS_3A .X.......X.mmmmm oooS..nnnnnttttt Rt Rn Rm ext(Rm) LSL {}
10877 assert(insOptsLSExtend(id->idInsOpt()));
10878 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10879 if (id->idIsLclVar())
10881 emitDispAddrRRExt(id->idReg2(), codeGen->rsGetRsvdReg(), id->idInsOpt(), false, size);
10885 emitDispAddrRRExt(id->idReg2(), id->idReg3(), id->idInsOpt(), id->idReg3Scaled(), size);
10889 case IF_LS_3B: // LS_3B X............... .aaaaannnnnddddd Rt Ra Rn
10890 assert(insOptsNone(id->idInsOpt()));
10891 assert(emitGetInsSC(id) == 0);
10892 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10893 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10894 emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
10897 case IF_LS_3C: // LS_3C X.........iiiiii iaaaaannnnnddddd Rt Ra Rn imm(im7,sh)
10898 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
10899 imm = emitGetInsSC(id);
10900 scale = NaturalScale_helper(emitInsLoadStoreSize(id));
10902 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10903 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10904 emitDispAddrRI(id->idReg3(), id->idInsOpt(), imm);
10907 case IF_LS_3D: // LS_3D .X.......X.mmmmm ......nnnnnttttt Wm Rt Rn
10908 assert(insOptsNone(id->idInsOpt()));
10909 emitDispReg(id->idReg1(), EA_4BYTE, true);
10910 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10911 emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
10914 case IF_DI_1A: // DI_1A X.......shiiiiii iiiiiinnnnn..... Rn imm(i12,sh)
10915 emitDispReg(id->idReg1(), size, true);
10916 emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
10919 case IF_DI_1B: // DI_1B X........hwiiiii iiiiiiiiiiiddddd Rd imm(i16,hw)
10920 emitDispReg(id->idReg1(), size, true);
10921 hwi.immHWVal = (unsigned)emitGetInsSC(id);
10922 if (ins == INS_mov)
10924 emitDispImm(emitDecodeHalfwordImm(hwi, size), false);
10926 else // movz, movn, movk
10928 emitDispImm(hwi.immVal, false);
10929 if (hwi.immHW != 0)
10931 emitDispShiftOpts(INS_OPTS_LSL);
10932 emitDispImm(hwi.immHW * 16, false);
10937 case IF_DI_1C: // DI_1C X........Nrrrrrr ssssssnnnnn..... Rn imm(N,r,s)
10938 emitDispReg(id->idReg1(), size, true);
10939 bmi.immNRS = (unsigned)emitGetInsSC(id);
10940 emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
10943 case IF_DI_1D: // DI_1D X........Nrrrrrr ssssss.....ddddd Rd imm(N,r,s)
10944 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
10945 bmi.immNRS = (unsigned)emitGetInsSC(id);
10946 emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
10949 case IF_DI_2A: // DI_2A X.......shiiiiii iiiiiinnnnnddddd Rd Rn imm(i12,sh)
10950 if ((ins == INS_add) || (ins == INS_sub))
10952 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
10953 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
10957 emitDispReg(id->idReg1(), size, true);
10958 emitDispReg(id->idReg2(), size, true);
10960 emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
10963 case IF_DI_2B: // DI_2B X........X.nnnnn ssssssnnnnnddddd Rd Rn imm(0-63)
10964 emitDispReg(id->idReg1(), size, true);
10965 emitDispReg(id->idReg2(), size, true);
10966 emitDispImm(emitGetInsSC(id), false);
10969 case IF_DI_2C: // DI_2C X........Nrrrrrr ssssssnnnnnddddd Rd Rn imm(N,r,s)
10970 if (ins == INS_ands)
10972 emitDispReg(id->idReg1(), size, true);
10976 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
10978 emitDispReg(id->idReg2(), size, true);
10979 bmi.immNRS = (unsigned)emitGetInsSC(id);
10980 emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
10983 case IF_DI_2D: // DI_2D X........Nrrrrrr ssssssnnnnnddddd Rd Rn imr, ims (N,r,s)
10984 emitDispReg(id->idReg1(), size, true);
10985 emitDispReg(id->idReg2(), size, true);
10987 imm = emitGetInsSC(id);
10988 bmi.immNRS = (unsigned)imm;
10995 emitDispImm(bmi.immR, true);
10996 emitDispImm(bmi.immS, false);
11002 emitDispImm(getBitWidth(size) - bmi.immR, true);
11003 emitDispImm(bmi.immS + 1, false);
11009 emitDispImm(bmi.immR, true);
11010 emitDispImm(bmi.immS - bmi.immR + 1, false);
11016 emitDispImm(imm, false);
11020 assert(!"Unexpected instruction in IF_DI_2D");
11025 case IF_DI_1F: // DI_1F X..........iiiii cccc..nnnnn.nzcv Rn imm5 nzcv cond
11026 emitDispReg(id->idReg1(), size, true);
11027 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11028 emitDispImm(cfi.imm5, true);
11029 emitDispFlags(cfi.flags);
11031 emitDispCond(cfi.cond);
11034 case IF_DR_1D: // DR_1D X............... cccc.......mmmmm Rd cond
11035 emitDispReg(id->idReg1(), size, true);
11036 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11037 emitDispCond(cfi.cond);
11040 case IF_DR_2A: // DR_2A X..........mmmmm ......nnnnn..... Rn Rm
11041 emitDispReg(id->idReg1(), size, true);
11042 emitDispReg(id->idReg2(), size, false);
11045 case IF_DR_2B: // DR_2B X.......sh.mmmmm ssssssnnnnn..... Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
11046 emitDispReg(id->idReg1(), size, true);
11047 emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
11050 case IF_DR_2C: // DR_2C X..........mmmmm ooosssnnnnn..... Rn Rm ext(Rm) LSL imm(0-4)
11051 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11052 imm = emitGetInsSC(id);
11053 emitDispExtendReg(id->idReg2(), id->idInsOpt(), imm);
11056 case IF_DR_2D: // DR_2D X..........nnnnn cccc..nnnnnddddd Rd Rn cond
11057 emitDispReg(id->idReg1(), size, true);
11058 emitDispReg(id->idReg2(), size, true);
11059 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11060 emitDispCond(cfi.cond);
11063 case IF_DR_2E: // DR_2E X..........mmmmm ...........ddddd Rd Rm
11064 emitDispReg(id->idReg1(), size, true);
11065 emitDispReg(id->idReg2(), size, false);
11068 case IF_DR_2F: // DR_2F X.......sh.mmmmm ssssss.....ddddd Rd Rm {LSL,LSR,ASR} imm(0-63)
11069 emitDispReg(id->idReg1(), size, true);
11070 emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
11073 case IF_DR_2G: // DR_2G X............... ......nnnnnddddd Rd Rn
11074 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11075 emitDispReg(encodingZRtoSP(id->idReg2()), size, false);
11078 case IF_DR_2H: // DR_2H X........X...... ......nnnnnddddd Rd Rn
11079 emitDispReg(id->idReg1(), size, true);
11080 emitDispReg(id->idReg2(), size, false);
11083 case IF_DR_2I: // DR_2I X..........mmmmm cccc..nnnnn.nzcv Rn Rm nzcv cond
11084 emitDispReg(id->idReg1(), size, true);
11085 emitDispReg(id->idReg2(), size, true);
11086 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11087 emitDispFlags(cfi.flags);
11089 emitDispCond(cfi.cond);
11092 case IF_DR_3A: // DR_3A X..........mmmmm ......nnnnnmmmmm Rd Rn Rm
11093 if ((ins == INS_add) || (ins == INS_sub))
11095 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11096 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11098 else if ((ins == INS_smull) || (ins == INS_smulh))
11100 // Rd is always 8 bytes
11101 emitDispReg(id->idReg1(), EA_8BYTE, true);
11103 // Rn, Rm effective size depends on instruction type
11104 size = (ins == INS_smulh) ? EA_8BYTE : EA_4BYTE;
11105 emitDispReg(id->idReg2(), size, true);
11109 emitDispReg(id->idReg1(), size, true);
11110 emitDispReg(id->idReg2(), size, true);
11112 if (id->idIsLclVar())
11114 emitDispReg(codeGen->rsGetRsvdReg(), size, false);
11118 emitDispReg(id->idReg3(), size, false);
11123 case IF_DR_3B: // DR_3B X.......sh.mmmmm ssssssnnnnnddddd Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
11124 emitDispReg(id->idReg1(), size, true);
11125 emitDispReg(id->idReg2(), size, true);
11126 emitDispShiftedReg(id->idReg3(), id->idInsOpt(), emitGetInsSC(id), size);
11129 case IF_DR_3C: // DR_3C X..........mmmmm ooosssnnnnnddddd Rd Rn Rm ext(Rm) LSL imm(0-4)
11130 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11131 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11132 imm = emitGetInsSC(id);
11133 emitDispExtendReg(id->idReg3(), id->idInsOpt(), imm);
11136 case IF_DR_3D: // DR_3D X..........mmmmm cccc..nnnnnmmmmm Rd Rn Rm cond
11137 emitDispReg(id->idReg1(), size, true);
11138 emitDispReg(id->idReg2(), size, true);
11139 emitDispReg(id->idReg3(), size, true);
11140 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11141 emitDispCond(cfi.cond);
11144 case IF_DR_3E: // DR_3E X........X.mmmmm ssssssnnnnnddddd Rd Rn Rm imm(0-63)
11145 emitDispReg(id->idReg1(), size, true);
11146 emitDispReg(id->idReg2(), size, true);
11147 emitDispReg(id->idReg3(), size, true);
11148 emitDispImm(emitGetInsSC(id), false);
11151 case IF_DR_4A: // DR_4A X..........mmmmm .aaaaannnnnmmmmm Rd Rn Rm Ra
11152 emitDispReg(id->idReg1(), size, true);
11153 emitDispReg(id->idReg2(), size, true);
11154 emitDispReg(id->idReg3(), size, true);
11155 emitDispReg(id->idReg4(), size, false);
11158 case IF_DV_1A: // DV_1A .........X.iiiii iii........ddddd Vd imm8 (fmov - immediate scalar)
11159 elemsize = id->idOpSize();
11160 emitDispReg(id->idReg1(), elemsize, true);
11161 emitDispFloatImm(emitGetInsSC(id));
11164 case IF_DV_1B: // DV_1B .QX..........iii cmod..iiiiiddddd Vd imm8 (immediate vector)
11165 imm = emitGetInsSC(id) & 0x0ff;
11166 immShift = (emitGetInsSC(id) & 0x700) >> 8;
11167 hasShift = (immShift != 0);
11168 elemsize = optGetElemsize(id->idInsOpt());
11169 if (id->idInsOpt() == INS_OPTS_1D)
11171 assert(elemsize == size);
11172 emitDispReg(id->idReg1(), size, true);
11176 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11178 if (ins == INS_fmov)
11180 emitDispFloatImm(imm);
11181 assert(hasShift == false);
11185 if (elemsize == EA_8BYTE)
11187 assert(ins == INS_movi);
11189 const ssize_t mask8 = 0xFF;
11190 for (unsigned b = 0; b < 8; b++)
11192 if (imm & (1 << b))
11194 imm64 |= (mask8 << (b * 8));
11197 emitDispImm(imm64, hasShift, true);
11201 emitDispImm(imm, hasShift, true);
11205 insOpts opt = (immShift & 0x4) ? INS_OPTS_MSL : INS_OPTS_LSL;
11206 unsigned shift = (immShift & 0x3) * 8;
11207 emitDispShiftOpts(opt);
11208 emitDispImm(shift, false);
11213 case IF_DV_1C: // DV_1C .........X...... ......nnnnn..... Vn #0.0 (fcmp - with zero)
11214 elemsize = id->idOpSize();
11215 emitDispReg(id->idReg1(), elemsize, true);
11216 emitDispFloatZero();
11219 case IF_DV_2A: // DV_2A .Q.......X...... ......nnnnnddddd Vd Vn (fabs, fcvt - vector)
11220 case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
11221 case IF_DV_2P: // DV_2P ................ ......nnnnnddddd Vd Vn (aes*)
11222 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11223 emitDispVectorReg(id->idReg2(), id->idInsOpt(), false);
11226 case IF_DV_2N: // DV_2N .........iiiiiii ......nnnnnddddd Vd Vn imm (shift - scalar)
11227 elemsize = id->idOpSize();
11228 emitDispReg(id->idReg1(), elemsize, true);
11229 emitDispReg(id->idReg2(), elemsize, true);
11230 emitDispImm(emitGetInsSC(id), false);
11233 case IF_DV_2O: // DV_2O .Q.......iiiiiii ......nnnnnddddd Vd Vn imm (shift - vector)
11234 imm = emitGetInsSC(id);
11235 // Do we have a sxtl or uxtl instruction?
11236 isExtendAlias = ((ins == INS_sxtl) || (ins == INS_sxtl2) || (ins == INS_uxtl) || (ins == INS_uxtl2));
11237 code = emitInsCode(ins, fmt);
11238 if (code & 0x00008000) // widen/narrow opcodes
11240 if (code & 0x00002000) // SHL opcodes
11242 emitDispVectorReg(id->idReg1(), optWidenElemsize(id->idInsOpt()), true);
11243 emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11245 else // SHR opcodes
11247 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11248 emitDispVectorReg(id->idReg2(), optWidenElemsize(id->idInsOpt()), !isExtendAlias);
11253 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11254 emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11256 // Print the immediate unless we have a sxtl or uxtl instruction
11257 if (!isExtendAlias)
11259 emitDispImm(imm, false);
11263 case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov/smov - to general)
11264 srcsize = id->idOpSize();
11265 index = emitGetInsSC(id);
11266 if (ins == INS_smov)
11268 dstsize = EA_8BYTE;
11270 else // INS_umov or INS_mov
11272 dstsize = (srcsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE;
11274 emitDispReg(id->idReg1(), dstsize, true);
11275 emitDispVectorRegIndex(id->idReg2(), srcsize, index, false);
11278 case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
11279 if (ins == INS_dup)
11281 datasize = id->idOpSize();
11282 assert(isValidVectorDatasize(datasize));
11283 assert(isValidArrangement(datasize, id->idInsOpt()));
11284 elemsize = optGetElemsize(id->idInsOpt());
11285 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11289 elemsize = id->idOpSize();
11290 index = emitGetInsSC(id);
11291 assert(isValidVectorElemsize(elemsize));
11292 emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11294 emitDispReg(id->idReg2(), (elemsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE, false);
11297 case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
11298 datasize = id->idOpSize();
11299 assert(isValidVectorDatasize(datasize));
11300 assert(isValidArrangement(datasize, id->idInsOpt()));
11301 elemsize = optGetElemsize(id->idInsOpt());
11302 index = emitGetInsSC(id);
11303 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11304 emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11307 case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
11308 elemsize = id->idOpSize();
11309 index = emitGetInsSC(id);
11310 emitDispReg(id->idReg1(), elemsize, true);
11311 emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11314 case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
11315 imm = emitGetInsSC(id);
11316 index = (imm >> 4) & 0xf;
11317 index2 = imm & 0xf;
11318 elemsize = id->idOpSize();
11319 emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11320 emitDispVectorRegIndex(id->idReg2(), elemsize, index2, false);
11323 case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov, fcvtXX - register)
11324 case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
11325 case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
11326 elemsize = id->idOpSize();
11327 emitDispReg(id->idReg1(), elemsize, true);
11328 emitDispReg(id->idReg2(), elemsize, false);
11331 case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov, fcvtXX - to general)
11332 case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov, Xcvtf - from general)
11333 case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
11334 dstsize = optGetDstsize(id->idInsOpt());
11335 srcsize = optGetSrcsize(id->idInsOpt());
11337 emitDispReg(id->idReg1(), dstsize, true);
11338 emitDispReg(id->idReg2(), srcsize, false);
11341 case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11342 case IF_DV_3B: // DV_3B .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11343 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11344 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11345 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11348 case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11349 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11350 if (ins != INS_mov)
11352 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11354 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11357 case IF_DV_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
11358 case IF_DV_3BI: // DV_3BI .Q........Lmmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
11359 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11360 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11361 elemsize = optGetElemsize(id->idInsOpt());
11362 emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11365 case IF_DV_3D: // DV_3D .........X.mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
11366 case IF_DV_3E: // DV_3E ...........mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
11367 emitDispReg(id->idReg1(), size, true);
11368 emitDispReg(id->idReg2(), size, true);
11369 emitDispReg(id->idReg3(), size, false);
11372 case IF_DV_3DI: // DV_3DI .........XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (scalar by elem)
11373 emitDispReg(id->idReg1(), size, true);
11374 emitDispReg(id->idReg2(), size, true);
11376 emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11379 case IF_DV_4A: // DV_4A .........X.mmmmm .aaaaannnnnddddd Vd Va Vn Vm (scalar)
11380 emitDispReg(id->idReg1(), size, true);
11381 emitDispReg(id->idReg2(), size, true);
11382 emitDispReg(id->idReg3(), size, true);
11383 emitDispReg(id->idReg4(), size, false);
11386 case IF_SN_0A: // SN_0A ................ ................
11389 case IF_SI_0A: // SI_0A ...........iiiii iiiiiiiiiii..... imm16
11390 emitDispImm(emitGetInsSC(id), false);
11393 case IF_SI_0B: // SI_0B ................ ....bbbb........ imm4 - barrier
11394 emitDispBarrier((insBarrier)emitGetInsSC(id));
11398 printf("unexpected format %s", emitIfName(id->idInsFmt()));
11399 assert(!"unexpectedFormat");
11403 if (id->idDebugOnlyInfo()->idVarRefOffs)
11406 emitDispFrameRef(id->idAddr()->iiaLclVar.lvaVarNum(), id->idAddr()->iiaLclVar.lvaOffset(),
11407 id->idDebugOnlyInfo()->idVarRefOffs, asmfm);
11413 /*****************************************************************************
11415 * Display a stack frame reference.
11418 void emitter::emitDispFrameRef(int varx, int disp, int offs, bool asmfm)
11423 printf("TEMP_%02u", -varx);
11425 emitComp->gtDispLclVar(+varx, false);
11428 printf("-0x%02x", -disp);
11430 printf("+0x%02x", +disp);
11434 if (varx >= 0 && emitComp->opts.varNames)
11437 const char* varName;
11439 assert((unsigned)varx < emitComp->lvaCount);
11440 varDsc = emitComp->lvaTable + varx;
11441 varName = emitComp->compLocalVarName(varx, offs);
11445 printf("'%s", varName);
11448 printf("-%d", -disp);
11450 printf("+%d", +disp);
11459 // Generate code for a load or store operation with a potentially complex addressing mode
11460 // This method handles the case of a GT_IND with contained GT_LEA op1 of the x86 form [base + index*sccale + offset]
11461 // Since Arm64 does not directly support this complex of an addressing mode
11462 // we may generates up to three instructions for this for Arm64
11464 void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataReg, GenTreeIndir* indir)
11466 emitAttr ldstAttr = isVectorRegister(dataReg) ? attr : emitInsAdjustLoadStoreAttr(ins, attr);
11468 GenTree* addr = indir->Addr();
11470 if (addr->isContained())
11472 assert(addr->OperGet() == GT_LCL_VAR_ADDR || addr->OperGet() == GT_LEA);
11477 if (addr->OperGet() == GT_LEA)
11479 offset = addr->AsAddrMode()->Offset();
11480 if (addr->AsAddrMode()->gtScale > 0)
11482 assert(isPow2(addr->AsAddrMode()->gtScale));
11483 BitScanForward(&lsl, addr->AsAddrMode()->gtScale);
11487 GenTree* memBase = indir->Base();
11489 if (indir->HasIndex())
11491 GenTree* index = indir->Index();
11495 regNumber tmpReg = indir->GetSingleTempReg();
11497 emitAttr addType = varTypeIsGC(memBase) ? EA_BYREF : EA_PTRSIZE;
11499 if (emitIns_valid_imm_for_add(offset, EA_8BYTE))
11503 // Generate code to set tmpReg = base + index*scale
11504 emitIns_R_R_R_I(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum, lsl,
11509 // Generate code to set tmpReg = base + index
11510 emitIns_R_R_R(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum);
11513 noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11515 // Then load/store dataReg from/to [tmpReg + offset]
11516 emitIns_R_R_I(ins, ldstAttr, dataReg, tmpReg, offset);
11518 else // large offset
11520 // First load/store tmpReg with the large offset constant
11521 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11522 // Then add the base register
11524 emitIns_R_R_R(INS_add, addType, tmpReg, tmpReg, memBase->gtRegNum);
11526 noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11527 noway_assert(tmpReg != index->gtRegNum);
11529 // Then load/store dataReg from/to [tmpReg + index*scale]
11530 emitIns_R_R_R_I(ins, ldstAttr, dataReg, tmpReg, index->gtRegNum, lsl, INS_OPTS_LSL);
11533 else // (offset == 0)
11537 // Then load/store dataReg from/to [memBase + index*scale]
11538 emitIns_R_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum, lsl, INS_OPTS_LSL);
11542 // Then load/store dataReg from/to [memBase + index]
11543 emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum);
11547 else // no Index register
11549 if (emitIns_valid_imm_for_ldst_offset(offset, EA_SIZE(attr)))
11551 // Then load/store dataReg from/to [memBase + offset]
11552 emitIns_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, offset);
11556 // We require a tmpReg to hold the offset
11557 regNumber tmpReg = indir->GetSingleTempReg();
11559 // First load/store tmpReg with the large offset constant
11560 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11562 // Then load/store dataReg from/to [memBase + tmpReg]
11563 emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, tmpReg);
11567 else // addr is not contained, so we evaluate it into a register
11569 // Then load/store dataReg from/to [addrReg]
11570 emitIns_R_R(ins, ldstAttr, dataReg, addr->gtRegNum);
11574 // The callee must call genConsumeReg() for any non-contained srcs
11575 // and genProduceReg() for any non-contained dsts.
11577 regNumber emitter::emitInsBinary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src)
11579 regNumber result = REG_NA;
11581 // dst can only be a reg
11582 assert(!dst->isContained());
11584 // src can be immed or reg
11585 assert(!src->isContained() || src->isContainedIntOrIImmed());
11587 // find immed (if any) - it cannot be a dst
11588 GenTreeIntConCommon* intConst = nullptr;
11589 if (src->isContainedIntOrIImmed())
11591 intConst = src->AsIntConCommon();
11596 emitIns_R_I(ins, attr, dst->gtRegNum, intConst->IconValue());
11597 return dst->gtRegNum;
11601 emitIns_R_R(ins, attr, dst->gtRegNum, src->gtRegNum);
11602 return dst->gtRegNum;
11606 // The callee must call genConsumeReg() for any non-contained srcs
11607 // and genProduceReg() for any non-contained dsts.
11609 regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src1, GenTree* src2)
11611 regNumber result = REG_NA;
11613 // dst can only be a reg
11614 assert(!dst->isContained());
11616 // find immed (if any) - it cannot be a dst
11617 // Only one src can be an int.
11618 GenTreeIntConCommon* intConst = nullptr;
11619 GenTree* nonIntReg = nullptr;
11621 if (varTypeIsFloating(dst))
11623 // src1 can only be a reg
11624 assert(!src1->isContained());
11625 // src2 can only be a reg
11626 assert(!src2->isContained());
11628 else // not floating point
11630 // src2 can be immed or reg
11631 assert(!src2->isContained() || src2->isContainedIntOrIImmed());
11633 // Check src2 first as we can always allow it to be a contained immediate
11634 if (src2->isContainedIntOrIImmed())
11636 intConst = src2->AsIntConCommon();
11639 // Only for commutative operations do we check src1 and allow it to be a contained immediate
11640 else if (dst->OperIsCommutative())
11642 // src1 can be immed or reg
11643 assert(!src1->isContained() || src1->isContainedIntOrIImmed());
11645 // Check src1 and allow it to be a contained immediate
11646 if (src1->isContainedIntOrIImmed())
11648 assert(!src2->isContainedIntOrIImmed());
11649 intConst = src1->AsIntConCommon();
11655 // src1 can only be a reg
11656 assert(!src1->isContained());
11660 bool isMulOverflow = false;
11661 if (dst->gtOverflowEx())
11663 if ((ins == INS_add) || (ins == INS_adds))
11667 else if ((ins == INS_sub) || (ins == INS_subs))
11671 else if (ins == INS_mul)
11673 isMulOverflow = true;
11674 assert(intConst == nullptr); // overflow format doesn't support an int constant operand
11678 assert(!"Invalid ins for overflow check");
11681 if (intConst != nullptr)
11683 emitIns_R_R_I(ins, attr, dst->gtRegNum, nonIntReg->gtRegNum, intConst->IconValue());
11689 regNumber extraReg = dst->GetSingleTempReg();
11690 assert(extraReg != dst->gtRegNum);
11692 if ((dst->gtFlags & GTF_UNSIGNED) != 0)
11694 if (attr == EA_4BYTE)
11696 // Compute 8 byte results from 4 byte by 4 byte multiplication.
11697 emitIns_R_R_R(INS_umull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11699 // Get the high result by shifting dst.
11700 emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11704 assert(attr == EA_8BYTE);
11705 // Compute the high result.
11706 emitIns_R_R_R(INS_umulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11708 // Now multiply without skewing the high result.
11709 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11712 // zero-sign bit comparison to detect overflow.
11713 emitIns_R_I(INS_cmp, attr, extraReg, 0);
11718 if (attr == EA_4BYTE)
11720 // Compute 8 byte results from 4 byte by 4 byte multiplication.
11721 emitIns_R_R_R(INS_smull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11723 // Get the high result by shifting dst.
11724 emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11730 assert(attr == EA_8BYTE);
11731 // Save the high result in a temporary register.
11732 emitIns_R_R_R(INS_smulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11734 // Now multiply without skewing the high result.
11735 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11740 // Sign bit comparison to detect overflow.
11741 emitIns_R_R_I(INS_cmp, attr, extraReg, dst->gtRegNum, bitShift, INS_OPTS_ASR);
11746 // We can just multiply.
11747 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11751 if (dst->gtOverflowEx())
11753 assert(!varTypeIsFloating(dst));
11754 codeGen->genCheckOverflow(dst);
11757 return dst->gtRegNum;
11760 #endif // defined(_TARGET_ARM64_)