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_LS_3E: // LS_3E .X.........mmmmm ......nnnnnttttt Rm Rt Rn ARMv8.1 LSE Atomics
282 assert(isIntegerRegister(id->idReg1()));
283 assert(isIntegerRegister(id->idReg2()));
284 assert(isIntegerRegister(id->idReg3()));
285 assert(emitGetInsSC(id) == 0);
286 assert(!id->idIsLclVar());
287 assert(insOptsNone(id->idInsOpt()));
290 case IF_DI_1A: // DI_1A X.......shiiiiii iiiiiinnnnn..... Rn imm(i12,sh)
291 assert(isValidGeneralDatasize(id->idOpSize()));
292 assert(isGeneralRegister(id->idReg1()));
293 assert(isValidUimm12(emitGetInsSC(id)));
294 assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
297 case IF_DI_1B: // DI_1B X........hwiiiii iiiiiiiiiiiddddd Rd imm(i16,hw)
298 assert(isValidGeneralDatasize(id->idOpSize()));
299 assert(isGeneralRegister(id->idReg1()));
300 assert(isValidImmHWVal(emitGetInsSC(id), id->idOpSize()));
303 case IF_DI_1C: // DI_1C X........Nrrrrrr ssssssnnnnn..... Rn imm(N,r,s)
304 assert(isValidGeneralDatasize(id->idOpSize()));
305 assert(isGeneralRegister(id->idReg1()));
306 assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
309 case IF_DI_1D: // DI_1D X........Nrrrrrr ssssss.....ddddd Rd imm(N,r,s)
310 assert(isValidGeneralDatasize(id->idOpSize()));
311 assert(isIntegerRegister(id->idReg1())); // SP
312 assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
315 case IF_DI_1E: // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
316 assert(isGeneralRegister(id->idReg1()));
319 case IF_DI_1F: // DI_1F X..........iiiii cccc..nnnnn.nzcv Rn imm5 nzcv cond
320 assert(isValidGeneralDatasize(id->idOpSize()));
321 assert(isGeneralRegister(id->idReg1()));
322 assert(isValidImmCondFlagsImm5(emitGetInsSC(id)));
325 case IF_DI_2A: // DI_2A X.......shiiiiii iiiiiinnnnnddddd Rd Rn imm(i12,sh)
326 assert(isValidGeneralDatasize(id->idOpSize()));
327 assert(isIntegerRegister(id->idReg1())); // SP
328 assert(isIntegerRegister(id->idReg2())); // SP
329 assert(isValidUimm12(emitGetInsSC(id)));
330 assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
333 case IF_DI_2B: // DI_2B X.........Xnnnnn ssssssnnnnnddddd Rd Rn imm(0-63)
334 assert(isValidGeneralDatasize(id->idOpSize()));
335 assert(isGeneralRegister(id->idReg1()));
336 assert(isGeneralRegister(id->idReg2()));
337 assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
340 case IF_DI_2C: // DI_2C X........Nrrrrrr ssssssnnnnnddddd Rd Rn imm(N,r,s)
341 assert(isValidGeneralDatasize(id->idOpSize()));
342 assert(isIntegerRegister(id->idReg1())); // SP
343 assert(isGeneralRegister(id->idReg2()));
344 assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
347 case IF_DI_2D: // DI_2D X........Nrrrrrr ssssssnnnnnddddd Rd Rn imr, imms (N,r,s)
348 assert(isValidGeneralDatasize(id->idOpSize()));
349 assert(isGeneralRegister(id->idReg1()));
350 assert(isGeneralRegister(id->idReg2()));
351 assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
354 case IF_DR_1D: // DR_1D X............... cccc.......ddddd Rd cond
355 assert(isValidGeneralDatasize(id->idOpSize()));
356 assert(isGeneralRegister(id->idReg1()));
357 assert(isValidImmCond(emitGetInsSC(id)));
360 case IF_DR_2A: // DR_2A X..........mmmmm ......nnnnn..... Rn Rm
361 assert(isValidGeneralDatasize(id->idOpSize()));
362 assert(isGeneralRegister(id->idReg1()));
363 assert(isGeneralRegister(id->idReg2()));
366 case IF_DR_2B: // DR_2B X.......sh.mmmmm ssssssnnnnn..... Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
367 assert(isValidGeneralDatasize(id->idOpSize()));
368 assert(isIntegerRegister(id->idReg1())); // ZR
369 assert(isGeneralRegister(id->idReg2()));
370 assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
371 if (!insOptsNone(id->idInsOpt()))
373 if (id->idIns() == INS_tst) // tst allows ROR, cmp/cmn don't
375 assert(insOptsAnyShift(id->idInsOpt()));
379 assert(insOptsAluShift(id->idInsOpt()));
382 assert(insOptsNone(id->idInsOpt()) || (emitGetInsSC(id) > 0));
385 case IF_DR_2C: // DR_2C X..........mmmmm ooosssnnnnn..... Rn Rm ext(Rm) LSL imm(0-4)
386 assert(isValidGeneralDatasize(id->idOpSize()));
387 assert(isIntegerRegister(id->idReg1())); // SP
388 assert(isGeneralRegister(id->idReg2()));
389 assert(insOptsNone(id->idInsOpt()) || insOptsLSL(id->idInsOpt()) || insOptsAnyExtend(id->idInsOpt()));
390 assert(emitGetInsSC(id) >= 0);
391 assert(emitGetInsSC(id) <= 4);
392 if (insOptsLSL(id->idInsOpt()))
394 assert(emitGetInsSC(id) > 0);
398 case IF_DR_2D: // DR_2D X..........nnnnn cccc..nnnnnmmmmm Rd Rn cond
399 assert(isValidGeneralDatasize(id->idOpSize()));
400 assert(isGeneralRegister(id->idReg1()));
401 assert(isGeneralRegister(id->idReg2()));
402 assert(isValidImmCond(emitGetInsSC(id)));
405 case IF_DR_2E: // DR_2E X..........mmmmm ...........ddddd Rd Rm
406 assert(isValidGeneralDatasize(id->idOpSize()));
407 assert(isGeneralRegister(id->idReg1()));
408 assert(isIntegerRegister(id->idReg2())); // ZR
411 case IF_DR_2F: // DR_2F X.......sh.mmmmm ssssss.....ddddd Rd Rm {LSL,LSR,ASR} imm(0-63)
412 assert(isValidGeneralDatasize(id->idOpSize()));
413 assert(isGeneralRegister(id->idReg1()));
414 assert(isGeneralRegister(id->idReg2()));
415 assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
416 assert(insOptsNone(id->idInsOpt()) || insOptsAluShift(id->idInsOpt()));
417 assert(insOptsNone(id->idInsOpt()) || (emitGetInsSC(id) > 0));
420 case IF_DR_2G: // DR_2G X............... ......nnnnnddddd Rd Rm
421 assert(isValidGeneralDatasize(id->idOpSize()));
422 assert(isIntegerRegister(id->idReg1())); // SP
423 assert(isIntegerRegister(id->idReg2())); // SP
426 case IF_DR_2H: // DR_2H X........X...... ......nnnnnddddd Rd Rn
427 assert(isValidGeneralDatasize(id->idOpSize()));
428 assert(isGeneralRegister(id->idReg1()));
429 assert(isGeneralRegister(id->idReg2()));
432 case IF_DR_2I: // DR_2I X..........mmmmm cccc..nnnnn.nzcv Rn Rm nzcv cond
433 assert(isValidGeneralDatasize(id->idOpSize()));
434 assert(isGeneralRegister(id->idReg1()));
435 assert(isGeneralRegister(id->idReg2()));
436 assert(isValidImmCondFlags(emitGetInsSC(id)));
439 case IF_DR_2J: // DR_2J ................ ......nnnnnddddd Sd Sn (sha1h)
440 assert(isValidGeneralDatasize(id->idOpSize()));
441 assert(isVectorRegister(id->idReg1()));
442 assert(isVectorRegister(id->idReg2()));
445 case IF_DR_3A: // DR_3A X..........mmmmm ......nnnnnmmmmm Rd Rn Rm
446 assert(isValidGeneralDatasize(id->idOpSize()));
447 assert(isIntegerRegister(id->idReg1())); // SP
448 assert(isIntegerRegister(id->idReg2())); // SP
449 if (id->idIsLclVar())
451 assert(isGeneralRegister(codeGen->rsGetRsvdReg()));
455 assert(isGeneralRegister(id->idReg3()));
457 assert(insOptsNone(id->idInsOpt()));
460 case IF_DR_3B: // DR_3B X.......sh.mmmmm ssssssnnnnnddddd Rd Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
461 assert(isValidGeneralDatasize(id->idOpSize()));
462 assert(isGeneralRegister(id->idReg1()));
463 assert(isGeneralRegister(id->idReg2()));
464 assert(isGeneralRegister(id->idReg3()));
465 assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
466 assert(insOptsNone(id->idInsOpt()) || insOptsAnyShift(id->idInsOpt()));
467 assert(insOptsNone(id->idInsOpt()) || (emitGetInsSC(id) > 0));
470 case IF_DR_3C: // DR_3C X..........mmmmm ooosssnnnnnddddd Rd Rn Rm ext(Rm) LSL imm(0-4)
471 assert(isValidGeneralDatasize(id->idOpSize()));
472 assert(isIntegerRegister(id->idReg1())); // SP
473 assert(isIntegerRegister(id->idReg2())); // SP
474 assert(isGeneralRegister(id->idReg3()));
475 assert(insOptsNone(id->idInsOpt()) || insOptsLSL(id->idInsOpt()) || insOptsAnyExtend(id->idInsOpt()));
476 assert(emitGetInsSC(id) >= 0);
477 assert(emitGetInsSC(id) <= 4);
478 if (insOptsLSL(id->idInsOpt()))
480 assert((emitGetInsSC(id) > 0) ||
481 (id->idReg2() == REG_ZR)); // REG_ZR encodes SP and we allow a shift of zero
485 case IF_DR_3D: // DR_3D X..........mmmmm cccc..nnnnnmmmmm Rd Rn Rm cond
486 assert(isValidGeneralDatasize(id->idOpSize()));
487 assert(isGeneralRegister(id->idReg1()));
488 assert(isGeneralRegister(id->idReg2()));
489 assert(isGeneralRegister(id->idReg3()));
490 assert(isValidImmCond(emitGetInsSC(id)));
493 case IF_DR_3E: // DR_3E X........X.mmmmm ssssssnnnnnddddd Rd Rn Rm imm(0-63)
494 assert(isValidGeneralDatasize(id->idOpSize()));
495 assert(isGeneralRegister(id->idReg1()));
496 assert(isGeneralRegister(id->idReg2()));
497 assert(isGeneralRegister(id->idReg3()));
498 assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
499 assert(insOptsNone(id->idInsOpt()));
502 case IF_DR_4A: // DR_4A X..........mmmmm .aaaaannnnnddddd Rd Rn Rm Ra
503 assert(isValidGeneralDatasize(id->idOpSize()));
504 assert(isGeneralRegister(id->idReg1()));
505 assert(isGeneralRegister(id->idReg2()));
506 assert(isGeneralRegister(id->idReg3()));
507 assert(isGeneralRegister(id->idReg4()));
510 case IF_DV_1A: // DV_1A .........X.iiiii iii........ddddd Vd imm8 (fmov - immediate scalar)
511 assert(insOptsNone(id->idInsOpt()));
512 elemsize = id->idOpSize();
513 assert(isValidVectorElemsizeFloat(elemsize));
514 assert(isVectorRegister(id->idReg1()));
515 assert(isValidUimm8(emitGetInsSC(id)));
518 case IF_DV_1B: // DV_1B .QX..........iii cmod..iiiiiddddd Vd imm8 (immediate vector)
520 imm = emitGetInsSC(id) & 0x0ff;
521 immShift = (emitGetInsSC(id) & 0x700) >> 8;
522 assert(immShift >= 0);
523 datasize = id->idOpSize();
524 assert(isValidVectorDatasize(datasize));
525 assert(isValidArrangement(datasize, id->idInsOpt()));
526 elemsize = optGetElemsize(id->idInsOpt());
529 assert(isValidVectorElemsizeFloat(elemsize));
530 assert(id->idInsOpt() != INS_OPTS_1D); // Reserved encoding
531 assert(immShift == 0);
535 assert(isValidVectorElemsize(elemsize));
536 assert((immShift != 4) && (immShift != 7)); // always invalid values
537 if (ins != INS_movi) // INS_mvni, INS_orr, INS_bic
539 assert((elemsize != EA_1BYTE) && (elemsize != EA_8BYTE)); // only H or S
540 if (elemsize == EA_2BYTE)
542 assert(immShift < 2);
544 else // (elemsize == EA_4BYTE)
548 assert(immShift < 4);
553 assert(isVectorRegister(id->idReg1()));
554 assert(isValidUimm8(imm));
557 case IF_DV_1C: // DV_1C .........X...... ......nnnnn..... Vn #0.0 (fcmp - with zero)
558 assert(insOptsNone(id->idInsOpt()));
559 elemsize = id->idOpSize();
560 assert(isValidVectorElemsizeFloat(elemsize));
561 assert(isVectorRegister(id->idReg1()));
564 case IF_DV_2A: // DV_2A .Q.......X...... ......nnnnnddddd Vd Vn (fabs, fcvt - vector)
565 case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
566 case IF_DV_2P: // DV_2P ................ ......nnnnnddddd Vd Vn (aes*, sha1su1)
567 assert(isValidVectorDatasize(id->idOpSize()));
568 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
569 assert(isVectorRegister(id->idReg1()));
570 assert(isVectorRegister(id->idReg2()));
573 case IF_DV_2N: // DV_2N .........iiiiiii ......nnnnnddddd Vd Vn imm (shift - scalar)
574 assert(id->idOpSize() == EA_8BYTE);
575 assert(insOptsNone(id->idInsOpt()));
576 assert(isVectorRegister(id->idReg1()));
577 assert(isVectorRegister(id->idReg2()));
578 assert(isValidImmShift(emitGetInsSC(id), EA_8BYTE));
581 case IF_DV_2O: // DV_2O .Q.......iiiiiii ......nnnnnddddd Vd Vn imm (shift - vector)
582 assert(isValidVectorDatasize(id->idOpSize()));
583 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
584 assert(isVectorRegister(id->idReg1()));
585 assert(isVectorRegister(id->idReg2()));
586 elemsize = optGetElemsize(id->idInsOpt());
587 assert(isValidImmShift(emitGetInsSC(id), elemsize));
590 case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov/smov - to general)
591 elemsize = id->idOpSize();
592 index = emitGetInsSC(id);
593 assert(insOptsNone(id->idInsOpt()));
594 assert(isValidVectorIndex(EA_16BYTE, elemsize, index));
595 assert(isValidVectorElemsize(elemsize));
596 assert(isGeneralRegister(id->idReg1()));
597 assert(isVectorRegister(id->idReg2()));
600 case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
601 if (id->idIns() == INS_dup)
603 datasize = id->idOpSize();
604 assert(isValidVectorDatasize(datasize));
605 assert(isValidArrangement(datasize, id->idInsOpt()));
606 elemsize = optGetElemsize(id->idInsOpt());
610 datasize = EA_16BYTE;
611 elemsize = id->idOpSize();
612 assert(isValidVectorElemsize(elemsize));
614 assert(isVectorRegister(id->idReg1()));
615 assert(isGeneralRegisterOrZR(id->idReg2()));
618 case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
619 datasize = id->idOpSize();
620 assert(isValidVectorDatasize(datasize));
621 assert(isValidArrangement(datasize, id->idInsOpt()));
622 elemsize = optGetElemsize(id->idInsOpt());
623 index = emitGetInsSC(id);
624 assert(isValidVectorIndex(datasize, elemsize, index));
625 assert(isVectorRegister(id->idReg1()));
626 assert(isVectorRegister(id->idReg2()));
629 case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
630 elemsize = id->idOpSize();
631 index = emitGetInsSC(id);
632 assert(isValidVectorIndex(EA_16BYTE, elemsize, index));
633 assert(isValidVectorElemsize(elemsize));
634 assert(isVectorRegister(id->idReg1()));
635 assert(isVectorRegister(id->idReg2()));
638 case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
639 imm = emitGetInsSC(id);
640 index = (imm >> 4) & 0xf;
642 elemsize = id->idOpSize();
643 assert(isValidVectorElemsize(elemsize));
644 assert(isValidVectorIndex(EA_16BYTE, elemsize, index));
645 assert(isValidVectorIndex(EA_16BYTE, elemsize, index2));
646 assert(isVectorRegister(id->idReg1()));
647 assert(isVectorRegister(id->idReg2()));
650 case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
651 assert(id->idOpSize() == EA_8BYTE); // only type D is supported
654 case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov, fcvtXX - register)
655 case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
656 assert(insOptsNone(id->idInsOpt()));
657 assert(isValidVectorElemsizeFloat(id->idOpSize()));
658 assert(isVectorRegister(id->idReg1()));
659 assert(isVectorRegister(id->idReg2()));
662 case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov/fcvtXX - to general)
663 assert(insOptsConvertFloatToInt(id->idInsOpt()));
664 dstsize = optGetDstsize(id->idInsOpt());
665 srcsize = optGetSrcsize(id->idInsOpt());
666 assert(isValidGeneralDatasize(dstsize));
667 assert(isValidVectorElemsizeFloat(srcsize));
668 assert(dstsize == id->idOpSize());
669 assert(isGeneralRegister(id->idReg1()));
670 assert(isVectorRegister(id->idReg2()));
673 case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov/Xcvtf - from general)
674 assert(insOptsConvertIntToFloat(id->idInsOpt()));
675 dstsize = optGetDstsize(id->idInsOpt());
676 srcsize = optGetSrcsize(id->idInsOpt());
677 assert(isValidGeneralDatasize(srcsize));
678 assert(isValidVectorElemsizeFloat(dstsize));
679 assert(dstsize == id->idOpSize());
680 assert(isVectorRegister(id->idReg1()));
681 assert(isGeneralRegister(id->idReg2()));
684 case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
685 assert(insOptsConvertFloatToFloat(id->idInsOpt()));
686 dstsize = optGetDstsize(id->idInsOpt());
687 srcsize = optGetSrcsize(id->idInsOpt());
688 assert(isValidVectorFcvtsize(srcsize));
689 assert(isValidVectorFcvtsize(dstsize));
690 assert(dstsize == id->idOpSize());
691 assert(isVectorRegister(id->idReg1()));
692 assert(isVectorRegister(id->idReg2()));
695 case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
696 assert(isValidVectorDatasize(id->idOpSize()));
697 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
698 assert(isVectorRegister(id->idReg1()));
699 assert(isVectorRegister(id->idReg2()));
700 assert(isVectorRegister(id->idReg3()));
701 elemsize = optGetElemsize(id->idInsOpt());
705 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
707 else if (ins == INS_pmul)
709 assert(elemsize == EA_1BYTE); // only supports 8B or 16B
713 case IF_DV_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
714 assert(isValidVectorDatasize(id->idOpSize()));
715 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
716 assert(isVectorRegister(id->idReg1()));
717 assert(isVectorRegister(id->idReg2()));
718 assert(isVectorRegister(id->idReg3()));
719 elemsize = optGetElemsize(id->idInsOpt());
720 assert(isValidVectorIndex(EA_16BYTE, elemsize, emitGetInsSC(id)));
721 // Only has encodings for H or S elemsize
722 assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE));
725 case IF_DV_3B: // DV_3B .Q.......X.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
726 assert(isValidVectorDatasize(id->idOpSize()));
727 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
728 assert(isVectorRegister(id->idReg1()));
729 assert(isVectorRegister(id->idReg2()));
730 assert(isVectorRegister(id->idReg3()));
733 case IF_DV_3BI: // DV_3BI .Q.......XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
734 assert(isValidVectorDatasize(id->idOpSize()));
735 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
736 assert(isVectorRegister(id->idReg1()));
737 assert(isVectorRegister(id->idReg2()));
738 assert(isVectorRegister(id->idReg3()));
739 elemsize = optGetElemsize(id->idInsOpt());
740 assert(isValidVectorIndex(id->idOpSize(), elemsize, emitGetInsSC(id)));
743 case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
744 assert(isValidVectorDatasize(id->idOpSize()));
745 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
746 assert(isVectorRegister(id->idReg1()));
747 assert(isVectorRegister(id->idReg2()));
748 assert(isVectorRegister(id->idReg3()));
751 case IF_DV_3D: // DV_3D .........X.mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
752 assert(isValidScalarDatasize(id->idOpSize()));
753 assert(insOptsNone(id->idInsOpt()));
754 assert(isVectorRegister(id->idReg1()));
755 assert(isVectorRegister(id->idReg2()));
756 assert(isVectorRegister(id->idReg3()));
759 case IF_DV_3DI: // DV_3DI .........XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (scalar by elem)
760 assert(isValidScalarDatasize(id->idOpSize()));
761 assert(insOptsNone(id->idInsOpt()));
762 assert(isVectorRegister(id->idReg1()));
763 assert(isVectorRegister(id->idReg2()));
764 assert(isVectorRegister(id->idReg3()));
765 elemsize = id->idOpSize();
766 assert(isValidVectorIndex(EA_16BYTE, elemsize, emitGetInsSC(id)));
769 case IF_DV_3E: // DV_3E ...........mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
770 assert(insOptsNone(id->idInsOpt()));
771 assert(id->idOpSize() == EA_8BYTE);
772 assert(isVectorRegister(id->idReg1()));
773 assert(isVectorRegister(id->idReg2()));
774 assert(isVectorRegister(id->idReg3()));
777 case IF_DV_3F: // DV_3F ...........mmmmm ......nnnnnddddd Vd Vn Vm
778 assert(isValidVectorDatasize(id->idOpSize()));
779 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
780 assert(isVectorRegister(id->idReg1()));
781 assert(isVectorRegister(id->idReg2()));
782 assert(isVectorRegister(id->idReg3()));
785 case IF_DV_4A: // DR_4A .........X.mmmmm .aaaaannnnnddddd Rd Rn Rm Ra (scalar)
786 assert(isValidGeneralDatasize(id->idOpSize()));
787 assert(isVectorRegister(id->idReg1()));
788 assert(isVectorRegister(id->idReg2()));
789 assert(isVectorRegister(id->idReg3()));
790 assert(isVectorRegister(id->idReg4()));
793 case IF_SN_0A: // SN_0A ................ ................
794 case IF_SI_0A: // SI_0A ...........iiiii iiiiiiiiiii..... imm16
795 case IF_SI_0B: // SI_0B ................ ....bbbb........ imm4 - barrier
799 printf("unexpected format %s\n", emitIfName(id->idInsFmt()));
800 assert(!"Unexpected format");
806 bool emitter::emitInsMayWriteToGCReg(instrDesc* id)
808 instruction ins = id->idIns();
809 insFormat fmt = id->idInsFmt();
814 // These are the formats with "destination" registers:
816 case IF_DI_1B: // DI_1B X........hwiiiii iiiiiiiiiiiddddd Rd imm(i16,hw)
817 case IF_DI_1D: // DI_1D X........Nrrrrrr ssssss.....ddddd Rd imm(N,r,s)
818 case IF_DI_1E: // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
820 case IF_DI_2A: // DI_2A X.......shiiiiii iiiiiinnnnnddddd Rd Rn imm(i12,sh)
821 case IF_DI_2B: // DI_2B X.........Xnnnnn ssssssnnnnnddddd Rd Rn imm(0-63)
822 case IF_DI_2C: // DI_2C X........Nrrrrrr ssssssnnnnnddddd Rd Rn imm(N,r,s)
823 case IF_DI_2D: // DI_2D X........Nrrrrrr ssssssnnnnnddddd Rd Rn imr, imms (N,r,s)
825 case IF_DR_1D: // DR_1D X............... cccc.......ddddd Rd cond
827 case IF_DR_2D: // DR_2D X..........nnnnn cccc..nnnnnddddd Rd Rn cond
828 case IF_DR_2E: // DR_2E X..........mmmmm ...........ddddd Rd Rm
829 case IF_DR_2F: // DR_2F X.......sh.mmmmm ssssss.....ddddd Rd Rm {LSL,LSR,ASR} imm(0-63)
830 case IF_DR_2G: // DR_2G X............... ......nnnnnddddd Rd Rn
831 case IF_DR_2H: // DR_2H X........X...... ......nnnnnddddd Rd Rn
833 case IF_DR_3A: // DR_3A X..........mmmmm ......nnnnnddddd Rd Rn Rm
834 case IF_DR_3B: // DR_3B X.......sh.mmmmm ssssssnnnnnddddd Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
835 case IF_DR_3C: // DR_3C X..........mmmmm xxxsssnnnnnddddd Rd Rn Rm ext(Rm) LSL imm(0-4)
836 case IF_DR_3D: // DR_3D X..........mmmmm cccc..nnnnnddddd Rd Rn Rm cond
837 case IF_DR_3E: // DR_3E X........X.mmmmm ssssssnnnnnddddd Rd Rn Rm imm(0-63)
838 case IF_DV_3F: // DV_3F ...........mmmmm ......nnnnnddddd Vd Vn Vm (vector) - Vd both source and dest
840 case IF_DR_4A: // DR_4A X..........mmmmm .aaaaannnnnddddd Rd Rn Rm Ra
842 case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov - to general)
843 case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov - to general)
847 case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
848 case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
849 case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
850 case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
851 case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov, fcvtXX - register)
852 case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov - from general)
853 case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
854 case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
855 case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
856 case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
857 case IF_DV_2P: // DV_2P ................ ......nnnnnddddd Vd Vn (aes*, sha1su1) - Vd both source and
860 case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
861 case IF_DV_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector)
862 case IF_DV_3B: // DV_3B .Q.......X.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
863 case IF_DV_3BI: // DV_3BI .Q.......XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
864 case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
865 case IF_DV_3D: // DV_3D .........X.mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
866 case IF_DV_3DI: // DV_3DI .........XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (scalar by elem)
867 case IF_DV_3E: // DV_3E ...........mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
868 case IF_DV_4A: // DV_4A .........X.mmmmm .aaaaannnnnddddd Vd Va Vn Vm (scalar)
869 // Tracked GC pointers cannot be placed into the SIMD registers.
872 // These are the load/store formats with "target" registers:
874 case IF_LS_1A: // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB)
875 case IF_LS_2A: // LS_2A .X.......X...... ......nnnnnttttt Rt Rn
876 case IF_LS_2B: // LS_2B .X.......Xiiiiii iiiiiinnnnnttttt Rt Rn imm(0-4095)
877 case IF_LS_2C: // LS_2C .X.......X.iiiii iiiiP.nnnnnttttt Rt Rn imm(-256..+255) pre/post inc
878 case IF_LS_3A: // LS_3A .X.......X.mmmmm xxxS..nnnnnttttt Rt Rn Rm ext(Rm) LSL {}
879 case IF_LS_3B: // LS_3B X............... .aaaaannnnnttttt Rt Ra Rn
880 case IF_LS_3C: // LS_3C X.........iiiiii iaaaaannnnnttttt Rt Ra Rn imm(im7,sh)
881 case IF_LS_3D: // LS_3D .X.......X.mmmmm ......nnnnnttttt Wm Rt Rn
883 // For the Store instructions the "target" register is actually a "source" value
885 if (emitInsIsStore(ins))
891 assert(emitInsIsLoad(ins));
895 case IF_LS_3E: // LS_3E .X.........mmmmm ......nnnnnttttt Rm Rt Rn ARMv8.1 LSE Atomics
897 assert(emitInsIsStore(ins));
898 assert(emitInsIsLoad(ins));
906 bool emitter::emitInsWritesToLclVarStackLoc(instrDesc* id)
908 if (!id->idIsLclVar())
911 instruction ins = id->idIns();
913 // This list is related to the list of instructions used to store local vars in emitIns_S_R().
914 // We don't accept writing to float local vars.
930 bool emitter::emitInsWritesToLclVarStackLocPair(instrDesc* id)
932 if (!id->idIsLclVar())
935 instruction ins = id->idIns();
937 // This list is related to the list of instructions used to store local vars in emitIns_S_S_R_R().
938 // We don't accept writing to float local vars.
950 bool emitter::emitInsMayWriteMultipleRegs(instrDesc* id)
952 instruction ins = id->idIns();
965 // For the small loads/store instruction we adjust the size 'attr'
966 // depending upon whether we have a load or a store
968 emitAttr emitter::emitInsAdjustLoadStoreAttr(instruction ins, emitAttr attr)
970 if (EA_SIZE(attr) <= EA_4BYTE)
972 if (emitInsIsLoad(ins))
974 // The value of 'ins' encodes the size to load
975 // we use EA_8BYTE here because it is the size we will write (into dataReg)
976 // it is also required when ins is INS_ldrsw
982 assert(emitInsIsStore(ins));
984 // The value of 'ins' encodes the size to store
985 // we use EA_4BYTE here because it is the size of the register
986 // that we want to display when storing small values
994 // Takes an instrDesc 'id' and uses the instruction 'ins' to determine the
995 // size of the target register that is written or read by the instruction.
996 // Note that even if EA_4BYTE is returned a load instruction will still
997 // always zero the upper 4 bytes of the target register.
998 // This method is required so that we can distinguish between loads that are
999 // sign-extending as they can have two different sizes for their target register.
1000 // Additionally for instructions like 'ldr' and 'str' these can load/store
1001 // either 4 byte or 8 bytes to/from the target register.
1002 // By convention the small unsigned load instructions are considered to write
1003 // a 4 byte sized target register, though since these also zero the upper 4 bytes
1004 // they could equally be considered to write the unsigned value to full 8 byte register.
1006 emitAttr emitter::emitInsTargetRegSize(instrDesc* id)
1008 instruction ins = id->idIns();
1009 emitAttr result = EA_UNKNOWN;
1011 // This is used to determine the size of the target registers for a load/store instruction
1045 if (id->idOpSize() == EA_8BYTE)
1061 result = id->idOpSize();
1074 result = id->idOpSize();
1078 NO_WAY("unexpected instruction");
1084 // Takes an instrDesc and uses the instruction to determine the 'size' of the
1085 // data that is loaded from memory.
1087 emitAttr emitter::emitInsLoadStoreSize(instrDesc* id)
1089 instruction ins = id->idIns();
1090 emitAttr result = EA_UNKNOWN;
1092 // The 'result' returned is the 'size' of the data that is loaded from memory.
1128 result = id->idOpSize();
1137 result = id->idOpSize();
1141 NO_WAY("unexpected instruction");
1147 /*****************************************************************************/
1151 static const char * const xRegNames[] =
1153 #define REGDEF(name, rnum, mask, xname, wname) xname,
1154 #include "register.h"
1157 static const char * const wRegNames[] =
1159 #define REGDEF(name, rnum, mask, xname, wname) wname,
1160 #include "register.h"
1163 static const char * const vRegNames[] =
1165 "v0", "v1", "v2", "v3", "v4",
1166 "v5", "v6", "v7", "v8", "v9",
1167 "v10", "v11", "v12", "v13", "v14",
1168 "v15", "v16", "v17", "v18", "v19",
1169 "v20", "v21", "v22", "v23", "v24",
1170 "v25", "v26", "v27", "v28", "v29",
1174 static const char * const qRegNames[] =
1176 "q0", "q1", "q2", "q3", "q4",
1177 "q5", "q6", "q7", "q8", "q9",
1178 "q10", "q11", "q12", "q13", "q14",
1179 "q15", "q16", "q17", "q18", "q19",
1180 "q20", "q21", "q22", "q23", "q24",
1181 "q25", "q26", "q27", "q28", "q29",
1185 static const char * const hRegNames[] =
1187 "h0", "h1", "h2", "h3", "h4",
1188 "h5", "h6", "h7", "h8", "h9",
1189 "h10", "h11", "h12", "h13", "h14",
1190 "h15", "h16", "h17", "h18", "h19",
1191 "h20", "h21", "h22", "h23", "h24",
1192 "h25", "h26", "h27", "h28", "h29",
1195 static const char * const bRegNames[] =
1197 "b0", "b1", "b2", "b3", "b4",
1198 "b5", "b6", "b7", "b8", "b9",
1199 "b10", "b11", "b12", "b13", "b14",
1200 "b15", "b16", "b17", "b18", "b19",
1201 "b20", "b21", "b22", "b23", "b24",
1202 "b25", "b26", "b27", "b28", "b29",
1207 /*****************************************************************************
1209 * Return a string that represents the given register.
1212 const char* emitter::emitRegName(regNumber reg, emitAttr size, bool varName)
1214 assert(reg < REG_COUNT);
1216 const char* rn = nullptr;
1218 if (size == EA_8BYTE)
1220 rn = xRegNames[reg];
1222 else if (size == EA_4BYTE)
1224 rn = wRegNames[reg];
1226 else if (isVectorRegister(reg))
1228 if (size == EA_16BYTE)
1230 rn = qRegNames[reg - REG_V0];
1232 else if (size == EA_2BYTE)
1234 rn = hRegNames[reg - REG_V0];
1236 else if (size == EA_1BYTE)
1238 rn = bRegNames[reg - REG_V0];
1242 assert(rn != nullptr);
1247 /*****************************************************************************
1249 * Return a string that represents the given register.
1252 const char* emitter::emitVectorRegName(regNumber reg)
1254 assert((reg >= REG_V0) && (reg <= REG_V31));
1256 int index = (int)reg - (int)REG_V0;
1258 return vRegNames[index];
1262 /*****************************************************************************
1264 * Returns the base encoding of the given CPU instruction.
1267 emitter::insFormat emitter::emitInsFormat(instruction ins)
1270 const static insFormat insFormats[] =
1272 #define INST1(id, nm, fp, ldst, fmt, e1 ) fmt,
1273 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) fmt,
1274 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) fmt,
1275 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) fmt,
1276 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) fmt,
1277 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) fmt,
1278 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) fmt,
1283 assert(ins < ArrLen(insFormats));
1284 assert((insFormats[ins] != IF_NONE));
1286 return insFormats[ins];
1295 /*static*/ const BYTE CodeGenInterface::instInfo[] =
1297 #define INST1(id, nm, fp, ldst, fmt, e1 ) ldst | INST_FP*fp,
1298 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) ldst | INST_FP*fp,
1299 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) ldst | INST_FP*fp,
1300 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) ldst | INST_FP*fp,
1301 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) ldst | INST_FP*fp,
1302 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) ldst | INST_FP*fp,
1303 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) ldst | INST_FP*fp,
1308 /*****************************************************************************
1310 * Returns true if the instruction is some kind of compare or test instruction
1313 bool emitter::emitInsIsCompare(instruction ins)
1315 // We have pseudo ins like lea which are not included in emitInsLdStTab.
1316 if (ins < ArrLen(CodeGenInterface::instInfo))
1317 return (CodeGenInterface::instInfo[ins] & CMP) ? true : false;
1322 /*****************************************************************************
1324 * Returns true if the instruction is some kind of load instruction
1327 bool emitter::emitInsIsLoad(instruction ins)
1329 // We have pseudo ins like lea which are not included in emitInsLdStTab.
1330 if (ins < ArrLen(CodeGenInterface::instInfo))
1331 return (CodeGenInterface::instInfo[ins] & LD) ? true : false;
1335 /*****************************************************************************
1337 * Returns true if the instruction is some kind of store instruction
1340 bool emitter::emitInsIsStore(instruction ins)
1342 // We have pseudo ins like lea which are not included in emitInsLdStTab.
1343 if (ins < ArrLen(CodeGenInterface::instInfo))
1344 return (CodeGenInterface::instInfo[ins] & ST) ? true : false;
1349 /*****************************************************************************
1351 * Returns true if the instruction is some kind of load/store instruction
1354 bool emitter::emitInsIsLoadOrStore(instruction ins)
1356 // We have pseudo ins like lea which are not included in emitInsLdStTab.
1357 if (ins < ArrLen(CodeGenInterface::instInfo))
1358 return (CodeGenInterface::instInfo[ins] & (LD | ST)) ? true : false;
1367 /*****************************************************************************
1369 * Returns the specific encoding of the given CPU instruction and format
1372 emitter::code_t emitter::emitInsCode(instruction ins, insFormat fmt)
1375 const static code_t insCodes1[] =
1377 #define INST1(id, nm, fp, ldst, fmt, e1 ) e1,
1378 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) e1,
1379 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) e1,
1380 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e1,
1381 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e1,
1382 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e1,
1383 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e1,
1386 const static code_t insCodes2[] =
1388 #define INST1(id, nm, fp, ldst, fmt, e1 )
1389 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) e2,
1390 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) e2,
1391 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e2,
1392 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e2,
1393 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e2,
1394 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e2,
1397 const static code_t insCodes3[] =
1399 #define INST1(id, nm, fp, ldst, fmt, e1 )
1400 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1401 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) e3,
1402 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e3,
1403 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e3,
1404 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e3,
1405 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e3,
1408 const static code_t insCodes4[] =
1410 #define INST1(id, nm, fp, ldst, fmt, e1 )
1411 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1412 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
1413 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e4,
1414 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e4,
1415 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e4,
1416 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e4,
1419 const static code_t insCodes5[] =
1421 #define INST1(id, nm, fp, ldst, fmt, e1 )
1422 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1423 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
1424 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
1425 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e5,
1426 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e5,
1427 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e5,
1430 const static code_t insCodes6[] =
1432 #define INST1(id, nm, fp, ldst, fmt, e1 )
1433 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1434 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
1435 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
1436 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
1437 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e6,
1438 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e6,
1441 const static code_t insCodes7[] =
1443 #define INST1(id, nm, fp, ldst, fmt, e1 )
1444 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1445 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
1446 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
1447 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
1448 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 )
1449 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e7,
1452 const static code_t insCodes8[] =
1454 #define INST1(id, nm, fp, ldst, fmt, e1 )
1455 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1456 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
1457 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
1458 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
1459 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 )
1460 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e8,
1463 const static code_t insCodes9[] =
1465 #define INST1(id, nm, fp, ldst, fmt, e1 )
1466 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1467 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
1468 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
1469 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
1470 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 )
1471 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e9,
1476 const static insFormat formatEncode9[9] = {IF_DR_2E, IF_DR_2G, IF_DI_1B, IF_DI_1D, IF_DV_3C,
1477 IF_DV_2B, IF_DV_2C, IF_DV_2E, IF_DV_2F};
1478 const static insFormat formatEncode6A[6] = {IF_DR_3A, IF_DR_3B, IF_DR_3C, IF_DI_2A, IF_DV_3A, IF_DV_3E};
1479 const static insFormat formatEncode5A[5] = {IF_LS_2A, IF_LS_2B, IF_LS_2C, IF_LS_3A, IF_LS_1A};
1480 const static insFormat formatEncode5B[5] = {IF_DV_2G, IF_DV_2H, IF_DV_2I, IF_DV_1A, IF_DV_1B};
1481 const static insFormat formatEncode5C[5] = {IF_DR_3A, IF_DR_3B, IF_DI_2C, IF_DV_3C, IF_DV_1B};
1482 const static insFormat formatEncode4A[4] = {IF_LS_2A, IF_LS_2B, IF_LS_2C, IF_LS_3A};
1483 const static insFormat formatEncode4B[4] = {IF_DR_3A, IF_DR_3B, IF_DR_3C, IF_DI_2A};
1484 const static insFormat formatEncode4C[4] = {IF_DR_2A, IF_DR_2B, IF_DR_2C, IF_DI_1A};
1485 const static insFormat formatEncode4D[4] = {IF_DV_3B, IF_DV_3D, IF_DV_3BI, IF_DV_3DI};
1486 const static insFormat formatEncode4E[4] = {IF_DR_3A, IF_DR_3B, IF_DI_2C, IF_DV_3C};
1487 const static insFormat formatEncode4F[4] = {IF_DR_3A, IF_DR_3B, IF_DV_3C, IF_DV_1B};
1488 const static insFormat formatEncode4G[4] = {IF_DR_2E, IF_DR_2F, IF_DV_2M, IF_DV_2L};
1489 const static insFormat formatEncode4H[4] = {IF_DV_3E, IF_DV_3A, IF_DV_2L, IF_DV_2M};
1490 const static insFormat formatEncode4I[4] = {IF_DV_3D, IF_DV_3B, IF_DV_2G, IF_DV_2A};
1491 const static insFormat formatEncode3A[3] = {IF_DR_3A, IF_DR_3B, IF_DI_2C};
1492 const static insFormat formatEncode3B[3] = {IF_DR_2A, IF_DR_2B, IF_DI_1C};
1493 const static insFormat formatEncode3C[3] = {IF_DR_3A, IF_DR_3B, IF_DV_3C};
1494 const static insFormat formatEncode3D[3] = {IF_DV_2C, IF_DV_2D, IF_DV_2E};
1495 const static insFormat formatEncode3E[3] = {IF_DV_3B, IF_DV_3BI, IF_DV_3DI};
1496 const static insFormat formatEncode3F[3] = {IF_DV_2A, IF_DV_2G, IF_DV_2H};
1497 const static insFormat formatEncode3G[3] = {IF_DV_2A, IF_DV_2G, IF_DV_2I};
1498 const static insFormat formatEncode3H[3] = {IF_DR_3A, IF_DV_3A, IF_DV_3AI};
1499 const static insFormat formatEncode3I[3] = {IF_DR_2E, IF_DR_2F, IF_DV_2M};
1500 const static insFormat formatEncode2A[2] = {IF_DR_2E, IF_DR_2F};
1501 const static insFormat formatEncode2B[2] = {IF_DR_3A, IF_DR_3B};
1502 const static insFormat formatEncode2C[2] = {IF_DR_3A, IF_DI_2D};
1503 const static insFormat formatEncode2D[2] = {IF_DR_3A, IF_DI_2B};
1504 const static insFormat formatEncode2E[2] = {IF_LS_3B, IF_LS_3C};
1505 const static insFormat formatEncode2F[2] = {IF_DR_2I, IF_DI_1F};
1506 const static insFormat formatEncode2G[2] = {IF_DV_3B, IF_DV_3D};
1507 const static insFormat formatEncode2H[2] = {IF_DV_2C, IF_DV_2F};
1508 const static insFormat formatEncode2I[2] = {IF_DV_2K, IF_DV_1C};
1509 const static insFormat formatEncode2J[2] = {IF_DV_2A, IF_DV_2G};
1510 const static insFormat formatEncode2K[2] = {IF_DV_2M, IF_DV_2L};
1511 const static insFormat formatEncode2L[2] = {IF_DV_2G, IF_DV_2M};
1512 const static insFormat formatEncode2M[2] = {IF_DV_3A, IF_DV_3AI};
1513 const static insFormat formatEncode2N[2] = {IF_DV_2N, IF_DV_2O};
1514 const static insFormat formatEncode2O[2] = {IF_DV_3E, IF_DV_3A};
1515 const static insFormat formatEncode2P[2] = {IF_DV_2G, IF_DV_3B};
1517 code_t code = BAD_CODE;
1518 insFormat insFmt = emitInsFormat(ins);
1519 bool encoding_found = false;
1525 for (index = 0; index < 9; index++)
1527 if (fmt == formatEncode9[index])
1529 encoding_found = true;
1536 for (index = 0; index < 6; index++)
1538 if (fmt == formatEncode6A[index])
1540 encoding_found = true;
1547 for (index = 0; index < 5; index++)
1549 if (fmt == formatEncode5A[index])
1551 encoding_found = true;
1558 for (index = 0; index < 5; index++)
1560 if (fmt == formatEncode5B[index])
1562 encoding_found = true;
1569 for (index = 0; index < 5; index++)
1571 if (fmt == formatEncode5C[index])
1573 encoding_found = true;
1580 for (index = 0; index < 4; index++)
1582 if (fmt == formatEncode4A[index])
1584 encoding_found = true;
1591 for (index = 0; index < 4; index++)
1593 if (fmt == formatEncode4B[index])
1595 encoding_found = true;
1602 for (index = 0; index < 4; index++)
1604 if (fmt == formatEncode4C[index])
1606 encoding_found = true;
1613 for (index = 0; index < 4; index++)
1615 if (fmt == formatEncode4D[index])
1617 encoding_found = true;
1624 for (index = 0; index < 4; index++)
1626 if (fmt == formatEncode4E[index])
1628 encoding_found = true;
1635 for (index = 0; index < 4; index++)
1637 if (fmt == formatEncode4F[index])
1639 encoding_found = true;
1646 for (index = 0; index < 4; index++)
1648 if (fmt == formatEncode4G[index])
1650 encoding_found = true;
1657 for (index = 0; index < 4; index++)
1659 if (fmt == formatEncode4H[index])
1661 encoding_found = true;
1668 for (index = 0; index < 4; index++)
1670 if (fmt == formatEncode4I[index])
1672 encoding_found = true;
1679 for (index = 0; index < 3; index++)
1681 if (fmt == formatEncode3A[index])
1683 encoding_found = true;
1690 for (index = 0; index < 3; index++)
1692 if (fmt == formatEncode3B[index])
1694 encoding_found = true;
1701 for (index = 0; index < 3; index++)
1703 if (fmt == formatEncode3C[index])
1705 encoding_found = true;
1712 for (index = 0; index < 3; index++)
1714 if (fmt == formatEncode3D[index])
1716 encoding_found = true;
1723 for (index = 0; index < 3; index++)
1725 if (fmt == formatEncode3E[index])
1727 encoding_found = true;
1734 for (index = 0; index < 3; index++)
1736 if (fmt == formatEncode3F[index])
1738 encoding_found = true;
1745 for (index = 0; index < 3; index++)
1747 if (fmt == formatEncode3G[index])
1749 encoding_found = true;
1756 for (index = 0; index < 3; index++)
1758 if (fmt == formatEncode3H[index])
1760 encoding_found = true;
1767 for (index = 0; index < 3; index++)
1769 if (fmt == formatEncode3I[index])
1771 encoding_found = true;
1778 for (index = 0; index < 2; index++)
1780 if (fmt == formatEncode2A[index])
1782 encoding_found = true;
1789 for (index = 0; index < 2; index++)
1791 if (fmt == formatEncode2B[index])
1793 encoding_found = true;
1800 for (index = 0; index < 2; index++)
1802 if (fmt == formatEncode2C[index])
1804 encoding_found = true;
1811 for (index = 0; index < 2; index++)
1813 if (fmt == formatEncode2D[index])
1815 encoding_found = true;
1822 for (index = 0; index < 2; index++)
1824 if (fmt == formatEncode2E[index])
1826 encoding_found = true;
1833 for (index = 0; index < 2; index++)
1835 if (fmt == formatEncode2F[index])
1837 encoding_found = true;
1844 for (index = 0; index < 2; index++)
1846 if (fmt == formatEncode2G[index])
1848 encoding_found = true;
1855 for (index = 0; index < 2; index++)
1857 if (fmt == formatEncode2H[index])
1859 encoding_found = true;
1866 for (index = 0; index < 2; index++)
1868 if (fmt == formatEncode2I[index])
1870 encoding_found = true;
1877 for (index = 0; index < 2; index++)
1879 if (fmt == formatEncode2J[index])
1881 encoding_found = true;
1888 for (index = 0; index < 2; index++)
1890 if (fmt == formatEncode2K[index])
1892 encoding_found = true;
1899 for (index = 0; index < 2; index++)
1901 if (fmt == formatEncode2L[index])
1903 encoding_found = true;
1910 for (index = 0; index < 2; index++)
1912 if (fmt == formatEncode2M[index])
1914 encoding_found = true;
1921 for (index = 0; index < 2; index++)
1923 if (fmt == formatEncode2N[index])
1925 encoding_found = true;
1932 for (index = 0; index < 2; index++)
1934 if (fmt == formatEncode2O[index])
1936 encoding_found = true;
1943 for (index = 0; index < 2; index++)
1945 if (fmt == formatEncode2P[index])
1947 encoding_found = true;
2030 encoding_found = true;
2035 encoding_found = false;
2039 assert(encoding_found);
2044 assert(ins < ArrLen(insCodes1));
2045 code = insCodes1[ins];
2048 assert(ins < ArrLen(insCodes2));
2049 code = insCodes2[ins];
2052 assert(ins < ArrLen(insCodes3));
2053 code = insCodes3[ins];
2056 assert(ins < ArrLen(insCodes4));
2057 code = insCodes4[ins];
2060 assert(ins < ArrLen(insCodes5));
2061 code = insCodes5[ins];
2064 assert(ins < ArrLen(insCodes6));
2065 code = insCodes6[ins];
2068 assert(ins < ArrLen(insCodes7));
2069 code = insCodes7[ins];
2072 assert(ins < ArrLen(insCodes8));
2073 code = insCodes8[ins];
2076 assert(ins < ArrLen(insCodes9));
2077 code = insCodes9[ins];
2081 assert((code != BAD_CODE));
2086 // true if this 'imm' can be encoded as a input operand to a mov instruction
2087 /*static*/ bool emitter::emitIns_valid_imm_for_mov(INT64 imm, emitAttr size)
2089 // Check for "MOV (wide immediate)".
2090 if (canEncodeHalfwordImm(imm, size))
2093 // Next try the ones-complement form of 'halfword immediate' imm(i16,hw),
2094 // namely "MOV (inverted wide immediate)".
2095 ssize_t notOfImm = NOT_helper(imm, getBitWidth(size));
2096 if (canEncodeHalfwordImm(notOfImm, size))
2099 // Finally try "MOV (bitmask immediate)" imm(N,r,s)
2100 if (canEncodeBitMaskImm(imm, size))
2106 // true if this 'imm' can be encoded as a input operand to a vector movi instruction
2107 /*static*/ bool emitter::emitIns_valid_imm_for_movi(INT64 imm, emitAttr elemsize)
2109 if (elemsize == EA_8BYTE)
2114 INT64 loByte = uimm & 0xFF;
2115 if ((loByte == 0) || (loByte == 0xFF))
2129 // First try the standard 'byteShifted immediate' imm(i8,bySh)
2130 if (canEncodeByteShiftedImm(imm, elemsize, true))
2133 // Next try the ones-complement form of the 'immediate' imm(i8,bySh)
2134 ssize_t notOfImm = NOT_helper(imm, getBitWidth(elemsize));
2135 if (canEncodeByteShiftedImm(notOfImm, elemsize, true))
2141 // true if this 'imm' can be encoded as a input operand to a fmov instruction
2142 /*static*/ bool emitter::emitIns_valid_imm_for_fmov(double immDbl)
2144 if (canEncodeFloatImm8(immDbl))
2150 // true if this 'imm' can be encoded as a input operand to an add instruction
2151 /*static*/ bool emitter::emitIns_valid_imm_for_add(INT64 imm, emitAttr size)
2153 if (unsigned_abs(imm) <= 0x0fff)
2155 else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
2161 // true if this 'imm' can be encoded as a input operand to an non-add/sub alu instruction
2162 /*static*/ bool emitter::emitIns_valid_imm_for_cmp(INT64 imm, emitAttr size)
2164 return emitIns_valid_imm_for_add(imm, size);
2167 // true if this 'imm' can be encoded as a input operand to an non-add/sub alu instruction
2168 /*static*/ bool emitter::emitIns_valid_imm_for_alu(INT64 imm, emitAttr size)
2170 if (canEncodeBitMaskImm(imm, size))
2176 // true if this 'imm' can be encoded as the offset in a ldr/str instruction
2177 /*static*/ bool emitter::emitIns_valid_imm_for_ldst_offset(INT64 imm, emitAttr attr)
2180 return true; // Encodable using IF_LS_2A
2182 if ((imm >= -256) && (imm <= 255))
2183 return true; // Encodable using IF_LS_2C (or possibly IF_LS_2B)
2186 return false; // not encodable
2188 emitAttr size = EA_SIZE(attr);
2189 unsigned scale = NaturalScale_helper(size);
2190 ssize_t mask = size - 1; // the mask of low bits that must be zero to encode the immediate
2192 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
2193 return true; // Encodable using IF_LS_2B
2195 return false; // not encodable
2198 /************************************************************************
2200 * A helper method to return the natural scale for an EA 'size'
2203 /*static*/ unsigned emitter::NaturalScale_helper(emitAttr size)
2205 assert(size == EA_1BYTE || size == EA_2BYTE || size == EA_4BYTE || size == EA_8BYTE || size == EA_16BYTE);
2207 unsigned result = 0;
2208 unsigned utemp = (unsigned)size;
2210 // Compute log base 2 of utemp (aka 'size')
2220 /************************************************************************
2222 * A helper method to perform a Rotate-Right shift operation
2223 * the source is 'value' and it is rotated right by 'sh' bits
2224 * 'value' is considered to be a fixed size 'width' set of bits.
2227 * value is '00001111', sh is 2 and width is 8
2228 * result is '11000011'
2231 /*static*/ UINT64 emitter::ROR_helper(UINT64 value, unsigned sh, unsigned width)
2233 assert(width <= 64);
2234 // Check that 'value' fits in 'width' bits
2235 assert((width == 64) || (value < (1ULL << width)));
2236 // We don't support shifts >= width
2242 unsigned lsh = width - rsh;
2244 result = (value >> rsh);
2245 result |= (value << lsh);
2249 // mask off any extra bits that we got from the left shift
2250 result &= ((1ULL << width) - 1);
2254 /************************************************************************
2256 * A helper method to perform a 'NOT' bitwise complement operation.
2257 * 'value' is considered to be a fixed size 'width' set of bits.
2260 * value is '01001011', and width is 8
2261 * result is '10110100'
2264 /*static*/ UINT64 emitter::NOT_helper(UINT64 value, unsigned width)
2266 assert(width <= 64);
2268 UINT64 result = ~value;
2272 // Check that 'value' fits in 'width' bits. Don't consider "sign" bits above width.
2273 UINT64 maxVal = 1ULL << width;
2274 UINT64 lowBitsMask = maxVal - 1;
2275 UINT64 signBitsMask = ~lowBitsMask | (1ULL << (width - 1)); // The high bits must be set, and the top bit
2276 // (sign bit) must be set.
2277 assert((value < maxVal) || ((value & signBitsMask) == signBitsMask));
2279 // mask off any extra bits that we got from the complement operation
2280 result &= lowBitsMask;
2286 /************************************************************************
2288 * A helper method to perform a bit Replicate operation
2289 * the source is 'value' with a fixed size 'width' set of bits.
2290 * value is replicated to fill out 32 or 64 bits as determined by 'size'.
2293 * value is '11000011' (0xE3), width is 8 and size is EA_8BYTE
2294 * result is '11000011 11000011 11000011 11000011 11000011 11000011 11000011 11000011'
2295 * 0xE3E3E3E3E3E3E3E3
2298 /*static*/ UINT64 emitter::Replicate_helper(UINT64 value, unsigned width, emitAttr size)
2300 assert(emitter::isValidGeneralDatasize(size));
2302 unsigned immWidth = (size == EA_8BYTE) ? 64 : 32;
2303 assert(width <= immWidth);
2305 UINT64 result = value;
2306 unsigned filledBits = width;
2308 while (filledBits < immWidth)
2312 filledBits += width;
2317 /************************************************************************
2319 * Convert an imm(N,r,s) into a 64-bit immediate
2320 * inputs 'bmImm' a bitMaskImm struct
2321 * 'size' specifies the size of the result (64 or 32 bits)
2324 /*static*/ INT64 emitter::emitDecodeBitMaskImm(const emitter::bitMaskImm bmImm, emitAttr size)
2326 assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2328 unsigned N = bmImm.immN; // read the N,R and S values from the 'bitMaskImm' encoding
2329 unsigned R = bmImm.immR;
2330 unsigned S = bmImm.immS;
2332 unsigned elemWidth = 64; // used when immN == 1
2334 if (bmImm.immN == 0) // find the smaller elemWidth when immN == 0
2336 // Scan S for the highest bit not set
2338 for (unsigned bitNum = 5; bitNum > 0; bitNum--)
2340 unsigned oneBit = elemWidth;
2341 if ((S & oneBit) == 0)
2348 assert(size == EA_8BYTE);
2351 unsigned maskSR = elemWidth - 1;
2356 // encoding for S is one less than the number of consecutive one bits
2357 S++; // Number of consecutive ones to generate in 'welem'
2361 // 'elemWidth' is the number of bits that we will use for the ROR and Replicate operations
2362 // 'S' is the number of consecutive 1 bits for the immediate
2363 // 'R' is the number of bits that we will Rotate Right the immediate
2364 // 'size' selects the final size of the immedate that we return (64 or 32 bits)
2366 assert(S < elemWidth); // 'elemWidth' consecutive one's is a reserved encoding
2371 welem = (1ULL << S) - 1;
2373 wmask = ROR_helper(welem, R, elemWidth);
2374 wmask = Replicate_helper(wmask, elemWidth, size);
2379 /*****************************************************************************
2381 * Check if an immediate can use the left shifted by 12 bits encoding
2384 /*static*/ bool emitter::canEncodeWithShiftImmBy12(INT64 imm)
2388 imm = -imm; // convert to unsigned
2393 return false; // Must be MIN_INT64
2396 if ((imm & 0xfff) != 0) // Now the low 12 bits all have to be zero
2401 imm >>= 12; // shift right by 12 bits
2403 return (imm <= 0x0fff); // Does it fit in 12 bits
2406 /*****************************************************************************
2408 * Normalize the 'imm' so that the upper bits, as defined by 'size' are zero
2411 /*static*/ INT64 emitter::normalizeImm64(INT64 imm, emitAttr size)
2413 unsigned immWidth = getBitWidth(size);
2418 // Check that 'imm' fits in 'immWidth' bits. Don't consider "sign" bits above width.
2419 INT64 maxVal = 1LL << immWidth;
2420 INT64 lowBitsMask = maxVal - 1;
2421 INT64 hiBitsMask = ~lowBitsMask;
2422 INT64 signBitsMask =
2423 hiBitsMask | (1LL << (immWidth - 1)); // The high bits must be set, and the top bit (sign bit) must be set.
2424 assert((imm < maxVal) || ((imm & signBitsMask) == signBitsMask));
2426 // mask off the hiBits
2427 result &= lowBitsMask;
2432 /*****************************************************************************
2434 * Normalize the 'imm' so that the upper bits, as defined by 'size' are zero
2437 /*static*/ INT32 emitter::normalizeImm32(INT32 imm, emitAttr size)
2439 unsigned immWidth = getBitWidth(size);
2444 // Check that 'imm' fits in 'immWidth' bits. Don't consider "sign" bits above width.
2445 INT32 maxVal = 1 << immWidth;
2446 INT32 lowBitsMask = maxVal - 1;
2447 INT32 hiBitsMask = ~lowBitsMask;
2448 INT32 signBitsMask = hiBitsMask | (1 << (immWidth - 1)); // The high bits must be set, and the top bit
2449 // (sign bit) must be set.
2450 assert((imm < maxVal) || ((imm & signBitsMask) == signBitsMask));
2452 // mask off the hiBits
2453 result &= lowBitsMask;
2458 /************************************************************************
2460 * returns true if 'imm' of 'size bits (32/64) can be encoded
2461 * using the ARM64 'bitmask immediate' form.
2462 * When a non-null value is passed for 'wbBMI' then this method
2463 * writes back the 'N','S' and 'R' values use to encode this immediate
2467 /*static*/ bool emitter::canEncodeBitMaskImm(INT64 imm, emitAttr size, emitter::bitMaskImm* wbBMI)
2469 assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2471 unsigned immWidth = (size == EA_8BYTE) ? 64 : 32;
2472 unsigned maxLen = (size == EA_8BYTE) ? 6 : 5;
2474 imm = normalizeImm64(imm, size);
2476 // Starting with len=1, elemWidth is 2 bits
2477 // len=2, elemWidth is 4 bits
2478 // len=3, elemWidth is 8 bits
2479 // len=4, elemWidth is 16 bits
2480 // len=5, elemWidth is 32 bits
2481 // (optionally) len=6, elemWidth is 64 bits
2483 for (unsigned len = 1; (len <= maxLen); len++)
2485 unsigned elemWidth = 1 << len;
2486 UINT64 elemMask = ((UINT64)-1) >> (64 - elemWidth);
2487 UINT64 tempImm = (UINT64)imm; // A working copy of 'imm' that we can mutate
2488 UINT64 elemVal = tempImm & elemMask; // The low 'elemWidth' bits of 'imm'
2490 // Check for all 1's or 0's as these can't be encoded
2491 if ((elemVal == 0) || (elemVal == elemMask))
2494 // 'checkedBits' is the count of bits that are known to match 'elemVal' when replicated
2495 unsigned checkedBits = elemWidth; // by definition the first 'elemWidth' bits match
2497 // Now check to see if each of the next bits match...
2499 while (checkedBits < immWidth)
2501 tempImm >>= elemWidth;
2503 UINT64 nextElem = tempImm & elemMask;
2504 if (nextElem != elemVal)
2506 // Not matching, exit this loop and checkedBits will not be equal to immWidth
2510 // The 'nextElem' is matching, so increment 'checkedBits'
2511 checkedBits += elemWidth;
2514 // Did the full immediate contain bits that can be formed by repeating 'elemVal'?
2515 if (checkedBits == immWidth)
2517 // We are not quite done, since the only values that we can encode as a
2518 // 'bitmask immediate' are those that can be formed by starting with a
2519 // bit string of 0*1* that is rotated by some number of bits.
2521 // We check to see if 'elemVal' can be formed using these restrictions.
2524 // Rotating by one bit any value that passes these restrictions
2525 // can be xor-ed with the original value and will result it a string
2526 // of bits that have exactly two 1 bits: 'elemRorXor'
2527 // Further the distance between the two one bits tells us the value
2528 // of S and the location of the 1 bits tells us the value of R
2530 // Some examples: (immWidth is 8)
2532 // S=4,R=0 S=5,R=3 S=3,R=6
2533 // elemVal: 00001111 11100011 00011100
2534 // elemRor: 10000111 11110001 00001110
2535 // elemRorXor: 10001000 00010010 00010010
2536 // compute S 45678--- ---5678- ---3210-
2537 // compute R 01234567 ---34567 ------67
2539 UINT64 elemRor = ROR_helper(elemVal, 1, elemWidth); // Rotate 'elemVal' Right by one bit
2540 UINT64 elemRorXor = elemVal ^ elemRor; // Xor elemVal and elemRor
2542 // If we only have a two-bit change in elemROR then we can form a mask for this value
2543 unsigned bitCount = 0;
2544 UINT64 oneBit = 0x1;
2545 unsigned R = elemWidth; // R is shift count for ROR (rotate right shift)
2546 unsigned S = 0; // S is number of consecutive one bits
2549 // Loop over the 'elemWidth' bits in 'elemRorXor'
2551 for (unsigned bitNum = 0; bitNum < elemWidth; bitNum++)
2555 R--; // We decrement R by one whenever incr is -1
2559 S += incr; // We incr/decr S, after we find the first one bit in 'elemRorXor'
2562 // Is this bit position a 1 bit in 'elemRorXor'?
2564 if (oneBit & elemRorXor)
2567 // Is this the first 1 bit that we found in 'elemRorXor'?
2570 // Does this 1 bit represent a transition to zero bits?
2571 bool toZeros = ((oneBit & elemVal) != 0);
2574 // S :: Count down from elemWidth
2578 else // this 1 bit represent a transition to one bits.
2580 // S :: Count up from zero
2585 else // bitCount > 1
2587 // We found the second (or third...) 1 bit in 'elemRorXor'
2588 incr = 0; // stop decrementing 'R'
2592 // More than 2 transitions from 0/1 in 'elemVal'
2593 // This means that 'elemVal' can't be encoded
2594 // using a 'bitmask immediate'.
2596 // Furthermore, it will continue to fail
2597 // with any larger 'len' that we try.
2598 // so just return false.
2605 // shift oneBit left by one bit to test the next position
2609 // We expect that bitCount will always be two at this point
2610 // but just in case return false for any bad cases.
2612 assert(bitCount == 2);
2616 // Perform some sanity checks on the values of 'S' and 'R'
2618 assert(S < elemWidth);
2619 assert(R < elemWidth);
2621 // Does the caller want us to return the N,R,S encoding values?
2623 if (wbBMI != nullptr)
2626 // The encoding used for S is one less than the
2627 // number of consecutive one bits
2637 // The encoding used for 'S' here is a bit peculiar.
2639 // The upper bits need to be complemented, followed by a zero bit
2640 // then the value of 'S-1'
2642 unsigned upperBitsOfS = 64 - (1 << (len + 1));
2648 // Verify that what we are returning is correct.
2649 assert(imm == emitDecodeBitMaskImm(*wbBMI, size));
2651 // Tell the caller that we can successfully encode this immediate
2652 // using a 'bitmask immediate'.
2660 /************************************************************************
2662 * Convert a 64-bit immediate into its 'bitmask immediate' representation imm(N,r,s)
2665 /*static*/ emitter::bitMaskImm emitter::emitEncodeBitMaskImm(INT64 imm, emitAttr size)
2667 emitter::bitMaskImm result;
2670 bool canEncode = canEncodeBitMaskImm(imm, size, &result);
2676 /************************************************************************
2678 * Convert an imm(i16,hw) into a 32/64-bit immediate
2679 * inputs 'hwImm' a halfwordImm struct
2680 * 'size' specifies the size of the result (64 or 32 bits)
2683 /*static*/ INT64 emitter::emitDecodeHalfwordImm(const emitter::halfwordImm hwImm, emitAttr size)
2685 assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2687 unsigned hw = hwImm.immHW;
2688 INT64 val = (INT64)hwImm.immVal;
2690 assert((hw <= 1) || (size == EA_8BYTE));
2692 INT64 result = val << (16 * hw);
2696 /************************************************************************
2698 * returns true if 'imm' of 'size' bits (32/64) can be encoded
2699 * using the ARM64 'halfword immediate' form.
2700 * When a non-null value is passed for 'wbHWI' then this method
2701 * writes back the 'immHW' and 'immVal' values use to encode this immediate
2705 /*static*/ bool emitter::canEncodeHalfwordImm(INT64 imm, emitAttr size, emitter::halfwordImm* wbHWI)
2707 assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2709 unsigned immWidth = (size == EA_8BYTE) ? 64 : 32;
2710 unsigned maxHW = (size == EA_8BYTE) ? 4 : 2;
2712 // setup immMask to a (EA_4BYTE) 0x00000000_FFFFFFFF or (EA_8BYTE) 0xFFFFFFFF_FFFFFFFF
2713 const UINT64 immMask = ((UINT64)-1) >> (64 - immWidth);
2714 const INT64 mask16 = (INT64)0xFFFF;
2716 imm = normalizeImm64(imm, size);
2718 // Try each of the valid hw shift sizes
2719 for (unsigned hw = 0; (hw < maxHW); hw++)
2721 INT64 curMask = mask16 << (hw * 16); // Represents the mask of the bits in the current halfword
2722 INT64 checkBits = immMask & ~curMask;
2724 // Excluding the current halfword (using ~curMask)
2725 // does the immediate have zero bits in every other bit that we care about?
2726 // note we care about all 64-bits for EA_8BYTE
2727 // and we care about the lowest 32 bits for EA_4BYTE
2729 if ((imm & checkBits) == 0)
2731 // Does the caller want us to return the imm(i16,hw) encoding values?
2733 if (wbHWI != nullptr)
2735 INT64 val = ((imm & curMask) >> (hw * 16)) & mask16;
2737 wbHWI->immVal = val;
2739 // Verify that what we are returning is correct.
2740 assert(imm == emitDecodeHalfwordImm(*wbHWI, size));
2742 // Tell the caller that we can successfully encode this immediate
2743 // using a 'halfword immediate'.
2751 /************************************************************************
2753 * Convert a 64-bit immediate into its 'halfword immediate' representation imm(i16,hw)
2756 /*static*/ emitter::halfwordImm emitter::emitEncodeHalfwordImm(INT64 imm, emitAttr size)
2758 emitter::halfwordImm result;
2759 result.immHWVal = 0;
2761 bool canEncode = canEncodeHalfwordImm(imm, size, &result);
2767 /************************************************************************
2769 * Convert an imm(i8,sh) into a 16/32-bit immediate
2770 * inputs 'bsImm' a byteShiftedImm struct
2771 * 'size' specifies the size of the result (16 or 32 bits)
2774 /*static*/ INT32 emitter::emitDecodeByteShiftedImm(const emitter::byteShiftedImm bsImm, emitAttr size)
2776 bool onesShift = (bsImm.immOnes == 1);
2777 unsigned bySh = bsImm.immBY; // Num Bytes to shift 0,1,2,3
2778 INT32 val = (INT32)bsImm.immVal; // 8-bit immediate
2783 assert((size == EA_2BYTE) || (size == EA_4BYTE)); // Only EA_2BYTE or EA_4BYTE forms
2784 if (size == EA_2BYTE)
2793 result <<= (8 * bySh);
2797 result |= ((1 << (8 * bySh)) - 1);
2803 /************************************************************************
2805 * returns true if 'imm' of 'size' bits (16/32) can be encoded
2806 * using the ARM64 'byteShifted immediate' form.
2807 * When a non-null value is passed for 'wbBSI' then this method
2808 * writes back the 'immBY' and 'immVal' values use to encode this immediate
2812 /*static*/ bool emitter::canEncodeByteShiftedImm(INT64 imm,
2815 emitter::byteShiftedImm* wbBSI)
2817 bool canEncode = false;
2818 bool onesShift = false; // true if we use the shifting ones variant
2819 unsigned bySh = 0; // number of bytes to shift: 0, 1, 2, 3
2820 unsigned imm8 = 0; // immediate to use in the encoding
2822 imm = normalizeImm64(imm, size);
2824 if (size == EA_1BYTE)
2826 imm8 = (unsigned)imm;
2827 assert(imm8 < 0x100);
2830 else if (size == EA_8BYTE)
2832 imm8 = (unsigned)imm;
2833 assert(imm8 < 0x100);
2838 assert((size == EA_2BYTE) || (size == EA_4BYTE)); // Only EA_2BYTE or EA_4BYTE forms
2840 unsigned immWidth = (size == EA_4BYTE) ? 32 : 16;
2841 unsigned maxBY = (size == EA_4BYTE) ? 4 : 2;
2843 // setup immMask to a (EA_2BYTE) 0x0000FFFF or (EA_4BYTE) 0xFFFFFFFF
2844 const UINT32 immMask = ((UINT32)-1) >> (32 - immWidth);
2845 const INT32 mask8 = (INT32)0xFF;
2847 // Try each of the valid by shift sizes
2848 for (bySh = 0; (bySh < maxBY); bySh++)
2850 INT32 curMask = mask8 << (bySh * 8); // Represents the mask of the bits in the current byteShifted
2851 INT32 checkBits = immMask & ~curMask;
2852 INT32 immCheck = (imm & checkBits);
2854 // Excluding the current byte (using ~curMask)
2855 // does the immediate have zero bits in every other bit that we care about?
2856 // or can be use the shifted one variant?
2857 // note we care about all 32-bits for EA_4BYTE
2858 // and we care about the lowest 16 bits for EA_2BYTE
2866 if ((bySh == 1) && (immCheck == 0xFF))
2871 else if ((bySh == 2) && (immCheck == 0xFFFF))
2879 imm8 = (unsigned)(((imm & curMask) >> (bySh * 8)) & mask8);
2887 // Does the caller want us to return the imm(i8,bySh) encoding values?
2889 if (wbBSI != nullptr)
2891 wbBSI->immOnes = onesShift;
2892 wbBSI->immBY = bySh;
2893 wbBSI->immVal = imm8;
2895 // Verify that what we are returning is correct.
2896 assert(imm == emitDecodeByteShiftedImm(*wbBSI, size));
2898 // Tell the caller that we can successfully encode this immediate
2899 // using a 'byteShifted immediate'.
2906 /************************************************************************
2908 * Convert a 32-bit immediate into its 'byteShifted immediate' representation imm(i8,by)
2911 /*static*/ emitter::byteShiftedImm emitter::emitEncodeByteShiftedImm(INT64 imm, emitAttr size, bool allow_MSL)
2913 emitter::byteShiftedImm result;
2914 result.immBSVal = 0;
2916 bool canEncode = canEncodeByteShiftedImm(imm, size, allow_MSL, &result);
2922 /************************************************************************
2924 * Convert a 'float 8-bit immediate' into a double.
2925 * inputs 'fpImm' a floatImm8 struct
2928 /*static*/ double emitter::emitDecodeFloatImm8(const emitter::floatImm8 fpImm)
2930 unsigned sign = fpImm.immSign;
2931 unsigned exp = fpImm.immExp ^ 0x4;
2932 unsigned mant = fpImm.immMant + 16;
2933 unsigned scale = 16 * 8;
2941 double result = ((double)mant) / ((double)scale);
2950 /************************************************************************
2952 * returns true if the 'immDbl' can be encoded using the 'float 8-bit immediate' form.
2953 * also returns the encoding if wbFPI is non-null
2957 /*static*/ bool emitter::canEncodeFloatImm8(double immDbl, emitter::floatImm8* wbFPI)
2959 bool canEncode = false;
2960 double val = immDbl;
2970 while ((val < 1.0) && (exp >= -4))
2975 while ((val >= 2.0) && (exp <= 5))
2982 int ival = (int)val;
2984 if ((exp >= 0) && (exp <= 7))
2986 if (val == (double)ival)
2990 if (wbFPI != nullptr)
2993 assert((ival >= 0) && (ival <= 15));
2995 wbFPI->immSign = sign;
2996 wbFPI->immExp = exp ^ 0x4;
2997 wbFPI->immMant = ival;
2998 unsigned imm8 = wbFPI->immFPIVal;
2999 assert((imm8 >= 0) && (imm8 <= 0xff));
3007 /************************************************************************
3009 * Convert a double into its 'float 8-bit immediate' representation
3012 /*static*/ emitter::floatImm8 emitter::emitEncodeFloatImm8(double immDbl)
3014 emitter::floatImm8 result;
3015 result.immFPIVal = 0;
3017 bool canEncode = canEncodeFloatImm8(immDbl, &result);
3023 /*****************************************************************************
3025 * For the given 'ins' returns the reverse instruction
3026 * if one exists, otherwise returns INS_INVALID
3029 /*static*/ instruction emitter::insReverse(instruction ins)
3058 /*****************************************************************************
3060 * For the given 'datasize' and 'elemsize', make the proper arrangement option
3061 * returns the insOpts that specifies the vector register arrangement
3062 * if one does not exist returns INS_OPTS_NONE
3065 /*static*/ insOpts emitter::optMakeArrangement(emitAttr datasize, emitAttr elemsize)
3067 insOpts result = INS_OPTS_NONE;
3069 if (datasize == EA_8BYTE)
3074 result = INS_OPTS_8B;
3077 result = INS_OPTS_4H;
3080 result = INS_OPTS_2S;
3083 result = INS_OPTS_1D;
3090 else if (datasize == EA_16BYTE)
3095 result = INS_OPTS_16B;
3098 result = INS_OPTS_8H;
3101 result = INS_OPTS_4S;
3104 result = INS_OPTS_2D;
3114 /*****************************************************************************
3116 * For the given 'datasize' and arrangement 'opts'
3117 * returns true is the pair spcifies a valid arrangement
3119 /*static*/ bool emitter::isValidArrangement(emitAttr datasize, insOpts opt)
3121 if (datasize == EA_8BYTE)
3123 if ((opt == INS_OPTS_8B) || (opt == INS_OPTS_4H) || (opt == INS_OPTS_2S) || (opt == INS_OPTS_1D))
3128 else if (datasize == EA_16BYTE)
3130 if ((opt == INS_OPTS_16B) || (opt == INS_OPTS_8H) || (opt == INS_OPTS_4S) || (opt == INS_OPTS_2D))
3138 // For the given 'arrangement' returns the 'datasize' specified by the vector register arrangement
3139 // asserts and returns EA_UNKNOWN if an invalid 'arrangement' value is passed
3141 /*static*/ emitAttr emitter::optGetDatasize(insOpts arrangement)
3143 if ((arrangement == INS_OPTS_8B) || (arrangement == INS_OPTS_4H) || (arrangement == INS_OPTS_2S) ||
3144 (arrangement == INS_OPTS_1D))
3148 else if ((arrangement == INS_OPTS_16B) || (arrangement == INS_OPTS_8H) || (arrangement == INS_OPTS_4S) ||
3149 (arrangement == INS_OPTS_2D))
3155 assert(!" invalid 'arrangement' value");
3160 // For the given 'arrangement' returns the 'elemsize' specified by the vector register arrangement
3161 // asserts and returns EA_UNKNOWN if an invalid 'arrangement' value is passed
3163 /*static*/ emitAttr emitter::optGetElemsize(insOpts arrangement)
3165 if ((arrangement == INS_OPTS_8B) || (arrangement == INS_OPTS_16B))
3169 else if ((arrangement == INS_OPTS_4H) || (arrangement == INS_OPTS_8H))
3173 else if ((arrangement == INS_OPTS_2S) || (arrangement == INS_OPTS_4S))
3177 else if ((arrangement == INS_OPTS_1D) || (arrangement == INS_OPTS_2D))
3183 assert(!" invalid 'arrangement' value");
3188 // For the given 'arrangement' returns the 'widen-arrangement' specified by the vector register arrangement
3189 // asserts and returns INS_OPTS_NONE if an invalid 'arrangement' value is passed
3191 /*static*/ insOpts emitter::optWidenElemsize(insOpts arrangement)
3193 if ((arrangement == INS_OPTS_8B) || (arrangement == INS_OPTS_16B))
3197 else if ((arrangement == INS_OPTS_4H) || (arrangement == INS_OPTS_8H))
3201 else if ((arrangement == INS_OPTS_2S) || (arrangement == INS_OPTS_4S))
3207 assert(!" invalid 'arrangement' value");
3208 return INS_OPTS_NONE;
3212 // For the given 'conversion' returns the 'dstsize' specified by the conversion option
3213 /*static*/ emitAttr emitter::optGetDstsize(insOpts conversion)
3217 case INS_OPTS_S_TO_8BYTE:
3218 case INS_OPTS_D_TO_8BYTE:
3219 case INS_OPTS_4BYTE_TO_D:
3220 case INS_OPTS_8BYTE_TO_D:
3221 case INS_OPTS_S_TO_D:
3222 case INS_OPTS_H_TO_D:
3226 case INS_OPTS_S_TO_4BYTE:
3227 case INS_OPTS_D_TO_4BYTE:
3228 case INS_OPTS_4BYTE_TO_S:
3229 case INS_OPTS_8BYTE_TO_S:
3230 case INS_OPTS_D_TO_S:
3231 case INS_OPTS_H_TO_S:
3235 case INS_OPTS_S_TO_H:
3236 case INS_OPTS_D_TO_H:
3241 assert(!" invalid 'conversion' value");
3246 // For the given 'conversion' returns the 'srcsize' specified by the conversion option
3247 /*static*/ emitAttr emitter::optGetSrcsize(insOpts conversion)
3251 case INS_OPTS_D_TO_8BYTE:
3252 case INS_OPTS_D_TO_4BYTE:
3253 case INS_OPTS_8BYTE_TO_D:
3254 case INS_OPTS_8BYTE_TO_S:
3255 case INS_OPTS_D_TO_S:
3256 case INS_OPTS_D_TO_H:
3260 case INS_OPTS_S_TO_8BYTE:
3261 case INS_OPTS_S_TO_4BYTE:
3262 case INS_OPTS_4BYTE_TO_S:
3263 case INS_OPTS_4BYTE_TO_D:
3264 case INS_OPTS_S_TO_D:
3265 case INS_OPTS_S_TO_H:
3269 case INS_OPTS_H_TO_S:
3270 case INS_OPTS_H_TO_D:
3275 assert(!" invalid 'conversion' value");
3280 // For the given 'size' and 'index' returns true if it specifies a valid index for a vector register of 'size'
3281 /*static*/ bool emitter::isValidVectorIndex(emitAttr datasize, emitAttr elemsize, ssize_t index)
3283 assert(isValidVectorDatasize(datasize));
3284 assert(isValidVectorElemsize(elemsize));
3286 bool result = false;
3289 if (datasize == EA_8BYTE)
3294 result = (index < 8);
3297 result = (index < 4);
3300 result = (index < 2);
3303 result = (index < 1);
3310 else if (datasize == EA_16BYTE)
3315 result = (index < 16);
3318 result = (index < 8);
3321 result = (index < 4);
3324 result = (index < 2);
3335 /*****************************************************************************
3337 * Add an instruction with no operands.
3340 void emitter::emitIns(instruction ins)
3342 instrDesc* id = emitNewInstrSmall(EA_8BYTE);
3343 insFormat fmt = emitInsFormat(ins);
3345 assert(fmt == IF_SN_0A);
3354 /*****************************************************************************
3356 * Add an instruction with a single immediate value.
3359 void emitter::emitIns_I(instruction ins, emitAttr attr, ssize_t imm)
3361 insFormat fmt = IF_NONE;
3363 /* Figure out the encoding format of the instruction */
3367 if ((imm & 0x0000ffff) == imm)
3373 assert(!"Instruction cannot be encoded: IF_SI_0A");
3380 assert(fmt != IF_NONE);
3382 instrDesc* id = emitNewInstrSC(attr, imm);
3391 /*****************************************************************************
3393 * Add an instruction referencing a single register.
3396 void emitter::emitIns_R(instruction ins, emitAttr attr, regNumber reg)
3398 emitAttr size = EA_SIZE(attr);
3399 insFormat fmt = IF_NONE;
3400 instrDesc* id = nullptr;
3402 /* Figure out the encoding format of the instruction */
3407 assert(isGeneralRegister(reg));
3408 id = emitNewInstrSmall(attr);
3417 assert(fmt != IF_NONE);
3426 /*****************************************************************************
3428 * Add an instruction referencing a register and a constant.
3431 void emitter::emitIns_R_I(instruction ins, emitAttr attr, regNumber reg, ssize_t imm, insOpts opt /* = INS_OPTS_NONE */)
3433 emitAttr size = EA_SIZE(attr);
3434 emitAttr elemsize = EA_UNKNOWN;
3435 insFormat fmt = IF_NONE;
3436 bool canEncode = false;
3438 /* Figure out the encoding format of the instruction */
3447 assert(insOptsNone(opt));
3448 assert(isGeneralRegister(reg));
3450 canEncode = canEncodeBitMaskImm(imm, size, &bmi);
3454 assert(isValidImmNRS(imm, size));
3462 assert(isValidGeneralDatasize(size));
3463 assert(insOptsNone(opt)); // No LSL here (you must use emitIns_R_I_I if a shift is needed)
3464 assert(isGeneralRegister(reg));
3465 assert(isValidUimm16(imm));
3469 assert(imm == emitDecodeHalfwordImm(hwi, size));
3477 assert(isValidGeneralDatasize(size));
3478 assert(insOptsNone(opt)); // No explicit LSL here
3479 // We will automatically determine the shift based upon the imm
3481 // First try the standard 'halfword immediate' imm(i16,hw)
3483 canEncode = canEncodeHalfwordImm(imm, size, &hwi);
3486 // uses a movz encoding
3487 assert(isGeneralRegister(reg));
3489 assert(isValidImmHWVal(imm, size));
3494 // Next try the ones-complement form of 'halfword immediate' imm(i16,hw)
3495 notOfImm = NOT_helper(imm, getBitWidth(size));
3496 canEncode = canEncodeHalfwordImm(notOfImm, size, &hwi);
3499 assert(isGeneralRegister(reg));
3501 ins = INS_movn; // uses a movn encoding
3502 assert(isValidImmHWVal(imm, size));
3507 // Finally try the 'bitmask immediate' imm(N,r,s)
3509 canEncode = canEncodeBitMaskImm(imm, size, &bmi);
3512 assert(isGeneralRegisterOrSP(reg));
3513 reg = encodingSPtoZR(reg);
3515 assert(isValidImmNRS(imm, size));
3521 assert(!"Instruction cannot be encoded: mov imm");
3527 assert(isValidVectorDatasize(size));
3528 assert(isVectorRegister(reg));
3529 if (insOptsNone(opt) && (size == EA_8BYTE))
3533 assert(isValidArrangement(size, opt));
3534 elemsize = optGetElemsize(opt);
3536 if (elemsize == EA_8BYTE)
3542 bool failed = false;
3545 INT64 loByte = uimm & 0xFF;
3546 if (((loByte == 0) || (loByte == 0xFF)) && (pos < 8))
3562 assert(isValidUimm8(imm));
3570 // No explicit LSL/MSL is used for the immediate
3571 // We will automatically determine the shift based upon the value of imm
3573 // First try the standard 'byteShifted immediate' imm(i8,bySh)
3575 canEncode = canEncodeByteShiftedImm(imm, elemsize, true, &bsi);
3579 assert(isValidImmBSVal(imm, size));
3584 // Next try the ones-complement form of the 'immediate' imm(i8,bySh)
3585 if ((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE)) // Only EA_2BYTE or EA_4BYTE forms
3587 notOfImm = NOT_helper(imm, getBitWidth(elemsize));
3588 canEncode = canEncodeByteShiftedImm(notOfImm, elemsize, true, &bsi);
3592 ins = INS_mvni; // uses a mvni encoding
3593 assert(isValidImmBSVal(imm, size));
3604 assert(isValidVectorDatasize(size));
3605 assert(isVectorRegister(reg));
3606 assert(isValidArrangement(size, opt));
3607 elemsize = optGetElemsize(opt);
3608 assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE)); // Only EA_2BYTE or EA_4BYTE forms
3612 // No explicit LSL/MSL is used for the immediate
3613 // We will automatically determine the shift based upon the value of imm
3615 // First try the standard 'byteShifted immediate' imm(i8,bySh)
3617 canEncode = canEncodeByteShiftedImm(imm, elemsize,
3618 (ins == INS_mvni), // mvni supports the ones shifting variant (aka MSL)
3623 assert(isValidImmBSVal(imm, size));
3631 assert(insOptsNone(opt));
3632 assert(isGeneralRegister(reg));
3634 if (unsigned_abs(imm) <= 0x0fff)
3638 ins = insReverse(ins);
3641 assert(isValidUimm12(imm));
3645 else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
3647 // Encoding will use a 12-bit left shift of the immediate
3648 opt = INS_OPTS_LSL12;
3651 ins = insReverse(ins);
3654 assert((imm & 0xfff) == 0);
3656 assert(isValidUimm12(imm));
3662 assert(!"Instruction cannot be encoded: IF_DI_1A");
3670 } // end switch (ins)
3673 assert(fmt != IF_NONE);
3675 instrDesc* id = emitNewInstrSC(attr, imm);
3687 /*****************************************************************************
3689 * Add an instruction referencing a register and a floating point constant.
3692 void emitter::emitIns_R_F(
3693 instruction ins, emitAttr attr, regNumber reg, double immDbl, insOpts opt /* = INS_OPTS_NONE */)
3696 emitAttr size = EA_SIZE(attr);
3697 emitAttr elemsize = EA_UNKNOWN;
3698 insFormat fmt = IF_NONE;
3700 bool canEncode = false;
3702 /* Figure out the encoding format of the instruction */
3709 assert(insOptsNone(opt));
3710 assert(isValidVectorElemsizeFloat(size));
3711 assert(isVectorRegister(reg));
3720 assert(isVectorRegister(reg));
3722 canEncode = canEncodeFloatImm8(immDbl, &fpi);
3724 if (insOptsAnyArrangement(opt))
3727 assert(isValidVectorDatasize(size));
3728 assert(isValidArrangement(size, opt));
3729 elemsize = optGetElemsize(opt);
3730 assert(isValidVectorElemsizeFloat(elemsize));
3731 assert(opt != INS_OPTS_1D); // Reserved encoding
3735 imm = fpi.immFPIVal;
3736 assert((imm >= 0) && (imm <= 0xff));
3743 assert(insOptsNone(opt));
3744 assert(isValidVectorElemsizeFloat(size));
3748 imm = fpi.immFPIVal;
3749 assert((imm >= 0) && (imm <= 0xff));
3759 } // end switch (ins)
3762 assert(fmt != IF_NONE);
3764 instrDesc* id = emitNewInstrSC(attr, imm);
3776 /*****************************************************************************
3778 * Add an instruction referencing two registers
3781 void emitter::emitIns_R_R(
3782 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insOpts opt /* = INS_OPTS_NONE */)
3784 emitAttr size = EA_SIZE(attr);
3785 emitAttr elemsize = EA_UNKNOWN;
3786 insFormat fmt = IF_NONE;
3788 /* Figure out the encoding format of the instruction */
3792 assert(insOptsNone(opt));
3793 // Is the mov even necessary?
3796 // A mov with a EA_4BYTE has the side-effect of clearing the upper bits
3797 // So only eliminate mov instructions that are not clearing the upper bits
3799 if (isGeneralRegisterOrSP(reg1) && (size == EA_8BYTE))
3803 else if (isVectorRegister(reg1) && (size == EA_16BYTE))
3809 // Check for the 'mov' aliases for the vector registers
3810 if (isVectorRegister(reg1))
3812 if (isVectorRegister(reg2) && isValidVectorDatasize(size))
3814 return emitIns_R_R_R(INS_mov, size, reg1, reg2, reg2);
3818 return emitIns_R_R_I(INS_mov, size, reg1, reg2, 0);
3823 if (isVectorRegister(reg2))
3825 assert(isGeneralRegister(reg1));
3826 return emitIns_R_R_I(INS_mov, size, reg1, reg2, 0);
3830 // Is this a MOV to/from SP instruction?
3831 if ((reg1 == REG_SP) || (reg2 == REG_SP))
3833 assert(isGeneralRegisterOrSP(reg1));
3834 assert(isGeneralRegisterOrSP(reg2));
3835 reg1 = encodingSPtoZR(reg1);
3836 reg2 = encodingSPtoZR(reg2);
3841 assert(insOptsNone(opt));
3842 assert(isGeneralRegister(reg1));
3843 assert(isGeneralRegisterOrZR(reg2));
3850 assert(insOptsAnyArrangement(opt));
3851 assert(isVectorRegister(reg1));
3852 assert(isGeneralRegisterOrZR(reg2));
3853 assert(isValidVectorDatasize(size));
3854 assert(isValidArrangement(size, opt));
3860 assert(isVectorRegister(reg1));
3861 assert(isVectorRegister(reg2));
3864 assert(isValidVectorDatasize(size));
3865 // Bitwise behavior is independent of element size, but is always encoded as 1 Byte
3866 opt = optMakeArrangement(size, EA_1BYTE);
3868 if (insOptsNone(opt))
3871 assert(size == EA_8BYTE); // Only type D is supported
3877 assert(insOptsAnyArrangement(opt));
3878 assert(isValidVectorDatasize(size));
3879 assert(isValidArrangement(size, opt));
3880 elemsize = optGetElemsize(opt);
3887 if (isVectorRegister(reg1))
3889 assert(isVectorRegister(reg2));
3892 assert(isValidVectorDatasize(size));
3893 // Bitwise behavior is independent of element size, but is always encoded as 1 Byte
3894 opt = optMakeArrangement(size, EA_1BYTE);
3896 if (insOptsNone(opt))
3899 assert(size == EA_8BYTE); // Only type D is supported
3905 assert(isValidVectorDatasize(size));
3906 assert(isValidArrangement(size, opt));
3907 elemsize = optGetElemsize(opt);
3915 assert(insOptsNone(opt));
3916 assert(isGeneralRegister(reg1));
3917 assert(isGeneralRegisterOrZR(reg2));
3922 assert(size == EA_8BYTE);
3929 assert(insOptsNone(opt));
3930 assert(isValidGeneralDatasize(size));
3931 assert(isGeneralRegister(reg1));
3932 assert(isGeneralRegister(reg2));
3940 return emitIns_R_R_I(ins, size, reg1, reg2, 0, opt);
3948 if (isVectorRegister(reg1))
3950 assert(isVectorRegister(reg2));
3951 assert(isValidVectorDatasize(size));
3952 assert(isValidArrangement(size, opt));
3953 elemsize = optGetElemsize(opt);
3954 if ((ins == INS_cls) || (ins == INS_clz))
3956 assert(elemsize != EA_8BYTE); // No encoding for type D
3958 else if (ins == INS_rev32)
3960 assert((elemsize == EA_2BYTE) || (elemsize == EA_1BYTE));
3964 assert(elemsize == EA_1BYTE); // Only supports 8B or 16B
3971 // Doesn't have general register version(s)
3978 assert(insOptsNone(opt));
3979 assert(isGeneralRegister(reg1));
3980 assert(isGeneralRegister(reg2));
3981 if (ins == INS_rev32)
3983 assert(size == EA_8BYTE);
3987 assert(isValidGeneralDatasize(size));
4000 assert(isVectorRegister(reg1));
4001 assert(isVectorRegister(reg2));
4002 assert(isValidVectorDatasize(size));
4003 assert(isValidArrangement(size, opt));
4004 elemsize = optGetElemsize(opt);
4005 assert(elemsize != EA_8BYTE); // No encoding for type D
4011 assert(isVectorRegister(reg1));
4012 assert(isVectorRegister(reg2));
4013 assert(isValidVectorDatasize(size));
4014 assert(isValidArrangement(size, opt));
4015 elemsize = optGetElemsize(opt);
4016 // size is determined by instruction
4019 assert(size == EA_8BYTE);
4021 else // ins == INS_xtn2
4023 assert(size == EA_16BYTE);
4025 assert(elemsize != EA_8BYTE); // Narrowing must not end with 8 byte data
4033 assert(isValidGeneralDatasize(size));
4045 assert(isValidGeneralLSDatasize(size));
4046 assert(isGeneralRegisterOrZR(reg1));
4047 assert(isGeneralRegisterOrSP(reg2));
4048 assert(insOptsNone(opt));
4050 reg2 = encodingSPtoZR(reg2);
4068 assert(insOptsNone(opt));
4069 emitIns_R_R_I(ins, attr, reg1, reg2, 0, INS_OPTS_NONE);
4073 emitIns_R_R_R(INS_ldaddb, attr, reg1, REG_ZR, reg2);
4076 emitIns_R_R_R(INS_ldaddlb, attr, reg1, REG_ZR, reg2);
4079 emitIns_R_R_R(INS_ldaddh, attr, reg1, REG_ZR, reg2);
4082 emitIns_R_R_R(INS_ldaddlh, attr, reg1, REG_ZR, reg2);
4085 emitIns_R_R_R(INS_ldadd, attr, reg1, REG_ZR, reg2);
4088 emitIns_R_R_R(INS_ldaddl, attr, reg1, REG_ZR, reg2);
4092 assert(isValidVectorElemsizeFloat(size));
4094 // Is the mov even necessary?
4100 if (isVectorRegister(reg1))
4102 if (isVectorRegister(reg2))
4104 assert(insOptsNone(opt));
4109 assert(isGeneralRegister(reg2));
4111 // if the optional conversion specifier is not present we calculate it
4112 if (opt == INS_OPTS_NONE)
4114 opt = (size == EA_4BYTE) ? INS_OPTS_4BYTE_TO_S : INS_OPTS_8BYTE_TO_D;
4116 assert(insOptsConvertIntToFloat(opt));
4123 assert(isGeneralRegister(reg1));
4124 assert(isVectorRegister(reg2));
4126 // if the optional conversion specifier is not present we calculate it
4127 if (opt == INS_OPTS_NONE)
4129 opt = (size == EA_4BYTE) ? INS_OPTS_S_TO_4BYTE : INS_OPTS_D_TO_8BYTE;
4131 assert(insOptsConvertFloatToInt(opt));
4139 assert(insOptsNone(opt));
4140 assert(isValidVectorElemsizeFloat(size));
4141 assert(isVectorRegister(reg1));
4142 assert(isVectorRegister(reg2));
4156 if (insOptsAnyArrangement(opt))
4159 assert(isVectorRegister(reg1));
4160 assert(isVectorRegister(reg2));
4161 assert(isValidVectorDatasize(size));
4162 assert(isValidArrangement(size, opt));
4163 elemsize = optGetElemsize(opt);
4164 assert(isValidVectorElemsizeFloat(elemsize));
4165 assert(opt != INS_OPTS_1D); // Reserved encoding
4171 assert(isVectorRegister(reg2));
4172 if (isVectorRegister(reg1))
4174 assert(insOptsNone(opt));
4175 assert(isValidVectorElemsizeFloat(size));
4180 assert(isGeneralRegister(reg1));
4181 assert(insOptsConvertFloatToInt(opt));
4182 assert(isValidVectorElemsizeFloat(size));
4192 assert(isVectorRegister(reg1));
4193 assert(isVectorRegister(reg2));
4194 assert(isValidVectorDatasize(size));
4195 assert(insOptsNone(opt));
4196 assert(size == EA_8BYTE); // Narrowing from Double or Widening to Double (Half not supported)
4202 if (insOptsAnyArrangement(opt))
4205 assert(isVectorRegister(reg1));
4206 assert(isVectorRegister(reg2));
4207 assert(isValidVectorDatasize(size));
4208 assert(isValidArrangement(size, opt));
4209 elemsize = optGetElemsize(opt);
4210 assert(isValidVectorElemsizeFloat(elemsize));
4211 assert(opt != INS_OPTS_1D); // Reserved encoding
4217 assert(isVectorRegister(reg1));
4218 if (isVectorRegister(reg2))
4220 assert(insOptsNone(opt));
4221 assert(isValidVectorElemsizeFloat(size));
4226 assert(isGeneralRegister(reg2));
4227 assert(insOptsConvertIntToFloat(opt));
4228 assert(isValidVectorElemsizeFloat(size));
4244 if (insOptsAnyArrangement(opt))
4247 assert(isVectorRegister(reg1));
4248 assert(isVectorRegister(reg2));
4249 assert(isValidVectorDatasize(size));
4250 assert(isValidArrangement(size, opt));
4251 elemsize = optGetElemsize(opt);
4252 assert(isValidVectorElemsizeFloat(elemsize));
4253 assert(opt != INS_OPTS_1D); // Reserved encoding
4259 assert(insOptsNone(opt));
4260 assert(isValidVectorElemsizeFloat(size));
4261 assert(isVectorRegister(reg1));
4262 assert(isVectorRegister(reg2));
4269 assert(insOptsNone(opt));
4270 assert(isValidVectorElemsizeFloat(size));
4271 assert(isVectorRegister(reg1));
4272 assert(isVectorRegister(reg2));
4277 assert(insOptsConvertFloatToFloat(opt));
4278 assert(isValidVectorFcvtsize(size));
4279 assert(isVectorRegister(reg1));
4280 assert(isVectorRegister(reg2));
4289 assert(isVectorRegister(reg1));
4290 assert(isVectorRegister(reg2));
4292 if (isValidVectorDatasize(size))
4295 assert(insOptsAnyArrangement(opt));
4296 assert(isValidArrangement(size, opt));
4297 elemsize = optGetElemsize(opt);
4304 assert(size == EA_8BYTE); // Only Double supported
4314 assert(isVectorRegister(reg1));
4315 assert(isVectorRegister(reg2));
4317 if (isValidVectorDatasize(size))
4320 assert(insOptsAnyArrangement(opt));
4321 assert(isValidArrangement(size, opt));
4322 elemsize = optGetElemsize(opt);
4323 assert((elemsize == EA_8BYTE) || (elemsize == EA_4BYTE)); // Only Double/Float supported
4324 assert(opt != INS_OPTS_1D); // Reserved encoding
4331 assert((size == EA_8BYTE) || (size == EA_4BYTE)); // Only Double/Float supported
4339 assert(isVectorRegister(reg1));
4340 assert(isVectorRegister(reg2));
4341 assert(isValidVectorDatasize(size));
4342 elemsize = optGetElemsize(opt);
4343 assert(elemsize == EA_1BYTE);
4348 assert(insOptsNone(opt));
4349 assert(isVectorRegister(reg1));
4350 assert(isVectorRegister(reg2));
4356 assert(isVectorRegister(reg1));
4357 assert(isVectorRegister(reg2));
4358 assert(isValidVectorDatasize(size));
4359 elemsize = optGetElemsize(opt);
4360 assert(elemsize == EA_4BYTE);
4368 } // end switch (ins)
4370 assert(fmt != IF_NONE);
4372 instrDesc* id = emitNewInstrSmall(attr);
4385 /*****************************************************************************
4387 * Add an instruction referencing a register and two constants.
4390 void emitter::emitIns_R_I_I(
4391 instruction ins, emitAttr attr, regNumber reg, ssize_t imm1, ssize_t imm2, insOpts opt /* = INS_OPTS_NONE */)
4393 emitAttr size = EA_SIZE(attr);
4394 insFormat fmt = IF_NONE;
4395 size_t immOut = 0; // composed from imm1 and imm2 and stored in the instrDesc
4397 /* Figure out the encoding format of the instruction */
4404 ins = INS_movz; // INS_mov with LSL is an alias for INS_movz LSL
4410 assert(isValidGeneralDatasize(size));
4411 assert(isGeneralRegister(reg));
4412 assert(isValidUimm16(imm1));
4413 assert(insOptsLSL(opt)); // Must be INS_OPTS_LSL
4415 if (size == EA_8BYTE)
4417 assert((imm2 == 0) || (imm2 == 16) || // shift amount: 0, 16, 32 or 48
4418 (imm2 == 32) || (imm2 == 48));
4422 assert((imm2 == 0) || (imm2 == 16)); // shift amount: 0 or 16
4457 immOut = hwi.immHWVal;
4458 assert(isValidImmHWVal(immOut, size));
4467 } // end switch (ins)
4469 assert(fmt != IF_NONE);
4471 instrDesc* id = emitNewInstrSC(attr, immOut);
4482 /*****************************************************************************
4484 * Add an instruction referencing two registers and a constant.
4487 void emitter::emitIns_R_R_I(
4488 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm, insOpts opt /* = INS_OPTS_NONE */)
4490 emitAttr size = EA_SIZE(attr);
4491 emitAttr elemsize = EA_UNKNOWN;
4492 insFormat fmt = IF_NONE;
4493 bool isLdSt = false;
4494 bool isSIMD = false;
4495 bool isAddSub = false;
4496 bool setFlags = false;
4498 bool unscaledOp = false;
4500 /* Figure out the encoding format of the instruction */
4507 // Check for the 'mov' aliases for the vector registers
4508 assert(insOptsNone(opt));
4509 assert(isValidVectorElemsize(size));
4511 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4513 if (isVectorRegister(reg1))
4515 if (isGeneralRegisterOrZR(reg2))
4517 fmt = IF_DV_2C; // Alias for 'ins'
4520 else if (isVectorRegister(reg2))
4522 fmt = IF_DV_2E; // Alias for 'dup'
4526 else // isGeneralRegister(reg1)
4528 assert(isGeneralRegister(reg1));
4529 if (isVectorRegister(reg2))
4531 fmt = IF_DV_2B; // Alias for 'umov'
4535 assert(!" invalid INS_mov operands");
4541 assert(insOptsNone(opt));
4542 assert(isValidGeneralDatasize(size));
4543 assert(isGeneralRegister(reg1));
4544 assert(isGeneralRegister(reg2));
4545 assert(isValidImmShift(imm, size));
4550 assert(insOptsNone(opt));
4551 assert(isValidGeneralDatasize(size));
4552 assert(isGeneralRegister(reg1));
4553 assert(isGeneralRegister(reg2));
4554 assert(isValidImmShift(imm, size));
4569 assert(isVectorRegister(reg1));
4570 assert(isVectorRegister(reg2));
4571 if (insOptsAnyArrangement(opt))
4574 assert(isValidVectorDatasize(size));
4575 assert(isValidArrangement(size, opt));
4576 elemsize = optGetElemsize(opt);
4577 assert(isValidVectorElemsize(elemsize));
4578 assert(isValidImmShift(imm, elemsize));
4579 assert(opt != INS_OPTS_1D); // Reserved encoding
4586 assert(insOptsNone(opt));
4587 assert(size == EA_8BYTE); // only supported size
4588 assert(isValidImmShift(imm, size));
4602 assert(isVectorRegister(reg1));
4603 assert(isVectorRegister(reg2));
4605 assert(size == EA_8BYTE);
4606 assert(isValidArrangement(size, opt));
4607 elemsize = optGetElemsize(opt);
4608 assert(elemsize != EA_8BYTE); // Reserved encodings
4609 assert(isValidVectorElemsize(elemsize));
4610 assert(isValidImmShift(imm, elemsize));
4623 assert(isVectorRegister(reg1));
4624 assert(isVectorRegister(reg2));
4626 assert(size == EA_16BYTE);
4627 assert(isValidArrangement(size, opt));
4628 elemsize = optGetElemsize(opt);
4629 assert(elemsize != EA_8BYTE); // Reserved encodings
4630 assert(isValidVectorElemsize(elemsize));
4631 assert(isValidImmShift(imm, elemsize));
4638 assert(isValidGeneralDatasize(size));
4639 assert(isGeneralRegister(reg1));
4640 assert(isGeneralRegisterOrZR(reg2));
4644 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4652 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
4656 assert(insOptsAluShift(opt)); // a non-zero imm, must select shift kind, can't use ROR
4658 assert(isValidImmShift(imm, size));
4664 assert(isValidGeneralDatasize(size));
4665 assert(isGeneralRegisterOrZR(reg1));
4666 assert(isGeneralRegister(reg2));
4668 if (insOptsAnyShift(opt))
4670 assert(isValidImmShift(imm, size) && (imm != 0));
4675 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4683 assert(isValidGeneralDatasize(size));
4684 assert(isGeneralRegisterOrSP(reg1));
4685 assert(isGeneralRegister(reg2));
4687 reg1 = encodingSPtoZR(reg1);
4688 if (insOptsAnyExtend(opt))
4690 assert((imm >= 0) && (imm <= 4));
4696 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4702 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
4703 assert(isValidImmShift(imm, size));
4712 assert(insOptsNone(opt));
4713 assert(isGeneralRegister(reg2));
4714 if (ins == INS_ands)
4716 assert(isGeneralRegister(reg1));
4720 assert(isGeneralRegisterOrSP(reg1));
4721 reg1 = encodingSPtoZR(reg1);
4725 canEncode = canEncodeBitMaskImm(imm, size, &bmi);
4729 assert(isValidImmNRS(imm, size));
4734 case INS_dup: // by element, imm selects the element of reg2
4735 assert(isVectorRegister(reg1));
4736 if (isVectorRegister(reg2))
4738 if (insOptsAnyArrangement(opt))
4741 assert(isValidVectorDatasize(size));
4742 assert(isValidArrangement(size, opt));
4743 elemsize = optGetElemsize(opt);
4744 assert(isValidVectorElemsize(elemsize));
4745 assert(isValidVectorIndex(size, elemsize, imm));
4746 assert(opt != INS_OPTS_1D); // Reserved encoding
4753 assert(insOptsNone(opt));
4755 assert(isValidVectorElemsize(elemsize));
4756 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4763 case INS_ins: // (MOV from general)
4764 assert(insOptsNone(opt));
4765 assert(isValidVectorElemsize(size));
4766 assert(isVectorRegister(reg1));
4767 assert(isGeneralRegisterOrZR(reg2));
4769 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4773 case INS_umov: // (MOV to general)
4774 assert(insOptsNone(opt));
4775 assert(isValidVectorElemsize(size));
4776 assert(isGeneralRegister(reg1));
4777 assert(isVectorRegister(reg2));
4779 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4784 assert(insOptsNone(opt));
4785 assert(isValidVectorElemsize(size));
4786 assert(size != EA_8BYTE); // no encoding, use INS_umov
4787 assert(isGeneralRegister(reg1));
4788 assert(isVectorRegister(reg2));
4790 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4808 // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4809 assert(isValidGeneralDatasize(size));
4810 unscaledOp = (ins == INS_ldursb);
4817 // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4818 assert(isValidGeneralDatasize(size));
4819 unscaledOp = (ins == INS_ldursh);
4826 // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4827 assert(size == EA_8BYTE);
4828 unscaledOp = (ins == INS_ldursw);
4867 // Is the target a vector register?
4868 if (isVectorRegister(reg1))
4870 assert(isValidVectorLSDatasize(size));
4871 assert(isGeneralRegisterOrSP(reg2));
4876 assert(isValidGeneralDatasize(size));
4879 scale = NaturalScale_helper(size);
4885 // Is the target a vector register?
4886 if (isVectorRegister(reg1))
4888 assert(isValidVectorLSDatasize(size));
4889 assert(isGeneralRegisterOrSP(reg2));
4894 assert(isValidGeneralDatasize(size));
4905 } // end switch (ins)
4913 assert(isValidVectorLSDatasize(size));
4914 assert(isVectorRegister(reg1));
4915 assert((scale >= 0) && (scale <= 4));
4919 assert(isValidGeneralLSDatasize(size));
4920 assert(isGeneralRegisterOrZR(reg1));
4921 assert((scale >= 0) && (scale <= 3));
4924 assert(isGeneralRegisterOrSP(reg2));
4926 // Load/Store reserved encodings:
4927 if (insOptsIndexed(opt))
4929 assert(reg1 != reg2);
4932 reg2 = encodingSPtoZR(reg2);
4934 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
4937 assert(insOptsNone(opt)); // PRE/POST Index doesn't make sense with an immediate of zero
4941 else if (insOptsIndexed(opt) || unscaledOp || (imm < 0) || ((imm & mask) != 0))
4943 if ((imm >= -256) && (imm <= 255))
4949 assert(!"Instruction cannot be encoded: IF_LS_2C");
4954 assert(insOptsNone(opt));
4955 assert(!unscaledOp);
4957 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
4959 imm >>= scale; // The immediate is scaled by the size of the ld/st
4965 assert(!"Instruction cannot be encoded: IF_LS_2B");
4972 assert(insOptsNone(opt));
4974 if (setFlags) // Can't encode SP with setFlags
4976 assert(isGeneralRegister(reg1));
4977 assert(isGeneralRegister(reg2));
4981 assert(isGeneralRegisterOrSP(reg1));
4982 assert(isGeneralRegisterOrSP(reg2));
4984 // Is it just a mov?
4987 // Is the mov even necessary?
4990 emitIns_R_R(INS_mov, attr, reg1, reg2);
4995 reg1 = encodingSPtoZR(reg1);
4996 reg2 = encodingSPtoZR(reg2);
4999 if (unsigned_abs(imm) <= 0x0fff)
5003 ins = insReverse(ins);
5006 assert(isValidUimm12(imm));
5009 else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
5011 // Encoding will use a 12-bit left shift of the immediate
5012 opt = INS_OPTS_LSL12;
5015 ins = insReverse(ins);
5018 assert((imm & 0xfff) == 0);
5020 assert(isValidUimm12(imm));
5025 assert(!"Instruction cannot be encoded: IF_DI_2A");
5029 assert(fmt != IF_NONE);
5031 instrDesc* id = emitNewInstrSC(attr, imm);
5044 /*****************************************************************************
5046 * Add an instruction referencing two registers and a constant.
5047 * Also checks for a large immediate that needs a second instruction
5048 * and will load it in reg1
5050 * - Supports instructions: add, adds, sub, subs, and, ands, eor and orr
5051 * - Requires that reg1 is a general register and not SP or ZR
5052 * - Requires that reg1 != reg2
5054 void emitter::emitIns_R_R_Imm(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm)
5056 assert(isGeneralRegister(reg1));
5057 assert(reg1 != reg2);
5059 bool immFits = true;
5067 immFits = emitter::emitIns_valid_imm_for_add(imm, attr);
5074 immFits = emitter::emitIns_valid_imm_for_alu(imm, attr);
5078 assert(!"Unsupported instruction in emitIns_R_R_Imm");
5083 emitIns_R_R_I(ins, attr, reg1, reg2, imm);
5087 // Load 'imm' into the reg1 register
5088 // then issue: 'ins' reg1, reg2, reg1
5090 codeGen->instGen_Set_Reg_To_Imm(attr, reg1, imm);
5091 emitIns_R_R_R(ins, attr, reg1, reg2, reg1);
5095 /*****************************************************************************
5097 * Add an instruction referencing three registers.
5100 void emitter::emitIns_R_R_R(
5101 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insOpts opt) /* = INS_OPTS_NONE */
5103 emitAttr size = EA_SIZE(attr);
5104 emitAttr elemsize = EA_UNKNOWN;
5105 insFormat fmt = IF_NONE;
5107 /* Figure out the encoding format of the instruction */
5131 assert(insOptsNone(opt));
5132 assert(isValidGeneralDatasize(size));
5133 assert(isGeneralRegister(reg1));
5134 assert(isGeneralRegister(reg2));
5135 assert(isGeneralRegister(reg3));
5140 if (insOptsNone(opt))
5143 assert(isValidGeneralDatasize(size));
5144 assert(isGeneralRegister(reg1));
5145 assert(isGeneralRegister(reg2));
5146 assert(isGeneralRegister(reg3));
5155 assert(insOptsAnyArrangement(opt));
5156 assert(isVectorRegister(reg1));
5157 assert(isVectorRegister(reg2));
5158 assert(isVectorRegister(reg3));
5159 assert(isValidVectorDatasize(size));
5160 assert(isValidArrangement(size, opt));
5161 elemsize = optGetElemsize(opt);
5162 if (ins == INS_pmul)
5164 assert(elemsize == EA_1BYTE); // only supports 8B or 16B
5166 else // INS_mul, INS_mla, INS_mls
5168 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
5175 if (isVectorRegister(reg1))
5177 assert(isVectorRegister(reg2));
5178 assert(isVectorRegister(reg3));
5180 if (insOptsAnyArrangement(opt))
5183 assert(opt != INS_OPTS_1D); // Reserved encoding
5184 assert(isValidVectorDatasize(size));
5185 assert(isValidArrangement(size, opt));
5191 assert(insOptsNone(opt));
5192 assert(size == EA_8BYTE);
5201 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, INS_OPTS_NONE);
5210 assert(isVectorRegister(reg1));
5211 assert(isVectorRegister(reg2));
5212 assert(isVectorRegister(reg3));
5214 if (isValidVectorDatasize(size))
5217 assert(insOptsAnyArrangement(opt));
5218 assert(isValidArrangement(size, opt));
5219 elemsize = optGetElemsize(opt);
5226 assert(size == EA_8BYTE); // Only Double supported
5234 assert(isVectorRegister(reg1));
5235 assert(isVectorRegister(reg2));
5236 assert(isVectorRegister(reg3));
5238 if (isValidVectorDatasize(size))
5241 assert(insOptsAnyArrangement(opt));
5242 assert(isValidArrangement(size, opt));
5243 elemsize = optGetElemsize(opt);
5244 assert((elemsize == EA_8BYTE) || (elemsize == EA_4BYTE)); // Only Double/Float supported
5245 assert(opt != INS_OPTS_1D); // Reserved encoding
5252 assert((size == EA_8BYTE) || (size == EA_4BYTE)); // Only Double/Float supported
5265 assert(isVectorRegister(reg1));
5266 assert(isVectorRegister(reg2));
5267 assert(isVectorRegister(reg3));
5268 assert(insOptsAnyArrangement(opt));
5271 assert(isValidVectorDatasize(size));
5272 assert(isValidArrangement(size, opt));
5273 elemsize = optGetElemsize(opt);
5274 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
5280 assert(isVectorRegister(reg1));
5281 assert(isVectorRegister(reg2));
5282 assert(reg2 == reg3);
5283 assert(isValidVectorDatasize(size));
5284 // INS_mov is an alias for INS_orr (vector register)
5285 if (opt == INS_OPTS_NONE)
5287 elemsize = EA_1BYTE;
5288 opt = optMakeArrangement(size, elemsize);
5290 assert(isValidArrangement(size, opt));
5299 if (isVectorRegister(reg1))
5301 assert(isValidVectorDatasize(size));
5302 assert(isVectorRegister(reg2));
5303 assert(isVectorRegister(reg3));
5304 if (opt == INS_OPTS_NONE)
5306 elemsize = EA_1BYTE;
5307 opt = optMakeArrangement(size, elemsize);
5309 assert(isValidArrangement(size, opt));
5318 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, INS_OPTS_NONE);
5324 assert(isValidVectorDatasize(size));
5325 assert(isVectorRegister(reg1));
5326 assert(isVectorRegister(reg2));
5327 assert(isVectorRegister(reg3));
5328 if (opt == INS_OPTS_NONE)
5330 elemsize = EA_1BYTE;
5331 opt = optMakeArrangement(size, elemsize);
5333 assert(isValidArrangement(size, opt));
5345 assert(isVectorRegister(reg1));
5346 assert(isVectorRegister(reg2));
5347 assert(isVectorRegister(reg3));
5348 if (insOptsAnyArrangement(opt))
5351 assert(isValidVectorDatasize(size));
5352 assert(isValidArrangement(size, opt));
5353 elemsize = optGetElemsize(opt);
5354 assert(isValidVectorElemsizeFloat(elemsize));
5355 assert(opt != INS_OPTS_1D); // Reserved encoding
5361 assert(insOptsNone(opt));
5362 assert(isValidScalarDatasize(size));
5369 assert(insOptsNone(opt));
5370 assert(isVectorRegister(reg1));
5371 assert(isVectorRegister(reg2));
5372 assert(isVectorRegister(reg3));
5373 assert(isValidScalarDatasize(size));
5380 assert(isVectorRegister(reg1));
5381 assert(isVectorRegister(reg2));
5382 assert(isVectorRegister(reg3));
5383 assert(insOptsAnyArrangement(opt)); // no scalar encoding, use 4-operand 'fmadd' or 'fmsub'
5386 assert(isValidVectorDatasize(size));
5387 assert(isValidArrangement(size, opt));
5388 elemsize = optGetElemsize(opt);
5389 assert(isValidVectorElemsizeFloat(elemsize));
5390 assert(opt != INS_OPTS_1D); // Reserved encoding
5403 emitIns_R_R_R_Ext(ins, attr, reg1, reg2, reg3, opt);
5411 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0);
5420 assert(isGeneralRegisterOrZR(reg1));
5421 assert(isGeneralRegisterOrZR(reg2));
5422 assert(isGeneralRegisterOrSP(reg3));
5462 assert(isGeneralRegisterOrZR(reg1));
5463 assert(isGeneralRegisterOrZR(reg2));
5464 assert(isGeneralRegisterOrSP(reg3));
5475 assert(isValidVectorDatasize(size));
5476 assert(isVectorRegister(reg1));
5477 assert(isVectorRegister(reg2));
5478 assert(isVectorRegister(reg3));
5479 if (opt == INS_OPTS_NONE)
5481 elemsize = EA_4BYTE;
5482 opt = optMakeArrangement(size, elemsize);
5484 assert(isValidArrangement(size, opt));
5492 } // end switch (ins)
5494 assert(fmt != IF_NONE);
5496 instrDesc* id = emitNewInstr(attr);
5510 /*****************************************************************************
5512 * Add an instruction referencing three registers and a constant.
5515 void emitter::emitIns_R_R_R_I(instruction ins,
5521 insOpts opt /* = INS_OPTS_NONE */,
5522 emitAttr attrReg2 /* = EA_UNKNOWN */)
5524 emitAttr size = EA_SIZE(attr);
5525 emitAttr elemsize = EA_UNKNOWN;
5526 insFormat fmt = IF_NONE;
5527 bool isLdSt = false;
5528 bool isSIMD = false;
5529 bool isAddSub = false;
5530 bool setFlags = false;
5533 /* Figure out the encoding format of the instruction */
5537 assert(insOptsNone(opt));
5538 assert(isValidGeneralDatasize(size));
5539 assert(isGeneralRegister(reg1));
5540 assert(isGeneralRegister(reg2));
5541 assert(isGeneralRegister(reg3));
5542 assert(isValidImmShift(imm, size));
5554 assert(isValidGeneralDatasize(size));
5555 assert(isGeneralRegister(reg1));
5556 assert(isGeneralRegister(reg2));
5557 assert(isGeneralRegister(reg3));
5558 assert(isValidImmShift(imm, size));
5561 assert(insOptsNone(opt)); // a zero imm, means no shift kind
5566 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
5571 case INS_fmul: // by element, imm[0..3] selects the element of reg3
5575 assert(isVectorRegister(reg1));
5576 assert(isVectorRegister(reg2));
5577 assert(isVectorRegister(reg3));
5578 if (insOptsAnyArrangement(opt))
5581 assert(isValidVectorDatasize(size));
5582 assert(isValidArrangement(size, opt));
5583 elemsize = optGetElemsize(opt);
5584 assert(isValidVectorElemsizeFloat(elemsize));
5585 assert(isValidVectorIndex(size, elemsize, imm));
5586 assert(opt != INS_OPTS_1D); // Reserved encoding
5592 assert(insOptsNone(opt));
5593 assert(isValidScalarDatasize(size));
5595 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
5600 case INS_mul: // by element, imm[0..7] selects the element of reg3
5603 assert(isVectorRegister(reg1));
5604 assert(isVectorRegister(reg2));
5605 assert(isVectorRegister(reg3));
5607 assert(insOptsAnyArrangement(opt));
5608 assert(isValidVectorDatasize(size));
5609 assert(isValidArrangement(size, opt));
5610 elemsize = optGetElemsize(opt);
5611 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
5612 // Only has encodings for H or S elemsize
5613 assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE));
5614 // Only has encodings for V0..V15
5615 if ((elemsize == EA_2BYTE) && (reg3 >= REG_V16))
5617 noway_assert(!"Invalid reg3");
5641 assert(insOptsNone(opt)); // Can't use Pre/Post index on these two instructions
5646 // Is the target a vector register?
5647 if (isVectorRegister(reg1))
5649 scale = NaturalScale_helper(size);
5654 scale = (size == EA_8BYTE) ? 3 : 2;
5663 } // end switch (ins)
5668 assert(isGeneralRegisterOrSP(reg3));
5669 assert(insOptsNone(opt) || insOptsIndexed(opt));
5673 assert(isValidVectorLSPDatasize(size));
5674 assert(isVectorRegister(reg1));
5675 assert(isVectorRegister(reg2));
5676 assert((scale >= 2) && (scale <= 4));
5680 assert(isValidGeneralDatasize(size));
5681 assert(isGeneralRegisterOrZR(reg1));
5682 assert(isGeneralRegisterOrZR(reg2));
5683 assert((scale == 2) || (scale == 3));
5686 // Load/Store Pair reserved encodings:
5687 if (emitInsIsLoad(ins))
5689 assert(reg1 != reg2);
5691 if (insOptsIndexed(opt))
5693 assert(reg1 != reg3);
5694 assert(reg2 != reg3);
5697 reg3 = encodingSPtoZR(reg3);
5699 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
5702 assert(insOptsNone(opt)); // PRE/POST Index doesn't make sense with an immediate of zero
5708 if ((imm & mask) == 0)
5710 imm >>= scale; // The immediate is scaled by the size of the ld/st
5712 if ((imm >= -64) && (imm <= 63))
5718 if (fmt != IF_LS_3C)
5720 assert(!"Instruction cannot be encoded: IF_LS_3C");
5727 bool reg2IsSP = (reg2 == REG_SP);
5729 assert(isValidGeneralDatasize(size));
5730 assert(isGeneralRegister(reg3));
5732 if (setFlags || insOptsAluShift(opt)) // Can't encode SP in reg1 with setFlags or AluShift option
5734 assert(isGeneralRegisterOrZR(reg1));
5738 assert(isGeneralRegisterOrSP(reg1));
5739 reg1 = encodingSPtoZR(reg1);
5742 if (insOptsAluShift(opt)) // Can't encode SP in reg2 with AluShift option
5744 assert(isGeneralRegister(reg2));
5748 assert(isGeneralRegisterOrSP(reg2));
5749 reg2 = encodingSPtoZR(reg2);
5752 if (insOptsAnyExtend(opt))
5754 assert((imm >= 0) && (imm <= 4));
5758 else if (insOptsAluShift(opt))
5760 // imm should be non-zero and in [1..63]
5761 assert(isValidImmShift(imm, size) && (imm != 0));
5766 assert(insOptsNone(opt));
5770 // To encode the SP register as reg2 we must use the IF_DR_3C encoding
5771 // and also specify a LSL of zero (imm == 0)
5782 assert(!"Instruction cannot be encoded: Add/Sub IF_DR_3A");
5785 assert(fmt != IF_NONE);
5787 instrDesc* id = emitNewInstrCns(attr, imm);
5797 // Record the attribute for the second register in the pair
5798 id->idGCrefReg2(GCT_NONE);
5799 if (attrReg2 != EA_UNKNOWN)
5801 // Record the attribute for the second register in the pair
5802 assert((fmt == IF_LS_3B) || (fmt == IF_LS_3C));
5803 if (EA_IS_GCREF(attrReg2))
5805 id->idGCrefReg2(GCT_GCREF);
5807 else if (EA_IS_BYREF(attrReg2))
5809 id->idGCrefReg2(GCT_BYREF);
5817 /*****************************************************************************
5819 * Add an instruction referencing three registers, with an extend option
5822 void emitter::emitIns_R_R_R_Ext(instruction ins,
5827 insOpts opt, /* = INS_OPTS_NONE */
5828 int shiftAmount) /* = -1 -- unset */
5830 emitAttr size = EA_SIZE(attr);
5831 insFormat fmt = IF_NONE;
5832 bool isSIMD = false;
5835 /* Figure out the encoding format of the instruction */
5856 // Is the target a vector register?
5857 if (isVectorRegister(reg1))
5859 assert(isValidVectorLSDatasize(size));
5860 scale = NaturalScale_helper(size);
5865 assert(isValidGeneralDatasize(size));
5866 scale = (size == EA_8BYTE) ? 3 : 2;
5875 } // end switch (ins)
5877 assert(scale != -1);
5878 assert(insOptsLSExtend(opt));
5882 assert(isValidVectorLSDatasize(size));
5883 assert(isVectorRegister(reg1));
5887 assert(isValidGeneralLSDatasize(size));
5888 assert(isGeneralRegisterOrZR(reg1));
5891 assert(isGeneralRegisterOrSP(reg2));
5892 assert(isGeneralRegister(reg3));
5894 // Load/Store reserved encodings:
5895 if (insOptsIndexed(opt))
5897 assert(reg1 != reg2);
5900 if (shiftAmount == -1)
5902 shiftAmount = insOptsLSL(opt) ? scale : 0;
5904 assert((shiftAmount == scale) || (shiftAmount == 0));
5906 reg2 = encodingSPtoZR(reg2);
5909 instrDesc* id = emitNewInstr(attr);
5918 id->idReg3Scaled(shiftAmount == scale);
5924 /*****************************************************************************
5926 * Add an instruction referencing two registers and two constants.
5929 void emitter::emitIns_R_R_I_I(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, int imm1, int imm2)
5931 emitAttr size = EA_SIZE(attr);
5932 emitAttr elemsize = EA_UNKNOWN;
5933 insFormat fmt = IF_NONE;
5934 size_t immOut = 0; // composed from imm1 and imm2 and stored in the instrDesc
5936 /* Figure out the encoding format of the instruction */
5946 assert(isGeneralRegister(reg1));
5947 assert(isGeneralRegister(reg2));
5948 assert(isValidImmShift(imm1, size));
5949 assert(isValidImmShift(imm2, size));
5951 bmi.immN = (size == EA_8BYTE);
5954 immOut = bmi.immNRS;
5961 assert(isGeneralRegister(reg1));
5962 assert(isGeneralRegister(reg2));
5963 lsb = getBitWidth(size) - imm1;
5965 assert(isValidImmShift(lsb, size));
5966 assert(isValidImmShift(width, size));
5968 bmi.immN = (size == EA_8BYTE);
5971 immOut = bmi.immNRS;
5978 assert(isGeneralRegister(reg1));
5979 assert(isGeneralRegister(reg2));
5981 width = imm2 + imm1 - 1;
5982 assert(isValidImmShift(lsb, size));
5983 assert(isValidImmShift(width, size));
5985 bmi.immN = (size == EA_8BYTE);
5987 bmi.immS = imm2 + imm1 - 1;
5988 immOut = bmi.immNRS;
5994 assert(isVectorRegister(reg1));
5995 assert(isVectorRegister(reg2));
5997 assert(isValidVectorElemsize(elemsize));
5998 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm1));
5999 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm2));
6000 immOut = (imm1 << 4) + imm2;
6008 assert(fmt != IF_NONE);
6010 instrDesc* id = emitNewInstrSC(attr, immOut);
6022 /*****************************************************************************
6024 * Add an instruction referencing four registers.
6027 void emitter::emitIns_R_R_R_R(
6028 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, regNumber reg4)
6030 emitAttr size = EA_SIZE(attr);
6031 insFormat fmt = IF_NONE;
6033 /* Figure out the encoding format of the instruction */
6042 assert(isValidGeneralDatasize(size));
6043 assert(isGeneralRegister(reg1));
6044 assert(isGeneralRegister(reg2));
6045 assert(isGeneralRegister(reg3));
6046 assert(isGeneralRegister(reg4));
6055 assert(isValidScalarDatasize(size));
6056 assert(isVectorRegister(reg1));
6057 assert(isVectorRegister(reg2));
6058 assert(isVectorRegister(reg3));
6059 assert(isVectorRegister(reg4));
6071 assert(fmt != IF_NONE);
6073 instrDesc* id = emitNewInstr(attr);
6087 /*****************************************************************************
6089 * Add an instruction referencing a register and a condition code
6092 void emitter::emitIns_R_COND(instruction ins, emitAttr attr, regNumber reg, insCond cond)
6094 emitAttr size = EA_SIZE(attr);
6095 insFormat fmt = IF_NONE;
6099 /* Figure out the encoding format of the instruction */
6104 assert(isGeneralRegister(reg));
6113 } // end switch (ins)
6115 assert(fmt != IF_NONE);
6116 assert(isValidImmCond(cfi.immCFVal));
6118 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6122 id->idInsOpt(INS_OPTS_NONE);
6130 /*****************************************************************************
6132 * Add an instruction referencing two registers and a condition code
6135 void emitter::emitIns_R_R_COND(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insCond cond)
6137 emitAttr size = EA_SIZE(attr);
6138 insFormat fmt = IF_NONE;
6142 /* Figure out the encoding format of the instruction */
6148 assert(isGeneralRegister(reg1));
6149 assert(isGeneralRegister(reg2));
6157 } // end switch (ins)
6159 assert(fmt != IF_NONE);
6160 assert(isValidImmCond(cfi.immCFVal));
6162 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6166 id->idInsOpt(INS_OPTS_NONE);
6175 /*****************************************************************************
6177 * Add an instruction referencing two registers and a condition code
6180 void emitter::emitIns_R_R_R_COND(
6181 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insCond cond)
6183 emitAttr size = EA_SIZE(attr);
6184 insFormat fmt = IF_NONE;
6188 /* Figure out the encoding format of the instruction */
6195 assert(isGeneralRegister(reg1));
6196 assert(isGeneralRegister(reg2));
6197 assert(isGeneralRegister(reg3));
6206 } // end switch (ins)
6208 assert(fmt != IF_NONE);
6209 assert(isValidImmCond(cfi.immCFVal));
6211 instrDesc* id = emitNewInstr(attr);
6215 id->idInsOpt(INS_OPTS_NONE);
6220 id->idSmallCns(cfi.immCFVal);
6226 /*****************************************************************************
6228 * Add an instruction referencing two registers the flags and a condition code
6231 void emitter::emitIns_R_R_FLAGS_COND(
6232 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insCflags flags, insCond cond)
6234 emitAttr size = EA_SIZE(attr);
6235 insFormat fmt = IF_NONE;
6239 /* Figure out the encoding format of the instruction */
6244 assert(isGeneralRegister(reg1));
6245 assert(isGeneralRegister(reg2));
6253 } // end switch (ins)
6255 assert(fmt != IF_NONE);
6256 assert(isValidImmCondFlags(cfi.immCFVal));
6258 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6262 id->idInsOpt(INS_OPTS_NONE);
6271 /*****************************************************************************
6273 * Add an instruction referencing a register, an immediate, the flags and a condition code
6276 void emitter::emitIns_R_I_FLAGS_COND(
6277 instruction ins, emitAttr attr, regNumber reg, int imm, insCflags flags, insCond cond)
6279 emitAttr size = EA_SIZE(attr);
6280 insFormat fmt = IF_NONE;
6284 /* Figure out the encoding format of the instruction */
6289 assert(isGeneralRegister(reg));
6292 ins = insReverse(ins);
6295 if ((imm >= 0) && (imm <= 31))
6304 assert(!"Instruction cannot be encoded: ccmp/ccmn imm5");
6310 } // end switch (ins)
6312 assert(fmt != IF_NONE);
6313 assert(isValidImmCondFlagsImm5(cfi.immCFVal));
6315 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6319 id->idInsOpt(INS_OPTS_NONE);
6327 /*****************************************************************************
6329 * Add a memory barrier instruction with a 'barrier' immediate
6332 void emitter::emitIns_BARR(instruction ins, insBarrier barrier)
6334 insFormat fmt = IF_NONE;
6337 /* Figure out the encoding format of the instruction */
6345 imm = (ssize_t)barrier;
6350 } // end switch (ins)
6352 assert(fmt != IF_NONE);
6354 instrDesc* id = emitNewInstrSC(EA_8BYTE, imm);
6358 id->idInsOpt(INS_OPTS_NONE);
6364 /*****************************************************************************
6366 * Add an instruction with a static data member operand. If 'size' is 0, the
6367 * instruction operates on the address of the static member instead of its
6368 * value (e.g. "push offset clsvar", rather than "push dword ptr [clsvar]").
6371 void emitter::emitIns_C(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, int offs)
6376 /*****************************************************************************
6378 * Add an instruction referencing stack-based local variable.
6381 void emitter::emitIns_S(instruction ins, emitAttr attr, int varx, int offs)
6386 /*****************************************************************************
6388 * Add an instruction referencing a register and a stack-based local variable.
6390 void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
6392 emitAttr size = EA_SIZE(attr);
6393 insFormat fmt = IF_NONE;
6399 // TODO-ARM64-CQ: use unscaled loads?
6400 /* Figure out the encoding format of the instruction */
6421 assert(isValidGeneralDatasize(size) || isValidVectorDatasize(size));
6422 scale = genLog2(EA_SIZE_IN_BYTES(size));
6426 assert(size == EA_8BYTE);
6431 NYI("emitIns_R_S"); // FP locals?
6434 } // end switch (ins)
6436 /* Figure out the variable's frame position */
6441 base = emitComp->lvaFrameAddress(varx, &FPbased);
6443 assert((scale >= 0) && (scale <= 4));
6445 regNumber reg2 = FPbased ? REG_FPBASE : REG_SPBASE;
6446 reg2 = encodingSPtoZR(reg2);
6463 fmt = IF_DI_2A; // add reg1,reg2,#disp
6467 regNumber rsvdReg = codeGen->rsGetRsvdReg();
6468 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6469 fmt = IF_DR_3A; // add reg1,reg2,rsvdReg
6474 bool useRegForImm = false;
6475 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6482 else if ((imm < 0) || ((imm & mask) != 0))
6484 if ((imm >= -256) && (imm <= 255))
6490 useRegForImm = true;
6495 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
6497 imm >>= scale; // The immediate is scaled by the size of the ld/st
6503 useRegForImm = true;
6509 regNumber rsvdReg = codeGen->rsGetRsvdReg();
6510 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6515 assert(fmt != IF_NONE);
6517 instrDesc* id = emitNewInstrCns(attr, imm);
6521 id->idInsOpt(INS_OPTS_NONE);
6525 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6526 id->idSetIsLclVar();
6529 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6536 /*****************************************************************************
6538 * Add an instruction referencing two register and consectutive stack-based local variable slots.
6540 void emitter::emitIns_R_R_S_S(
6541 instruction ins, emitAttr attr1, emitAttr attr2, regNumber reg1, regNumber reg2, int varx, int offs)
6543 assert((ins == INS_ldp) || (ins == INS_ldnp));
6544 assert(EA_8BYTE == EA_SIZE(attr1));
6545 assert(EA_8BYTE == EA_SIZE(attr2));
6546 assert(isGeneralRegisterOrZR(reg1));
6547 assert(isGeneralRegisterOrZR(reg2));
6550 insFormat fmt = IF_LS_3B;
6552 const unsigned scale = 3;
6554 /* Figure out the variable's frame position */
6558 base = emitComp->lvaFrameAddress(varx, &FPbased);
6561 // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6562 regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE;
6563 reg3 = encodingSPtoZR(reg3);
6565 bool useRegForAdr = true;
6567 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6570 useRegForAdr = false;
6574 if ((imm & mask) == 0)
6576 ssize_t immShift = imm >> scale; // The immediate is scaled by the size of the ld/st
6578 if ((immShift >= -64) && (immShift <= 63))
6581 useRegForAdr = false;
6589 regNumber rsvd = codeGen->rsGetRsvdReg();
6590 emitIns_R_R_Imm(INS_add, EA_PTRSIZE, rsvd, reg3, imm);
6595 assert(fmt != IF_NONE);
6597 instrDesc* id = emitNewInstrCns(attr1, imm);
6601 id->idInsOpt(INS_OPTS_NONE);
6603 // Record the attribute for the second register in the pair
6604 if (EA_IS_GCREF(attr2))
6606 id->idGCrefReg2(GCT_GCREF);
6608 else if (EA_IS_BYREF(attr2))
6610 id->idGCrefReg2(GCT_BYREF);
6614 id->idGCrefReg2(GCT_NONE);
6620 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6621 id->idSetIsLclVar();
6624 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6631 /*****************************************************************************
6633 * Add an instruction referencing a stack-based local variable and a register
6635 void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
6638 emitAttr size = EA_SIZE(attr);
6639 insFormat fmt = IF_NONE;
6642 bool isVectorStore = false;
6644 // TODO-ARM64-CQ: use unscaled loads?
6645 /* Figure out the encoding format of the instruction */
6650 assert(isGeneralRegisterOrZR(reg1));
6655 assert(isGeneralRegisterOrZR(reg1));
6659 if (isGeneralRegisterOrZR(reg1))
6661 assert(isValidGeneralDatasize(size));
6662 scale = (size == EA_8BYTE) ? 3 : 2;
6666 assert(isVectorRegister(reg1));
6667 assert(isValidVectorLSDatasize(size));
6668 scale = NaturalScale_helper(size);
6669 isVectorStore = true;
6674 NYI("emitIns_S_R"); // FP locals?
6677 } // end switch (ins)
6679 /* Figure out the variable's frame position */
6683 base = emitComp->lvaFrameAddress(varx, &FPbased);
6695 // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6696 regNumber reg2 = FPbased ? REG_FPBASE : REG_SPBASE;
6697 reg2 = encodingSPtoZR(reg2);
6699 bool useRegForImm = false;
6701 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6706 else if ((imm < 0) || ((imm & mask) != 0))
6708 if ((imm >= -256) && (imm <= 255))
6714 useRegForImm = true;
6719 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
6721 imm >>= scale; // The immediate is scaled by the size of the ld/st
6727 useRegForImm = true;
6733 // The reserved register is not stored in idReg3() since that field overlaps with iiaLclVar.
6734 // It is instead implicit when idSetIsLclVar() is set, with this encoding format.
6735 regNumber rsvdReg = codeGen->rsGetRsvdReg();
6736 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6740 assert(fmt != IF_NONE);
6742 instrDesc* id = emitNewInstrCns(attr, imm);
6746 id->idInsOpt(INS_OPTS_NONE);
6750 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6751 id->idSetIsLclVar();
6754 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6761 /*****************************************************************************
6763 * Add an instruction referencing consecutive stack-based local variable slots and two registers
6765 void emitter::emitIns_S_S_R_R(
6766 instruction ins, emitAttr attr1, emitAttr attr2, regNumber reg1, regNumber reg2, int varx, int offs)
6768 assert((ins == INS_stp) || (ins == INS_stnp));
6769 assert(EA_8BYTE == EA_SIZE(attr1));
6770 assert(EA_8BYTE == EA_SIZE(attr2));
6771 assert(isGeneralRegisterOrZR(reg1));
6772 assert(isGeneralRegisterOrZR(reg2));
6775 insFormat fmt = IF_LS_3B;
6777 const unsigned scale = 3;
6779 /* Figure out the variable's frame position */
6783 base = emitComp->lvaFrameAddress(varx, &FPbased);
6786 // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6787 regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE;
6788 reg3 = encodingSPtoZR(reg3);
6790 bool useRegForAdr = true;
6792 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6795 useRegForAdr = false;
6799 if ((imm & mask) == 0)
6801 ssize_t immShift = imm >> scale; // The immediate is scaled by the size of the ld/st
6803 if ((immShift >= -64) && (immShift <= 63))
6806 useRegForAdr = false;
6814 regNumber rsvd = codeGen->rsGetRsvdReg();
6815 emitIns_R_R_Imm(INS_add, EA_PTRSIZE, rsvd, reg3, imm);
6820 assert(fmt != IF_NONE);
6822 instrDesc* id = emitNewInstrCns(attr1, imm);
6826 id->idInsOpt(INS_OPTS_NONE);
6828 // Record the attribute for the second register in the pair
6829 if (EA_IS_GCREF(attr2))
6831 id->idGCrefReg2(GCT_GCREF);
6833 else if (EA_IS_BYREF(attr2))
6835 id->idGCrefReg2(GCT_BYREF);
6839 id->idGCrefReg2(GCT_NONE);
6845 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6846 id->idSetIsLclVar();
6849 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6856 /*****************************************************************************
6858 * Add an instruction referencing stack-based local variable and an immediate
6860 void emitter::emitIns_S_I(instruction ins, emitAttr attr, int varx, int offs, int val)
6865 /*****************************************************************************
6867 * Add an instruction with a register + static member operands.
6868 * Constant is stored into JIT data which is adjacent to code.
6869 * No relocation is needed. PC-relative offset will be encoded directly into instruction.
6872 void emitter::emitIns_R_C(
6873 instruction ins, emitAttr attr, regNumber reg, regNumber addrReg, CORINFO_FIELD_HANDLE fldHnd, int offs)
6876 assert(instrDesc::fitsInSmallCns(offs));
6878 emitAttr size = EA_SIZE(attr);
6879 insFormat fmt = IF_NONE;
6881 instrDescJmp* id = emitNewInstrJmp();
6886 // This is case to get address to the constant data.
6888 assert(isGeneralRegister(reg));
6889 assert(isValidGeneralDatasize(size));
6894 if (isVectorRegister(reg))
6896 assert(isValidScalarDatasize(size));
6897 // For vector (float/double) register, we should have an integer address reg to
6898 // compute long address which consists of page address and page offset.
6899 // For integer constant, this is not needed since the dest reg can be used to
6900 // compute address as well as contain the final contents.
6901 assert(isGeneralRegister(reg) || (addrReg != REG_NA));
6905 assert(isGeneralRegister(reg));
6906 assert(isValidGeneralDatasize(size));
6913 assert(fmt != IF_NONE);
6917 id->idInsOpt(INS_OPTS_NONE);
6918 id->idSmallCns(offs);
6920 id->idAddr()->iiaFieldHnd = fldHnd;
6921 id->idSetIsBound(); // We won't patch address since we will know the exact distance once JIT code and data are
6922 // allocated together.
6924 id->idReg1(reg); // destination register that will get the constant value.
6925 if (addrReg != REG_NA)
6927 id->idReg2(addrReg); // integer register to compute long address (used for vector dest when we end up with long
6930 id->idjShort = false; // Assume loading constant from long address
6932 // Keep it long if it's in cold code.
6933 id->idjKeepLong = emitComp->fgIsBlockCold(emitComp->compCurBB);
6936 if (emitComp->opts.compLongAddress)
6937 id->idjKeepLong = 1;
6940 // If it's possible to be shortened, then put it in jump list
6941 // to be revisited by emitJumpDistBind.
6942 if (!id->idjKeepLong)
6944 /* Record the jump's IG and offset within it */
6945 id->idjIG = emitCurIG;
6946 id->idjOffs = emitCurIGsize;
6948 /* Append this jump to this IG's jump list */
6949 id->idjNext = emitCurIGjmpList;
6950 emitCurIGjmpList = id;
6961 /*****************************************************************************
6963 * Add an instruction with a static member + constant.
6966 void emitter::emitIns_C_I(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, ssize_t offs, ssize_t val)
6971 /*****************************************************************************
6973 * Add an instruction with a static member + register operands.
6976 void emitter::emitIns_C_R(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, regNumber reg, int offs)
6978 assert(!"emitIns_C_R not supported for RyuJIT backend");
6981 void emitter::emitIns_R_AR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
6983 NYI("emitIns_R_AR");
6986 // This computes address from the immediate which is relocatable.
6987 void emitter::emitIns_R_AI(instruction ins, emitAttr attr, regNumber ireg, ssize_t addr)
6989 assert(EA_IS_RELOC(attr));
6990 emitAttr size = EA_SIZE(attr);
6991 insFormat fmt = IF_DI_1E;
6992 bool needAdd = false;
6993 instrDescJmp* id = emitNewInstrJmp();
6998 // This computes page address.
6999 // page offset is needed using add.
7010 id->idInsOpt(INS_OPTS_NONE);
7012 id->idAddr()->iiaAddr = (BYTE*)addr;
7014 id->idSetIsDspReloc();
7021 // add reg, reg, imm
7024 instrDesc* id = emitAllocInstr(attr);
7025 assert(id->idIsReloc());
7029 id->idInsOpt(INS_OPTS_NONE);
7031 id->idAddr()->iiaAddr = (BYTE*)addr;
7040 void emitter::emitIns_AR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
7042 NYI("emitIns_AR_R");
7045 void emitter::emitIns_R_ARR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
7047 NYI("emitIns_R_ARR");
7050 void emitter::emitIns_ARR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
7052 NYI("emitIns_R_ARR");
7055 void emitter::emitIns_R_ARX(
7056 instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, unsigned mul, int disp)
7058 NYI("emitIns_R_ARR");
7061 /*****************************************************************************
7063 * Record that a jump instruction uses the short encoding
7066 void emitter::emitSetShortJump(instrDescJmp* id)
7068 if (id->idjKeepLong)
7071 insFormat fmt = IF_NONE;
7072 if (emitIsCondJump(id))
7074 switch (id->idIns())
7089 else if (emitIsLoadLabel(id))
7093 else if (emitIsLoadConstant(id))
7103 id->idjShort = true;
7106 /*****************************************************************************
7108 * Add a label instruction.
7111 void emitter::emitIns_R_L(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
7113 assert(dst->bbFlags & BBF_JMP_TARGET);
7115 insFormat fmt = IF_NONE;
7126 instrDescJmp* id = emitNewInstrJmp();
7130 id->idjShort = false;
7131 id->idAddr()->iiaBBlabel = dst;
7133 id->idOpSize(EA_PTRSIZE);
7136 // Mark the catch return
7137 if (emitComp->compCurBB->bbJumpKind == BBJ_EHCATCHRET)
7139 id->idDebugOnlyInfo()->idCatchRet = true;
7143 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7146 if (emitComp->opts.compLongAddress)
7147 id->idjKeepLong = 1;
7150 /* Record the jump's IG and offset within it */
7152 id->idjIG = emitCurIG;
7153 id->idjOffs = emitCurIGsize;
7155 /* Append this jump to this IG's jump list */
7157 id->idjNext = emitCurIGjmpList;
7158 emitCurIGjmpList = id;
7168 /*****************************************************************************
7170 * Add a data label instruction.
7173 void emitter::emitIns_R_D(instruction ins, emitAttr attr, unsigned offs, regNumber reg)
7178 void emitter::emitIns_J_R(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
7180 assert((ins == INS_cbz) || (ins == INS_cbnz));
7182 assert(dst != nullptr);
7183 assert((dst->bbFlags & BBF_JMP_TARGET) != 0);
7185 insFormat fmt = IF_LARGEJMP;
7187 instrDescJmp* id = emitNewInstrJmp();
7192 id->idjShort = false;
7193 id->idOpSize(EA_SIZE(attr));
7195 id->idAddr()->iiaBBlabel = dst;
7196 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7198 /* Record the jump's IG and offset within it */
7200 id->idjIG = emitCurIG;
7201 id->idjOffs = emitCurIGsize;
7203 /* Append this jump to this IG's jump list */
7205 id->idjNext = emitCurIGjmpList;
7206 emitCurIGjmpList = id;
7216 void emitter::emitIns_J_R_I(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg, int imm)
7218 assert((ins == INS_tbz) || (ins == INS_tbnz));
7220 assert(dst != nullptr);
7221 assert((dst->bbFlags & BBF_JMP_TARGET) != 0);
7222 assert((EA_SIZE(attr) == EA_4BYTE) || (EA_SIZE(attr) == EA_8BYTE));
7223 assert(imm < ((EA_SIZE(attr) == EA_4BYTE) ? 32 : 64));
7225 insFormat fmt = IF_LARGEJMP;
7227 instrDescJmp* id = emitNewInstrJmp();
7232 id->idjShort = false;
7233 id->idSmallCns(imm);
7234 id->idOpSize(EA_SIZE(attr));
7236 id->idAddr()->iiaBBlabel = dst;
7237 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7239 /* Record the jump's IG and offset within it */
7241 id->idjIG = emitCurIG;
7242 id->idjOffs = emitCurIGsize;
7244 /* Append this jump to this IG's jump list */
7246 id->idjNext = emitCurIGjmpList;
7247 emitCurIGjmpList = id;
7257 void emitter::emitIns_J(instruction ins, BasicBlock* dst, int instrCount)
7259 insFormat fmt = IF_NONE;
7263 assert(dst->bbFlags & BBF_JMP_TARGET);
7267 assert(instrCount != 0);
7270 /* Figure out the encoding format of the instruction */
7272 bool idjShort = false;
7277 // Unconditional jump is a single form.
7296 // Assume conditional jump is long.
7305 instrDescJmp* id = emitNewInstrJmp();
7309 id->idjShort = idjShort;
7312 // Mark the finally call
7313 if (ins == INS_bl_local && emitComp->compCurBB->bbJumpKind == BBJ_CALLFINALLY)
7315 id->idDebugOnlyInfo()->idFinallyCall = true;
7321 id->idAddr()->iiaBBlabel = dst;
7323 // Skip unconditional jump that has a single form.
7324 // TODO-ARM64-NYI: enable hot/cold splittingNYI.
7325 // The target needs to be relocated.
7328 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7331 if (emitComp->opts.compLongAddress) // Force long branches
7332 id->idjKeepLong = 1;
7338 id->idAddr()->iiaSetInstrCount(instrCount);
7339 id->idjKeepLong = false;
7340 /* This jump must be short */
7341 emitSetShortJump(id);
7345 /* Record the jump's IG and offset within it */
7347 id->idjIG = emitCurIG;
7348 id->idjOffs = emitCurIGsize;
7350 /* Append this jump to this IG's jump list */
7352 id->idjNext = emitCurIGjmpList;
7353 emitCurIGjmpList = id;
7363 /*****************************************************************************
7365 * Add a call instruction (direct or indirect).
7366 * argSize<0 means that the caller will pop the arguments
7368 * The other arguments are interpreted depending on callType as shown:
7369 * Unless otherwise specified, ireg,xreg,xmul,disp should have default values.
7371 * EC_FUNC_TOKEN : addr is the method address
7372 * EC_FUNC_ADDR : addr is the absolute address of the function
7374 * If callType is one of these emitCallTypes, addr has to be NULL.
7375 * EC_INDIR_R : "call ireg".
7377 * For ARM xreg, xmul and disp are never used and should always be 0/REG_NA.
7379 * Please consult the "debugger team notification" comment in genFnProlog().
7382 void emitter::emitIns_Call(EmitCallType callType,
7383 CORINFO_METHOD_HANDLE methHnd,
7384 INDEBUG_LDISASM_COMMA(CORINFO_SIG_INFO* sigInfo) // used to report call sites to the EE
7388 emitAttr secondRetSize,
7389 VARSET_VALARG_TP ptrVars,
7390 regMaskTP gcrefRegs,
7391 regMaskTP byrefRegs,
7392 IL_OFFSETX ilOffset /* = BAD_IL_OFFSET */,
7393 regNumber ireg /* = REG_NA */,
7394 regNumber xreg /* = REG_NA */,
7395 unsigned xmul /* = 0 */,
7396 ssize_t disp /* = 0 */,
7397 bool isJump /* = false */,
7398 bool isNoGC /* = false */,
7399 bool isProfLeaveCB /* = false */)
7401 /* Sanity check the arguments depending on callType */
7403 assert(callType < EC_COUNT);
7404 assert((callType != EC_FUNC_TOKEN && callType != EC_FUNC_ADDR) ||
7405 (ireg == REG_NA && xreg == REG_NA && xmul == 0 && disp == 0));
7406 assert(callType < EC_INDIR_R || addr == NULL);
7407 assert(callType != EC_INDIR_R || (ireg < REG_COUNT && xreg == REG_NA && xmul == 0 && disp == 0));
7409 // ARM never uses these
7410 assert(xreg == REG_NA && xmul == 0 && disp == 0);
7412 // Our stack level should be always greater than the bytes of arguments we push. Just
7414 assert((unsigned)abs(argSize) <= codeGen->genStackLevel);
7419 /* This is the saved set of registers after a normal call */
7420 regMaskTP savedSet = RBM_CALLEE_SAVED;
7422 /* some special helper calls have a different saved set registers */
7426 assert(emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
7428 // Get the set of registers that this call kills and remove it from the saved set.
7429 savedSet = RBM_ALLINT & ~emitComp->compNoGCHelperCallKillSet(Compiler::eeGetHelperNum(methHnd));
7431 // In case of Leave profiler callback, we need to preserve liveness of REG_PROFILER_RET_SCRATCH
7434 savedSet |= RBM_PROFILER_RET_SCRATCH;
7438 if (emitComp->verbose)
7440 printf("NOGC Call: savedSet=");
7441 printRegMaskInt(savedSet);
7442 emitDispRegSet(savedSet);
7449 assert(!emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
7452 /* Trim out any callee-trashed registers from the live set */
7454 gcrefRegs &= savedSet;
7455 byrefRegs &= savedSet;
7458 if (EMIT_GC_VERBOSE)
7460 printf("Call: GCvars=%s ", VarSetOps::ToString(emitComp, ptrVars));
7461 dumpConvertedVarSet(emitComp, ptrVars);
7462 printf(", gcrefRegs=");
7463 printRegMaskInt(gcrefRegs);
7464 emitDispRegSet(gcrefRegs);
7465 printf(", byrefRegs=");
7466 printRegMaskInt(byrefRegs);
7467 emitDispRegSet(byrefRegs);
7472 assert(argSize % REGSIZE_BYTES == 0);
7473 argCnt = (int)(argSize / (int)REGSIZE_BYTES);
7475 /* Managed RetVal: emit sequence point for the call */
7476 if (emitComp->opts.compDbgInfo && ilOffset != BAD_IL_OFFSET)
7478 codeGen->genIPmappingAdd(ilOffset, false);
7482 We need to allocate the appropriate instruction descriptor based
7483 on whether this is a direct/indirect call, and whether we need to
7484 record an updated set of live GC variables.
7487 if (callType >= EC_INDIR_R)
7489 /* Indirect call, virtual calls */
7491 assert(callType == EC_INDIR_R);
7493 id = emitNewInstrCallInd(argCnt, disp, ptrVars, gcrefRegs, byrefRegs, retSize, secondRetSize);
7497 /* Helper/static/nonvirtual/function calls (direct or through handle),
7498 and calls to an absolute addr. */
7500 assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
7502 id = emitNewInstrCallDir(argCnt, ptrVars, gcrefRegs, byrefRegs, retSize, secondRetSize);
7505 /* Update the emitter's live GC ref sets */
7507 VarSetOps::Assign(emitComp, emitThisGCrefVars, ptrVars);
7508 emitThisGCrefRegs = gcrefRegs;
7509 emitThisByrefRegs = byrefRegs;
7511 /* Set the instruction - special case jumping a function */
7513 insFormat fmt = IF_NONE;
7515 id->idSetIsNoGC(isNoGC);
7517 /* Record the address: method, indirection, or funcptr */
7519 if (callType > EC_FUNC_ADDR)
7521 /* This is an indirect call (either a virtual call or func ptr call) */
7525 case EC_INDIR_R: // the address is in a register
7527 id->idSetIsCallRegPtr();
7531 ins = INS_br_tail; // INS_br_tail Reg
7535 ins = INS_blr; // INS_blr Reg
7543 assert(xreg == REG_NA);
7547 NO_WAY("unexpected instruction");
7553 /* This is a simple direct call: "call helper/method/addr" */
7555 assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
7557 assert(addr != NULL);
7561 ins = INS_b_tail; // INS_b_tail imm28
7565 ins = INS_bl; // INS_bl imm28
7572 id->idAddr()->iiaAddr = (BYTE*)addr;
7574 if (callType == EC_FUNC_ADDR)
7576 id->idSetIsCallAddr();
7579 if (emitComp->opts.compReloc)
7581 id->idSetIsDspReloc();
7586 if (EMIT_GC_VERBOSE)
7588 if (id->idIsLargeCall())
7590 printf("[%02u] Rec call GC vars = %s\n", id->idDebugOnlyInfo()->idNum,
7591 VarSetOps::ToString(emitComp, ((instrDescCGCA*)id)->idcGCvars));
7595 id->idDebugOnlyInfo()->idMemCookie = (size_t)methHnd; // method token
7596 id->idDebugOnlyInfo()->idCallSig = sigInfo;
7600 if (addr != nullptr)
7602 codeGen->getDisAssembler().disSetMethod((size_t)addr, methHnd);
7604 #endif // LATE_DISASM
7610 /*****************************************************************************
7612 * Returns true if 'imm' is valid Cond encoding
7615 /*static*/ bool emitter::isValidImmCond(ssize_t imm)
7617 // range check the ssize_t value, to make sure it is a small unsigned value
7618 // and that only the bits in the cfi.cond are set
7619 if ((imm < 0) || (imm > 0xF))
7623 cfi.immCFVal = (unsigned)imm;
7625 return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7628 /*****************************************************************************
7630 * Returns true if 'imm' is valid Cond/Flags encoding
7633 /*static*/ bool emitter::isValidImmCondFlags(ssize_t imm)
7635 // range check the ssize_t value, to make sure it is a small unsigned value
7636 // and that only the bits in the cfi.cond or cfi.flags are set
7637 if ((imm < 0) || (imm > 0xFF))
7641 cfi.immCFVal = (unsigned)imm;
7643 return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7646 /*****************************************************************************
7648 * Returns true if 'imm' is valid Cond/Flags/Imm5 encoding
7651 /*static*/ bool emitter::isValidImmCondFlagsImm5(ssize_t imm)
7653 // range check the ssize_t value, to make sure it is a small unsigned value
7654 // and that only the bits in the cfi.cond, cfi.flags or cfi.imm5 are set
7655 if ((imm < 0) || (imm > 0x1FFF))
7659 cfi.immCFVal = (unsigned)imm;
7661 return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7664 /*****************************************************************************
7666 * Returns an encoding for the specified register used in the 'Rd' position
7669 /*static*/ emitter::code_t emitter::insEncodeReg_Rd(regNumber reg)
7671 assert(isIntegerRegister(reg));
7672 emitter::code_t ureg = (emitter::code_t)reg;
7673 assert((ureg >= 0) && (ureg <= 31));
7677 /*****************************************************************************
7679 * Returns an encoding for the specified register used in the 'Rt' position
7682 /*static*/ emitter::code_t emitter::insEncodeReg_Rt(regNumber reg)
7684 assert(isIntegerRegister(reg));
7685 emitter::code_t ureg = (emitter::code_t)reg;
7686 assert((ureg >= 0) && (ureg <= 31));
7690 /*****************************************************************************
7692 * Returns an encoding for the specified register used in the 'Rn' position
7695 /*static*/ emitter::code_t emitter::insEncodeReg_Rn(regNumber reg)
7697 assert(isIntegerRegister(reg));
7698 emitter::code_t ureg = (emitter::code_t)reg;
7699 assert((ureg >= 0) && (ureg <= 31));
7703 /*****************************************************************************
7705 * Returns an encoding for the specified register used in the 'Rm' position
7708 /*static*/ emitter::code_t emitter::insEncodeReg_Rm(regNumber reg)
7710 assert(isIntegerRegister(reg));
7711 emitter::code_t ureg = (emitter::code_t)reg;
7712 assert((ureg >= 0) && (ureg <= 31));
7716 /*****************************************************************************
7718 * Returns an encoding for the specified register used in the 'Ra' position
7721 /*static*/ emitter::code_t emitter::insEncodeReg_Ra(regNumber reg)
7723 assert(isIntegerRegister(reg));
7724 emitter::code_t ureg = (emitter::code_t)reg;
7725 assert((ureg >= 0) && (ureg <= 31));
7729 /*****************************************************************************
7731 * Returns an encoding for the specified register used in the 'Vd' position
7734 /*static*/ emitter::code_t emitter::insEncodeReg_Vd(regNumber reg)
7736 assert(emitter::isVectorRegister(reg));
7737 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7738 assert((ureg >= 0) && (ureg <= 31));
7742 /*****************************************************************************
7744 * Returns an encoding for the specified register used in the 'Vt' position
7747 /*static*/ emitter::code_t emitter::insEncodeReg_Vt(regNumber reg)
7749 assert(emitter::isVectorRegister(reg));
7750 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7751 assert((ureg >= 0) && (ureg <= 31));
7755 /*****************************************************************************
7757 * Returns an encoding for the specified register used in the 'Vn' position
7760 /*static*/ emitter::code_t emitter::insEncodeReg_Vn(regNumber reg)
7762 assert(emitter::isVectorRegister(reg));
7763 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7764 assert((ureg >= 0) && (ureg <= 31));
7768 /*****************************************************************************
7770 * Returns an encoding for the specified register used in the 'Vm' position
7773 /*static*/ emitter::code_t emitter::insEncodeReg_Vm(regNumber reg)
7775 assert(emitter::isVectorRegister(reg));
7776 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7777 assert((ureg >= 0) && (ureg <= 31));
7781 /*****************************************************************************
7783 * Returns an encoding for the specified register used in the 'Va' position
7786 /*static*/ emitter::code_t emitter::insEncodeReg_Va(regNumber reg)
7788 assert(emitter::isVectorRegister(reg));
7789 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7790 assert((ureg >= 0) && (ureg <= 31));
7794 /*****************************************************************************
7796 * Returns an encoding for the specified condition code.
7799 /*static*/ emitter::code_t emitter::insEncodeCond(insCond cond)
7801 emitter::code_t uimm = (emitter::code_t)cond;
7805 /*****************************************************************************
7807 * Returns an encoding for the condition code with the lowest bit inverted (marked by invert(<cond>) in the
7808 * architecture manual).
7811 /*static*/ emitter::code_t emitter::insEncodeInvertedCond(insCond cond)
7813 emitter::code_t uimm = (emitter::code_t)cond;
7814 uimm ^= 1; // invert the lowest bit
7818 /*****************************************************************************
7820 * Returns an encoding for the specified flags.
7823 /*static*/ emitter::code_t emitter::insEncodeFlags(insCflags flags)
7825 emitter::code_t uimm = (emitter::code_t)flags;
7829 /*****************************************************************************
7831 * Returns the encoding for the Shift Count bits to be used for Arm64 encodings
7834 /*static*/ emitter::code_t emitter::insEncodeShiftCount(ssize_t imm, emitAttr size)
7836 assert((imm & 0x003F) == imm);
7837 assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
7839 return (emitter::code_t)imm << 10;
7842 /*****************************************************************************
7844 * Returns the encoding to select a 64-bit datasize for an Arm64 instruction
7847 /*static*/ emitter::code_t emitter::insEncodeDatasize(emitAttr size)
7849 if (size == EA_8BYTE)
7851 return 0x80000000; // set the bit at location 31
7855 assert(size == EA_4BYTE);
7860 /*****************************************************************************
7862 * Returns the encoding to select the datasize for the general load/store Arm64 instructions
7866 /*static*/ emitter::code_t emitter::insEncodeDatasizeLS(emitter::code_t code, emitAttr size)
7868 bool exclusive = ((code & 0x35000000) == 0);
7869 bool atomic = ((code & 0x31200C00) == 0x30200000);
7871 if ((code & 0x00800000) && !exclusive && !atomic) // Is this a sign-extending opcode? (i.e. ldrsw, ldrsh, ldrsb)
7873 if ((code & 0x80000000) == 0) // Is it a ldrsh or ldrsb and not ldrsw ?
7875 if (EA_SIZE(size) != EA_8BYTE) // Do we need to encode the 32-bit Rt size bit?
7877 return 0x00400000; // set the bit at location 22
7881 else if (code & 0x80000000) // Is this a ldr/str/ldur/stur opcode?
7883 if (EA_SIZE(size) == EA_8BYTE) // Do we need to encode the 64-bit size bit?
7885 return 0x40000000; // set the bit at location 30
7891 /*****************************************************************************
7893 * Returns the encoding to select the datasize for the vector load/store Arm64 instructions
7897 /*static*/ emitter::code_t emitter::insEncodeDatasizeVLS(emitter::code_t code, emitAttr size)
7902 if ((code & 0x20000000) == 0)
7906 if (size == EA_16BYTE)
7908 // set the operation size in bit 31
7909 result = 0x80000000;
7911 else if (size == EA_8BYTE)
7913 // set the operation size in bit 30
7914 result = 0x40000000;
7918 assert(size == EA_4BYTE);
7920 result = 0x00000000;
7927 if (size == EA_16BYTE)
7929 // The operation size in bits 31 and 30 are zero
7930 // Bit 23 specifies a 128-bit Load/Store
7931 result = 0x00800000;
7933 else if (size == EA_8BYTE)
7935 // set the operation size in bits 31 and 30
7936 result = 0xC0000000;
7938 else if (size == EA_4BYTE)
7940 // set the operation size in bit 31
7941 result = 0x80000000;
7943 else if (size == EA_2BYTE)
7945 // set the operation size in bit 30
7946 result = 0x40000000;
7950 assert(size == EA_1BYTE);
7951 // The operation size in bits 31 and 30 are zero
7952 result = 0x00000000;
7956 // Or in bit 26 to indicate a Vector register is used as 'target'
7957 result |= 0x04000000;
7962 /*****************************************************************************
7964 * Returns the encoding to select the datasize for the vector load/store Arm64 instructions
7968 /*static*/ emitter::code_t emitter::insEncodeDatasizeVPLS(emitter::code_t code, emitAttr size)
7972 if (size == EA_16BYTE)
7974 // The operation size in bits 31 and 30 are zero
7975 // Bit 23 specifies a 128-bit Load/Store
7976 result = 0x80000000;
7978 else if (size == EA_8BYTE)
7980 // set the operation size in bits 31 and 30
7981 result = 0x40000000;
7983 else if (size == EA_4BYTE)
7985 // set the operation size in bit 31
7986 result = 0x00000000;
7989 // Or in bit 26 to indicate a Vector register is used as 'target'
7990 result |= 0x04000000;
7995 /*****************************************************************************
7997 * Returns the encoding to set the size bit and the N bits for a 'bitfield' instruction
8001 /*static*/ emitter::code_t emitter::insEncodeDatasizeBF(emitter::code_t code, emitAttr size)
8003 // is bit 30 equal to 0?
8004 if ((code & 0x40000000) == 0) // is the opcode one of extr, sxtb, sxth or sxtw
8006 if (size == EA_8BYTE) // Do we need to set the sf and N bits?
8008 return 0x80400000; // set the sf-bit at location 31 and the N-bit at location 22
8011 return 0; // don't set any bits
8014 /*****************************************************************************
8016 * Returns the encoding to select the 64/128-bit datasize for an Arm64 vector instruction
8019 /*static*/ emitter::code_t emitter::insEncodeVectorsize(emitAttr size)
8021 if (size == EA_16BYTE)
8023 return 0x40000000; // set the bit at location 30
8027 assert(size == EA_8BYTE);
8032 /*****************************************************************************
8034 * Returns the encoding to select 'index' for an Arm64 vector elem instruction
8036 /*static*/ emitter::code_t emitter::insEncodeVectorIndex(emitAttr elemsize, ssize_t index)
8038 code_t bits = (code_t)index;
8039 if (elemsize == EA_1BYTE)
8044 else if (elemsize == EA_2BYTE)
8049 else if (elemsize == EA_4BYTE)
8056 assert(elemsize == EA_8BYTE);
8060 assert((bits >= 1) && (bits <= 0x1f));
8062 return (bits << 16); // bits at locations [20,19,18,17,16]
8065 /*****************************************************************************
8067 * Returns the encoding to select 'index2' for an Arm64 'ins' elem instruction
8069 /*static*/ emitter::code_t emitter::insEncodeVectorIndex2(emitAttr elemsize, ssize_t index2)
8071 code_t bits = (code_t)index2;
8072 if (elemsize == EA_1BYTE)
8076 else if (elemsize == EA_2BYTE)
8080 else if (elemsize == EA_4BYTE)
8086 assert(elemsize == EA_8BYTE);
8089 assert((bits >= 0) && (bits <= 0xf));
8091 return (bits << 11); // bits at locations [14,13,12,11]
8094 /*****************************************************************************
8096 * Returns the encoding to select the 'index' for an Arm64 'mul' by elem instruction
8098 /*static*/ emitter::code_t emitter::insEncodeVectorIndexLMH(emitAttr elemsize, ssize_t index)
8102 if (elemsize == EA_2BYTE)
8104 assert((index >= 0) && (index <= 7));
8107 bits |= (1 << 11); // set bit 11 'H'
8111 bits |= (1 << 21); // set bit 21 'L'
8115 bits |= (1 << 20); // set bit 20 'M'
8118 else if (elemsize == EA_4BYTE)
8120 assert((index >= 0) && (index <= 3));
8123 bits |= (1 << 11); // set bit 11 'H'
8127 bits |= (1 << 21); // set bit 21 'L'
8132 assert(!"Invalid 'elemsize' value");
8138 /*****************************************************************************
8140 * Returns the encoding to shift by 'shift' for an Arm64 vector or scalar instruction
8143 /*static*/ emitter::code_t emitter::insEncodeVectorShift(emitAttr size, ssize_t shift)
8145 assert(shift < getBitWidth(size));
8147 code_t imm = (code_t)(getBitWidth(size) + shift);
8152 /*****************************************************************************
8154 * Returns the encoding to select the 1/2/4/8 byte elemsize for an Arm64 vector instruction
8157 /*static*/ emitter::code_t emitter::insEncodeElemsize(emitAttr size)
8159 if (size == EA_8BYTE)
8161 return 0x00C00000; // set the bit at location 23 and 22
8163 else if (size == EA_4BYTE)
8165 return 0x00800000; // set the bit at location 23
8167 else if (size == EA_2BYTE)
8169 return 0x00400000; // set the bit at location 22
8171 assert(size == EA_1BYTE);
8175 /*****************************************************************************
8177 * Returns the encoding to select the 4/8 byte elemsize for an Arm64 float vector instruction
8180 /*static*/ emitter::code_t emitter::insEncodeFloatElemsize(emitAttr size)
8182 if (size == EA_8BYTE)
8184 return 0x00400000; // set the bit at location 22
8186 assert(size == EA_4BYTE);
8190 // Returns the encoding to select the index for an Arm64 float vector by elem instruction
8191 /*static*/ emitter::code_t emitter::insEncodeFloatIndex(emitAttr elemsize, ssize_t index)
8193 code_t result = 0x00000000;
8194 if (elemsize == EA_8BYTE)
8196 assert((index >= 0) && (index <= 1));
8199 result |= 0x00000800; // 'H' - set the bit at location 11
8204 assert(elemsize == EA_4BYTE);
8205 assert((index >= 0) && (index <= 3));
8208 result |= 0x00000800; // 'H' - set the bit at location 11
8212 result |= 0x00200000; // 'L' - set the bit at location 21
8218 /*****************************************************************************
8220 * Returns the encoding to select the fcvt operation for Arm64 instructions
8222 /*static*/ emitter::code_t emitter::insEncodeConvertOpt(insFormat fmt, insOpts conversion)
8227 case INS_OPTS_S_TO_D: // Single to Double
8228 assert(fmt == IF_DV_2J);
8229 result = 0x00008000; // type=00, opc=01
8232 case INS_OPTS_D_TO_S: // Double to Single
8233 assert(fmt == IF_DV_2J);
8234 result = 0x00400000; // type=01, opc=00
8237 case INS_OPTS_H_TO_S: // Half to Single
8238 assert(fmt == IF_DV_2J);
8239 result = 0x00C00000; // type=11, opc=00
8242 case INS_OPTS_H_TO_D: // Half to Double
8243 assert(fmt == IF_DV_2J);
8244 result = 0x00C08000; // type=11, opc=01
8247 case INS_OPTS_S_TO_H: // Single to Half
8248 assert(fmt == IF_DV_2J);
8249 result = 0x00018000; // type=00, opc=11
8252 case INS_OPTS_D_TO_H: // Double to Half
8253 assert(fmt == IF_DV_2J);
8254 result = 0x00418000; // type=01, opc=11
8257 case INS_OPTS_S_TO_4BYTE: // Single to INT32
8258 assert(fmt == IF_DV_2H);
8259 result = 0x00000000; // sf=0, type=00
8262 case INS_OPTS_D_TO_4BYTE: // Double to INT32
8263 assert(fmt == IF_DV_2H);
8264 result = 0x00400000; // sf=0, type=01
8267 case INS_OPTS_S_TO_8BYTE: // Single to INT64
8268 assert(fmt == IF_DV_2H);
8269 result = 0x80000000; // sf=1, type=00
8272 case INS_OPTS_D_TO_8BYTE: // Double to INT64
8273 assert(fmt == IF_DV_2H);
8274 result = 0x80400000; // sf=1, type=01
8277 case INS_OPTS_4BYTE_TO_S: // INT32 to Single
8278 assert(fmt == IF_DV_2I);
8279 result = 0x00000000; // sf=0, type=00
8282 case INS_OPTS_4BYTE_TO_D: // INT32 to Double
8283 assert(fmt == IF_DV_2I);
8284 result = 0x00400000; // sf=0, type=01
8287 case INS_OPTS_8BYTE_TO_S: // INT64 to Single
8288 assert(fmt == IF_DV_2I);
8289 result = 0x80000000; // sf=1, type=00
8292 case INS_OPTS_8BYTE_TO_D: // INT64 to Double
8293 assert(fmt == IF_DV_2I);
8294 result = 0x80400000; // sf=1, type=01
8298 assert(!"Invalid 'conversion' value");
8304 /*****************************************************************************
8306 * Returns the encoding to have the Rn register be updated Pre/Post indexed
8310 /*static*/ emitter::code_t emitter::insEncodeIndexedOpt(insOpts opt)
8312 assert(emitter::insOptsNone(opt) || emitter::insOptsIndexed(opt));
8314 if (emitter::insOptsIndexed(opt))
8316 if (emitter::insOptsPostIndex(opt))
8318 return 0x00000400; // set the bit at location 10
8322 assert(emitter::insOptsPreIndex(opt));
8323 return 0x00000C00; // set the bit at location 10 and 11
8328 assert(emitter::insOptsNone(opt));
8329 return 0; // bits 10 and 11 are zero
8333 /*****************************************************************************
8335 * Returns the encoding for a ldp/stp instruction to have the Rn register
8336 * be updated Pre/Post indexed or not updated
8339 /*static*/ emitter::code_t emitter::insEncodePairIndexedOpt(instruction ins, insOpts opt)
8341 assert(emitter::insOptsNone(opt) || emitter::insOptsIndexed(opt));
8343 if ((ins == INS_ldnp) || (ins == INS_stnp))
8345 assert(emitter::insOptsNone(opt));
8346 return 0; // bits 23 and 24 are zero
8350 if (emitter::insOptsIndexed(opt))
8352 if (emitter::insOptsPostIndex(opt))
8354 return 0x00800000; // set the bit at location 23
8358 assert(emitter::insOptsPreIndex(opt));
8359 return 0x01800000; // set the bit at location 24 and 23
8364 assert(emitter::insOptsNone(opt));
8365 return 0x01000000; // set the bit at location 24
8370 /*****************************************************************************
8372 * Returns the encoding to apply a Shift Type on the Rm register
8375 /*static*/ emitter::code_t emitter::insEncodeShiftType(insOpts opt)
8377 if (emitter::insOptsNone(opt))
8379 // None implies the we encode LSL (with a zero immediate)
8382 assert(emitter::insOptsAnyShift(opt));
8384 emitter::code_t option = (emitter::code_t)opt - (emitter::code_t)INS_OPTS_LSL;
8385 assert(option <= 3);
8387 return option << 22; // bits 23, 22
8390 /*****************************************************************************
8392 * Returns the encoding to apply a 12 bit left shift to the immediate
8395 /*static*/ emitter::code_t emitter::insEncodeShiftImm12(insOpts opt)
8397 if (emitter::insOptsLSL12(opt))
8399 return 0x00400000; // set the bit at location 22
8404 /*****************************************************************************
8406 * Returns the encoding to have the Rm register use an extend operation
8409 /*static*/ emitter::code_t emitter::insEncodeExtend(insOpts opt)
8411 if (emitter::insOptsNone(opt) || (opt == INS_OPTS_LSL))
8413 // None or LSL implies the we encode UXTX
8414 opt = INS_OPTS_UXTX;
8416 assert(emitter::insOptsAnyExtend(opt));
8418 emitter::code_t option = (emitter::code_t)opt - (emitter::code_t)INS_OPTS_UXTB;
8419 assert(option <= 7);
8421 return option << 13; // bits 15,14,13
8424 /*****************************************************************************
8426 * Returns the encoding to scale the Rm register by {0,1,2,3,4}
8427 * when using an extend operation
8430 /*static*/ emitter::code_t emitter::insEncodeExtendScale(ssize_t imm)
8432 assert((imm >= 0) && (imm <= 4));
8434 return (emitter::code_t)imm << 10; // bits 12,11,10
8437 /*****************************************************************************
8439 * Returns the encoding to have the Rm register be auto scaled by the ld/st size
8442 /*static*/ emitter::code_t emitter::insEncodeReg3Scale(bool isScaled)
8446 return 0x00001000; // set the bit at location 12
8454 BYTE* emitter::emitOutputLoadLabel(BYTE* dst, BYTE* srcAddr, BYTE* dstAddr, instrDescJmp* id)
8456 instruction ins = id->idIns();
8457 insFormat fmt = id->idInsFmt();
8458 regNumber dstReg = id->idReg1();
8461 // adr x, [rel addr] -- compute address: current addr(ip) + rel addr.
8462 assert(ins == INS_adr);
8463 assert(fmt == IF_DI_1E);
8464 ssize_t distVal = (ssize_t)(dstAddr - srcAddr);
8465 dst = emitOutputShortAddress(dst, ins, fmt, distVal, dstReg);
8469 // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8470 assert(fmt == IF_LARGEADR);
8471 ssize_t relPageAddr =
8472 (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8473 dst = emitOutputShortAddress(dst, INS_adrp, IF_DI_1E, relPageAddr, dstReg);
8475 // add x, x, page offs -- compute address = page addr + page offs
8476 ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8477 assert(isValidUimm12(imm12));
8479 emitInsCode(INS_add, IF_DI_2A); // DI_2A X0010001shiiiiii iiiiiinnnnnddddd 1100 0000 imm(i12, sh)
8480 code |= insEncodeDatasize(EA_8BYTE); // X
8481 code |= ((code_t)imm12 << 10); // iiiiiiiiiiii
8482 code |= insEncodeReg_Rd(dstReg); // ddddd
8483 code |= insEncodeReg_Rn(dstReg); // nnnnn
8484 dst += emitOutput_Instr(dst, code);
8489 /*****************************************************************************
8491 * Output a local jump or other instruction with a pc-relative immediate.
8492 * Note that this may be invoked to overwrite an existing jump instruction at 'dst'
8493 * to handle forward branch patching.
8496 BYTE* emitter::emitOutputLJ(insGroup* ig, BYTE* dst, instrDesc* i)
8498 instrDescJmp* id = (instrDescJmp*)i;
8507 // Set default ins/fmt from id.
8508 instruction ins = id->idIns();
8509 insFormat fmt = id->idInsFmt();
8511 bool loadLabel = false;
8512 bool isJump = false;
8513 bool loadConstant = false;
8530 loadConstant = true;
8539 /* Figure out the distance to the target */
8541 srcOffs = emitCurCodeOffs(dst);
8542 srcAddr = emitOffsetToPtr(srcOffs);
8544 if (id->idAddr()->iiaIsJitDataOffset())
8546 assert(loadConstant || loadLabel);
8547 int doff = id->idAddr()->iiaGetJitDataOffset();
8549 ssize_t imm = emitGetInsSC(id);
8550 assert((imm >= 0) && (imm < 0x1000)); // 0x1000 is arbitrary, currently 'imm' is always 0
8552 unsigned dataOffs = (unsigned)(doff + imm);
8553 assert(dataOffs < emitDataSize());
8554 dstAddr = emitDataOffsetToPtr(dataOffs);
8556 regNumber dstReg = id->idReg1();
8557 regNumber addrReg = dstReg; // an integer register to compute long address.
8558 emitAttr opSize = id->idOpSize();
8564 // ldr x/v, [rel addr] -- load constant from current addr(ip) + rel addr.
8565 assert(ins == INS_ldr);
8566 assert(fmt == IF_LS_1A);
8567 distVal = (ssize_t)(dstAddr - srcAddr);
8568 dst = emitOutputShortConstant(dst, ins, fmt, distVal, dstReg, opSize);
8572 // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8573 assert(fmt == IF_LARGELDC);
8574 ssize_t relPageAddr =
8575 (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8576 if (isVectorRegister(dstReg))
8578 // Update addrReg with the reserved integer register
8579 // since we cannot use dstReg (vector) to load constant directly from memory.
8580 addrReg = id->idReg2();
8581 assert(isGeneralRegister(addrReg));
8585 dst = emitOutputShortAddress(dst, ins, fmt, relPageAddr, addrReg);
8587 // ldr x, [x, page offs] -- load constant from page address + page offset into integer register.
8588 ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8589 assert(isValidUimm12(imm12));
8592 dst = emitOutputShortConstant(dst, ins, fmt, imm12, addrReg, opSize);
8594 // fmov v, d -- copy constant in integer register to vector register.
8595 // This is needed only for vector constant.
8596 if (addrReg != dstReg)
8598 // fmov Vd,Rn DV_2I X00111100X100111 000000nnnnnddddd 1E27 0000 Vd,Rn
8599 // (scalar, from general)
8600 assert(isVectorRegister(dstReg) && isGeneralRegister(addrReg));
8603 code_t code = emitInsCode(ins, fmt);
8605 code |= insEncodeReg_Vd(dstReg); // ddddd
8606 code |= insEncodeReg_Rn(addrReg); // nnnnn
8607 if (id->idOpSize() == EA_8BYTE)
8609 code |= 0x80400000; // X ... X
8611 dst += emitOutput_Instr(dst, code);
8618 dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8624 assert(loadLabel || isJump);
8626 if (id->idAddr()->iiaHasInstrCount())
8629 int instrCount = id->idAddr()->iiaGetInstrCount();
8630 unsigned insNum = emitFindInsNum(ig, id);
8633 // Backward branches using instruction count must be within the same instruction group.
8634 assert(insNum + 1 >= (unsigned)(-instrCount));
8636 dstOffs = ig->igOffs + emitFindOffset(ig, (insNum + 1 + instrCount));
8637 dstAddr = emitOffsetToPtr(dstOffs);
8641 dstOffs = id->idAddr()->iiaIGlabel->igOffs;
8642 dstAddr = emitOffsetToPtr(dstOffs);
8645 distVal = (ssize_t)(dstAddr - srcAddr);
8647 if (dstOffs <= srcOffs)
8650 /* This is a backward jump - distance is known at this point */
8652 if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8654 size_t blkOffs = id->idjIG->igOffs;
8656 if (INTERESTING_JUMP_NUM == 0)
8657 printf("[3] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8658 printf("[3] Jump block is at %08X - %02X = %08X\n", blkOffs, emitOffsAdj, blkOffs - emitOffsAdj);
8659 printf("[3] Jump is at %08X - %02X = %08X\n", srcOffs, emitOffsAdj, srcOffs - emitOffsAdj);
8660 printf("[3] Label block is at %08X - %02X = %08X\n", dstOffs, emitOffsAdj, dstOffs - emitOffsAdj);
8666 /* This is a forward jump - distance will be an upper limit */
8668 emitFwdJumps = true;
8670 /* The target offset will be closer by at least 'emitOffsAdj', but only if this
8671 jump doesn't cross the hot-cold boundary. */
8673 if (!emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8675 dstOffs -= emitOffsAdj;
8676 distVal -= emitOffsAdj;
8679 /* Record the location of the jump for later patching */
8681 id->idjOffs = dstOffs;
8683 /* Are we overflowing the id->idjOffs bitfield? */
8684 if (id->idjOffs != dstOffs)
8685 IMPL_LIMITATION("Method is too large");
8688 if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8690 size_t blkOffs = id->idjIG->igOffs;
8692 if (INTERESTING_JUMP_NUM == 0)
8693 printf("[4] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8694 printf("[4] Jump block is at %08X\n", blkOffs);
8695 printf("[4] Jump is at %08X\n", srcOffs);
8696 printf("[4] Label block is at %08X - %02X = %08X\n", dstOffs + emitOffsAdj, emitOffsAdj, dstOffs);
8702 if (0 && emitComp->verbose)
8705 int distValSize = id->idjShort ? 4 : 8;
8706 printf("; %s jump [%08X/%03u] from %0*X to %0*X: dist = %08XH\n", (dstOffs <= srcOffs) ? "Fwd" : "Bwd",
8707 dspPtr(id), id->idDebugOnlyInfo()->idNum, distValSize, srcOffs + sz, distValSize, dstOffs, distVal);
8711 /* For forward jumps, record the address of the distance value */
8712 id->idjTemp.idjAddr = (distVal > 0) ? dst : NULL;
8714 if (emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8716 assert(!id->idjShort);
8717 NYI_ARM64("Relocation Support for long address");
8720 assert(insOptsNone(id->idInsOpt()));
8726 // Short conditional/unconditional jump
8727 assert(!id->idjKeepLong);
8728 assert(emitJumpCrossHotColdBoundary(srcOffs, dstOffs) == false);
8729 assert((fmt == IF_BI_0A) || (fmt == IF_BI_0B) || (fmt == IF_BI_1A) || (fmt == IF_BI_1B));
8733 // Long conditional jump
8734 assert(fmt == IF_LARGEJMP);
8735 // This is a pseudo-instruction format representing a large conditional branch, to allow
8736 // us to get a greater branch target range than we can get by using a straightforward conditional
8737 // branch. It is encoded as a short conditional branch that branches around a long unconditional
8740 // Conceptually, we have:
8744 // The code we emit is:
8746 // b<!cond> L_not // 4 bytes. Note that we reverse the condition.
8747 // b L_target // 4 bytes
8750 // Note that we don't actually insert any blocks: we simply encode "b <!cond> L_not" as a branch with
8751 // the correct offset. Note also that this works for both integer and floating-point conditions, because
8752 // the condition inversion takes ordered/unordered into account, preserving NaN behavior. For example,
8753 // "GT" (greater than) is inverted to "LE" (less than, equal, or unordered).
8755 instruction reverseIns;
8756 insFormat reverseFmt;
8761 reverseIns = INS_cbnz;
8762 reverseFmt = IF_BI_1A;
8765 reverseIns = INS_cbz;
8766 reverseFmt = IF_BI_1A;
8769 reverseIns = INS_tbnz;
8770 reverseFmt = IF_BI_1B;
8773 reverseIns = INS_tbz;
8774 reverseFmt = IF_BI_1B;
8777 reverseIns = emitJumpKindToIns(emitReverseJumpKind(emitInsToJumpKind(ins)));
8778 reverseFmt = IF_BI_0B;
8782 emitOutputShortBranch(dst,
8783 reverseIns, // reverse the conditional instruction
8785 8, /* 8 bytes from start of this large conditional pseudo-instruction to L_not. */
8788 // Now, pretend we've got a normal unconditional branch, and fall through to the code to emit that.
8792 // The distVal was computed based on the beginning of the pseudo-instruction,
8793 // So subtract the size of the conditional branch so that it is relative to the
8794 // unconditional branch.
8798 dst = emitOutputShortBranch(dst, ins, fmt, distVal, id);
8802 dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8808 /*****************************************************************************
8810 * Output a short branch instruction.
8812 BYTE* emitter::emitOutputShortBranch(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, instrDescJmp* id)
8814 code_t code = emitInsCode(ins, fmt);
8816 ssize_t loBits = (distVal & 3);
8817 noway_assert(loBits == 0);
8818 distVal >>= 2; // branch offset encodings are scaled by 4.
8820 if (fmt == IF_BI_0A)
8822 // INS_b or INS_bl_local
8823 noway_assert(isValidSimm26(distVal));
8824 distVal &= 0x3FFFFFFLL;
8827 else if (fmt == IF_BI_0B) // BI_0B 01010100iiiiiiii iiiiiiiiiiiXXXXX simm19:00
8829 // INS_beq, INS_bne, etc...
8830 noway_assert(isValidSimm19(distVal));
8831 distVal &= 0x7FFFFLL;
8832 code |= distVal << 5;
8834 else if (fmt == IF_BI_1A) // BI_1A X.......iiiiiiii iiiiiiiiiiittttt Rt simm19:00
8836 // INS_cbz or INS_cbnz
8837 assert(id != nullptr);
8838 code |= insEncodeDatasize(id->idOpSize()); // X
8839 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
8841 noway_assert(isValidSimm19(distVal));
8842 distVal &= 0x7FFFFLL; // 19 bits
8843 code |= distVal << 5;
8845 else if (fmt == IF_BI_1B) // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
8847 // INS_tbz or INS_tbnz
8848 assert(id != nullptr);
8849 ssize_t imm = emitGetInsSC(id);
8850 assert(isValidImmShift(imm, id->idOpSize()));
8852 if (imm & 0x20) // test bit 32-63 ?
8854 code |= 0x80000000; // B
8856 code |= ((imm & 0x1F) << 19); // bbbbb
8857 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
8859 noway_assert(isValidSimm14(distVal));
8860 distVal &= 0x3FFFLL; // 14 bits
8861 code |= distVal << 5;
8865 assert(!"Unknown fmt for emitOutputShortBranch");
8868 dst += emitOutput_Instr(dst, code);
8873 /*****************************************************************************
8875 * Output a short address instruction.
8877 BYTE* emitter::emitOutputShortAddress(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, regNumber reg)
8879 ssize_t loBits = (distVal & 3);
8882 code_t code = emitInsCode(ins, fmt);
8883 if (fmt == IF_DI_1E) // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
8885 // INS_adr or INS_adrp
8886 code |= insEncodeReg_Rd(reg); // ddddd
8888 noway_assert(isValidSimm19(distVal));
8889 distVal &= 0x7FFFFLL; // 19 bits
8890 code |= distVal << 5;
8891 code |= loBits << 29; // 2 bits
8895 assert(!"Unknown fmt for emitOutputShortAddress");
8898 dst += emitOutput_Instr(dst, code);
8903 /*****************************************************************************
8905 * Output a short constant instruction.
8907 BYTE* emitter::emitOutputShortConstant(
8908 BYTE* dst, instruction ins, insFormat fmt, ssize_t imm, regNumber reg, emitAttr opSize)
8910 code_t code = emitInsCode(ins, fmt);
8912 if (fmt == IF_LS_1A)
8914 // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt simm21
8915 // INS_ldr or INS_ldrsw (PC-Relative)
8917 ssize_t loBits = (imm & 3);
8918 noway_assert(loBits == 0);
8919 ssize_t distVal = imm >>= 2; // load offset encodings are scaled by 4.
8921 noway_assert(isValidSimm19(distVal));
8923 // Is the target a vector register?
8924 if (isVectorRegister(reg))
8926 code |= insEncodeDatasizeVLS(code, opSize); // XX V
8927 code |= insEncodeReg_Vt(reg); // ttttt
8931 assert(isGeneralRegister(reg));
8932 // insEncodeDatasizeLS is not quite right for this case.
8933 // So just specialize it.
8934 if ((ins == INS_ldr) && (opSize == EA_8BYTE))
8936 // set the operation size in bit 30
8940 code |= insEncodeReg_Rt(reg); // ttttt
8943 distVal &= 0x7FFFFLL; // 19 bits
8944 code |= distVal << 5;
8946 else if (fmt == IF_LS_2B)
8948 // ldr Rt,[Xn+pimm12] LS_2B 1X11100101iiiiii iiiiiinnnnnttttt B940 0000 imm(0-4095<<{2,3})
8949 // INS_ldr or INS_ldrsw (PC-Relative)
8950 noway_assert(isValidUimm12(imm));
8951 assert(isGeneralRegister(reg));
8953 if (opSize == EA_8BYTE)
8955 // insEncodeDatasizeLS is not quite right for this case.
8956 // So just specialize it.
8959 // set the operation size in bit 30
8962 // Low 3 bits should be 0 -- 8 byte JIT data should be aligned on 8 byte.
8963 assert((imm & 7) == 0);
8968 assert(opSize == EA_4BYTE);
8969 // Low 2 bits should be 0 -- 4 byte aligned data.
8970 assert((imm & 3) == 0);
8974 code |= insEncodeReg_Rt(reg); // ttttt
8975 code |= insEncodeReg_Rn(reg); // nnnnn
8980 assert(!"Unknown fmt for emitOutputShortConstant");
8983 dst += emitOutput_Instr(dst, code);
8987 /*****************************************************************************
8989 * Output a call instruction.
8992 unsigned emitter::emitOutputCall(insGroup* ig, BYTE* dst, instrDesc* id, code_t code)
8994 const unsigned char callInstrSize = sizeof(code_t); // 4 bytes
8995 regMaskTP gcrefRegs;
8996 regMaskTP byrefRegs;
8998 VARSET_TP GCvars(VarSetOps::UninitVal());
9000 // Is this a "fat" call descriptor?
9001 if (id->idIsLargeCall())
9003 instrDescCGCA* idCall = (instrDescCGCA*)id;
9004 gcrefRegs = idCall->idcGcrefRegs;
9005 byrefRegs = idCall->idcByrefRegs;
9006 VarSetOps::Assign(emitComp, GCvars, idCall->idcGCvars);
9010 assert(!id->idIsLargeDsp());
9011 assert(!id->idIsLargeCns());
9013 gcrefRegs = emitDecodeCallGCregs(id);
9015 VarSetOps::AssignNoCopy(emitComp, GCvars, VarSetOps::MakeEmpty(emitComp));
9018 /* We update the GC info before the call as the variables cannot be
9019 used by the call. Killing variables before the call helps with
9020 boundary conditions if the call is CORINFO_HELP_THROW - see bug 50029.
9021 If we ever track aliased variables (which could be used by the
9022 call), we would have to keep them alive past the call. */
9024 emitUpdateLiveGCvars(GCvars, dst);
9026 // Now output the call instruction and update the 'dst' pointer
9028 unsigned outputInstrSize = emitOutput_Instr(dst, code);
9029 dst += outputInstrSize;
9031 // All call instructions are 4-byte in size on ARM64
9033 assert(outputInstrSize == callInstrSize);
9035 // If the method returns a GC ref, mark INTRET (R0) appropriately.
9036 if (id->idGCref() == GCT_GCREF)
9038 gcrefRegs |= RBM_INTRET;
9040 else if (id->idGCref() == GCT_BYREF)
9042 byrefRegs |= RBM_INTRET;
9045 // If is a multi-register return method is called, mark INTRET_1 (X1) appropriately
9046 if (id->idIsLargeCall())
9048 instrDescCGCA* idCall = (instrDescCGCA*)id;
9049 if (idCall->idSecondGCref() == GCT_GCREF)
9051 gcrefRegs |= RBM_INTRET_1;
9053 else if (idCall->idSecondGCref() == GCT_BYREF)
9055 byrefRegs |= RBM_INTRET_1;
9059 // If the GC register set has changed, report the new set.
9060 if (gcrefRegs != emitThisGCrefRegs)
9062 emitUpdateLiveGCregs(GCT_GCREF, gcrefRegs, dst);
9064 // If the Byref register set has changed, report the new set.
9065 if (byrefRegs != emitThisByrefRegs)
9067 emitUpdateLiveGCregs(GCT_BYREF, byrefRegs, dst);
9070 // Some helper calls may be marked as not requiring GC info to be recorded.
9071 if ((!id->idIsNoGC()))
9073 // On ARM64, as on AMD64, we don't change the stack pointer to push/pop args.
9074 // So we're not really doing a "stack pop" here (note that "args" is 0), but we use this mechanism
9075 // to record the call for GC info purposes. (It might be best to use an alternate call,
9076 // and protect "emitStackPop" under the EMIT_TRACK_STACK_DEPTH preprocessor variable.)
9077 emitStackPop(dst, /*isCall*/ true, callInstrSize, /*args*/ 0);
9079 // Do we need to record a call location for GC purposes?
9081 if (!emitFullGCinfo)
9083 emitRecordGCcall(dst, callInstrSize);
9086 return callInstrSize;
9089 /*****************************************************************************
9091 * Emit a 32-bit Arm64 instruction
9094 /*static*/ unsigned emitter::emitOutput_Instr(BYTE* dst, code_t code)
9096 assert(sizeof(code_t) == 4);
9097 *((code_t*)dst) = code;
9099 return sizeof(code_t);
9102 /*****************************************************************************
9104 * Append the machine code corresponding to the given instruction descriptor
9105 * to the code block at '*dp'; the base of the code block is 'bp', and 'ig'
9106 * is the instruction group that contains the instruction. Updates '*dp' to
9107 * point past the generated code, and returns the size of the instruction
9108 * descriptor in bytes.
9111 size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
9116 size_t sz = emitGetInstrDescSize(id); // TODO-ARM64-Cleanup: on ARM, this is set in each case. why?
9117 instruction ins = id->idIns();
9118 insFormat fmt = id->idInsFmt();
9119 emitAttr size = id->idOpSize();
9120 unsigned char callInstrSize = 0;
9125 bool dspOffs = emitComp->opts.dspGCtbls;
9127 bool dspOffs = !emitComp->opts.disDiffable;
9131 assert(REG_NA == (int)REG_NA);
9133 VARSET_TP GCvars(VarSetOps::UninitVal());
9135 /* What instruction format have we got? */
9150 case IF_BI_0A: // BI_0A ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
9151 case IF_BI_0B: // BI_0B ......iiiiiiiiii iiiiiiiiiii..... simm19:00
9153 assert(id->idGCref() == GCT_NONE);
9154 assert(id->idIsBound());
9155 dst = emitOutputLJ(ig, dst, id);
9156 sz = sizeof(instrDescJmp);
9159 case IF_BI_0C: // BI_0C ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
9160 code = emitInsCode(ins, fmt);
9161 sz = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
9162 dst += emitOutputCall(ig, dst, id, code);
9163 // Always call RecordRelocation so that we wire in a JumpStub when we don't reach
9164 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_BRANCH26);
9167 case IF_BI_1A: // BI_1A ......iiiiiiiiii iiiiiiiiiiittttt Rt simm19:00
9168 assert(insOptsNone(id->idInsOpt()));
9169 assert(id->idIsBound());
9171 dst = emitOutputLJ(ig, dst, id);
9172 sz = sizeof(instrDescJmp);
9175 case IF_BI_1B: // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
9176 assert(insOptsNone(id->idInsOpt()));
9177 assert(id->idIsBound());
9179 dst = emitOutputLJ(ig, dst, id);
9180 sz = sizeof(instrDescJmp);
9183 case IF_BR_1A: // BR_1A ................ ......nnnnn..... Rn
9184 assert(insOptsNone(id->idInsOpt()));
9185 assert((ins == INS_ret) || (ins == INS_br));
9186 code = emitInsCode(ins, fmt);
9187 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9189 dst += emitOutput_Instr(dst, code);
9192 case IF_BR_1B: // BR_1B ................ ......nnnnn..... Rn
9193 assert(insOptsNone(id->idInsOpt()));
9194 assert((ins == INS_br_tail) || (ins == INS_blr));
9195 code = emitInsCode(ins, fmt);
9196 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9198 sz = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
9199 dst += emitOutputCall(ig, dst, id, code);
9202 case IF_LS_1A: // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB)
9204 assert(insOptsNone(id->idInsOpt()));
9205 assert(id->idIsBound());
9207 dst = emitOutputLJ(ig, dst, id);
9208 sz = sizeof(instrDescJmp);
9211 case IF_LS_2A: // LS_2A .X.......X...... ......nnnnnttttt Rt Rn
9212 assert(insOptsNone(id->idInsOpt()));
9213 code = emitInsCode(ins, fmt);
9214 // Is the target a vector register?
9215 if (isVectorRegister(id->idReg1()))
9217 code &= 0x3FFFFFFF; // clear the size bits
9218 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9219 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9223 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9224 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9226 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9227 dst += emitOutput_Instr(dst, code);
9230 case IF_LS_2B: // LS_2B .X.......Xiiiiii iiiiiinnnnnttttt Rt Rn imm(0-4095)
9231 assert(insOptsNone(id->idInsOpt()));
9232 imm = emitGetInsSC(id);
9233 assert(isValidUimm12(imm));
9234 code = emitInsCode(ins, fmt);
9235 // Is the target a vector register?
9236 if (isVectorRegister(id->idReg1()))
9238 code &= 0x3FFFFFFF; // clear the size bits
9239 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9240 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9244 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9245 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9247 code |= ((code_t)imm << 10); // iiiiiiiiiiii
9248 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9249 dst += emitOutput_Instr(dst, code);
9252 case IF_LS_2C: // LS_2C .X.......X.iiiii iiiiPPnnnnnttttt Rt Rn imm(-256..+255) no/pre/post inc
9253 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9254 imm = emitGetInsSC(id);
9255 assert((imm >= -256) && (imm <= 255)); // signed 9 bits
9256 imm &= 0x1ff; // force into unsigned 9 bit representation
9257 code = emitInsCode(ins, fmt);
9258 // Is the target a vector register?
9259 if (isVectorRegister(id->idReg1()))
9261 code &= 0x3FFFFFFF; // clear the size bits
9262 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9263 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9267 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9268 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9270 code |= insEncodeIndexedOpt(id->idInsOpt()); // PP
9271 code |= ((code_t)imm << 12); // iiiiiiiii
9272 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9273 dst += emitOutput_Instr(dst, code);
9276 case IF_LS_3A: // LS_3A .X.......X.mmmmm oooS..nnnnnttttt Rt Rn Rm ext(Rm) LSL {}
9277 assert(insOptsLSExtend(id->idInsOpt()));
9278 code = emitInsCode(ins, fmt);
9279 // Is the target a vector register?
9280 if (isVectorRegister(id->idReg1()))
9282 code &= 0x3FFFFFFF; // clear the size bits
9283 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9284 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9288 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9289 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9291 code |= insEncodeExtend(id->idInsOpt()); // ooo
9292 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9293 if (id->idIsLclVar())
9295 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9299 code |= insEncodeReg3Scale(id->idReg3Scaled()); // S
9300 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9302 dst += emitOutput_Instr(dst, code);
9305 case IF_LS_3B: // LS_3B X............... .aaaaannnnnddddd Rd Ra Rn
9306 assert(insOptsNone(id->idInsOpt()));
9307 code = emitInsCode(ins, fmt);
9308 // Is the target a vector register?
9309 if (isVectorRegister(id->idReg1()))
9311 code &= 0x3FFFFFFF; // clear the size bits
9312 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9313 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9314 code |= insEncodeReg_Va(id->idReg2()); // aaaaa
9318 code |= insEncodeDatasize(id->idOpSize()); // X
9319 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9320 code |= insEncodeReg_Ra(id->idReg2()); // aaaaa
9322 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9323 dst += emitOutput_Instr(dst, code);
9326 case IF_LS_3C: // LS_3C X......PP.iiiiii iaaaaannnnnddddd Rd Ra Rn imm(im7,sh)
9327 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9328 imm = emitGetInsSC(id);
9329 assert((imm >= -64) && (imm <= 63)); // signed 7 bits
9330 imm &= 0x7f; // force into unsigned 7 bit representation
9331 code = emitInsCode(ins, fmt);
9332 // Is the target a vector register?
9333 if (isVectorRegister(id->idReg1()))
9335 code &= 0x3FFFFFFF; // clear the size bits
9336 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9337 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9338 code |= insEncodeReg_Va(id->idReg2()); // aaaaa
9342 code |= insEncodeDatasize(id->idOpSize()); // X
9343 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9344 code |= insEncodeReg_Ra(id->idReg2()); // aaaaa
9346 code |= insEncodePairIndexedOpt(ins, id->idInsOpt()); // PP
9347 code |= ((code_t)imm << 15); // iiiiiiiii
9348 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9349 dst += emitOutput_Instr(dst, code);
9352 case IF_LS_3D: // LS_3D .X.......X.mmmmm ......nnnnnttttt Wm Rt Rn
9353 code = emitInsCode(ins, fmt);
9354 // Arm64 store exclusive unpredictable cases
9355 assert(id->idReg1() != id->idReg2());
9356 assert(id->idReg1() != id->idReg3());
9357 code |= insEncodeDatasizeLS(code, id->idOpSize()); // X
9358 code |= insEncodeReg_Rm(id->idReg1()); // mmmmm
9359 code |= insEncodeReg_Rt(id->idReg2()); // ttttt
9360 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9361 dst += emitOutput_Instr(dst, code);
9364 case IF_LS_3E: // LS_3E .X.........mmmmm ......nnnnnttttt Rm Rt Rn ARMv8.1 LSE Atomics
9365 code = emitInsCode(ins, fmt);
9366 code |= insEncodeDatasizeLS(code, id->idOpSize()); // X
9367 code |= insEncodeReg_Rm(id->idReg1()); // mmmmm
9368 code |= insEncodeReg_Rt(id->idReg2()); // ttttt
9369 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9370 dst += emitOutput_Instr(dst, code);
9373 case IF_DI_1A: // DI_1A X.......shiiiiii iiiiiinnnnn..... Rn imm(i12,sh)
9374 assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9375 imm = emitGetInsSC(id);
9376 assert(isValidUimm12(imm));
9377 code = emitInsCode(ins, fmt);
9378 code |= insEncodeDatasize(id->idOpSize()); // X
9379 code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9380 code |= ((code_t)imm << 10); // iiiiiiiiiiii
9381 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9382 dst += emitOutput_Instr(dst, code);
9385 case IF_DI_1B: // DI_1B X........hwiiiii iiiiiiiiiiiddddd Rd imm(i16,hw)
9386 imm = emitGetInsSC(id);
9387 assert(isValidImmHWVal(imm, id->idOpSize()));
9388 code = emitInsCode(ins, fmt);
9389 code |= insEncodeDatasize(id->idOpSize()); // X
9390 code |= ((code_t)imm << 5); // hwiiiii iiiiiiiiiii
9391 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9392 dst += emitOutput_Instr(dst, code);
9395 case IF_DI_1C: // DI_1C X........Nrrrrrr ssssssnnnnn..... Rn imm(N,r,s)
9396 imm = emitGetInsSC(id);
9397 assert(isValidImmNRS(imm, id->idOpSize()));
9398 code = emitInsCode(ins, fmt);
9399 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9400 code |= insEncodeDatasize(id->idOpSize()); // X
9401 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9402 dst += emitOutput_Instr(dst, code);
9405 case IF_DI_1D: // DI_1D X........Nrrrrrr ssssss.....ddddd Rd imm(N,r,s)
9406 imm = emitGetInsSC(id);
9407 assert(isValidImmNRS(imm, id->idOpSize()));
9408 code = emitInsCode(ins, fmt);
9409 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9410 code |= insEncodeDatasize(id->idOpSize()); // X
9411 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9412 dst += emitOutput_Instr(dst, code);
9415 case IF_DI_1E: // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
9417 assert(insOptsNone(id->idInsOpt()));
9418 if (id->idIsReloc())
9420 code = emitInsCode(ins, fmt);
9421 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9422 dst += emitOutput_Instr(dst, code);
9423 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEBASE_REL21);
9427 // Local jmp/load case which does not need a relocation.
9428 assert(id->idIsBound());
9429 dst = emitOutputLJ(ig, dst, id);
9431 sz = sizeof(instrDescJmp);
9434 case IF_DI_1F: // DI_1F X..........iiiii cccc..nnnnn.nzcv Rn imm5 nzcv cond
9435 imm = emitGetInsSC(id);
9436 assert(isValidImmCondFlagsImm5(imm));
9439 cfi.immCFVal = (unsigned)imm;
9440 code = emitInsCode(ins, fmt);
9441 code |= insEncodeDatasize(id->idOpSize()); // X
9442 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9443 code |= ((code_t)cfi.imm5 << 16); // iiiii
9444 code |= insEncodeFlags(cfi.flags); // nzcv
9445 code |= insEncodeCond(cfi.cond); // cccc
9446 dst += emitOutput_Instr(dst, code);
9450 case IF_DI_2A: // DI_2A X.......shiiiiii iiiiiinnnnnddddd Rd Rn imm(i12,sh)
9451 assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9452 imm = emitGetInsSC(id);
9453 assert(isValidUimm12(imm));
9454 code = emitInsCode(ins, fmt);
9455 code |= insEncodeDatasize(id->idOpSize()); // X
9456 code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9457 code |= ((code_t)imm << 10); // iiiiiiiiiiii
9458 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9459 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9460 dst += emitOutput_Instr(dst, code);
9462 if (id->idIsReloc())
9464 assert(sz == sizeof(instrDesc));
9465 assert(id->idAddr()->iiaAddr != nullptr);
9466 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEOFFSET_12A);
9470 case IF_DI_2B: // DI_2B X.........Xnnnnn ssssssnnnnnddddd Rd Rn imm(0-63)
9471 code = emitInsCode(ins, fmt);
9472 imm = emitGetInsSC(id);
9473 assert(isValidImmShift(imm, id->idOpSize()));
9474 code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9475 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9476 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9477 code |= insEncodeReg_Rm(id->idReg2()); // Reg2 also in mmmmm
9478 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9479 dst += emitOutput_Instr(dst, code);
9482 case IF_DI_2C: // DI_2C X........Nrrrrrr ssssssnnnnnddddd Rd Rn imm(N,r,s)
9483 imm = emitGetInsSC(id);
9484 assert(isValidImmNRS(imm, id->idOpSize()));
9485 code = emitInsCode(ins, fmt);
9486 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9487 code |= insEncodeDatasize(id->idOpSize()); // X
9488 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9489 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9490 dst += emitOutput_Instr(dst, code);
9493 case IF_DI_2D: // DI_2D X........Nrrrrrr ssssssnnnnnddddd Rd Rn imr, imms (N,r,s)
9494 if (ins == INS_asr || ins == INS_lsl || ins == INS_lsr)
9496 imm = emitGetInsSC(id);
9497 assert(isValidImmShift(imm, id->idOpSize()));
9499 // Shift immediates are aliases of the SBFM/UBFM instructions
9500 // that actually take 2 registers and 2 constants,
9501 // Since we stored the shift immediate value
9502 // we need to calculate the N,R and S values here.
9507 bmi.immN = (size == EA_8BYTE) ? 1 : 0;
9509 bmi.immS = (size == EA_8BYTE) ? 0x3f : 0x1f;
9511 // immR and immS are now set correctly for INS_asr and INS_lsr
9512 // but for INS_lsl we have to adjust the values for immR and immS
9516 bmi.immR = -imm & bmi.immS;
9517 bmi.immS = bmi.immS - imm;
9520 // setup imm with the proper 13 bit value N:R:S
9526 // The other instructions have already have encoded N,R and S values
9527 imm = emitGetInsSC(id);
9529 assert(isValidImmNRS(imm, id->idOpSize()));
9531 code = emitInsCode(ins, fmt);
9532 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9533 code |= insEncodeDatasize(id->idOpSize()); // X
9534 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9535 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9536 dst += emitOutput_Instr(dst, code);
9539 case IF_DR_1D: // DR_1D X............... cccc.......ddddd Rd cond
9540 imm = emitGetInsSC(id);
9541 assert(isValidImmCond(imm));
9544 cfi.immCFVal = (unsigned)imm;
9545 code = emitInsCode(ins, fmt);
9546 code |= insEncodeDatasize(id->idOpSize()); // X
9547 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9548 code |= insEncodeInvertedCond(cfi.cond); // cccc
9549 dst += emitOutput_Instr(dst, code);
9553 case IF_DR_2A: // DR_2A X..........mmmmm ......nnnnn..... Rn Rm
9554 assert(insOptsNone(id->idInsOpt()));
9555 code = emitInsCode(ins, fmt);
9556 code |= insEncodeDatasize(id->idOpSize()); // X
9557 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9558 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9559 dst += emitOutput_Instr(dst, code);
9562 case IF_DR_2B: // DR_2B X.......sh.mmmmm ssssssnnnnn..... Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
9563 code = emitInsCode(ins, fmt);
9564 imm = emitGetInsSC(id);
9565 assert(isValidImmShift(imm, id->idOpSize()));
9566 code |= insEncodeDatasize(id->idOpSize()); // X
9567 code |= insEncodeShiftType(id->idInsOpt()); // sh
9568 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9569 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9570 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9571 dst += emitOutput_Instr(dst, code);
9574 case IF_DR_2C: // DR_2C X..........mmmmm ooosssnnnnn..... Rn Rm ext(Rm) LSL imm(0-4)
9575 code = emitInsCode(ins, fmt);
9576 imm = emitGetInsSC(id);
9577 assert((imm >= 0) && (imm <= 4)); // imm [0..4]
9578 code |= insEncodeDatasize(id->idOpSize()); // X
9579 code |= insEncodeExtend(id->idInsOpt()); // ooo
9580 code |= insEncodeExtendScale(imm); // sss
9581 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9582 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9583 dst += emitOutput_Instr(dst, code);
9586 case IF_DR_2D: // DR_2D X..........nnnnn cccc..nnnnnddddd Rd Rn cond
9587 imm = emitGetInsSC(id);
9588 assert(isValidImmCond(imm));
9591 cfi.immCFVal = (unsigned)imm;
9592 code = emitInsCode(ins, fmt);
9593 code |= insEncodeDatasize(id->idOpSize()); // X
9594 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9595 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9596 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9597 code |= insEncodeInvertedCond(cfi.cond); // cccc
9598 dst += emitOutput_Instr(dst, code);
9602 case IF_DR_2E: // DR_2E X..........mmmmm ...........ddddd Rd Rm
9603 code = emitInsCode(ins, fmt);
9604 code |= insEncodeDatasize(id->idOpSize()); // X
9605 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9606 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9607 dst += emitOutput_Instr(dst, code);
9610 case IF_DR_2F: // DR_2F X.......sh.mmmmm ssssss.....ddddd Rd Rm {LSL,LSR,ASR} imm(0-63)
9611 code = emitInsCode(ins, fmt);
9612 imm = emitGetInsSC(id);
9613 assert(isValidImmShift(imm, id->idOpSize()));
9614 code |= insEncodeDatasize(id->idOpSize()); // X
9615 code |= insEncodeShiftType(id->idInsOpt()); // sh
9616 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9617 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9618 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9619 dst += emitOutput_Instr(dst, code);
9622 case IF_DR_2G: // DR_2G X............... .....xnnnnnddddd Rd Rn
9623 code = emitInsCode(ins, fmt);
9624 code |= insEncodeDatasize(id->idOpSize()); // X
9627 if (size == EA_8BYTE)
9629 code |= 0x00000400; // x - bit at location 10
9632 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9633 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9634 dst += emitOutput_Instr(dst, code);
9637 case IF_DR_2H: // DR_2H X........X...... ......nnnnnddddd Rd Rn
9638 code = emitInsCode(ins, fmt);
9639 code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9640 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9641 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9642 dst += emitOutput_Instr(dst, code);
9645 case IF_DR_2I: // DR_2I X..........mmmmm cccc..nnnnn.nzcv Rn Rm nzcv cond
9646 imm = emitGetInsSC(id);
9647 assert(isValidImmCondFlags(imm));
9650 cfi.immCFVal = (unsigned)imm;
9651 code = emitInsCode(ins, fmt);
9652 code |= insEncodeDatasize(id->idOpSize()); // X
9653 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9654 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9655 code |= insEncodeFlags(cfi.flags); // nzcv
9656 code |= insEncodeCond(cfi.cond); // cccc
9657 dst += emitOutput_Instr(dst, code);
9661 case IF_DR_2J: // DR_2J ................ ......nnnnnddddd Sd Sn (sha1h)
9662 code = emitInsCode(ins, fmt);
9663 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9664 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9665 dst += emitOutput_Instr(dst, code);
9668 case IF_DR_3A: // DR_3A X..........mmmmm ......nnnnnmmmmm Rd Rn Rm
9669 code = emitInsCode(ins, fmt);
9670 code |= insEncodeDatasize(id->idOpSize()); // X
9671 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9672 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9673 if (id->idIsLclVar())
9675 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9679 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9681 dst += emitOutput_Instr(dst, code);
9684 case IF_DR_3B: // DR_3B X.......sh.mmmmm ssssssnnnnnddddd Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
9685 code = emitInsCode(ins, fmt);
9686 imm = emitGetInsSC(id);
9687 assert(isValidImmShift(imm, id->idOpSize()));
9688 code |= insEncodeDatasize(id->idOpSize()); // X
9689 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9690 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9691 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9692 code |= insEncodeShiftType(id->idInsOpt()); // sh
9693 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9694 dst += emitOutput_Instr(dst, code);
9697 case IF_DR_3C: // DR_3C X..........mmmmm ooosssnnnnnddddd Rd Rn Rm ext(Rm) LSL imm(0-4)
9698 code = emitInsCode(ins, fmt);
9699 imm = emitGetInsSC(id);
9700 assert((imm >= 0) && (imm <= 4)); // imm [0..4]
9701 code |= insEncodeDatasize(id->idOpSize()); // X
9702 code |= insEncodeExtend(id->idInsOpt()); // ooo
9703 code |= insEncodeExtendScale(imm); // sss
9704 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9705 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9706 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9707 dst += emitOutput_Instr(dst, code);
9710 case IF_DR_3D: // DR_3D X..........mmmmm cccc..nnnnnddddd Rd Rn Rm cond
9711 imm = emitGetInsSC(id);
9712 assert(isValidImmCond(imm));
9715 cfi.immCFVal = (unsigned)imm;
9716 code = emitInsCode(ins, fmt);
9717 code |= insEncodeDatasize(id->idOpSize()); // X
9718 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9719 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9720 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9721 code |= insEncodeCond(cfi.cond); // cccc
9722 dst += emitOutput_Instr(dst, code);
9726 case IF_DR_3E: // DR_3E X........X.mmmmm ssssssnnnnnddddd Rd Rn Rm imm(0-63)
9727 code = emitInsCode(ins, fmt);
9728 imm = emitGetInsSC(id);
9729 assert(isValidImmShift(imm, id->idOpSize()));
9730 code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9731 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9732 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9733 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9734 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9735 dst += emitOutput_Instr(dst, code);
9738 case IF_DR_4A: // DR_4A X..........mmmmm .aaaaannnnnmmmmm Rd Rn Rm Ra
9739 code = emitInsCode(ins, fmt);
9740 code |= insEncodeDatasize(id->idOpSize()); // X
9741 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9742 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9743 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9744 code |= insEncodeReg_Ra(id->idReg4()); // aaaaa
9745 dst += emitOutput_Instr(dst, code);
9748 case IF_DV_1A: // DV_1A .........X.iiiii iii........ddddd Vd imm8 (fmov - immediate scalar)
9749 imm = emitGetInsSC(id);
9750 elemsize = id->idOpSize();
9751 code = emitInsCode(ins, fmt);
9752 code |= insEncodeFloatElemsize(elemsize); // X
9753 code |= ((code_t)imm << 13); // iiiii iii
9754 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9755 dst += emitOutput_Instr(dst, code);
9758 case IF_DV_1B: // DV_1B .QX..........iii cmod..iiiiiddddd Vd imm8 (immediate vector)
9759 imm = emitGetInsSC(id) & 0x0ff;
9760 immShift = (emitGetInsSC(id) & 0x700) >> 8;
9761 elemsize = optGetElemsize(id->idInsOpt());
9766 cmode = 0xE; // 1110
9770 cmode |= (immShift << 1); // 10x0
9776 cmode |= (immShift << 1); // 0xx0
9786 cmode = 0xE; // 1110
9793 code = emitInsCode(ins, fmt);
9794 code |= insEncodeVectorsize(id->idOpSize()); // Q
9795 if ((ins == INS_fmov) || (ins == INS_movi))
9797 if (elemsize == EA_8BYTE)
9799 code |= 0x20000000; // X
9802 if (ins != INS_fmov)
9804 assert((cmode >= 0) && (cmode <= 0xF));
9805 code |= (cmode << 12); // cmod
9807 code |= (((code_t)imm >> 5) << 16); // iii
9808 code |= (((code_t)imm & 0x1f) << 5); // iiiii
9809 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9810 dst += emitOutput_Instr(dst, code);
9813 case IF_DV_1C: // DV_1C .........X...... ......nnnnn..... Vn #0.0 (fcmp - with zero)
9814 elemsize = id->idOpSize();
9815 code = emitInsCode(ins, fmt);
9816 code |= insEncodeFloatElemsize(elemsize); // X
9817 code |= insEncodeReg_Vn(id->idReg1()); // nnnnn
9818 dst += emitOutput_Instr(dst, code);
9821 case IF_DV_2A: // DV_2A .Q.......X...... ......nnnnnddddd Vd Vn (fabs, fcvt - vector)
9822 elemsize = optGetElemsize(id->idInsOpt());
9823 code = emitInsCode(ins, fmt);
9824 code |= insEncodeVectorsize(id->idOpSize()); // Q
9825 code |= insEncodeFloatElemsize(elemsize); // X
9826 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9827 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9828 dst += emitOutput_Instr(dst, code);
9831 case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov/smov - to general)
9832 elemsize = id->idOpSize();
9833 index = emitGetInsSC(id);
9834 datasize = (elemsize == EA_8BYTE) ? EA_16BYTE : EA_8BYTE;
9835 if (ins == INS_smov)
9837 datasize = EA_16BYTE;
9839 code = emitInsCode(ins, fmt);
9840 code |= insEncodeVectorsize(datasize); // Q
9841 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9842 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9843 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9844 dst += emitOutput_Instr(dst, code);
9847 case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
9850 datasize = id->idOpSize();
9851 elemsize = optGetElemsize(id->idInsOpt());
9856 datasize = EA_16BYTE;
9857 elemsize = id->idOpSize();
9858 index = emitGetInsSC(id);
9860 code = emitInsCode(ins, fmt);
9861 code |= insEncodeVectorsize(datasize); // Q
9862 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9863 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9864 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9865 dst += emitOutput_Instr(dst, code);
9868 case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
9869 index = emitGetInsSC(id);
9870 elemsize = optGetElemsize(id->idInsOpt());
9871 code = emitInsCode(ins, fmt);
9872 code |= insEncodeVectorsize(id->idOpSize()); // Q
9873 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9874 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9875 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9876 dst += emitOutput_Instr(dst, code);
9879 case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
9880 index = emitGetInsSC(id);
9881 elemsize = id->idOpSize();
9882 code = emitInsCode(ins, fmt);
9883 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9884 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9885 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9886 dst += emitOutput_Instr(dst, code);
9889 case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
9890 elemsize = id->idOpSize();
9891 imm = emitGetInsSC(id);
9892 index = (imm >> 4) & 0xf;
9894 code = emitInsCode(ins, fmt);
9895 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9896 code |= insEncodeVectorIndex2(elemsize, index2); // jjjj
9897 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9898 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9899 dst += emitOutput_Instr(dst, code);
9902 case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov,fcvtXX - register)
9903 elemsize = id->idOpSize();
9904 code = emitInsCode(ins, fmt);
9905 code |= insEncodeFloatElemsize(elemsize); // X
9906 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9907 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9908 dst += emitOutput_Instr(dst, code);
9911 case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov - to general)
9912 elemsize = id->idOpSize();
9913 code = emitInsCode(ins, fmt);
9914 code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X X
9915 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9916 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9917 dst += emitOutput_Instr(dst, code);
9920 case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov - from general)
9921 elemsize = id->idOpSize();
9922 code = emitInsCode(ins, fmt);
9923 code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X X
9924 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9925 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9926 dst += emitOutput_Instr(dst, code);
9929 case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
9930 code = emitInsCode(ins, fmt);
9931 code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // SS DD
9932 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9933 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9934 dst += emitOutput_Instr(dst, code);
9937 case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
9938 elemsize = id->idOpSize();
9939 code = emitInsCode(ins, fmt);
9940 code |= insEncodeFloatElemsize(elemsize); // X
9941 code |= insEncodeReg_Vn(id->idReg1()); // nnnnn
9942 code |= insEncodeReg_Vm(id->idReg2()); // mmmmm
9943 dst += emitOutput_Instr(dst, code);
9946 case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
9947 elemsize = id->idOpSize();
9948 code = emitInsCode(ins, fmt);
9949 code |= insEncodeElemsize(elemsize); // XX
9950 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9951 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9952 dst += emitOutput_Instr(dst, code);
9955 case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
9956 elemsize = optGetElemsize(id->idInsOpt());
9957 code = emitInsCode(ins, fmt);
9958 code |= insEncodeVectorsize(id->idOpSize()); // Q
9959 code |= insEncodeElemsize(elemsize); // XX
9960 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9961 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9962 dst += emitOutput_Instr(dst, code);
9965 case IF_DV_2N: // DV_2N .........iiiiiii ......nnnnnddddd Vd Vn imm (shift - scalar)
9966 imm = emitGetInsSC(id);
9967 code = emitInsCode(ins, fmt);
9968 code |= insEncodeVectorShift(EA_8BYTE, imm); // iiiiiii
9969 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9970 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9971 dst += emitOutput_Instr(dst, code);
9974 case IF_DV_2O: // DV_2O .Q.......iiiiiii ......nnnnnddddd Vd Vn imm (shift - vector)
9975 imm = emitGetInsSC(id);
9976 elemsize = optGetElemsize(id->idInsOpt());
9977 code = emitInsCode(ins, fmt);
9978 code |= insEncodeVectorsize(id->idOpSize()); // Q
9979 code |= insEncodeVectorShift(elemsize, imm); // iiiiiii
9980 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9981 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9982 dst += emitOutput_Instr(dst, code);
9985 case IF_DV_2P: // DV_2P ............... ......nnnnnddddd Vd Vn (aes*, sha1su1)
9986 elemsize = optGetElemsize(id->idInsOpt());
9987 code = emitInsCode(ins, fmt);
9988 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9989 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9990 dst += emitOutput_Instr(dst, code);
9993 case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
9994 code = emitInsCode(ins, fmt);
9995 elemsize = optGetElemsize(id->idInsOpt());
9996 code |= insEncodeVectorsize(id->idOpSize()); // Q
9997 code |= insEncodeElemsize(elemsize); // XX
9998 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9999 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
10000 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
10001 dst += emitOutput_Instr(dst, code);
10004 case IF_DV_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector)
10005 code = emitInsCode(ins, fmt);
10006 imm = emitGetInsSC(id);
10007 elemsize = optGetElemsize(id->idInsOpt());
10008 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
10009 code |= insEncodeVectorsize(id->idOpSize()); // Q
10010 code |= insEncodeElemsize(elemsize); // XX
10011 code |= insEncodeVectorIndexLMH(elemsize, imm); // LM H
10012 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
10013 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
10014 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
10015 dst += emitOutput_Instr(dst, code);
10018 case IF_DV_3B: // DV_3B .Q.......X.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
10019 code = emitInsCode(ins, fmt);
10020 elemsize = optGetElemsize(id->idInsOpt());
10021 code |= insEncodeVectorsize(id->idOpSize()); // Q
10022 code |= insEncodeFloatElemsize(elemsize); // X
10023 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
10024 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
10025 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
10026 dst += emitOutput_Instr(dst, code);
10029 case IF_DV_3BI: // DV_3BI .Q.......XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
10030 code = emitInsCode(ins, fmt);
10031 imm = emitGetInsSC(id);
10032 elemsize = optGetElemsize(id->idInsOpt());
10033 assert(isValidVectorIndex(id->idOpSize(), elemsize, imm));
10034 code |= insEncodeVectorsize(id->idOpSize()); // Q
10035 code |= insEncodeFloatElemsize(elemsize); // X
10036 code |= insEncodeFloatIndex(elemsize, imm); // L H
10037 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
10038 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
10039 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
10040 dst += emitOutput_Instr(dst, code);
10043 case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
10044 code = emitInsCode(ins, fmt);
10045 code |= insEncodeVectorsize(id->idOpSize()); // Q
10046 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
10047 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
10048 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
10049 dst += emitOutput_Instr(dst, code);
10052 case IF_DV_3D: // DV_3D .........X.mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
10053 code = emitInsCode(ins, fmt);
10054 code |= insEncodeFloatElemsize(id->idOpSize()); // X
10055 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
10056 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
10057 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
10058 dst += emitOutput_Instr(dst, code);
10061 case IF_DV_3DI: // DV_3DI .........XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (scalar by elem)
10062 code = emitInsCode(ins, fmt);
10063 imm = emitGetInsSC(id);
10064 elemsize = id->idOpSize();
10065 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
10066 code |= insEncodeFloatElemsize(elemsize); // X
10067 code |= insEncodeFloatIndex(elemsize, imm); // L H
10068 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
10069 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
10070 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
10071 dst += emitOutput_Instr(dst, code);
10074 case IF_DV_3E: // DV_3E ...........mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
10075 case IF_DV_3F: // DV_3F ...........mmmmm ......nnnnnddddd Vd Vn Vm (vector) - source dest regs overlap
10076 code = emitInsCode(ins, fmt);
10077 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
10078 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
10079 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
10080 dst += emitOutput_Instr(dst, code);
10083 case IF_DV_4A: // DV_4A .........X.mmmmm .aaaaannnnnddddd Vd Va Vn Vm (scalar)
10084 code = emitInsCode(ins, fmt);
10085 elemsize = id->idOpSize();
10086 code |= insEncodeFloatElemsize(elemsize); // X
10087 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
10088 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
10089 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
10090 code |= insEncodeReg_Va(id->idReg4()); // aaaaa
10091 dst += emitOutput_Instr(dst, code);
10094 case IF_SN_0A: // SN_0A ................ ................
10095 code = emitInsCode(ins, fmt);
10096 dst += emitOutput_Instr(dst, code);
10099 case IF_SI_0A: // SI_0A ...........iiiii iiiiiiiiiii..... imm16
10100 imm = emitGetInsSC(id);
10101 assert(isValidUimm16(imm));
10102 code = emitInsCode(ins, fmt);
10103 code |= ((code_t)imm << 5); // iiiii iiiiiiiiiii
10104 dst += emitOutput_Instr(dst, code);
10107 case IF_SI_0B: // SI_0B ................ ....bbbb........ imm4 - barrier
10108 imm = emitGetInsSC(id);
10109 assert((imm >= 0) && (imm <= 15));
10110 code = emitInsCode(ins, fmt);
10111 code |= ((code_t)imm << 8); // bbbb
10112 dst += emitOutput_Instr(dst, code);
10116 assert(!"Unexpected format");
10120 // Determine if any registers now hold GC refs, or whether a register that was overwritten held a GC ref.
10121 // We assume here that "id->idGCref()" is not GC_NONE only if the instruction described by "id" writes a
10122 // GC ref to register "id->idReg1()". (It may, apparently, also not be GC_NONE in other cases, such as
10123 // for stores, but we ignore those cases here.)
10124 if (emitInsMayWriteToGCReg(id)) // True if "id->idIns()" writes to a register than can hold GC ref.
10126 // We assume that "idReg1" is the primary destination register for all instructions
10127 if (id->idGCref() != GCT_NONE)
10129 emitGCregLiveUpd(id->idGCref(), id->idReg1(), dst);
10133 emitGCregDeadUpd(id->idReg1(), dst);
10136 if (emitInsMayWriteMultipleRegs(id))
10139 // "idReg2" is the secondary destination register
10140 if (id->idGCrefReg2() != GCT_NONE)
10142 emitGCregLiveUpd(id->idGCrefReg2(), id->idReg2(), dst);
10146 emitGCregDeadUpd(id->idReg2(), dst);
10151 // Now we determine if the instruction has written to a (local variable) stack location, and either written a GC
10152 // ref or overwritten one.
10153 if (emitInsWritesToLclVarStackLoc(id) || emitInsWritesToLclVarStackLocPair(id))
10155 int varNum = id->idAddr()->iiaLclVar.lvaVarNum();
10156 unsigned ofs = AlignDown(id->idAddr()->iiaLclVar.lvaOffset(), TARGET_POINTER_SIZE);
10158 int adr = emitComp->lvaFrameAddress(varNum, &FPbased);
10159 if (id->idGCref() != GCT_NONE)
10161 emitGCvarLiveUpd(adr + ofs, varNum, id->idGCref(), dst);
10165 // If the type of the local is a gc ref type, update the liveness.
10169 // "Regular" (non-spill-temp) local.
10170 vt = var_types(emitComp->lvaTable[varNum].lvType);
10174 TempDsc* tmpDsc = emitComp->tmpFindNum(varNum);
10175 vt = tmpDsc->tdTempType();
10177 if (vt == TYP_REF || vt == TYP_BYREF)
10178 emitGCvarDeadUpd(adr + ofs, dst);
10180 if (emitInsWritesToLclVarStackLocPair(id))
10182 unsigned ofs2 = ofs + TARGET_POINTER_SIZE;
10183 if (id->idGCrefReg2() != GCT_NONE)
10185 emitGCvarLiveUpd(adr + ofs2, varNum, id->idGCrefReg2(), dst);
10189 // If the type of the local is a gc ref type, update the liveness.
10193 // "Regular" (non-spill-temp) local.
10194 vt = var_types(emitComp->lvaTable[varNum].lvType);
10198 TempDsc* tmpDsc = emitComp->tmpFindNum(varNum);
10199 vt = tmpDsc->tdTempType();
10201 if (vt == TYP_REF || vt == TYP_BYREF)
10202 emitGCvarDeadUpd(adr + ofs2, dst);
10208 /* Make sure we set the instruction descriptor size correctly */
10210 size_t expected = emitSizeOfInsDsc(id);
10211 assert(sz == expected);
10213 if (emitComp->opts.disAsm || emitComp->opts.dspEmit || emitComp->verbose)
10215 emitDispIns(id, false, dspOffs, true, emitCurCodeOffs(odst), *dp, (dst - *dp), ig);
10218 if (emitComp->compDebugBreak)
10220 // For example, set JitBreakEmitOutputInstr=a6 will break when this method is called for
10221 // emitting instruction a6, (i.e. IN00a6 in jitdump).
10222 if ((unsigned)JitConfig.JitBreakEmitOutputInstr() == id->idDebugOnlyInfo()->idNum)
10224 assert(!"JitBreakEmitOutputInstr reached");
10229 /* All instructions are expected to generate code */
10231 assert(*dp != dst);
10238 /*****************************************************************************/
10239 /*****************************************************************************/
10243 /*****************************************************************************
10245 * Display the instruction name
10247 void emitter::emitDispInst(instruction ins)
10249 const char* insstr = codeGen->genInsName(ins);
10250 size_t len = strlen(insstr);
10252 /* Display the instruction name */
10254 printf("%s", insstr);
10257 // Add at least one space after the instruction name
10258 // and add spaces until we have reach the normal size of 8
10266 /*****************************************************************************
10268 * Display an reloc value
10269 * If we are formatting for an assembly listing don't print the hex value
10270 * since it will prevent us from doing assembly diffs
10272 void emitter::emitDispReloc(int value, bool addComma)
10274 if (emitComp->opts.disAsm)
10280 printf("(reloc 0x%x)", dspPtr(value));
10287 /*****************************************************************************
10289 * Display an immediate value
10291 void emitter::emitDispImm(ssize_t imm, bool addComma, bool alwaysHex /* =false */)
10298 // Munge any pointers if we want diff-able disassembly.
10299 // Since some may be emitted as partial words, print as diffable anything that has
10300 // significant bits beyond the lowest 8-bits.
10301 if (emitComp->opts.disDiffable)
10303 ssize_t top56bits = (imm >> 8);
10304 if ((top56bits != 0) && (top56bits != -1))
10308 if (!alwaysHex && (imm > -1000) && (imm < 1000))
10314 if ((imm < 0) && ((imm & 0xFFFFFFFF00000000LL) == 0xFFFFFFFF00000000LL))
10320 if ((imm & 0xFFFFFFFF00000000LL) != 0)
10322 printf("0x%llx", imm);
10326 printf("0x%02x", imm);
10334 /*****************************************************************************
10336 * Display a float zero constant
10338 void emitter::emitDispFloatZero()
10347 /*****************************************************************************
10349 * Display an encoded float constant value
10351 void emitter::emitDispFloatImm(ssize_t imm8)
10353 assert((0 <= imm8) && (imm8 <= 0x0ff));
10360 fpImm.immFPIVal = (unsigned)imm8;
10361 double result = emitDecodeFloatImm8(fpImm);
10363 printf("%.4f", result);
10366 /*****************************************************************************
10368 * Display an immediate that is optionally LSL12.
10370 void emitter::emitDispImmOptsLSL12(ssize_t imm, insOpts opt)
10372 if (!strictArmAsm && insOptsLSL12(opt))
10376 emitDispImm(imm, false);
10377 if (strictArmAsm && insOptsLSL12(opt))
10379 printf(", LSL #12");
10383 /*****************************************************************************
10385 * Display an ARM64 condition code for the conditional instructions
10387 void emitter::emitDispCond(insCond cond)
10389 const static char* armCond[16] = {"eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc",
10390 "hi", "ls", "ge", "lt", "gt", "le", "AL", "NV"}; // The last two are invalid
10391 unsigned imm = (unsigned)cond;
10392 assert((0 <= imm) && (imm < ArrLen(armCond)));
10393 printf(armCond[imm]);
10396 /*****************************************************************************
10398 * Display an ARM64 flags for the conditional instructions
10400 void emitter::emitDispFlags(insCflags flags)
10402 const static char* armFlags[16] = {"0", "v", "c", "cv", "z", "zv", "zc", "zcv",
10403 "n", "nv", "nc", "ncv", "nz", "nzv", "nzc", "nzcv"};
10404 unsigned imm = (unsigned)flags;
10405 assert((0 <= imm) && (imm < ArrLen(armFlags)));
10406 printf(armFlags[imm]);
10409 /*****************************************************************************
10411 * Display an ARM64 'barrier' for the memory barrier instructions
10413 void emitter::emitDispBarrier(insBarrier barrier)
10415 const static char* armBarriers[16] = {"#0", "oshld", "oshst", "osh", "#4", "nshld", "nshst", "nsh",
10416 "#8", "ishld", "ishst", "ish", "#12", "ld", "st", "sy"};
10417 unsigned imm = (unsigned)barrier;
10418 assert((0 <= imm) && (imm < ArrLen(armBarriers)));
10419 printf(armBarriers[imm]);
10422 /*****************************************************************************
10424 * Prints the encoding for the Shift Type encoding
10427 void emitter::emitDispShiftOpts(insOpts opt)
10429 if (opt == INS_OPTS_LSL)
10431 else if (opt == INS_OPTS_LSR)
10433 else if (opt == INS_OPTS_ASR)
10435 else if (opt == INS_OPTS_ROR)
10437 else if (opt == INS_OPTS_MSL)
10440 assert(!"Bad value");
10443 /*****************************************************************************
10445 * Prints the encoding for the Extend Type encoding
10448 void emitter::emitDispExtendOpts(insOpts opt)
10450 if (opt == INS_OPTS_UXTB)
10452 else if (opt == INS_OPTS_UXTH)
10454 else if (opt == INS_OPTS_UXTW)
10456 else if (opt == INS_OPTS_UXTX)
10458 else if (opt == INS_OPTS_SXTB)
10460 else if (opt == INS_OPTS_SXTH)
10462 else if (opt == INS_OPTS_SXTW)
10464 else if (opt == INS_OPTS_SXTX)
10467 assert(!"Bad value");
10470 /*****************************************************************************
10472 * Prints the encoding for the Extend Type encoding in loads/stores
10475 void emitter::emitDispLSExtendOpts(insOpts opt)
10477 if (opt == INS_OPTS_LSL)
10479 else if (opt == INS_OPTS_UXTW)
10481 else if (opt == INS_OPTS_UXTX)
10483 else if (opt == INS_OPTS_SXTW)
10485 else if (opt == INS_OPTS_SXTX)
10488 assert(!"Bad value");
10491 /*****************************************************************************
10493 * Display a register
10495 void emitter::emitDispReg(regNumber reg, emitAttr attr, bool addComma)
10497 emitAttr size = EA_SIZE(attr);
10498 printf(emitRegName(reg, size));
10504 /*****************************************************************************
10506 * Display a vector register with an arrangement suffix
10508 void emitter::emitDispVectorReg(regNumber reg, insOpts opt, bool addComma)
10510 assert(isVectorRegister(reg));
10511 printf(emitVectorRegName(reg));
10512 emitDispArrangement(opt);
10518 /*****************************************************************************
10520 * Display an vector register index suffix
10522 void emitter::emitDispVectorRegIndex(regNumber reg, emitAttr elemsize, ssize_t index, bool addComma)
10524 assert(isVectorRegister(reg));
10525 printf(emitVectorRegName(reg));
10542 assert(!"invalid elemsize");
10546 printf("[%d]", index);
10552 /*****************************************************************************
10554 * Display an arrangement suffix
10556 void emitter::emitDispArrangement(insOpts opt)
10558 const char* str = "???";
10588 assert(!"Invalid insOpt for vector register");
10594 /*****************************************************************************
10596 * Display a register with an optional shift operation
10598 void emitter::emitDispShiftedReg(regNumber reg, insOpts opt, ssize_t imm, emitAttr attr)
10600 emitAttr size = EA_SIZE(attr);
10601 assert((imm & 0x003F) == imm);
10602 assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
10604 printf(emitRegName(reg, size));
10612 emitDispShiftOpts(opt);
10613 emitDispImm(imm, false);
10617 /*****************************************************************************
10619 * Display a register with an optional extend and scale operations
10621 void emitter::emitDispExtendReg(regNumber reg, insOpts opt, ssize_t imm)
10623 assert((imm >= 0) && (imm <= 4));
10624 assert(insOptsNone(opt) || insOptsAnyExtend(opt) || (opt == INS_OPTS_LSL));
10626 // size is based on the extend option, not the instr size.
10627 emitAttr size = insOpts32BitExtend(opt) ? EA_4BYTE : EA_8BYTE;
10631 if (insOptsNone(opt))
10633 emitDispReg(reg, size, false);
10637 emitDispReg(reg, size, true);
10638 if (opt == INS_OPTS_LSL)
10641 emitDispExtendOpts(opt);
10642 if ((imm > 0) || (opt == INS_OPTS_LSL))
10645 emitDispImm(imm, false);
10649 else // !strictArmAsm
10651 if (insOptsNone(opt))
10653 emitDispReg(reg, size, false);
10657 if (opt != INS_OPTS_LSL)
10659 emitDispExtendOpts(opt);
10661 emitDispReg(reg, size, false);
10668 emitDispImm(1 << imm, false);
10673 /*****************************************************************************
10675 * Display an addressing operand [reg + imm]
10677 void emitter::emitDispAddrRI(regNumber reg, insOpts opt, ssize_t imm)
10679 reg = encodingZRtoSP(reg); // ZR (R31) encodes the SP register
10685 emitDispReg(reg, EA_8BYTE, false);
10687 if (!insOptsPostIndex(opt) && (imm != 0))
10690 emitDispImm(imm, false);
10694 if (insOptsPreIndex(opt))
10698 else if (insOptsPostIndex(opt))
10701 emitDispImm(imm, false);
10704 else // !strictArmAsm
10708 const char* operStr = "++";
10715 if (insOptsPreIndex(opt))
10720 emitDispReg(reg, EA_8BYTE, false);
10722 if (insOptsPostIndex(opt))
10727 if (insOptsIndexed(opt))
10733 printf("%c", operStr[1]);
10735 emitDispImm(imm, false);
10740 /*****************************************************************************
10742 * Display an addressing operand [reg + extended reg]
10744 void emitter::emitDispAddrRRExt(regNumber reg1, regNumber reg2, insOpts opt, bool isScaled, emitAttr size)
10746 reg1 = encodingZRtoSP(reg1); // ZR (R31) encodes the SP register
10748 unsigned scale = 0;
10751 scale = NaturalScale_helper(size);
10758 emitDispReg(reg1, EA_8BYTE, true);
10759 emitDispExtendReg(reg2, opt, scale);
10761 else // !strictArmAsm
10763 emitDispReg(reg1, EA_8BYTE, false);
10765 emitDispExtendReg(reg2, opt, scale);
10771 /*****************************************************************************
10773 * Display (optionally) the instruction encoding in hex
10776 void emitter::emitDispInsHex(BYTE* code, size_t sz)
10778 // We do not display the instruction hex if we want diff-able disassembly
10779 if (!emitComp->opts.disDiffable)
10783 printf(" %08X ", (*((code_t*)code)));
10792 /****************************************************************************
10794 * Display the given instruction.
10797 void emitter::emitDispIns(
10798 instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* pCode, size_t sz, insGroup* ig)
10803 id->idDebugOnlyInfo()->idNum; // Do not remove this! It is needed for VisualStudio conditional breakpoints
10805 printf("IN%04x: ", idNum);
10811 if (!emitComp->opts.dspEmit && !isNew && !asmfm && sz)
10814 /* Display the instruction offset */
10816 emitDispInsOffs(offset, doffs);
10818 /* Display the instruction hex code */
10820 emitDispInsHex(pCode, sz);
10824 /* Get the instruction and format */
10826 instruction ins = id->idIns();
10827 insFormat fmt = id->idInsFmt();
10831 /* If this instruction has just been added, check its size */
10833 assert(isNew == false || (int)emitSizeOfInsDsc(id) == emitCurIGfreeNext - (BYTE*)id);
10835 /* Figure out the operand size */
10836 emitAttr size = id->idOpSize();
10837 emitAttr attr = size;
10838 if (id->idGCref() == GCT_GCREF)
10840 else if (id->idGCref() == GCT_BYREF)
10848 bool isExtendAlias;
10857 const char* methodName;
10865 case IF_BI_0A: // BI_0A ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
10866 case IF_BI_0B: // BI_0B ......iiiiiiiiii iiiiiiiiiii..... simm19:00
10869 if (fmt == IF_LARGEJMP)
10871 printf("(LARGEJMP)");
10873 if (id->idAddr()->iiaHasInstrCount())
10875 int instrCount = id->idAddr()->iiaGetInstrCount();
10879 printf("pc%s%d instructions", (instrCount >= 0) ? "+" : "", instrCount);
10883 unsigned insNum = emitFindInsNum(ig, id);
10884 UNATIVE_OFFSET srcOffs = ig->igOffs + emitFindOffset(ig, insNum + 1);
10885 UNATIVE_OFFSET dstOffs = ig->igOffs + emitFindOffset(ig, insNum + 1 + instrCount);
10886 ssize_t relOffs = (ssize_t)(emitOffsetToPtr(dstOffs) - emitOffsetToPtr(srcOffs));
10887 printf("pc%s%d (%d instructions)", (relOffs >= 0) ? "+" : "", relOffs, instrCount);
10890 else if (id->idIsBound())
10892 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10896 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10901 case IF_BI_0C: // BI_0C ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
10902 if (id->idIsCallAddr())
10904 offs = (ssize_t)id->idAddr()->iiaAddr;
10910 methodName = emitComp->eeGetMethodFullName((CORINFO_METHOD_HANDLE)id->idDebugOnlyInfo()->idMemCookie);
10915 if (id->idIsDspReloc())
10917 printf("%08X", offs);
10921 printf("%s", methodName);
10925 case IF_BI_1A: // BI_1A ......iiiiiiiiii iiiiiiiiiiittttt Rt simm19:00
10926 assert(insOptsNone(id->idInsOpt()));
10927 emitDispReg(id->idReg1(), size, true);
10928 if (id->idIsBound())
10930 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10934 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10938 case IF_BI_1B: // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
10939 assert(insOptsNone(id->idInsOpt()));
10940 emitDispReg(id->idReg1(), size, true);
10941 emitDispImm(emitGetInsSC(id), true);
10942 if (id->idIsBound())
10944 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10948 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10952 case IF_BR_1A: // BR_1A ................ ......nnnnn..... Rn
10953 assert(insOptsNone(id->idInsOpt()));
10954 emitDispReg(id->idReg1(), size, false);
10957 case IF_BR_1B: // BR_1B ................ ......nnnnn..... Rn
10958 assert(insOptsNone(id->idInsOpt()));
10959 emitDispReg(id->idReg3(), size, false);
10962 case IF_LS_1A: // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB)
10963 case IF_DI_1E: // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
10966 assert(insOptsNone(id->idInsOpt()));
10967 emitDispReg(id->idReg1(), size, true);
10968 imm = emitGetInsSC(id);
10970 /* Is this actually a reference to a data section? */
10971 if (fmt == IF_LARGEADR)
10973 printf("(LARGEADR)");
10975 else if (fmt == IF_LARGELDC)
10977 printf("(LARGELDC)");
10981 if (id->idAddr()->iiaIsJitDataOffset())
10983 doffs = Compiler::eeGetJitDataOffs(id->idAddr()->iiaFieldHnd);
10984 /* Display a data section reference */
10987 printf("@CNS%02u", doffs - 1);
10989 printf("@RWD%02u", doffs);
10992 printf("%+Id", imm);
10997 if (id->idIsReloc())
11000 emitDispImm((ssize_t)id->idAddr()->iiaAddr, false);
11002 else if (id->idIsBound())
11004 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
11008 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
11014 case IF_LS_2A: // LS_2A .X.......X...... ......nnnnnttttt Rt Rn
11015 assert(insOptsNone(id->idInsOpt()));
11016 assert(emitGetInsSC(id) == 0);
11017 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
11018 emitDispAddrRI(id->idReg2(), id->idInsOpt(), 0);
11021 case IF_LS_2B: // LS_2B .X.......Xiiiiii iiiiiinnnnnttttt Rt Rn imm(0-4095)
11022 assert(insOptsNone(id->idInsOpt()));
11023 imm = emitGetInsSC(id);
11024 scale = NaturalScale_helper(emitInsLoadStoreSize(id));
11025 imm <<= scale; // The immediate is scaled by the size of the ld/st
11026 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
11027 emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
11030 case IF_LS_2C: // LS_2C .X.......X.iiiii iiiiPPnnnnnttttt Rt Rn imm(-256..+255) no/pre/post inc
11031 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
11032 imm = emitGetInsSC(id);
11033 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
11034 emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
11037 case IF_LS_3A: // LS_3A .X.......X.mmmmm oooS..nnnnnttttt Rt Rn Rm ext(Rm) LSL {}
11038 assert(insOptsLSExtend(id->idInsOpt()));
11039 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
11040 if (id->idIsLclVar())
11042 emitDispAddrRRExt(id->idReg2(), codeGen->rsGetRsvdReg(), id->idInsOpt(), false, size);
11046 emitDispAddrRRExt(id->idReg2(), id->idReg3(), id->idInsOpt(), id->idReg3Scaled(), size);
11050 case IF_LS_3B: // LS_3B X............... .aaaaannnnnddddd Rt Ra Rn
11051 assert(insOptsNone(id->idInsOpt()));
11052 assert(emitGetInsSC(id) == 0);
11053 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
11054 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
11055 emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
11058 case IF_LS_3C: // LS_3C X.........iiiiii iaaaaannnnnddddd Rt Ra Rn imm(im7,sh)
11059 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
11060 imm = emitGetInsSC(id);
11061 scale = NaturalScale_helper(emitInsLoadStoreSize(id));
11063 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
11064 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
11065 emitDispAddrRI(id->idReg3(), id->idInsOpt(), imm);
11068 case IF_LS_3D: // LS_3D .X.......X.mmmmm ......nnnnnttttt Wm Rt Rn
11069 assert(insOptsNone(id->idInsOpt()));
11070 emitDispReg(id->idReg1(), EA_4BYTE, true);
11071 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
11072 emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
11075 case IF_LS_3E: // LS_3E .X.........mmmmm ......nnnnnttttt Rm Rt Rn ARMv8.1 LSE Atomics
11076 assert(insOptsNone(id->idInsOpt()));
11077 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
11078 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
11079 emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
11082 case IF_DI_1A: // DI_1A X.......shiiiiii iiiiiinnnnn..... Rn imm(i12,sh)
11083 emitDispReg(id->idReg1(), size, true);
11084 emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
11087 case IF_DI_1B: // DI_1B X........hwiiiii iiiiiiiiiiiddddd Rd imm(i16,hw)
11088 emitDispReg(id->idReg1(), size, true);
11089 hwi.immHWVal = (unsigned)emitGetInsSC(id);
11090 if (ins == INS_mov)
11092 emitDispImm(emitDecodeHalfwordImm(hwi, size), false);
11094 else // movz, movn, movk
11096 emitDispImm(hwi.immVal, false);
11097 if (hwi.immHW != 0)
11099 emitDispShiftOpts(INS_OPTS_LSL);
11100 emitDispImm(hwi.immHW * 16, false);
11105 case IF_DI_1C: // DI_1C X........Nrrrrrr ssssssnnnnn..... Rn imm(N,r,s)
11106 emitDispReg(id->idReg1(), size, true);
11107 bmi.immNRS = (unsigned)emitGetInsSC(id);
11108 emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
11111 case IF_DI_1D: // DI_1D X........Nrrrrrr ssssss.....ddddd Rd imm(N,r,s)
11112 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11113 bmi.immNRS = (unsigned)emitGetInsSC(id);
11114 emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
11117 case IF_DI_2A: // DI_2A X.......shiiiiii iiiiiinnnnnddddd Rd Rn imm(i12,sh)
11118 if ((ins == INS_add) || (ins == INS_sub))
11120 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11121 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11125 emitDispReg(id->idReg1(), size, true);
11126 emitDispReg(id->idReg2(), size, true);
11128 emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
11131 case IF_DI_2B: // DI_2B X........X.nnnnn ssssssnnnnnddddd Rd Rn imm(0-63)
11132 emitDispReg(id->idReg1(), size, true);
11133 emitDispReg(id->idReg2(), size, true);
11134 emitDispImm(emitGetInsSC(id), false);
11137 case IF_DI_2C: // DI_2C X........Nrrrrrr ssssssnnnnnddddd Rd Rn imm(N,r,s)
11138 if (ins == INS_ands)
11140 emitDispReg(id->idReg1(), size, true);
11144 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11146 emitDispReg(id->idReg2(), size, true);
11147 bmi.immNRS = (unsigned)emitGetInsSC(id);
11148 emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
11151 case IF_DI_2D: // DI_2D X........Nrrrrrr ssssssnnnnnddddd Rd Rn imr, ims (N,r,s)
11152 emitDispReg(id->idReg1(), size, true);
11153 emitDispReg(id->idReg2(), size, true);
11155 imm = emitGetInsSC(id);
11156 bmi.immNRS = (unsigned)imm;
11163 emitDispImm(bmi.immR, true);
11164 emitDispImm(bmi.immS, false);
11170 emitDispImm(getBitWidth(size) - bmi.immR, true);
11171 emitDispImm(bmi.immS + 1, false);
11177 emitDispImm(bmi.immR, true);
11178 emitDispImm(bmi.immS - bmi.immR + 1, false);
11184 emitDispImm(imm, false);
11188 assert(!"Unexpected instruction in IF_DI_2D");
11193 case IF_DI_1F: // DI_1F X..........iiiii cccc..nnnnn.nzcv Rn imm5 nzcv cond
11194 emitDispReg(id->idReg1(), size, true);
11195 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11196 emitDispImm(cfi.imm5, true);
11197 emitDispFlags(cfi.flags);
11199 emitDispCond(cfi.cond);
11202 case IF_DR_1D: // DR_1D X............... cccc.......mmmmm Rd cond
11203 emitDispReg(id->idReg1(), size, true);
11204 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11205 emitDispCond(cfi.cond);
11208 case IF_DR_2A: // DR_2A X..........mmmmm ......nnnnn..... Rn Rm
11209 emitDispReg(id->idReg1(), size, true);
11210 emitDispReg(id->idReg2(), size, false);
11213 case IF_DR_2B: // DR_2B X.......sh.mmmmm ssssssnnnnn..... Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
11214 emitDispReg(id->idReg1(), size, true);
11215 emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
11218 case IF_DR_2C: // DR_2C X..........mmmmm ooosssnnnnn..... Rn Rm ext(Rm) LSL imm(0-4)
11219 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11220 imm = emitGetInsSC(id);
11221 emitDispExtendReg(id->idReg2(), id->idInsOpt(), imm);
11224 case IF_DR_2D: // DR_2D X..........nnnnn cccc..nnnnnddddd Rd Rn cond
11225 emitDispReg(id->idReg1(), size, true);
11226 emitDispReg(id->idReg2(), size, true);
11227 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11228 emitDispCond(cfi.cond);
11231 case IF_DR_2E: // DR_2E X..........mmmmm ...........ddddd Rd Rm
11232 case IF_DR_2J: // DR_2J ................ ......nnnnnddddd Sd Sn
11233 emitDispReg(id->idReg1(), size, true);
11234 emitDispReg(id->idReg2(), size, false);
11237 case IF_DR_2F: // DR_2F X.......sh.mmmmm ssssss.....ddddd Rd Rm {LSL,LSR,ASR} imm(0-63)
11238 emitDispReg(id->idReg1(), size, true);
11239 emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
11242 case IF_DR_2G: // DR_2G X............... ......nnnnnddddd Rd Rn
11243 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11244 emitDispReg(encodingZRtoSP(id->idReg2()), size, false);
11247 case IF_DR_2H: // DR_2H X........X...... ......nnnnnddddd Rd Rn
11248 emitDispReg(id->idReg1(), size, true);
11249 emitDispReg(id->idReg2(), size, false);
11252 case IF_DR_2I: // DR_2I X..........mmmmm cccc..nnnnn.nzcv Rn Rm nzcv cond
11253 emitDispReg(id->idReg1(), size, true);
11254 emitDispReg(id->idReg2(), size, true);
11255 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11256 emitDispFlags(cfi.flags);
11258 emitDispCond(cfi.cond);
11261 case IF_DR_3A: // DR_3A X..........mmmmm ......nnnnnmmmmm Rd Rn Rm
11262 if ((ins == INS_add) || (ins == INS_sub))
11264 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11265 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11267 else if ((ins == INS_smull) || (ins == INS_smulh))
11269 // Rd is always 8 bytes
11270 emitDispReg(id->idReg1(), EA_8BYTE, true);
11272 // Rn, Rm effective size depends on instruction type
11273 size = (ins == INS_smulh) ? EA_8BYTE : EA_4BYTE;
11274 emitDispReg(id->idReg2(), size, true);
11278 emitDispReg(id->idReg1(), size, true);
11279 emitDispReg(id->idReg2(), size, true);
11281 if (id->idIsLclVar())
11283 emitDispReg(codeGen->rsGetRsvdReg(), size, false);
11287 emitDispReg(id->idReg3(), size, false);
11292 case IF_DR_3B: // DR_3B X.......sh.mmmmm ssssssnnnnnddddd Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
11293 emitDispReg(id->idReg1(), size, true);
11294 emitDispReg(id->idReg2(), size, true);
11295 emitDispShiftedReg(id->idReg3(), id->idInsOpt(), emitGetInsSC(id), size);
11298 case IF_DR_3C: // DR_3C X..........mmmmm ooosssnnnnnddddd Rd Rn Rm ext(Rm) LSL imm(0-4)
11299 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11300 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11301 imm = emitGetInsSC(id);
11302 emitDispExtendReg(id->idReg3(), id->idInsOpt(), imm);
11305 case IF_DR_3D: // DR_3D X..........mmmmm cccc..nnnnnmmmmm Rd Rn Rm cond
11306 emitDispReg(id->idReg1(), size, true);
11307 emitDispReg(id->idReg2(), size, true);
11308 emitDispReg(id->idReg3(), size, true);
11309 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11310 emitDispCond(cfi.cond);
11313 case IF_DR_3E: // DR_3E X........X.mmmmm ssssssnnnnnddddd Rd Rn Rm imm(0-63)
11314 emitDispReg(id->idReg1(), size, true);
11315 emitDispReg(id->idReg2(), size, true);
11316 emitDispReg(id->idReg3(), size, true);
11317 emitDispImm(emitGetInsSC(id), false);
11320 case IF_DR_4A: // DR_4A X..........mmmmm .aaaaannnnnmmmmm Rd Rn Rm Ra
11321 emitDispReg(id->idReg1(), size, true);
11322 emitDispReg(id->idReg2(), size, true);
11323 emitDispReg(id->idReg3(), size, true);
11324 emitDispReg(id->idReg4(), size, false);
11327 case IF_DV_1A: // DV_1A .........X.iiiii iii........ddddd Vd imm8 (fmov - immediate scalar)
11328 elemsize = id->idOpSize();
11329 emitDispReg(id->idReg1(), elemsize, true);
11330 emitDispFloatImm(emitGetInsSC(id));
11333 case IF_DV_1B: // DV_1B .QX..........iii cmod..iiiiiddddd Vd imm8 (immediate vector)
11334 imm = emitGetInsSC(id) & 0x0ff;
11335 immShift = (emitGetInsSC(id) & 0x700) >> 8;
11336 hasShift = (immShift != 0);
11337 elemsize = optGetElemsize(id->idInsOpt());
11338 if (id->idInsOpt() == INS_OPTS_1D)
11340 assert(elemsize == size);
11341 emitDispReg(id->idReg1(), size, true);
11345 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11347 if (ins == INS_fmov)
11349 emitDispFloatImm(imm);
11350 assert(hasShift == false);
11354 if (elemsize == EA_8BYTE)
11356 assert(ins == INS_movi);
11358 const ssize_t mask8 = 0xFF;
11359 for (unsigned b = 0; b < 8; b++)
11361 if (imm & (1 << b))
11363 imm64 |= (mask8 << (b * 8));
11366 emitDispImm(imm64, hasShift, true);
11370 emitDispImm(imm, hasShift, true);
11374 insOpts opt = (immShift & 0x4) ? INS_OPTS_MSL : INS_OPTS_LSL;
11375 unsigned shift = (immShift & 0x3) * 8;
11376 emitDispShiftOpts(opt);
11377 emitDispImm(shift, false);
11382 case IF_DV_1C: // DV_1C .........X...... ......nnnnn..... Vn #0.0 (fcmp - with zero)
11383 elemsize = id->idOpSize();
11384 emitDispReg(id->idReg1(), elemsize, true);
11385 emitDispFloatZero();
11388 case IF_DV_2A: // DV_2A .Q.......X...... ......nnnnnddddd Vd Vn (fabs, fcvt - vector)
11389 case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
11390 case IF_DV_2P: // DV_2P ................ ......nnnnnddddd Vd Vn (aes*, sha1su1)
11391 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11392 emitDispVectorReg(id->idReg2(), id->idInsOpt(), false);
11395 case IF_DV_2N: // DV_2N .........iiiiiii ......nnnnnddddd Vd Vn imm (shift - scalar)
11396 elemsize = id->idOpSize();
11397 emitDispReg(id->idReg1(), elemsize, true);
11398 emitDispReg(id->idReg2(), elemsize, true);
11399 emitDispImm(emitGetInsSC(id), false);
11402 case IF_DV_2O: // DV_2O .Q.......iiiiiii ......nnnnnddddd Vd Vn imm (shift - vector)
11403 imm = emitGetInsSC(id);
11404 // Do we have a sxtl or uxtl instruction?
11405 isExtendAlias = ((ins == INS_sxtl) || (ins == INS_sxtl2) || (ins == INS_uxtl) || (ins == INS_uxtl2));
11406 code = emitInsCode(ins, fmt);
11407 if (code & 0x00008000) // widen/narrow opcodes
11409 if (code & 0x00002000) // SHL opcodes
11411 emitDispVectorReg(id->idReg1(), optWidenElemsize(id->idInsOpt()), true);
11412 emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11414 else // SHR opcodes
11416 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11417 emitDispVectorReg(id->idReg2(), optWidenElemsize(id->idInsOpt()), !isExtendAlias);
11422 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11423 emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11425 // Print the immediate unless we have a sxtl or uxtl instruction
11426 if (!isExtendAlias)
11428 emitDispImm(imm, false);
11432 case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov/smov - to general)
11433 srcsize = id->idOpSize();
11434 index = emitGetInsSC(id);
11435 if (ins == INS_smov)
11437 dstsize = EA_8BYTE;
11439 else // INS_umov or INS_mov
11441 dstsize = (srcsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE;
11443 emitDispReg(id->idReg1(), dstsize, true);
11444 emitDispVectorRegIndex(id->idReg2(), srcsize, index, false);
11447 case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
11448 if (ins == INS_dup)
11450 datasize = id->idOpSize();
11451 assert(isValidVectorDatasize(datasize));
11452 assert(isValidArrangement(datasize, id->idInsOpt()));
11453 elemsize = optGetElemsize(id->idInsOpt());
11454 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11458 elemsize = id->idOpSize();
11459 index = emitGetInsSC(id);
11460 assert(isValidVectorElemsize(elemsize));
11461 emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11463 emitDispReg(id->idReg2(), (elemsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE, false);
11466 case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
11467 datasize = id->idOpSize();
11468 assert(isValidVectorDatasize(datasize));
11469 assert(isValidArrangement(datasize, id->idInsOpt()));
11470 elemsize = optGetElemsize(id->idInsOpt());
11471 index = emitGetInsSC(id);
11472 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11473 emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11476 case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
11477 elemsize = id->idOpSize();
11478 index = emitGetInsSC(id);
11479 emitDispReg(id->idReg1(), elemsize, true);
11480 emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11483 case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
11484 imm = emitGetInsSC(id);
11485 index = (imm >> 4) & 0xf;
11486 index2 = imm & 0xf;
11487 elemsize = id->idOpSize();
11488 emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11489 emitDispVectorRegIndex(id->idReg2(), elemsize, index2, false);
11492 case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov, fcvtXX - register)
11493 case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
11494 case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
11495 elemsize = id->idOpSize();
11496 emitDispReg(id->idReg1(), elemsize, true);
11497 emitDispReg(id->idReg2(), elemsize, false);
11500 case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov, fcvtXX - to general)
11501 case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov, Xcvtf - from general)
11502 case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
11503 dstsize = optGetDstsize(id->idInsOpt());
11504 srcsize = optGetSrcsize(id->idInsOpt());
11506 emitDispReg(id->idReg1(), dstsize, true);
11507 emitDispReg(id->idReg2(), srcsize, false);
11510 case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11511 case IF_DV_3B: // DV_3B .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11512 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11513 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11514 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11517 case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11518 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11519 if (ins != INS_mov)
11521 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11523 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11526 case IF_DV_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
11527 case IF_DV_3BI: // DV_3BI .Q........Lmmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
11528 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11529 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11530 elemsize = optGetElemsize(id->idInsOpt());
11531 emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11534 case IF_DV_3D: // DV_3D .........X.mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
11535 case IF_DV_3E: // DV_3E ...........mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
11536 emitDispReg(id->idReg1(), size, true);
11537 emitDispReg(id->idReg2(), size, true);
11538 emitDispReg(id->idReg3(), size, false);
11541 case IF_DV_3F: // DV_3F ..........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11542 if ((ins == INS_sha1c) || (ins == INS_sha1m) || (ins == INS_sha1p))
11544 // Qd, Sn, Vm (vector)
11545 emitDispReg(id->idReg1(), size, true);
11546 emitDispReg(id->idReg2(), EA_4BYTE, true);
11547 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11549 else if ((ins == INS_sha256h) || (ins == INS_sha256h2))
11551 // Qd Qn Vm (vector)
11552 emitDispReg(id->idReg1(), size, true);
11553 emitDispReg(id->idReg2(), size, true);
11554 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11556 else // INS_sha1su0, INS_sha256su1
11558 // Vd, Vn, Vm (vector)
11559 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11560 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11561 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11565 case IF_DV_3DI: // DV_3DI .........XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (scalar by elem)
11566 emitDispReg(id->idReg1(), size, true);
11567 emitDispReg(id->idReg2(), size, true);
11569 emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11572 case IF_DV_4A: // DV_4A .........X.mmmmm .aaaaannnnnddddd Vd Va Vn Vm (scalar)
11573 emitDispReg(id->idReg1(), size, true);
11574 emitDispReg(id->idReg2(), size, true);
11575 emitDispReg(id->idReg3(), size, true);
11576 emitDispReg(id->idReg4(), size, false);
11579 case IF_SN_0A: // SN_0A ................ ................
11582 case IF_SI_0A: // SI_0A ...........iiiii iiiiiiiiiii..... imm16
11583 emitDispImm(emitGetInsSC(id), false);
11586 case IF_SI_0B: // SI_0B ................ ....bbbb........ imm4 - barrier
11587 emitDispBarrier((insBarrier)emitGetInsSC(id));
11591 printf("unexpected format %s", emitIfName(id->idInsFmt()));
11592 assert(!"unexpectedFormat");
11596 if (id->idDebugOnlyInfo()->idVarRefOffs)
11599 emitDispFrameRef(id->idAddr()->iiaLclVar.lvaVarNum(), id->idAddr()->iiaLclVar.lvaOffset(),
11600 id->idDebugOnlyInfo()->idVarRefOffs, asmfm);
11606 /*****************************************************************************
11608 * Display a stack frame reference.
11611 void emitter::emitDispFrameRef(int varx, int disp, int offs, bool asmfm)
11616 printf("TEMP_%02u", -varx);
11618 emitComp->gtDispLclVar(+varx, false);
11621 printf("-0x%02x", -disp);
11623 printf("+0x%02x", +disp);
11627 if (varx >= 0 && emitComp->opts.varNames)
11630 const char* varName;
11632 assert((unsigned)varx < emitComp->lvaCount);
11633 varDsc = emitComp->lvaTable + varx;
11634 varName = emitComp->compLocalVarName(varx, offs);
11638 printf("'%s", varName);
11641 printf("-%d", -disp);
11643 printf("+%d", +disp);
11652 // Generate code for a load or store operation with a potentially complex addressing mode
11653 // This method handles the case of a GT_IND with contained GT_LEA op1 of the x86 form [base + index*sccale + offset]
11654 // Since Arm64 does not directly support this complex of an addressing mode
11655 // we may generates up to three instructions for this for Arm64
11657 void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataReg, GenTreeIndir* indir)
11659 emitAttr ldstAttr = isVectorRegister(dataReg) ? attr : emitInsAdjustLoadStoreAttr(ins, attr);
11661 GenTree* addr = indir->Addr();
11663 if (addr->isContained())
11665 assert(addr->OperGet() == GT_LCL_VAR_ADDR || addr->OperGet() == GT_LEA);
11670 if (addr->OperGet() == GT_LEA)
11672 offset = addr->AsAddrMode()->Offset();
11673 if (addr->AsAddrMode()->gtScale > 0)
11675 assert(isPow2(addr->AsAddrMode()->gtScale));
11676 BitScanForward(&lsl, addr->AsAddrMode()->gtScale);
11680 GenTree* memBase = indir->Base();
11682 if (indir->HasIndex())
11684 GenTree* index = indir->Index();
11688 regNumber tmpReg = indir->GetSingleTempReg();
11690 emitAttr addType = varTypeIsGC(memBase) ? EA_BYREF : EA_PTRSIZE;
11692 if (emitIns_valid_imm_for_add(offset, EA_8BYTE))
11696 // Generate code to set tmpReg = base + index*scale
11697 emitIns_R_R_R_I(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum, lsl,
11702 // Generate code to set tmpReg = base + index
11703 emitIns_R_R_R(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum);
11706 noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11708 // Then load/store dataReg from/to [tmpReg + offset]
11709 emitIns_R_R_I(ins, ldstAttr, dataReg, tmpReg, offset);
11711 else // large offset
11713 // First load/store tmpReg with the large offset constant
11714 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11715 // Then add the base register
11717 emitIns_R_R_R(INS_add, addType, tmpReg, tmpReg, memBase->gtRegNum);
11719 noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11720 noway_assert(tmpReg != index->gtRegNum);
11722 // Then load/store dataReg from/to [tmpReg + index*scale]
11723 emitIns_R_R_R_I(ins, ldstAttr, dataReg, tmpReg, index->gtRegNum, lsl, INS_OPTS_LSL);
11726 else // (offset == 0)
11730 // Then load/store dataReg from/to [memBase + index*scale]
11731 emitIns_R_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum, lsl, INS_OPTS_LSL);
11735 // Then load/store dataReg from/to [memBase + index]
11736 emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum);
11740 else // no Index register
11742 if (emitIns_valid_imm_for_ldst_offset(offset, EA_SIZE(attr)))
11744 // Then load/store dataReg from/to [memBase + offset]
11745 emitIns_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, offset);
11749 // We require a tmpReg to hold the offset
11750 regNumber tmpReg = indir->GetSingleTempReg();
11752 // First load/store tmpReg with the large offset constant
11753 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11755 // Then load/store dataReg from/to [memBase + tmpReg]
11756 emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, tmpReg);
11760 else // addr is not contained, so we evaluate it into a register
11762 // Then load/store dataReg from/to [addrReg]
11763 emitIns_R_R(ins, ldstAttr, dataReg, addr->gtRegNum);
11767 // The callee must call genConsumeReg() for any non-contained srcs
11768 // and genProduceReg() for any non-contained dsts.
11770 regNumber emitter::emitInsBinary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src)
11772 regNumber result = REG_NA;
11774 // dst can only be a reg
11775 assert(!dst->isContained());
11777 // src can be immed or reg
11778 assert(!src->isContained() || src->isContainedIntOrIImmed());
11780 // find immed (if any) - it cannot be a dst
11781 GenTreeIntConCommon* intConst = nullptr;
11782 if (src->isContainedIntOrIImmed())
11784 intConst = src->AsIntConCommon();
11789 emitIns_R_I(ins, attr, dst->gtRegNum, intConst->IconValue());
11790 return dst->gtRegNum;
11794 emitIns_R_R(ins, attr, dst->gtRegNum, src->gtRegNum);
11795 return dst->gtRegNum;
11799 // The callee must call genConsumeReg() for any non-contained srcs
11800 // and genProduceReg() for any non-contained dsts.
11802 regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src1, GenTree* src2)
11804 regNumber result = REG_NA;
11806 // dst can only be a reg
11807 assert(!dst->isContained());
11809 // find immed (if any) - it cannot be a dst
11810 // Only one src can be an int.
11811 GenTreeIntConCommon* intConst = nullptr;
11812 GenTree* nonIntReg = nullptr;
11814 if (varTypeIsFloating(dst))
11816 // src1 can only be a reg
11817 assert(!src1->isContained());
11818 // src2 can only be a reg
11819 assert(!src2->isContained());
11821 else // not floating point
11823 // src2 can be immed or reg
11824 assert(!src2->isContained() || src2->isContainedIntOrIImmed());
11826 // Check src2 first as we can always allow it to be a contained immediate
11827 if (src2->isContainedIntOrIImmed())
11829 intConst = src2->AsIntConCommon();
11832 // Only for commutative operations do we check src1 and allow it to be a contained immediate
11833 else if (dst->OperIsCommutative())
11835 // src1 can be immed or reg
11836 assert(!src1->isContained() || src1->isContainedIntOrIImmed());
11838 // Check src1 and allow it to be a contained immediate
11839 if (src1->isContainedIntOrIImmed())
11841 assert(!src2->isContainedIntOrIImmed());
11842 intConst = src1->AsIntConCommon();
11848 // src1 can only be a reg
11849 assert(!src1->isContained());
11853 bool isMulOverflow = false;
11854 if (dst->gtOverflowEx())
11856 if ((ins == INS_add) || (ins == INS_adds))
11860 else if ((ins == INS_sub) || (ins == INS_subs))
11864 else if (ins == INS_mul)
11866 isMulOverflow = true;
11867 assert(intConst == nullptr); // overflow format doesn't support an int constant operand
11871 assert(!"Invalid ins for overflow check");
11874 if (intConst != nullptr)
11876 emitIns_R_R_I(ins, attr, dst->gtRegNum, nonIntReg->gtRegNum, intConst->IconValue());
11882 regNumber extraReg = dst->GetSingleTempReg();
11883 assert(extraReg != dst->gtRegNum);
11885 if ((dst->gtFlags & GTF_UNSIGNED) != 0)
11887 if (attr == EA_4BYTE)
11889 // Compute 8 byte results from 4 byte by 4 byte multiplication.
11890 emitIns_R_R_R(INS_umull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11892 // Get the high result by shifting dst.
11893 emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11897 assert(attr == EA_8BYTE);
11898 // Compute the high result.
11899 emitIns_R_R_R(INS_umulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11901 // Now multiply without skewing the high result.
11902 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11905 // zero-sign bit comparison to detect overflow.
11906 emitIns_R_I(INS_cmp, attr, extraReg, 0);
11911 if (attr == EA_4BYTE)
11913 // Compute 8 byte results from 4 byte by 4 byte multiplication.
11914 emitIns_R_R_R(INS_smull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11916 // Get the high result by shifting dst.
11917 emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11923 assert(attr == EA_8BYTE);
11924 // Save the high result in a temporary register.
11925 emitIns_R_R_R(INS_smulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11927 // Now multiply without skewing the high result.
11928 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11933 // Sign bit comparison to detect overflow.
11934 emitIns_R_R_I(INS_cmp, attr, extraReg, dst->gtRegNum, bitShift, INS_OPTS_ASR);
11939 // We can just multiply.
11940 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11944 if (dst->gtOverflowEx())
11946 assert(!varTypeIsFloating(dst));
11947 codeGen->genCheckOverflow(dst);
11950 return dst->gtRegNum;
11953 #endif // defined(_TARGET_ARM64_)