1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
5 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
6 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
10 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
11 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
19 #if defined(_TARGET_ARM64_)
21 /*****************************************************************************/
22 /*****************************************************************************/
28 /* static */ bool emitter::strictArmAsm = true;
30 /*****************************************************************************/
32 const instruction emitJumpKindInstructions[] = {
35 #define JMP_SMALL(en, rev, ins) INS_##ins,
39 const emitJumpKind emitReverseJumpKinds[] = {
42 #define JMP_SMALL(en, rev, ins) EJ_##rev,
46 /*****************************************************************************
47 * Look up the instruction for a jump kind
50 /*static*/ instruction emitter::emitJumpKindToIns(emitJumpKind jumpKind)
52 assert((unsigned)jumpKind < ArrLen(emitJumpKindInstructions));
53 return emitJumpKindInstructions[jumpKind];
56 /*****************************************************************************
57 * Look up the jump kind for an instruction. It better be a conditional
58 * branch instruction with a jump kind!
61 /*static*/ emitJumpKind emitter::emitInsToJumpKind(instruction ins)
63 for (unsigned i = 0; i < ArrLen(emitJumpKindInstructions); i++)
65 if (ins == emitJumpKindInstructions[i])
67 emitJumpKind ret = (emitJumpKind)i;
68 assert(EJ_NONE < ret && ret < EJ_COUNT);
75 /*****************************************************************************
76 * Reverse the conditional jump
79 /*static*/ emitJumpKind emitter::emitReverseJumpKind(emitJumpKind jumpKind)
81 assert(jumpKind < EJ_COUNT);
82 return emitReverseJumpKinds[jumpKind];
85 /*****************************************************************************
87 * Return the allocated size (in bytes) of the given instruction descriptor.
90 size_t emitter::emitSizeOfInsDsc(instrDesc* id)
92 assert(!emitIsTinyInsDsc(id));
94 if (emitIsScnsInsDsc(id))
95 return SMALL_IDSC_SIZE;
97 assert((unsigned)id->idInsFmt() < emitFmtCount);
99 ID_OPS idOp = (ID_OPS)emitFmtToOps[id->idInsFmt()];
100 bool isCallIns = (id->idIns() == INS_bl) || (id->idIns() == INS_blr) || (id->idIns() == INS_b_tail) ||
101 (id->idIns() == INS_br_tail);
102 bool maybeCallIns = (id->idIns() == INS_b) || (id->idIns() == INS_br);
110 return sizeof(instrDescJmp);
113 assert(isCallIns || maybeCallIns);
114 if (id->idIsLargeCall())
116 /* Must be a "fat" call descriptor */
117 return sizeof(instrDescCGCA);
121 assert(!id->idIsLargeDsp());
122 assert(!id->idIsLargeCns());
123 return sizeof(instrDesc);
128 NO_WAY("unexpected instruction descriptor format");
132 if (id->idIsLargeCns())
134 if (id->idIsLargeDsp())
135 return sizeof(instrDescCnsDsp);
137 return sizeof(instrDescCns);
141 if (id->idIsLargeDsp())
142 return sizeof(instrDescDsp);
144 return sizeof(instrDesc);
149 /*****************************************************************************
151 * The following called for each recorded instruction -- use for debugging.
153 void emitter::emitInsSanityCheck(instrDesc* id)
155 /* What instruction format have we got? */
157 switch (id->idInsFmt())
169 case IF_BI_0A: // BI_0A ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
172 case IF_BI_0B: // BI_0B ......iiiiiiiiii iiiiiiiiiiii.... simm19:00
180 case IF_BI_0C: // BI_0C ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
183 case IF_BI_1A: // BI_1A ......iiiiiiiiii iiiiiiiiiiittttt Rt simm19:00
184 assert(isValidGeneralDatasize(id->idOpSize()));
185 assert(isGeneralRegister(id->idReg1()));
188 case IF_BI_1B: // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
189 assert(isValidGeneralDatasize(id->idOpSize()));
190 assert(isGeneralRegister(id->idReg1()));
191 assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
194 case IF_BR_1A: // BR_1A ................ ......nnnnn..... Rn
195 assert(isGeneralRegister(id->idReg1()));
198 case IF_BR_1B: // BR_1B ................ ......nnnnn..... Rn
199 assert(isGeneralRegister(id->idReg3()));
202 case IF_LS_1A: // LS_1A .X......iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB)
203 assert(isGeneralRegister(id->idReg1()) || isVectorRegister(id->idReg1()));
204 assert(insOptsNone(id->idInsOpt()));
207 case IF_LS_2A: // LS_2A .X.......X...... ......nnnnnttttt Rt Rn
208 assert(isIntegerRegister(id->idReg1()) || // ZR
209 isVectorRegister(id->idReg1()));
210 assert(isIntegerRegister(id->idReg2())); // SP
211 assert(emitGetInsSC(id) == 0);
212 assert(insOptsNone(id->idInsOpt()));
215 case IF_LS_2B: // LS_2B .X.......Xiiiiii iiiiiinnnnnttttt Rt Rn imm(0-4095)
216 assert(isIntegerRegister(id->idReg1()) || // ZR
217 isVectorRegister(id->idReg1()));
218 assert(isIntegerRegister(id->idReg2())); // SP
219 assert(isValidUimm12(emitGetInsSC(id)));
220 assert(insOptsNone(id->idInsOpt()));
223 case IF_LS_2C: // LS_2C .X.......X.iiiii iiiiPPnnnnnttttt Rt Rn imm(-256..+255) no/pre/post inc
224 assert(isIntegerRegister(id->idReg1()) || // ZR
225 isVectorRegister(id->idReg1()));
226 assert(isIntegerRegister(id->idReg2())); // SP
227 assert(emitGetInsSC(id) >= -0x100);
228 assert(emitGetInsSC(id) < 0x100);
229 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
232 case IF_LS_3A: // LS_3A .X.......X.mmmmm oooS..nnnnnttttt Rt Rn Rm ext(Rm) LSL {}
233 assert(isIntegerRegister(id->idReg1()) || // ZR
234 isVectorRegister(id->idReg1()));
235 assert(isIntegerRegister(id->idReg2())); // SP
236 if (id->idIsLclVar())
238 assert(isGeneralRegister(codeGen->rsGetRsvdReg()));
242 assert(isGeneralRegister(id->idReg3()));
244 assert(insOptsLSExtend(id->idInsOpt()));
247 case IF_LS_3B: // LS_3B X............... .aaaaannnnnttttt Rt Ra Rn
248 assert((isValidGeneralDatasize(id->idOpSize()) && isIntegerRegister(id->idReg1())) ||
249 (isValidVectorLSPDatasize(id->idOpSize()) && isVectorRegister(id->idReg1())));
250 assert(isIntegerRegister(id->idReg1()) || // ZR
251 isVectorRegister(id->idReg1()));
252 assert(isIntegerRegister(id->idReg2()) || // ZR
253 isVectorRegister(id->idReg2()));
254 assert(isIntegerRegister(id->idReg3())); // SP
255 assert(emitGetInsSC(id) == 0);
256 assert(insOptsNone(id->idInsOpt()));
259 case IF_LS_3C: // LS_3C X.........iiiiii iaaaaannnnnttttt Rt Ra Rn imm(im7,sh)
260 assert((isValidGeneralDatasize(id->idOpSize()) && isIntegerRegister(id->idReg1())) ||
261 (isValidVectorLSPDatasize(id->idOpSize()) && isVectorRegister(id->idReg1())));
262 assert(isIntegerRegister(id->idReg1()) || // ZR
263 isVectorRegister(id->idReg1()));
264 assert(isIntegerRegister(id->idReg2()) || // ZR
265 isVectorRegister(id->idReg2()));
266 assert(isIntegerRegister(id->idReg3())); // SP
267 assert(emitGetInsSC(id) >= -0x40);
268 assert(emitGetInsSC(id) < 0x40);
269 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
272 case IF_LS_3D: // LS_3D .X.......X.mmmmm ......nnnnnttttt Wm Rt Rn
273 assert(isIntegerRegister(id->idReg1()));
274 assert(isIntegerRegister(id->idReg2()));
275 assert(isIntegerRegister(id->idReg3()));
276 assert(emitGetInsSC(id) == 0);
277 assert(!id->idIsLclVar());
278 assert(insOptsNone(id->idInsOpt()));
281 case IF_DI_1A: // DI_1A X.......shiiiiii iiiiiinnnnn..... Rn imm(i12,sh)
282 assert(isValidGeneralDatasize(id->idOpSize()));
283 assert(isGeneralRegister(id->idReg1()));
284 assert(isValidUimm12(emitGetInsSC(id)));
285 assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
288 case IF_DI_1B: // DI_1B X........hwiiiii iiiiiiiiiiiddddd Rd imm(i16,hw)
289 assert(isValidGeneralDatasize(id->idOpSize()));
290 assert(isGeneralRegister(id->idReg1()));
291 assert(isValidImmHWVal(emitGetInsSC(id), id->idOpSize()));
294 case IF_DI_1C: // DI_1C X........Nrrrrrr ssssssnnnnn..... Rn imm(N,r,s)
295 assert(isValidGeneralDatasize(id->idOpSize()));
296 assert(isGeneralRegister(id->idReg1()));
297 assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
300 case IF_DI_1D: // DI_1D X........Nrrrrrr ssssss.....ddddd Rd imm(N,r,s)
301 assert(isValidGeneralDatasize(id->idOpSize()));
302 assert(isIntegerRegister(id->idReg1())); // SP
303 assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
306 case IF_DI_1E: // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
307 assert(isGeneralRegister(id->idReg1()));
310 case IF_DI_1F: // DI_1F X..........iiiii cccc..nnnnn.nzcv Rn imm5 nzcv cond
311 assert(isValidGeneralDatasize(id->idOpSize()));
312 assert(isGeneralRegister(id->idReg1()));
313 assert(isValidImmCondFlagsImm5(emitGetInsSC(id)));
316 case IF_DI_2A: // DI_2A X.......shiiiiii iiiiiinnnnnddddd Rd Rn imm(i12,sh)
317 assert(isValidGeneralDatasize(id->idOpSize()));
318 assert(isIntegerRegister(id->idReg1())); // SP
319 assert(isIntegerRegister(id->idReg2())); // SP
320 assert(isValidUimm12(emitGetInsSC(id)));
321 assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
324 case IF_DI_2B: // DI_2B X.........Xnnnnn ssssssnnnnnddddd Rd Rn imm(0-63)
325 assert(isValidGeneralDatasize(id->idOpSize()));
326 assert(isGeneralRegister(id->idReg1()));
327 assert(isGeneralRegister(id->idReg2()));
328 assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
331 case IF_DI_2C: // DI_2C X........Nrrrrrr ssssssnnnnnddddd Rd Rn imm(N,r,s)
332 assert(isValidGeneralDatasize(id->idOpSize()));
333 assert(isIntegerRegister(id->idReg1())); // SP
334 assert(isGeneralRegister(id->idReg2()));
335 assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
338 case IF_DI_2D: // DI_2D X........Nrrrrrr ssssssnnnnnddddd Rd Rn imr, imms (N,r,s)
339 assert(isValidGeneralDatasize(id->idOpSize()));
340 assert(isGeneralRegister(id->idReg1()));
341 assert(isGeneralRegister(id->idReg2()));
342 assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
345 case IF_DR_1D: // DR_1D X............... cccc.......ddddd Rd cond
346 assert(isValidGeneralDatasize(id->idOpSize()));
347 assert(isGeneralRegister(id->idReg1()));
348 assert(isValidImmCond(emitGetInsSC(id)));
351 case IF_DR_2A: // DR_2A X..........mmmmm ......nnnnn..... Rn Rm
352 assert(isValidGeneralDatasize(id->idOpSize()));
353 assert(isGeneralRegister(id->idReg1()));
354 assert(isGeneralRegister(id->idReg2()));
357 case IF_DR_2B: // DR_2B X.......sh.mmmmm ssssssnnnnn..... Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
358 assert(isValidGeneralDatasize(id->idOpSize()));
359 assert(isIntegerRegister(id->idReg1())); // ZR
360 assert(isGeneralRegister(id->idReg2()));
361 assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
362 if (!insOptsNone(id->idInsOpt()))
364 if (id->idIns() == INS_tst) // tst allows ROR, cmp/cmn don't
366 assert(insOptsAnyShift(id->idInsOpt()));
370 assert(insOptsAluShift(id->idInsOpt()));
373 assert(insOptsNone(id->idInsOpt()) || (emitGetInsSC(id) > 0));
376 case IF_DR_2C: // DR_2C X..........mmmmm ooosssnnnnn..... Rn Rm ext(Rm) LSL imm(0-4)
377 assert(isValidGeneralDatasize(id->idOpSize()));
378 assert(isIntegerRegister(id->idReg1())); // SP
379 assert(isGeneralRegister(id->idReg2()));
380 assert(insOptsNone(id->idInsOpt()) || insOptsLSL(id->idInsOpt()) || insOptsAnyExtend(id->idInsOpt()));
381 assert(emitGetInsSC(id) >= 0);
382 assert(emitGetInsSC(id) <= 4);
383 if (insOptsLSL(id->idInsOpt()))
385 assert(emitGetInsSC(id) > 0);
389 case IF_DR_2D: // DR_2D X..........nnnnn cccc..nnnnnmmmmm Rd Rn cond
390 assert(isValidGeneralDatasize(id->idOpSize()));
391 assert(isGeneralRegister(id->idReg1()));
392 assert(isGeneralRegister(id->idReg2()));
393 assert(isValidImmCond(emitGetInsSC(id)));
396 case IF_DR_2E: // DR_2E X..........mmmmm ...........ddddd Rd Rm
397 assert(isValidGeneralDatasize(id->idOpSize()));
398 assert(isGeneralRegister(id->idReg1()));
399 assert(isIntegerRegister(id->idReg2())); // ZR
402 case IF_DR_2F: // DR_2F X.......sh.mmmmm ssssss.....ddddd Rd Rm {LSL,LSR,ASR} imm(0-63)
403 assert(isValidGeneralDatasize(id->idOpSize()));
404 assert(isGeneralRegister(id->idReg1()));
405 assert(isGeneralRegister(id->idReg2()));
406 assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
407 assert(insOptsNone(id->idInsOpt()) || insOptsAluShift(id->idInsOpt()));
408 assert(insOptsNone(id->idInsOpt()) || (emitGetInsSC(id) > 0));
411 case IF_DR_2G: // DR_2G X............... ......nnnnnddddd Rd Rm
412 assert(isValidGeneralDatasize(id->idOpSize()));
413 assert(isIntegerRegister(id->idReg1())); // SP
414 assert(isIntegerRegister(id->idReg2())); // SP
417 case IF_DR_2H: // DR_2H X........X...... ......nnnnnddddd Rd Rn
418 assert(isValidGeneralDatasize(id->idOpSize()));
419 assert(isGeneralRegister(id->idReg1()));
420 assert(isGeneralRegister(id->idReg2()));
423 case IF_DR_2I: // DR_2I X..........mmmmm cccc..nnnnn.nzcv Rn Rm nzcv cond
424 assert(isValidGeneralDatasize(id->idOpSize()));
425 assert(isGeneralRegister(id->idReg1()));
426 assert(isGeneralRegister(id->idReg2()));
427 assert(isValidImmCondFlags(emitGetInsSC(id)));
430 case IF_DR_2J: // DR_2J ................ ......nnnnnddddd Sd Sn (sha1h)
431 assert(isValidGeneralDatasize(id->idOpSize()));
432 assert(isVectorRegister(id->idReg1()));
433 assert(isVectorRegister(id->idReg2()));
436 case IF_DR_3A: // DR_3A X..........mmmmm ......nnnnnmmmmm Rd Rn Rm
437 assert(isValidGeneralDatasize(id->idOpSize()));
438 assert(isIntegerRegister(id->idReg1())); // SP
439 assert(isIntegerRegister(id->idReg2())); // SP
440 if (id->idIsLclVar())
442 assert(isGeneralRegister(codeGen->rsGetRsvdReg()));
446 assert(isGeneralRegister(id->idReg3()));
448 assert(insOptsNone(id->idInsOpt()));
451 case IF_DR_3B: // DR_3B X.......sh.mmmmm ssssssnnnnnddddd Rd Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
452 assert(isValidGeneralDatasize(id->idOpSize()));
453 assert(isGeneralRegister(id->idReg1()));
454 assert(isGeneralRegister(id->idReg2()));
455 assert(isGeneralRegister(id->idReg3()));
456 assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
457 assert(insOptsNone(id->idInsOpt()) || insOptsAnyShift(id->idInsOpt()));
458 assert(insOptsNone(id->idInsOpt()) || (emitGetInsSC(id) > 0));
461 case IF_DR_3C: // DR_3C X..........mmmmm ooosssnnnnnddddd Rd Rn Rm ext(Rm) LSL imm(0-4)
462 assert(isValidGeneralDatasize(id->idOpSize()));
463 assert(isIntegerRegister(id->idReg1())); // SP
464 assert(isIntegerRegister(id->idReg2())); // SP
465 assert(isGeneralRegister(id->idReg3()));
466 assert(insOptsNone(id->idInsOpt()) || insOptsLSL(id->idInsOpt()) || insOptsAnyExtend(id->idInsOpt()));
467 assert(emitGetInsSC(id) >= 0);
468 assert(emitGetInsSC(id) <= 4);
469 if (insOptsLSL(id->idInsOpt()))
471 assert((emitGetInsSC(id) > 0) ||
472 (id->idReg2() == REG_ZR)); // REG_ZR encodes SP and we allow a shift of zero
476 case IF_DR_3D: // DR_3D X..........mmmmm cccc..nnnnnmmmmm Rd Rn Rm cond
477 assert(isValidGeneralDatasize(id->idOpSize()));
478 assert(isGeneralRegister(id->idReg1()));
479 assert(isGeneralRegister(id->idReg2()));
480 assert(isGeneralRegister(id->idReg3()));
481 assert(isValidImmCond(emitGetInsSC(id)));
484 case IF_DR_3E: // DR_3E X........X.mmmmm ssssssnnnnnddddd Rd Rn Rm imm(0-63)
485 assert(isValidGeneralDatasize(id->idOpSize()));
486 assert(isGeneralRegister(id->idReg1()));
487 assert(isGeneralRegister(id->idReg2()));
488 assert(isGeneralRegister(id->idReg3()));
489 assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
490 assert(insOptsNone(id->idInsOpt()));
493 case IF_DR_4A: // DR_4A X..........mmmmm .aaaaannnnnddddd Rd Rn Rm Ra
494 assert(isValidGeneralDatasize(id->idOpSize()));
495 assert(isGeneralRegister(id->idReg1()));
496 assert(isGeneralRegister(id->idReg2()));
497 assert(isGeneralRegister(id->idReg3()));
498 assert(isGeneralRegister(id->idReg4()));
501 case IF_DV_1A: // DV_1A .........X.iiiii iii........ddddd Vd imm8 (fmov - immediate scalar)
502 assert(insOptsNone(id->idInsOpt()));
503 elemsize = id->idOpSize();
504 assert(isValidVectorElemsizeFloat(elemsize));
505 assert(isVectorRegister(id->idReg1()));
506 assert(isValidUimm8(emitGetInsSC(id)));
509 case IF_DV_1B: // DV_1B .QX..........iii cmod..iiiiiddddd Vd imm8 (immediate vector)
511 imm = emitGetInsSC(id) & 0x0ff;
512 immShift = (emitGetInsSC(id) & 0x700) >> 8;
513 assert(immShift >= 0);
514 datasize = id->idOpSize();
515 assert(isValidVectorDatasize(datasize));
516 assert(isValidArrangement(datasize, id->idInsOpt()));
517 elemsize = optGetElemsize(id->idInsOpt());
520 assert(isValidVectorElemsizeFloat(elemsize));
521 assert(id->idInsOpt() != INS_OPTS_1D); // Reserved encoding
522 assert(immShift == 0);
526 assert(isValidVectorElemsize(elemsize));
527 assert((immShift != 4) && (immShift != 7)); // always invalid values
528 if (ins != INS_movi) // INS_mvni, INS_orr, INS_bic
530 assert((elemsize != EA_1BYTE) && (elemsize != EA_8BYTE)); // only H or S
531 if (elemsize == EA_2BYTE)
533 assert(immShift < 2);
535 else // (elemsize == EA_4BYTE)
539 assert(immShift < 4);
544 assert(isVectorRegister(id->idReg1()));
545 assert(isValidUimm8(imm));
548 case IF_DV_1C: // DV_1C .........X...... ......nnnnn..... Vn #0.0 (fcmp - with zero)
549 assert(insOptsNone(id->idInsOpt()));
550 elemsize = id->idOpSize();
551 assert(isValidVectorElemsizeFloat(elemsize));
552 assert(isVectorRegister(id->idReg1()));
555 case IF_DV_2A: // DV_2A .Q.......X...... ......nnnnnddddd Vd Vn (fabs, fcvt - vector)
556 case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
557 case IF_DV_2P: // DV_2P ................ ......nnnnnddddd Vd Vn (aes*, sha1su1)
558 assert(isValidVectorDatasize(id->idOpSize()));
559 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
560 assert(isVectorRegister(id->idReg1()));
561 assert(isVectorRegister(id->idReg2()));
564 case IF_DV_2N: // DV_2N .........iiiiiii ......nnnnnddddd Vd Vn imm (shift - scalar)
565 assert(id->idOpSize() == EA_8BYTE);
566 assert(insOptsNone(id->idInsOpt()));
567 assert(isVectorRegister(id->idReg1()));
568 assert(isVectorRegister(id->idReg2()));
569 assert(isValidImmShift(emitGetInsSC(id), EA_8BYTE));
572 case IF_DV_2O: // DV_2O .Q.......iiiiiii ......nnnnnddddd Vd Vn imm (shift - vector)
573 assert(isValidVectorDatasize(id->idOpSize()));
574 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
575 assert(isVectorRegister(id->idReg1()));
576 assert(isVectorRegister(id->idReg2()));
577 elemsize = optGetElemsize(id->idInsOpt());
578 assert(isValidImmShift(emitGetInsSC(id), elemsize));
581 case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov/smov - to general)
582 elemsize = id->idOpSize();
583 index = emitGetInsSC(id);
584 assert(insOptsNone(id->idInsOpt()));
585 assert(isValidVectorIndex(EA_16BYTE, elemsize, index));
586 assert(isValidVectorElemsize(elemsize));
587 assert(isGeneralRegister(id->idReg1()));
588 assert(isVectorRegister(id->idReg2()));
591 case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
592 if (id->idIns() == INS_dup)
594 datasize = id->idOpSize();
595 assert(isValidVectorDatasize(datasize));
596 assert(isValidArrangement(datasize, id->idInsOpt()));
597 elemsize = optGetElemsize(id->idInsOpt());
601 datasize = EA_16BYTE;
602 elemsize = id->idOpSize();
603 assert(isValidVectorElemsize(elemsize));
605 assert(isVectorRegister(id->idReg1()));
606 assert(isGeneralRegisterOrZR(id->idReg2()));
609 case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
610 datasize = id->idOpSize();
611 assert(isValidVectorDatasize(datasize));
612 assert(isValidArrangement(datasize, id->idInsOpt()));
613 elemsize = optGetElemsize(id->idInsOpt());
614 index = emitGetInsSC(id);
615 assert(isValidVectorIndex(datasize, elemsize, index));
616 assert(isVectorRegister(id->idReg1()));
617 assert(isVectorRegister(id->idReg2()));
620 case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
621 elemsize = id->idOpSize();
622 index = emitGetInsSC(id);
623 assert(isValidVectorIndex(EA_16BYTE, elemsize, index));
624 assert(isValidVectorElemsize(elemsize));
625 assert(isVectorRegister(id->idReg1()));
626 assert(isVectorRegister(id->idReg2()));
629 case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
630 imm = emitGetInsSC(id);
631 index = (imm >> 4) & 0xf;
633 elemsize = id->idOpSize();
634 assert(isValidVectorElemsize(elemsize));
635 assert(isValidVectorIndex(EA_16BYTE, elemsize, index));
636 assert(isValidVectorIndex(EA_16BYTE, elemsize, index2));
637 assert(isVectorRegister(id->idReg1()));
638 assert(isVectorRegister(id->idReg2()));
641 case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
642 assert(id->idOpSize() == EA_8BYTE); // only type D is supported
645 case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov, fcvtXX - register)
646 case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
647 assert(insOptsNone(id->idInsOpt()));
648 assert(isValidVectorElemsizeFloat(id->idOpSize()));
649 assert(isVectorRegister(id->idReg1()));
650 assert(isVectorRegister(id->idReg2()));
653 case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov/fcvtXX - to general)
654 assert(insOptsConvertFloatToInt(id->idInsOpt()));
655 dstsize = optGetDstsize(id->idInsOpt());
656 srcsize = optGetSrcsize(id->idInsOpt());
657 assert(isValidGeneralDatasize(dstsize));
658 assert(isValidVectorElemsizeFloat(srcsize));
659 assert(dstsize == id->idOpSize());
660 assert(isGeneralRegister(id->idReg1()));
661 assert(isVectorRegister(id->idReg2()));
664 case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov/Xcvtf - from general)
665 assert(insOptsConvertIntToFloat(id->idInsOpt()));
666 dstsize = optGetDstsize(id->idInsOpt());
667 srcsize = optGetSrcsize(id->idInsOpt());
668 assert(isValidGeneralDatasize(srcsize));
669 assert(isValidVectorElemsizeFloat(dstsize));
670 assert(dstsize == id->idOpSize());
671 assert(isVectorRegister(id->idReg1()));
672 assert(isGeneralRegister(id->idReg2()));
675 case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
676 assert(insOptsConvertFloatToFloat(id->idInsOpt()));
677 dstsize = optGetDstsize(id->idInsOpt());
678 srcsize = optGetSrcsize(id->idInsOpt());
679 assert(isValidVectorFcvtsize(srcsize));
680 assert(isValidVectorFcvtsize(dstsize));
681 assert(dstsize == id->idOpSize());
682 assert(isVectorRegister(id->idReg1()));
683 assert(isVectorRegister(id->idReg2()));
686 case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
687 assert(isValidVectorDatasize(id->idOpSize()));
688 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
689 assert(isVectorRegister(id->idReg1()));
690 assert(isVectorRegister(id->idReg2()));
691 assert(isVectorRegister(id->idReg3()));
692 elemsize = optGetElemsize(id->idInsOpt());
696 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
698 else if (ins == INS_pmul)
700 assert(elemsize == EA_1BYTE); // only supports 8B or 16B
704 case IF_DV_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
705 assert(isValidVectorDatasize(id->idOpSize()));
706 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
707 assert(isVectorRegister(id->idReg1()));
708 assert(isVectorRegister(id->idReg2()));
709 assert(isVectorRegister(id->idReg3()));
710 elemsize = optGetElemsize(id->idInsOpt());
711 assert(isValidVectorIndex(EA_16BYTE, elemsize, emitGetInsSC(id)));
712 // Only has encodings for H or S elemsize
713 assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE));
716 case IF_DV_3B: // DV_3B .Q.......X.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
717 assert(isValidVectorDatasize(id->idOpSize()));
718 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
719 assert(isVectorRegister(id->idReg1()));
720 assert(isVectorRegister(id->idReg2()));
721 assert(isVectorRegister(id->idReg3()));
724 case IF_DV_3BI: // DV_3BI .Q.......XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
725 assert(isValidVectorDatasize(id->idOpSize()));
726 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
727 assert(isVectorRegister(id->idReg1()));
728 assert(isVectorRegister(id->idReg2()));
729 assert(isVectorRegister(id->idReg3()));
730 elemsize = optGetElemsize(id->idInsOpt());
731 assert(isValidVectorIndex(id->idOpSize(), elemsize, emitGetInsSC(id)));
734 case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
735 assert(isValidVectorDatasize(id->idOpSize()));
736 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
737 assert(isVectorRegister(id->idReg1()));
738 assert(isVectorRegister(id->idReg2()));
739 assert(isVectorRegister(id->idReg3()));
742 case IF_DV_3D: // DV_3D .........X.mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
743 assert(isValidScalarDatasize(id->idOpSize()));
744 assert(insOptsNone(id->idInsOpt()));
745 assert(isVectorRegister(id->idReg1()));
746 assert(isVectorRegister(id->idReg2()));
747 assert(isVectorRegister(id->idReg3()));
750 case IF_DV_3DI: // DV_3DI .........XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (scalar by elem)
751 assert(isValidScalarDatasize(id->idOpSize()));
752 assert(insOptsNone(id->idInsOpt()));
753 assert(isVectorRegister(id->idReg1()));
754 assert(isVectorRegister(id->idReg2()));
755 assert(isVectorRegister(id->idReg3()));
756 elemsize = id->idOpSize();
757 assert(isValidVectorIndex(EA_16BYTE, elemsize, emitGetInsSC(id)));
760 case IF_DV_3E: // DV_3E ...........mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
761 assert(insOptsNone(id->idInsOpt()));
762 assert(id->idOpSize() == EA_8BYTE);
763 assert(isVectorRegister(id->idReg1()));
764 assert(isVectorRegister(id->idReg2()));
765 assert(isVectorRegister(id->idReg3()));
768 case IF_DV_3F: // DV_3F ...........mmmmm ......nnnnnddddd Vd Vn Vm
769 assert(isValidVectorDatasize(id->idOpSize()));
770 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
771 assert(isVectorRegister(id->idReg1()));
772 assert(isVectorRegister(id->idReg2()));
773 assert(isVectorRegister(id->idReg3()));
776 case IF_DV_4A: // DR_4A .........X.mmmmm .aaaaannnnnddddd Rd Rn Rm Ra (scalar)
777 assert(isValidGeneralDatasize(id->idOpSize()));
778 assert(isVectorRegister(id->idReg1()));
779 assert(isVectorRegister(id->idReg2()));
780 assert(isVectorRegister(id->idReg3()));
781 assert(isVectorRegister(id->idReg4()));
784 case IF_SN_0A: // SN_0A ................ ................
785 case IF_SI_0A: // SI_0A ...........iiiii iiiiiiiiiii..... imm16
786 case IF_SI_0B: // SI_0B ................ ....bbbb........ imm4 - barrier
790 printf("unexpected format %s\n", emitIfName(id->idInsFmt()));
791 assert(!"Unexpected format");
797 bool emitter::emitInsMayWriteToGCReg(instrDesc* id)
799 instruction ins = id->idIns();
800 insFormat fmt = id->idInsFmt();
805 // These are the formats with "destination" registers:
807 case IF_DI_1B: // DI_1B X........hwiiiii iiiiiiiiiiiddddd Rd imm(i16,hw)
808 case IF_DI_1D: // DI_1D X........Nrrrrrr ssssss.....ddddd Rd imm(N,r,s)
809 case IF_DI_1E: // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
811 case IF_DI_2A: // DI_2A X.......shiiiiii iiiiiinnnnnddddd Rd Rn imm(i12,sh)
812 case IF_DI_2B: // DI_2B X.........Xnnnnn ssssssnnnnnddddd Rd Rn imm(0-63)
813 case IF_DI_2C: // DI_2C X........Nrrrrrr ssssssnnnnnddddd Rd Rn imm(N,r,s)
814 case IF_DI_2D: // DI_2D X........Nrrrrrr ssssssnnnnnddddd Rd Rn imr, imms (N,r,s)
816 case IF_DR_1D: // DR_1D X............... cccc.......ddddd Rd cond
818 case IF_DR_2D: // DR_2D X..........nnnnn cccc..nnnnnddddd Rd Rn cond
819 case IF_DR_2E: // DR_2E X..........mmmmm ...........ddddd Rd Rm
820 case IF_DR_2F: // DR_2F X.......sh.mmmmm ssssss.....ddddd Rd Rm {LSL,LSR,ASR} imm(0-63)
821 case IF_DR_2G: // DR_2G X............... ......nnnnnddddd Rd Rn
822 case IF_DR_2H: // DR_2H X........X...... ......nnnnnddddd Rd Rn
824 case IF_DR_3A: // DR_3A X..........mmmmm ......nnnnnddddd Rd Rn Rm
825 case IF_DR_3B: // DR_3B X.......sh.mmmmm ssssssnnnnnddddd Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
826 case IF_DR_3C: // DR_3C X..........mmmmm xxxsssnnnnnddddd Rd Rn Rm ext(Rm) LSL imm(0-4)
827 case IF_DR_3D: // DR_3D X..........mmmmm cccc..nnnnnddddd Rd Rn Rm cond
828 case IF_DR_3E: // DR_3E X........X.mmmmm ssssssnnnnnddddd Rd Rn Rm imm(0-63)
829 case IF_DV_3F: // DV_3F ...........mmmmm ......nnnnnddddd Vd Vn Vm (vector) - Vd both source and dest
831 case IF_DR_4A: // DR_4A X..........mmmmm .aaaaannnnnddddd Rd Rn Rm Ra
833 case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov - to general)
834 case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov - to general)
838 case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
839 case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
840 case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
841 case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
842 case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov, fcvtXX - register)
843 case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov - from general)
844 case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
845 case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
846 case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
847 case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
848 case IF_DV_2P: // DV_2P ................ ......nnnnnddddd Vd Vn (aes*, sha1su1) - Vd both source and
851 case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
852 case IF_DV_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector)
853 case IF_DV_3B: // DV_3B .Q.......X.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
854 case IF_DV_3BI: // DV_3BI .Q.......XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
855 case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
856 case IF_DV_3D: // DV_3D .........X.mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
857 case IF_DV_3DI: // DV_3DI .........XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (scalar by elem)
858 case IF_DV_3E: // DV_3E ...........mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
859 case IF_DV_4A: // DV_4A .........X.mmmmm .aaaaannnnnddddd Vd Va Vn Vm (scalar)
860 // Tracked GC pointers cannot be placed into the SIMD registers.
863 // These are the load/store formats with "target" registers:
865 case IF_LS_1A: // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB)
866 case IF_LS_2A: // LS_2A .X.......X...... ......nnnnnttttt Rt Rn
867 case IF_LS_2B: // LS_2B .X.......Xiiiiii iiiiiinnnnnttttt Rt Rn imm(0-4095)
868 case IF_LS_2C: // LS_2C .X.......X.iiiii iiiiP.nnnnnttttt Rt Rn imm(-256..+255) pre/post inc
869 case IF_LS_3A: // LS_3A .X.......X.mmmmm xxxS..nnnnnttttt Rt Rn Rm ext(Rm) LSL {}
870 case IF_LS_3B: // LS_3B X............... .aaaaannnnnttttt Rt Ra Rn
871 case IF_LS_3C: // LS_3C X.........iiiiii iaaaaannnnnttttt Rt Ra Rn imm(im7,sh)
872 case IF_LS_3D: // LS_3D .X.......X.mmmmm ......nnnnnttttt Wm Rt Rn
874 // For the Store instructions the "target" register is actually a "source" value
876 if (emitInsIsStore(ins))
882 assert(emitInsIsLoad(ins));
891 bool emitter::emitInsWritesToLclVarStackLoc(instrDesc* id)
893 if (!id->idIsLclVar())
896 instruction ins = id->idIns();
898 // This list is related to the list of instructions used to store local vars in emitIns_S_R().
899 // We don't accept writing to float local vars.
915 bool emitter::emitInsWritesToLclVarStackLocPair(instrDesc* id)
917 if (!id->idIsLclVar())
920 instruction ins = id->idIns();
922 // This list is related to the list of instructions used to store local vars in emitIns_S_S_R_R().
923 // We don't accept writing to float local vars.
935 bool emitter::emitInsMayWriteMultipleRegs(instrDesc* id)
937 instruction ins = id->idIns();
950 // For the small loads/store instruction we adjust the size 'attr'
951 // depending upon whether we have a load or a store
953 emitAttr emitter::emitInsAdjustLoadStoreAttr(instruction ins, emitAttr attr)
955 if (EA_SIZE(attr) <= EA_4BYTE)
957 if (emitInsIsLoad(ins))
959 // The value of 'ins' encodes the size to load
960 // we use EA_8BYTE here because it is the size we will write (into dataReg)
961 // it is also required when ins is INS_ldrsw
967 assert(emitInsIsStore(ins));
969 // The value of 'ins' encodes the size to store
970 // we use EA_4BYTE here because it is the size of the register
971 // that we want to display when storing small values
979 // Takes an instrDesc 'id' and uses the instruction 'ins' to determine the
980 // size of the target register that is written or read by the instruction.
981 // Note that even if EA_4BYTE is returned a load instruction will still
982 // always zero the upper 4 bytes of the target register.
983 // This method is required so that we can distinguish between loads that are
984 // sign-extending as they can have two different sizes for their target register.
985 // Additionally for instructions like 'ldr' and 'str' these can load/store
986 // either 4 byte or 8 bytes to/from the target register.
987 // By convention the small unsigned load instructions are considered to write
988 // a 4 byte sized target register, though since these also zero the upper 4 bytes
989 // they could equally be considered to write the unsigned value to full 8 byte register.
991 emitAttr emitter::emitInsTargetRegSize(instrDesc* id)
993 instruction ins = id->idIns();
994 emitAttr result = EA_UNKNOWN;
996 // This is used to determine the size of the target registers for a load/store instruction
1030 if (id->idOpSize() == EA_8BYTE)
1046 result = id->idOpSize();
1059 result = id->idOpSize();
1063 NO_WAY("unexpected instruction");
1069 // Takes an instrDesc and uses the instruction to determine the 'size' of the
1070 // data that is loaded from memory.
1072 emitAttr emitter::emitInsLoadStoreSize(instrDesc* id)
1074 instruction ins = id->idIns();
1075 emitAttr result = EA_UNKNOWN;
1077 // The 'result' returned is the 'size' of the data that is loaded from memory.
1113 result = id->idOpSize();
1122 result = id->idOpSize();
1126 NO_WAY("unexpected instruction");
1132 /*****************************************************************************/
1136 static const char * const xRegNames[] =
1138 #define REGDEF(name, rnum, mask, xname, wname) xname,
1139 #include "register.h"
1142 static const char * const wRegNames[] =
1144 #define REGDEF(name, rnum, mask, xname, wname) wname,
1145 #include "register.h"
1148 static const char * const vRegNames[] =
1150 "v0", "v1", "v2", "v3", "v4",
1151 "v5", "v6", "v7", "v8", "v9",
1152 "v10", "v11", "v12", "v13", "v14",
1153 "v15", "v16", "v17", "v18", "v19",
1154 "v20", "v21", "v22", "v23", "v24",
1155 "v25", "v26", "v27", "v28", "v29",
1159 static const char * const qRegNames[] =
1161 "q0", "q1", "q2", "q3", "q4",
1162 "q5", "q6", "q7", "q8", "q9",
1163 "q10", "q11", "q12", "q13", "q14",
1164 "q15", "q16", "q17", "q18", "q19",
1165 "q20", "q21", "q22", "q23", "q24",
1166 "q25", "q26", "q27", "q28", "q29",
1170 static const char * const hRegNames[] =
1172 "h0", "h1", "h2", "h3", "h4",
1173 "h5", "h6", "h7", "h8", "h9",
1174 "h10", "h11", "h12", "h13", "h14",
1175 "h15", "h16", "h17", "h18", "h19",
1176 "h20", "h21", "h22", "h23", "h24",
1177 "h25", "h26", "h27", "h28", "h29",
1180 static const char * const bRegNames[] =
1182 "b0", "b1", "b2", "b3", "b4",
1183 "b5", "b6", "b7", "b8", "b9",
1184 "b10", "b11", "b12", "b13", "b14",
1185 "b15", "b16", "b17", "b18", "b19",
1186 "b20", "b21", "b22", "b23", "b24",
1187 "b25", "b26", "b27", "b28", "b29",
1192 /*****************************************************************************
1194 * Return a string that represents the given register.
1197 const char* emitter::emitRegName(regNumber reg, emitAttr size, bool varName)
1199 assert(reg < REG_COUNT);
1201 const char* rn = nullptr;
1203 if (size == EA_8BYTE)
1205 rn = xRegNames[reg];
1207 else if (size == EA_4BYTE)
1209 rn = wRegNames[reg];
1211 else if (isVectorRegister(reg))
1213 if (size == EA_16BYTE)
1215 rn = qRegNames[reg - REG_V0];
1217 else if (size == EA_2BYTE)
1219 rn = hRegNames[reg - REG_V0];
1221 else if (size == EA_1BYTE)
1223 rn = bRegNames[reg - REG_V0];
1227 assert(rn != nullptr);
1232 /*****************************************************************************
1234 * Return a string that represents the given register.
1237 const char* emitter::emitVectorRegName(regNumber reg)
1239 assert((reg >= REG_V0) && (reg <= REG_V31));
1241 int index = (int)reg - (int)REG_V0;
1243 return vRegNames[index];
1247 /*****************************************************************************
1249 * Returns the base encoding of the given CPU instruction.
1252 emitter::insFormat emitter::emitInsFormat(instruction ins)
1255 const static insFormat insFormats[] =
1257 #define INST1(id, nm, fp, ldst, fmt, e1 ) fmt,
1258 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) fmt,
1259 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) fmt,
1260 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) fmt,
1261 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) fmt,
1262 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) fmt,
1263 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) fmt,
1268 assert(ins < ArrLen(insFormats));
1269 assert((insFormats[ins] != IF_NONE));
1271 return insFormats[ins];
1280 /*static*/ const BYTE CodeGenInterface::instInfo[] =
1282 #define INST1(id, nm, fp, ldst, fmt, e1 ) ldst | INST_FP*fp,
1283 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) ldst | INST_FP*fp,
1284 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) ldst | INST_FP*fp,
1285 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) ldst | INST_FP*fp,
1286 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) ldst | INST_FP*fp,
1287 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) ldst | INST_FP*fp,
1288 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) ldst | INST_FP*fp,
1293 /*****************************************************************************
1295 * Returns true if the instruction is some kind of compare or test instruction
1298 bool emitter::emitInsIsCompare(instruction ins)
1300 // We have pseudo ins like lea which are not included in emitInsLdStTab.
1301 if (ins < ArrLen(CodeGenInterface::instInfo))
1302 return (CodeGenInterface::instInfo[ins] & CMP) ? true : false;
1307 /*****************************************************************************
1309 * Returns true if the instruction is some kind of load instruction
1312 bool emitter::emitInsIsLoad(instruction ins)
1314 // We have pseudo ins like lea which are not included in emitInsLdStTab.
1315 if (ins < ArrLen(CodeGenInterface::instInfo))
1316 return (CodeGenInterface::instInfo[ins] & LD) ? true : false;
1320 /*****************************************************************************
1322 * Returns true if the instruction is some kind of store instruction
1325 bool emitter::emitInsIsStore(instruction ins)
1327 // We have pseudo ins like lea which are not included in emitInsLdStTab.
1328 if (ins < ArrLen(CodeGenInterface::instInfo))
1329 return (CodeGenInterface::instInfo[ins] & ST) ? true : false;
1334 /*****************************************************************************
1336 * Returns true if the instruction is some kind of load/store instruction
1339 bool emitter::emitInsIsLoadOrStore(instruction ins)
1341 // We have pseudo ins like lea which are not included in emitInsLdStTab.
1342 if (ins < ArrLen(CodeGenInterface::instInfo))
1343 return (CodeGenInterface::instInfo[ins] & (LD | ST)) ? true : false;
1352 /*****************************************************************************
1354 * Returns the specific encoding of the given CPU instruction and format
1357 emitter::code_t emitter::emitInsCode(instruction ins, insFormat fmt)
1360 const static code_t insCodes1[] =
1362 #define INST1(id, nm, fp, ldst, fmt, e1 ) e1,
1363 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) e1,
1364 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) e1,
1365 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e1,
1366 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e1,
1367 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e1,
1368 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e1,
1371 const static code_t insCodes2[] =
1373 #define INST1(id, nm, fp, ldst, fmt, e1 )
1374 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) e2,
1375 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) e2,
1376 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e2,
1377 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e2,
1378 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e2,
1379 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e2,
1382 const static code_t insCodes3[] =
1384 #define INST1(id, nm, fp, ldst, fmt, e1 )
1385 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1386 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) e3,
1387 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e3,
1388 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e3,
1389 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e3,
1390 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e3,
1393 const static code_t insCodes4[] =
1395 #define INST1(id, nm, fp, ldst, fmt, e1 )
1396 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1397 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
1398 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e4,
1399 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e4,
1400 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e4,
1401 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e4,
1404 const static code_t insCodes5[] =
1406 #define INST1(id, nm, fp, ldst, fmt, e1 )
1407 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1408 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
1409 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
1410 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e5,
1411 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e5,
1412 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e5,
1415 const static code_t insCodes6[] =
1417 #define INST1(id, nm, fp, ldst, fmt, e1 )
1418 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1419 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
1420 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
1421 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
1422 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e6,
1423 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e6,
1426 const static code_t insCodes7[] =
1428 #define INST1(id, nm, fp, ldst, fmt, e1 )
1429 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1430 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
1431 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
1432 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
1433 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 )
1434 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e7,
1437 const static code_t insCodes8[] =
1439 #define INST1(id, nm, fp, ldst, fmt, e1 )
1440 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1441 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
1442 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
1443 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
1444 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 )
1445 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e8,
1448 const static code_t insCodes9[] =
1450 #define INST1(id, nm, fp, ldst, fmt, e1 )
1451 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1452 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
1453 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
1454 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
1455 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 )
1456 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e9,
1461 const static insFormat formatEncode9[9] = {IF_DR_2E, IF_DR_2G, IF_DI_1B, IF_DI_1D, IF_DV_3C,
1462 IF_DV_2B, IF_DV_2C, IF_DV_2E, IF_DV_2F};
1463 const static insFormat formatEncode6A[6] = {IF_DR_3A, IF_DR_3B, IF_DR_3C, IF_DI_2A, IF_DV_3A, IF_DV_3E};
1464 const static insFormat formatEncode5A[5] = {IF_LS_2A, IF_LS_2B, IF_LS_2C, IF_LS_3A, IF_LS_1A};
1465 const static insFormat formatEncode5B[5] = {IF_DV_2G, IF_DV_2H, IF_DV_2I, IF_DV_1A, IF_DV_1B};
1466 const static insFormat formatEncode5C[5] = {IF_DR_3A, IF_DR_3B, IF_DI_2C, IF_DV_3C, IF_DV_1B};
1467 const static insFormat formatEncode4A[4] = {IF_LS_2A, IF_LS_2B, IF_LS_2C, IF_LS_3A};
1468 const static insFormat formatEncode4B[4] = {IF_DR_3A, IF_DR_3B, IF_DR_3C, IF_DI_2A};
1469 const static insFormat formatEncode4C[4] = {IF_DR_2A, IF_DR_2B, IF_DR_2C, IF_DI_1A};
1470 const static insFormat formatEncode4D[4] = {IF_DV_3B, IF_DV_3D, IF_DV_3BI, IF_DV_3DI};
1471 const static insFormat formatEncode4E[4] = {IF_DR_3A, IF_DR_3B, IF_DI_2C, IF_DV_3C};
1472 const static insFormat formatEncode4F[4] = {IF_DR_3A, IF_DR_3B, IF_DV_3C, IF_DV_1B};
1473 const static insFormat formatEncode4G[4] = {IF_DR_2E, IF_DR_2F, IF_DV_2M, IF_DV_2L};
1474 const static insFormat formatEncode4H[4] = {IF_DV_3E, IF_DV_3A, IF_DV_2L, IF_DV_2M};
1475 const static insFormat formatEncode4I[4] = {IF_DV_3D, IF_DV_3B, IF_DV_2G, IF_DV_2A};
1476 const static insFormat formatEncode3A[3] = {IF_DR_3A, IF_DR_3B, IF_DI_2C};
1477 const static insFormat formatEncode3B[3] = {IF_DR_2A, IF_DR_2B, IF_DI_1C};
1478 const static insFormat formatEncode3C[3] = {IF_DR_3A, IF_DR_3B, IF_DV_3C};
1479 const static insFormat formatEncode3D[3] = {IF_DV_2C, IF_DV_2D, IF_DV_2E};
1480 const static insFormat formatEncode3E[3] = {IF_DV_3B, IF_DV_3BI, IF_DV_3DI};
1481 const static insFormat formatEncode3F[3] = {IF_DV_2A, IF_DV_2G, IF_DV_2H};
1482 const static insFormat formatEncode3G[3] = {IF_DV_2A, IF_DV_2G, IF_DV_2I};
1483 const static insFormat formatEncode3H[3] = {IF_DR_3A, IF_DV_3A, IF_DV_3AI};
1484 const static insFormat formatEncode3I[3] = {IF_DR_2E, IF_DR_2F, IF_DV_2M};
1485 const static insFormat formatEncode2A[2] = {IF_DR_2E, IF_DR_2F};
1486 const static insFormat formatEncode2B[2] = {IF_DR_3A, IF_DR_3B};
1487 const static insFormat formatEncode2C[2] = {IF_DR_3A, IF_DI_2D};
1488 const static insFormat formatEncode2D[2] = {IF_DR_3A, IF_DI_2B};
1489 const static insFormat formatEncode2E[2] = {IF_LS_3B, IF_LS_3C};
1490 const static insFormat formatEncode2F[2] = {IF_DR_2I, IF_DI_1F};
1491 const static insFormat formatEncode2G[2] = {IF_DV_3B, IF_DV_3D};
1492 const static insFormat formatEncode2H[2] = {IF_DV_2C, IF_DV_2F};
1493 const static insFormat formatEncode2I[2] = {IF_DV_2K, IF_DV_1C};
1494 const static insFormat formatEncode2J[2] = {IF_DV_2A, IF_DV_2G};
1495 const static insFormat formatEncode2K[2] = {IF_DV_2M, IF_DV_2L};
1496 const static insFormat formatEncode2L[2] = {IF_DV_2G, IF_DV_2M};
1497 const static insFormat formatEncode2M[2] = {IF_DV_3A, IF_DV_3AI};
1498 const static insFormat formatEncode2N[2] = {IF_DV_2N, IF_DV_2O};
1499 const static insFormat formatEncode2O[2] = {IF_DV_3E, IF_DV_3A};
1500 const static insFormat formatEncode2P[2] = {IF_DV_2G, IF_DV_3B};
1502 code_t code = BAD_CODE;
1503 insFormat insFmt = emitInsFormat(ins);
1504 bool encoding_found = false;
1510 for (index = 0; index < 9; index++)
1512 if (fmt == formatEncode9[index])
1514 encoding_found = true;
1521 for (index = 0; index < 6; index++)
1523 if (fmt == formatEncode6A[index])
1525 encoding_found = true;
1532 for (index = 0; index < 5; index++)
1534 if (fmt == formatEncode5A[index])
1536 encoding_found = true;
1543 for (index = 0; index < 5; index++)
1545 if (fmt == formatEncode5B[index])
1547 encoding_found = true;
1554 for (index = 0; index < 5; index++)
1556 if (fmt == formatEncode5C[index])
1558 encoding_found = true;
1565 for (index = 0; index < 4; index++)
1567 if (fmt == formatEncode4A[index])
1569 encoding_found = true;
1576 for (index = 0; index < 4; index++)
1578 if (fmt == formatEncode4B[index])
1580 encoding_found = true;
1587 for (index = 0; index < 4; index++)
1589 if (fmt == formatEncode4C[index])
1591 encoding_found = true;
1598 for (index = 0; index < 4; index++)
1600 if (fmt == formatEncode4D[index])
1602 encoding_found = true;
1609 for (index = 0; index < 4; index++)
1611 if (fmt == formatEncode4E[index])
1613 encoding_found = true;
1620 for (index = 0; index < 4; index++)
1622 if (fmt == formatEncode4F[index])
1624 encoding_found = true;
1631 for (index = 0; index < 4; index++)
1633 if (fmt == formatEncode4G[index])
1635 encoding_found = true;
1642 for (index = 0; index < 4; index++)
1644 if (fmt == formatEncode4H[index])
1646 encoding_found = true;
1653 for (index = 0; index < 4; index++)
1655 if (fmt == formatEncode4I[index])
1657 encoding_found = true;
1664 for (index = 0; index < 3; index++)
1666 if (fmt == formatEncode3A[index])
1668 encoding_found = true;
1675 for (index = 0; index < 3; index++)
1677 if (fmt == formatEncode3B[index])
1679 encoding_found = true;
1686 for (index = 0; index < 3; index++)
1688 if (fmt == formatEncode3C[index])
1690 encoding_found = true;
1697 for (index = 0; index < 3; index++)
1699 if (fmt == formatEncode3D[index])
1701 encoding_found = true;
1708 for (index = 0; index < 3; index++)
1710 if (fmt == formatEncode3E[index])
1712 encoding_found = true;
1719 for (index = 0; index < 3; index++)
1721 if (fmt == formatEncode3F[index])
1723 encoding_found = true;
1730 for (index = 0; index < 3; index++)
1732 if (fmt == formatEncode3G[index])
1734 encoding_found = true;
1741 for (index = 0; index < 3; index++)
1743 if (fmt == formatEncode3H[index])
1745 encoding_found = true;
1752 for (index = 0; index < 3; index++)
1754 if (fmt == formatEncode3I[index])
1756 encoding_found = true;
1763 for (index = 0; index < 2; index++)
1765 if (fmt == formatEncode2A[index])
1767 encoding_found = true;
1774 for (index = 0; index < 2; index++)
1776 if (fmt == formatEncode2B[index])
1778 encoding_found = true;
1785 for (index = 0; index < 2; index++)
1787 if (fmt == formatEncode2C[index])
1789 encoding_found = true;
1796 for (index = 0; index < 2; index++)
1798 if (fmt == formatEncode2D[index])
1800 encoding_found = true;
1807 for (index = 0; index < 2; index++)
1809 if (fmt == formatEncode2E[index])
1811 encoding_found = true;
1818 for (index = 0; index < 2; index++)
1820 if (fmt == formatEncode2F[index])
1822 encoding_found = true;
1829 for (index = 0; index < 2; index++)
1831 if (fmt == formatEncode2G[index])
1833 encoding_found = true;
1840 for (index = 0; index < 2; index++)
1842 if (fmt == formatEncode2H[index])
1844 encoding_found = true;
1851 for (index = 0; index < 2; index++)
1853 if (fmt == formatEncode2I[index])
1855 encoding_found = true;
1862 for (index = 0; index < 2; index++)
1864 if (fmt == formatEncode2J[index])
1866 encoding_found = true;
1873 for (index = 0; index < 2; index++)
1875 if (fmt == formatEncode2K[index])
1877 encoding_found = true;
1884 for (index = 0; index < 2; index++)
1886 if (fmt == formatEncode2L[index])
1888 encoding_found = true;
1895 for (index = 0; index < 2; index++)
1897 if (fmt == formatEncode2M[index])
1899 encoding_found = true;
1906 for (index = 0; index < 2; index++)
1908 if (fmt == formatEncode2N[index])
1910 encoding_found = true;
1917 for (index = 0; index < 2; index++)
1919 if (fmt == formatEncode2O[index])
1921 encoding_found = true;
1928 for (index = 0; index < 2; index++)
1930 if (fmt == formatEncode2P[index])
1932 encoding_found = true;
2014 encoding_found = true;
2019 encoding_found = false;
2023 assert(encoding_found);
2028 assert(ins < ArrLen(insCodes1));
2029 code = insCodes1[ins];
2032 assert(ins < ArrLen(insCodes2));
2033 code = insCodes2[ins];
2036 assert(ins < ArrLen(insCodes3));
2037 code = insCodes3[ins];
2040 assert(ins < ArrLen(insCodes4));
2041 code = insCodes4[ins];
2044 assert(ins < ArrLen(insCodes5));
2045 code = insCodes5[ins];
2048 assert(ins < ArrLen(insCodes6));
2049 code = insCodes6[ins];
2052 assert(ins < ArrLen(insCodes7));
2053 code = insCodes7[ins];
2056 assert(ins < ArrLen(insCodes8));
2057 code = insCodes8[ins];
2060 assert(ins < ArrLen(insCodes9));
2061 code = insCodes9[ins];
2065 assert((code != BAD_CODE));
2070 // true if this 'imm' can be encoded as a input operand to a mov instruction
2071 /*static*/ bool emitter::emitIns_valid_imm_for_mov(INT64 imm, emitAttr size)
2073 // Check for "MOV (wide immediate)".
2074 if (canEncodeHalfwordImm(imm, size))
2077 // Next try the ones-complement form of 'halfword immediate' imm(i16,hw),
2078 // namely "MOV (inverted wide immediate)".
2079 ssize_t notOfImm = NOT_helper(imm, getBitWidth(size));
2080 if (canEncodeHalfwordImm(notOfImm, size))
2083 // Finally try "MOV (bitmask immediate)" imm(N,r,s)
2084 if (canEncodeBitMaskImm(imm, size))
2090 // true if this 'imm' can be encoded as a input operand to a vector movi instruction
2091 /*static*/ bool emitter::emitIns_valid_imm_for_movi(INT64 imm, emitAttr elemsize)
2093 if (elemsize == EA_8BYTE)
2098 INT64 loByte = uimm & 0xFF;
2099 if ((loByte == 0) || (loByte == 0xFF))
2113 // First try the standard 'byteShifted immediate' imm(i8,bySh)
2114 if (canEncodeByteShiftedImm(imm, elemsize, true))
2117 // Next try the ones-complement form of the 'immediate' imm(i8,bySh)
2118 ssize_t notOfImm = NOT_helper(imm, getBitWidth(elemsize));
2119 if (canEncodeByteShiftedImm(notOfImm, elemsize, true))
2125 // true if this 'imm' can be encoded as a input operand to a fmov instruction
2126 /*static*/ bool emitter::emitIns_valid_imm_for_fmov(double immDbl)
2128 if (canEncodeFloatImm8(immDbl))
2134 // true if this 'imm' can be encoded as a input operand to an add instruction
2135 /*static*/ bool emitter::emitIns_valid_imm_for_add(INT64 imm, emitAttr size)
2137 if (unsigned_abs(imm) <= 0x0fff)
2139 else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
2145 // true if this 'imm' can be encoded as a input operand to an non-add/sub alu instruction
2146 /*static*/ bool emitter::emitIns_valid_imm_for_cmp(INT64 imm, emitAttr size)
2148 return emitIns_valid_imm_for_add(imm, size);
2151 // true if this 'imm' can be encoded as a input operand to an non-add/sub alu instruction
2152 /*static*/ bool emitter::emitIns_valid_imm_for_alu(INT64 imm, emitAttr size)
2154 if (canEncodeBitMaskImm(imm, size))
2160 // true if this 'imm' can be encoded as the offset in a ldr/str instruction
2161 /*static*/ bool emitter::emitIns_valid_imm_for_ldst_offset(INT64 imm, emitAttr attr)
2164 return true; // Encodable using IF_LS_2A
2166 if ((imm >= -256) && (imm <= 255))
2167 return true; // Encodable using IF_LS_2C (or possibly IF_LS_2B)
2170 return false; // not encodable
2172 emitAttr size = EA_SIZE(attr);
2173 unsigned scale = NaturalScale_helper(size);
2174 ssize_t mask = size - 1; // the mask of low bits that must be zero to encode the immediate
2176 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
2177 return true; // Encodable using IF_LS_2B
2179 return false; // not encodable
2182 /************************************************************************
2184 * A helper method to return the natural scale for an EA 'size'
2187 /*static*/ unsigned emitter::NaturalScale_helper(emitAttr size)
2189 assert(size == EA_1BYTE || size == EA_2BYTE || size == EA_4BYTE || size == EA_8BYTE || size == EA_16BYTE);
2191 unsigned result = 0;
2192 unsigned utemp = (unsigned)size;
2194 // Compute log base 2 of utemp (aka 'size')
2204 /************************************************************************
2206 * A helper method to perform a Rotate-Right shift operation
2207 * the source is 'value' and it is rotated right by 'sh' bits
2208 * 'value' is considered to be a fixed size 'width' set of bits.
2211 * value is '00001111', sh is 2 and width is 8
2212 * result is '11000011'
2215 /*static*/ UINT64 emitter::ROR_helper(UINT64 value, unsigned sh, unsigned width)
2217 assert(width <= 64);
2218 // Check that 'value' fits in 'width' bits
2219 assert((width == 64) || (value < (1ULL << width)));
2220 // We don't support shifts >= width
2226 unsigned lsh = width - rsh;
2228 result = (value >> rsh);
2229 result |= (value << lsh);
2233 // mask off any extra bits that we got from the left shift
2234 result &= ((1ULL << width) - 1);
2238 /************************************************************************
2240 * A helper method to perform a 'NOT' bitwise complement operation.
2241 * 'value' is considered to be a fixed size 'width' set of bits.
2244 * value is '01001011', and width is 8
2245 * result is '10110100'
2248 /*static*/ UINT64 emitter::NOT_helper(UINT64 value, unsigned width)
2250 assert(width <= 64);
2252 UINT64 result = ~value;
2256 // Check that 'value' fits in 'width' bits. Don't consider "sign" bits above width.
2257 UINT64 maxVal = 1ULL << width;
2258 UINT64 lowBitsMask = maxVal - 1;
2259 UINT64 signBitsMask = ~lowBitsMask | (1ULL << (width - 1)); // The high bits must be set, and the top bit
2260 // (sign bit) must be set.
2261 assert((value < maxVal) || ((value & signBitsMask) == signBitsMask));
2263 // mask off any extra bits that we got from the complement operation
2264 result &= lowBitsMask;
2270 /************************************************************************
2272 * A helper method to perform a bit Replicate operation
2273 * the source is 'value' with a fixed size 'width' set of bits.
2274 * value is replicated to fill out 32 or 64 bits as determined by 'size'.
2277 * value is '11000011' (0xE3), width is 8 and size is EA_8BYTE
2278 * result is '11000011 11000011 11000011 11000011 11000011 11000011 11000011 11000011'
2279 * 0xE3E3E3E3E3E3E3E3
2282 /*static*/ UINT64 emitter::Replicate_helper(UINT64 value, unsigned width, emitAttr size)
2284 assert(emitter::isValidGeneralDatasize(size));
2286 unsigned immWidth = (size == EA_8BYTE) ? 64 : 32;
2287 assert(width <= immWidth);
2289 UINT64 result = value;
2290 unsigned filledBits = width;
2292 while (filledBits < immWidth)
2296 filledBits += width;
2301 /************************************************************************
2303 * Convert an imm(N,r,s) into a 64-bit immediate
2304 * inputs 'bmImm' a bitMaskImm struct
2305 * 'size' specifies the size of the result (64 or 32 bits)
2308 /*static*/ INT64 emitter::emitDecodeBitMaskImm(const emitter::bitMaskImm bmImm, emitAttr size)
2310 assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2312 unsigned N = bmImm.immN; // read the N,R and S values from the 'bitMaskImm' encoding
2313 unsigned R = bmImm.immR;
2314 unsigned S = bmImm.immS;
2316 unsigned elemWidth = 64; // used when immN == 1
2318 if (bmImm.immN == 0) // find the smaller elemWidth when immN == 0
2320 // Scan S for the highest bit not set
2322 for (unsigned bitNum = 5; bitNum > 0; bitNum--)
2324 unsigned oneBit = elemWidth;
2325 if ((S & oneBit) == 0)
2332 assert(size == EA_8BYTE);
2335 unsigned maskSR = elemWidth - 1;
2340 // encoding for S is one less than the number of consecutive one bits
2341 S++; // Number of consecutive ones to generate in 'welem'
2345 // 'elemWidth' is the number of bits that we will use for the ROR and Replicate operations
2346 // 'S' is the number of consecutive 1 bits for the immediate
2347 // 'R' is the number of bits that we will Rotate Right the immediate
2348 // 'size' selects the final size of the immedate that we return (64 or 32 bits)
2350 assert(S < elemWidth); // 'elemWidth' consecutive one's is a reserved encoding
2355 welem = (1ULL << S) - 1;
2357 wmask = ROR_helper(welem, R, elemWidth);
2358 wmask = Replicate_helper(wmask, elemWidth, size);
2363 /*****************************************************************************
2365 * Check if an immediate can use the left shifted by 12 bits encoding
2368 /*static*/ bool emitter::canEncodeWithShiftImmBy12(INT64 imm)
2372 imm = -imm; // convert to unsigned
2377 return false; // Must be MIN_INT64
2380 if ((imm & 0xfff) != 0) // Now the low 12 bits all have to be zero
2385 imm >>= 12; // shift right by 12 bits
2387 return (imm <= 0x0fff); // Does it fit in 12 bits
2390 /*****************************************************************************
2392 * Normalize the 'imm' so that the upper bits, as defined by 'size' are zero
2395 /*static*/ INT64 emitter::normalizeImm64(INT64 imm, emitAttr size)
2397 unsigned immWidth = getBitWidth(size);
2402 // Check that 'imm' fits in 'immWidth' bits. Don't consider "sign" bits above width.
2403 INT64 maxVal = 1LL << immWidth;
2404 INT64 lowBitsMask = maxVal - 1;
2405 INT64 hiBitsMask = ~lowBitsMask;
2406 INT64 signBitsMask =
2407 hiBitsMask | (1LL << (immWidth - 1)); // The high bits must be set, and the top bit (sign bit) must be set.
2408 assert((imm < maxVal) || ((imm & signBitsMask) == signBitsMask));
2410 // mask off the hiBits
2411 result &= lowBitsMask;
2416 /*****************************************************************************
2418 * Normalize the 'imm' so that the upper bits, as defined by 'size' are zero
2421 /*static*/ INT32 emitter::normalizeImm32(INT32 imm, emitAttr size)
2423 unsigned immWidth = getBitWidth(size);
2428 // Check that 'imm' fits in 'immWidth' bits. Don't consider "sign" bits above width.
2429 INT32 maxVal = 1 << immWidth;
2430 INT32 lowBitsMask = maxVal - 1;
2431 INT32 hiBitsMask = ~lowBitsMask;
2432 INT32 signBitsMask = hiBitsMask | (1 << (immWidth - 1)); // The high bits must be set, and the top bit
2433 // (sign bit) must be set.
2434 assert((imm < maxVal) || ((imm & signBitsMask) == signBitsMask));
2436 // mask off the hiBits
2437 result &= lowBitsMask;
2442 /************************************************************************
2444 * returns true if 'imm' of 'size bits (32/64) can be encoded
2445 * using the ARM64 'bitmask immediate' form.
2446 * When a non-null value is passed for 'wbBMI' then this method
2447 * writes back the 'N','S' and 'R' values use to encode this immediate
2451 /*static*/ bool emitter::canEncodeBitMaskImm(INT64 imm, emitAttr size, emitter::bitMaskImm* wbBMI)
2453 assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2455 unsigned immWidth = (size == EA_8BYTE) ? 64 : 32;
2456 unsigned maxLen = (size == EA_8BYTE) ? 6 : 5;
2458 imm = normalizeImm64(imm, size);
2460 // Starting with len=1, elemWidth is 2 bits
2461 // len=2, elemWidth is 4 bits
2462 // len=3, elemWidth is 8 bits
2463 // len=4, elemWidth is 16 bits
2464 // len=5, elemWidth is 32 bits
2465 // (optionally) len=6, elemWidth is 64 bits
2467 for (unsigned len = 1; (len <= maxLen); len++)
2469 unsigned elemWidth = 1 << len;
2470 UINT64 elemMask = ((UINT64)-1) >> (64 - elemWidth);
2471 UINT64 tempImm = (UINT64)imm; // A working copy of 'imm' that we can mutate
2472 UINT64 elemVal = tempImm & elemMask; // The low 'elemWidth' bits of 'imm'
2474 // Check for all 1's or 0's as these can't be encoded
2475 if ((elemVal == 0) || (elemVal == elemMask))
2478 // 'checkedBits' is the count of bits that are known to match 'elemVal' when replicated
2479 unsigned checkedBits = elemWidth; // by definition the first 'elemWidth' bits match
2481 // Now check to see if each of the next bits match...
2483 while (checkedBits < immWidth)
2485 tempImm >>= elemWidth;
2487 UINT64 nextElem = tempImm & elemMask;
2488 if (nextElem != elemVal)
2490 // Not matching, exit this loop and checkedBits will not be equal to immWidth
2494 // The 'nextElem' is matching, so increment 'checkedBits'
2495 checkedBits += elemWidth;
2498 // Did the full immediate contain bits that can be formed by repeating 'elemVal'?
2499 if (checkedBits == immWidth)
2501 // We are not quite done, since the only values that we can encode as a
2502 // 'bitmask immediate' are those that can be formed by starting with a
2503 // bit string of 0*1* that is rotated by some number of bits.
2505 // We check to see if 'elemVal' can be formed using these restrictions.
2508 // Rotating by one bit any value that passes these restrictions
2509 // can be xor-ed with the original value and will result it a string
2510 // of bits that have exactly two 1 bits: 'elemRorXor'
2511 // Further the distance between the two one bits tells us the value
2512 // of S and the location of the 1 bits tells us the value of R
2514 // Some examples: (immWidth is 8)
2516 // S=4,R=0 S=5,R=3 S=3,R=6
2517 // elemVal: 00001111 11100011 00011100
2518 // elemRor: 10000111 11110001 00001110
2519 // elemRorXor: 10001000 00010010 00010010
2520 // compute S 45678--- ---5678- ---3210-
2521 // compute R 01234567 ---34567 ------67
2523 UINT64 elemRor = ROR_helper(elemVal, 1, elemWidth); // Rotate 'elemVal' Right by one bit
2524 UINT64 elemRorXor = elemVal ^ elemRor; // Xor elemVal and elemRor
2526 // If we only have a two-bit change in elemROR then we can form a mask for this value
2527 unsigned bitCount = 0;
2528 UINT64 oneBit = 0x1;
2529 unsigned R = elemWidth; // R is shift count for ROR (rotate right shift)
2530 unsigned S = 0; // S is number of consecutive one bits
2533 // Loop over the 'elemWidth' bits in 'elemRorXor'
2535 for (unsigned bitNum = 0; bitNum < elemWidth; bitNum++)
2539 R--; // We decrement R by one whenever incr is -1
2543 S += incr; // We incr/decr S, after we find the first one bit in 'elemRorXor'
2546 // Is this bit position a 1 bit in 'elemRorXor'?
2548 if (oneBit & elemRorXor)
2551 // Is this the first 1 bit that we found in 'elemRorXor'?
2554 // Does this 1 bit represent a transition to zero bits?
2555 bool toZeros = ((oneBit & elemVal) != 0);
2558 // S :: Count down from elemWidth
2562 else // this 1 bit represent a transition to one bits.
2564 // S :: Count up from zero
2569 else // bitCount > 1
2571 // We found the second (or third...) 1 bit in 'elemRorXor'
2572 incr = 0; // stop decrementing 'R'
2576 // More than 2 transitions from 0/1 in 'elemVal'
2577 // This means that 'elemVal' can't be encoded
2578 // using a 'bitmask immediate'.
2580 // Furthermore, it will continue to fail
2581 // with any larger 'len' that we try.
2582 // so just return false.
2589 // shift oneBit left by one bit to test the next position
2593 // We expect that bitCount will always be two at this point
2594 // but just in case return false for any bad cases.
2596 assert(bitCount == 2);
2600 // Perform some sanity checks on the values of 'S' and 'R'
2602 assert(S < elemWidth);
2603 assert(R < elemWidth);
2605 // Does the caller want us to return the N,R,S encoding values?
2607 if (wbBMI != nullptr)
2610 // The encoding used for S is one less than the
2611 // number of consecutive one bits
2621 // The encoding used for 'S' here is a bit peculiar.
2623 // The upper bits need to be complemented, followed by a zero bit
2624 // then the value of 'S-1'
2626 unsigned upperBitsOfS = 64 - (1 << (len + 1));
2632 // Verify that what we are returning is correct.
2633 assert(imm == emitDecodeBitMaskImm(*wbBMI, size));
2635 // Tell the caller that we can successfully encode this immediate
2636 // using a 'bitmask immediate'.
2644 /************************************************************************
2646 * Convert a 64-bit immediate into its 'bitmask immediate' representation imm(N,r,s)
2649 /*static*/ emitter::bitMaskImm emitter::emitEncodeBitMaskImm(INT64 imm, emitAttr size)
2651 emitter::bitMaskImm result;
2654 bool canEncode = canEncodeBitMaskImm(imm, size, &result);
2660 /************************************************************************
2662 * Convert an imm(i16,hw) into a 32/64-bit immediate
2663 * inputs 'hwImm' a halfwordImm struct
2664 * 'size' specifies the size of the result (64 or 32 bits)
2667 /*static*/ INT64 emitter::emitDecodeHalfwordImm(const emitter::halfwordImm hwImm, emitAttr size)
2669 assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2671 unsigned hw = hwImm.immHW;
2672 INT64 val = (INT64)hwImm.immVal;
2674 assert((hw <= 1) || (size == EA_8BYTE));
2676 INT64 result = val << (16 * hw);
2680 /************************************************************************
2682 * returns true if 'imm' of 'size' bits (32/64) can be encoded
2683 * using the ARM64 'halfword immediate' form.
2684 * When a non-null value is passed for 'wbHWI' then this method
2685 * writes back the 'immHW' and 'immVal' values use to encode this immediate
2689 /*static*/ bool emitter::canEncodeHalfwordImm(INT64 imm, emitAttr size, emitter::halfwordImm* wbHWI)
2691 assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2693 unsigned immWidth = (size == EA_8BYTE) ? 64 : 32;
2694 unsigned maxHW = (size == EA_8BYTE) ? 4 : 2;
2696 // setup immMask to a (EA_4BYTE) 0x00000000_FFFFFFFF or (EA_8BYTE) 0xFFFFFFFF_FFFFFFFF
2697 const UINT64 immMask = ((UINT64)-1) >> (64 - immWidth);
2698 const INT64 mask16 = (INT64)0xFFFF;
2700 imm = normalizeImm64(imm, size);
2702 // Try each of the valid hw shift sizes
2703 for (unsigned hw = 0; (hw < maxHW); hw++)
2705 INT64 curMask = mask16 << (hw * 16); // Represents the mask of the bits in the current halfword
2706 INT64 checkBits = immMask & ~curMask;
2708 // Excluding the current halfword (using ~curMask)
2709 // does the immediate have zero bits in every other bit that we care about?
2710 // note we care about all 64-bits for EA_8BYTE
2711 // and we care about the lowest 32 bits for EA_4BYTE
2713 if ((imm & checkBits) == 0)
2715 // Does the caller want us to return the imm(i16,hw) encoding values?
2717 if (wbHWI != nullptr)
2719 INT64 val = ((imm & curMask) >> (hw * 16)) & mask16;
2721 wbHWI->immVal = val;
2723 // Verify that what we are returning is correct.
2724 assert(imm == emitDecodeHalfwordImm(*wbHWI, size));
2726 // Tell the caller that we can successfully encode this immediate
2727 // using a 'halfword immediate'.
2735 /************************************************************************
2737 * Convert a 64-bit immediate into its 'halfword immediate' representation imm(i16,hw)
2740 /*static*/ emitter::halfwordImm emitter::emitEncodeHalfwordImm(INT64 imm, emitAttr size)
2742 emitter::halfwordImm result;
2743 result.immHWVal = 0;
2745 bool canEncode = canEncodeHalfwordImm(imm, size, &result);
2751 /************************************************************************
2753 * Convert an imm(i8,sh) into a 16/32-bit immediate
2754 * inputs 'bsImm' a byteShiftedImm struct
2755 * 'size' specifies the size of the result (16 or 32 bits)
2758 /*static*/ INT32 emitter::emitDecodeByteShiftedImm(const emitter::byteShiftedImm bsImm, emitAttr size)
2760 bool onesShift = (bsImm.immOnes == 1);
2761 unsigned bySh = bsImm.immBY; // Num Bytes to shift 0,1,2,3
2762 INT32 val = (INT32)bsImm.immVal; // 8-bit immediate
2767 assert((size == EA_2BYTE) || (size == EA_4BYTE)); // Only EA_2BYTE or EA_4BYTE forms
2768 if (size == EA_2BYTE)
2777 result <<= (8 * bySh);
2781 result |= ((1 << (8 * bySh)) - 1);
2787 /************************************************************************
2789 * returns true if 'imm' of 'size' bits (16/32) can be encoded
2790 * using the ARM64 'byteShifted immediate' form.
2791 * When a non-null value is passed for 'wbBSI' then this method
2792 * writes back the 'immBY' and 'immVal' values use to encode this immediate
2796 /*static*/ bool emitter::canEncodeByteShiftedImm(INT64 imm,
2799 emitter::byteShiftedImm* wbBSI)
2801 bool canEncode = false;
2802 bool onesShift = false; // true if we use the shifting ones variant
2803 unsigned bySh = 0; // number of bytes to shift: 0, 1, 2, 3
2804 unsigned imm8 = 0; // immediate to use in the encoding
2806 imm = normalizeImm64(imm, size);
2808 if (size == EA_1BYTE)
2810 imm8 = (unsigned)imm;
2811 assert(imm8 < 0x100);
2814 else if (size == EA_8BYTE)
2816 imm8 = (unsigned)imm;
2817 assert(imm8 < 0x100);
2822 assert((size == EA_2BYTE) || (size == EA_4BYTE)); // Only EA_2BYTE or EA_4BYTE forms
2824 unsigned immWidth = (size == EA_4BYTE) ? 32 : 16;
2825 unsigned maxBY = (size == EA_4BYTE) ? 4 : 2;
2827 // setup immMask to a (EA_2BYTE) 0x0000FFFF or (EA_4BYTE) 0xFFFFFFFF
2828 const UINT32 immMask = ((UINT32)-1) >> (32 - immWidth);
2829 const INT32 mask8 = (INT32)0xFF;
2831 // Try each of the valid by shift sizes
2832 for (bySh = 0; (bySh < maxBY); bySh++)
2834 INT32 curMask = mask8 << (bySh * 8); // Represents the mask of the bits in the current byteShifted
2835 INT32 checkBits = immMask & ~curMask;
2836 INT32 immCheck = (imm & checkBits);
2838 // Excluding the current byte (using ~curMask)
2839 // does the immediate have zero bits in every other bit that we care about?
2840 // or can be use the shifted one variant?
2841 // note we care about all 32-bits for EA_4BYTE
2842 // and we care about the lowest 16 bits for EA_2BYTE
2850 if ((bySh == 1) && (immCheck == 0xFF))
2855 else if ((bySh == 2) && (immCheck == 0xFFFF))
2863 imm8 = (unsigned)(((imm & curMask) >> (bySh * 8)) & mask8);
2871 // Does the caller want us to return the imm(i8,bySh) encoding values?
2873 if (wbBSI != nullptr)
2875 wbBSI->immOnes = onesShift;
2876 wbBSI->immBY = bySh;
2877 wbBSI->immVal = imm8;
2879 // Verify that what we are returning is correct.
2880 assert(imm == emitDecodeByteShiftedImm(*wbBSI, size));
2882 // Tell the caller that we can successfully encode this immediate
2883 // using a 'byteShifted immediate'.
2890 /************************************************************************
2892 * Convert a 32-bit immediate into its 'byteShifted immediate' representation imm(i8,by)
2895 /*static*/ emitter::byteShiftedImm emitter::emitEncodeByteShiftedImm(INT64 imm, emitAttr size, bool allow_MSL)
2897 emitter::byteShiftedImm result;
2898 result.immBSVal = 0;
2900 bool canEncode = canEncodeByteShiftedImm(imm, size, allow_MSL, &result);
2906 /************************************************************************
2908 * Convert a 'float 8-bit immediate' into a double.
2909 * inputs 'fpImm' a floatImm8 struct
2912 /*static*/ double emitter::emitDecodeFloatImm8(const emitter::floatImm8 fpImm)
2914 unsigned sign = fpImm.immSign;
2915 unsigned exp = fpImm.immExp ^ 0x4;
2916 unsigned mant = fpImm.immMant + 16;
2917 unsigned scale = 16 * 8;
2925 double result = ((double)mant) / ((double)scale);
2934 /************************************************************************
2936 * returns true if the 'immDbl' can be encoded using the 'float 8-bit immediate' form.
2937 * also returns the encoding if wbFPI is non-null
2941 /*static*/ bool emitter::canEncodeFloatImm8(double immDbl, emitter::floatImm8* wbFPI)
2943 bool canEncode = false;
2944 double val = immDbl;
2954 while ((val < 1.0) && (exp >= -4))
2959 while ((val >= 2.0) && (exp <= 5))
2966 int ival = (int)val;
2968 if ((exp >= 0) && (exp <= 7))
2970 if (val == (double)ival)
2974 if (wbFPI != nullptr)
2977 assert((ival >= 0) && (ival <= 15));
2979 wbFPI->immSign = sign;
2980 wbFPI->immExp = exp ^ 0x4;
2981 wbFPI->immMant = ival;
2982 unsigned imm8 = wbFPI->immFPIVal;
2983 assert((imm8 >= 0) && (imm8 <= 0xff));
2991 /************************************************************************
2993 * Convert a double into its 'float 8-bit immediate' representation
2996 /*static*/ emitter::floatImm8 emitter::emitEncodeFloatImm8(double immDbl)
2998 emitter::floatImm8 result;
2999 result.immFPIVal = 0;
3001 bool canEncode = canEncodeFloatImm8(immDbl, &result);
3007 /*****************************************************************************
3009 * For the given 'ins' returns the reverse instruction
3010 * if one exists, otherwise returns INS_INVALID
3013 /*static*/ instruction emitter::insReverse(instruction ins)
3042 /*****************************************************************************
3044 * For the given 'datasize' and 'elemsize', make the proper arrangement option
3045 * returns the insOpts that specifies the vector register arrangement
3046 * if one does not exist returns INS_OPTS_NONE
3049 /*static*/ insOpts emitter::optMakeArrangement(emitAttr datasize, emitAttr elemsize)
3051 insOpts result = INS_OPTS_NONE;
3053 if (datasize == EA_8BYTE)
3058 result = INS_OPTS_8B;
3061 result = INS_OPTS_4H;
3064 result = INS_OPTS_2S;
3067 result = INS_OPTS_1D;
3074 else if (datasize == EA_16BYTE)
3079 result = INS_OPTS_16B;
3082 result = INS_OPTS_8H;
3085 result = INS_OPTS_4S;
3088 result = INS_OPTS_2D;
3098 /*****************************************************************************
3100 * For the given 'datasize' and arrangement 'opts'
3101 * returns true is the pair spcifies a valid arrangement
3103 /*static*/ bool emitter::isValidArrangement(emitAttr datasize, insOpts opt)
3105 if (datasize == EA_8BYTE)
3107 if ((opt == INS_OPTS_8B) || (opt == INS_OPTS_4H) || (opt == INS_OPTS_2S) || (opt == INS_OPTS_1D))
3112 else if (datasize == EA_16BYTE)
3114 if ((opt == INS_OPTS_16B) || (opt == INS_OPTS_8H) || (opt == INS_OPTS_4S) || (opt == INS_OPTS_2D))
3122 // For the given 'arrangement' returns the 'datasize' specified by the vector register arrangement
3123 // asserts and returns EA_UNKNOWN if an invalid 'arrangement' value is passed
3125 /*static*/ emitAttr emitter::optGetDatasize(insOpts arrangement)
3127 if ((arrangement == INS_OPTS_8B) || (arrangement == INS_OPTS_4H) || (arrangement == INS_OPTS_2S) ||
3128 (arrangement == INS_OPTS_1D))
3132 else if ((arrangement == INS_OPTS_16B) || (arrangement == INS_OPTS_8H) || (arrangement == INS_OPTS_4S) ||
3133 (arrangement == INS_OPTS_2D))
3139 assert(!" invalid 'arrangement' value");
3144 // For the given 'arrangement' returns the 'elemsize' specified by the vector register arrangement
3145 // asserts and returns EA_UNKNOWN if an invalid 'arrangement' value is passed
3147 /*static*/ emitAttr emitter::optGetElemsize(insOpts arrangement)
3149 if ((arrangement == INS_OPTS_8B) || (arrangement == INS_OPTS_16B))
3153 else if ((arrangement == INS_OPTS_4H) || (arrangement == INS_OPTS_8H))
3157 else if ((arrangement == INS_OPTS_2S) || (arrangement == INS_OPTS_4S))
3161 else if ((arrangement == INS_OPTS_1D) || (arrangement == INS_OPTS_2D))
3167 assert(!" invalid 'arrangement' value");
3172 // For the given 'arrangement' returns the 'widen-arrangement' specified by the vector register arrangement
3173 // asserts and returns INS_OPTS_NONE if an invalid 'arrangement' value is passed
3175 /*static*/ insOpts emitter::optWidenElemsize(insOpts arrangement)
3177 if ((arrangement == INS_OPTS_8B) || (arrangement == INS_OPTS_16B))
3181 else if ((arrangement == INS_OPTS_4H) || (arrangement == INS_OPTS_8H))
3185 else if ((arrangement == INS_OPTS_2S) || (arrangement == INS_OPTS_4S))
3191 assert(!" invalid 'arrangement' value");
3192 return INS_OPTS_NONE;
3196 // For the given 'conversion' returns the 'dstsize' specified by the conversion option
3197 /*static*/ emitAttr emitter::optGetDstsize(insOpts conversion)
3201 case INS_OPTS_S_TO_8BYTE:
3202 case INS_OPTS_D_TO_8BYTE:
3203 case INS_OPTS_4BYTE_TO_D:
3204 case INS_OPTS_8BYTE_TO_D:
3205 case INS_OPTS_S_TO_D:
3206 case INS_OPTS_H_TO_D:
3210 case INS_OPTS_S_TO_4BYTE:
3211 case INS_OPTS_D_TO_4BYTE:
3212 case INS_OPTS_4BYTE_TO_S:
3213 case INS_OPTS_8BYTE_TO_S:
3214 case INS_OPTS_D_TO_S:
3215 case INS_OPTS_H_TO_S:
3219 case INS_OPTS_S_TO_H:
3220 case INS_OPTS_D_TO_H:
3225 assert(!" invalid 'conversion' value");
3230 // For the given 'conversion' returns the 'srcsize' specified by the conversion option
3231 /*static*/ emitAttr emitter::optGetSrcsize(insOpts conversion)
3235 case INS_OPTS_D_TO_8BYTE:
3236 case INS_OPTS_D_TO_4BYTE:
3237 case INS_OPTS_8BYTE_TO_D:
3238 case INS_OPTS_8BYTE_TO_S:
3239 case INS_OPTS_D_TO_S:
3240 case INS_OPTS_D_TO_H:
3244 case INS_OPTS_S_TO_8BYTE:
3245 case INS_OPTS_S_TO_4BYTE:
3246 case INS_OPTS_4BYTE_TO_S:
3247 case INS_OPTS_4BYTE_TO_D:
3248 case INS_OPTS_S_TO_D:
3249 case INS_OPTS_S_TO_H:
3253 case INS_OPTS_H_TO_S:
3254 case INS_OPTS_H_TO_D:
3259 assert(!" invalid 'conversion' value");
3264 // For the given 'size' and 'index' returns true if it specifies a valid index for a vector register of 'size'
3265 /*static*/ bool emitter::isValidVectorIndex(emitAttr datasize, emitAttr elemsize, ssize_t index)
3267 assert(isValidVectorDatasize(datasize));
3268 assert(isValidVectorElemsize(elemsize));
3270 bool result = false;
3273 if (datasize == EA_8BYTE)
3278 result = (index < 8);
3281 result = (index < 4);
3284 result = (index < 2);
3287 result = (index < 1);
3294 else if (datasize == EA_16BYTE)
3299 result = (index < 16);
3302 result = (index < 8);
3305 result = (index < 4);
3308 result = (index < 2);
3319 /*****************************************************************************
3321 * Add an instruction with no operands.
3324 void emitter::emitIns(instruction ins)
3326 instrDesc* id = emitNewInstrSmall(EA_8BYTE);
3327 insFormat fmt = emitInsFormat(ins);
3329 assert(fmt == IF_SN_0A);
3338 /*****************************************************************************
3340 * Add an instruction with a single immediate value.
3343 void emitter::emitIns_I(instruction ins, emitAttr attr, ssize_t imm)
3345 insFormat fmt = IF_NONE;
3347 /* Figure out the encoding format of the instruction */
3351 if ((imm & 0x0000ffff) == imm)
3357 assert(!"Instruction cannot be encoded: IF_SI_0A");
3364 assert(fmt != IF_NONE);
3366 instrDesc* id = emitNewInstrSC(attr, imm);
3375 /*****************************************************************************
3377 * Add an instruction referencing a single register.
3380 void emitter::emitIns_R(instruction ins, emitAttr attr, regNumber reg)
3382 emitAttr size = EA_SIZE(attr);
3383 insFormat fmt = IF_NONE;
3384 instrDesc* id = nullptr;
3386 /* Figure out the encoding format of the instruction */
3391 assert(isGeneralRegister(reg));
3392 id = emitNewInstrSmall(attr);
3401 assert(fmt != IF_NONE);
3410 /*****************************************************************************
3412 * Add an instruction referencing a register and a constant.
3415 void emitter::emitIns_R_I(instruction ins, emitAttr attr, regNumber reg, ssize_t imm, insOpts opt /* = INS_OPTS_NONE */)
3417 emitAttr size = EA_SIZE(attr);
3418 emitAttr elemsize = EA_UNKNOWN;
3419 insFormat fmt = IF_NONE;
3420 bool canEncode = false;
3422 /* Figure out the encoding format of the instruction */
3431 assert(insOptsNone(opt));
3432 assert(isGeneralRegister(reg));
3434 canEncode = canEncodeBitMaskImm(imm, size, &bmi);
3438 assert(isValidImmNRS(imm, size));
3446 assert(isValidGeneralDatasize(size));
3447 assert(insOptsNone(opt)); // No LSL here (you must use emitIns_R_I_I if a shift is needed)
3448 assert(isGeneralRegister(reg));
3449 assert(isValidUimm16(imm));
3453 assert(imm == emitDecodeHalfwordImm(hwi, size));
3461 assert(isValidGeneralDatasize(size));
3462 assert(insOptsNone(opt)); // No explicit LSL here
3463 // We will automatically determine the shift based upon the imm
3465 // First try the standard 'halfword immediate' imm(i16,hw)
3467 canEncode = canEncodeHalfwordImm(imm, size, &hwi);
3470 // uses a movz encoding
3471 assert(isGeneralRegister(reg));
3473 assert(isValidImmHWVal(imm, size));
3478 // Next try the ones-complement form of 'halfword immediate' imm(i16,hw)
3479 notOfImm = NOT_helper(imm, getBitWidth(size));
3480 canEncode = canEncodeHalfwordImm(notOfImm, size, &hwi);
3483 assert(isGeneralRegister(reg));
3485 ins = INS_movn; // uses a movn encoding
3486 assert(isValidImmHWVal(imm, size));
3491 // Finally try the 'bitmask immediate' imm(N,r,s)
3493 canEncode = canEncodeBitMaskImm(imm, size, &bmi);
3496 assert(isGeneralRegisterOrSP(reg));
3497 reg = encodingSPtoZR(reg);
3499 assert(isValidImmNRS(imm, size));
3505 assert(!"Instruction cannot be encoded: mov imm");
3511 assert(isValidVectorDatasize(size));
3512 assert(isVectorRegister(reg));
3513 if (insOptsNone(opt) && (size == EA_8BYTE))
3517 assert(isValidArrangement(size, opt));
3518 elemsize = optGetElemsize(opt);
3520 if (elemsize == EA_8BYTE)
3526 bool failed = false;
3529 INT64 loByte = uimm & 0xFF;
3530 if (((loByte == 0) || (loByte == 0xFF)) && (pos < 8))
3546 assert(isValidUimm8(imm));
3554 // No explicit LSL/MSL is used for the immediate
3555 // We will automatically determine the shift based upon the value of imm
3557 // First try the standard 'byteShifted immediate' imm(i8,bySh)
3559 canEncode = canEncodeByteShiftedImm(imm, elemsize, true, &bsi);
3563 assert(isValidImmBSVal(imm, size));
3568 // Next try the ones-complement form of the 'immediate' imm(i8,bySh)
3569 if ((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE)) // Only EA_2BYTE or EA_4BYTE forms
3571 notOfImm = NOT_helper(imm, getBitWidth(elemsize));
3572 canEncode = canEncodeByteShiftedImm(notOfImm, elemsize, true, &bsi);
3576 ins = INS_mvni; // uses a mvni encoding
3577 assert(isValidImmBSVal(imm, size));
3588 assert(isValidVectorDatasize(size));
3589 assert(isVectorRegister(reg));
3590 assert(isValidArrangement(size, opt));
3591 elemsize = optGetElemsize(opt);
3592 assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE)); // Only EA_2BYTE or EA_4BYTE forms
3596 // No explicit LSL/MSL is used for the immediate
3597 // We will automatically determine the shift based upon the value of imm
3599 // First try the standard 'byteShifted immediate' imm(i8,bySh)
3601 canEncode = canEncodeByteShiftedImm(imm, elemsize,
3602 (ins == INS_mvni), // mvni supports the ones shifting variant (aka MSL)
3607 assert(isValidImmBSVal(imm, size));
3615 assert(insOptsNone(opt));
3616 assert(isGeneralRegister(reg));
3618 if (unsigned_abs(imm) <= 0x0fff)
3622 ins = insReverse(ins);
3625 assert(isValidUimm12(imm));
3629 else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
3631 // Encoding will use a 12-bit left shift of the immediate
3632 opt = INS_OPTS_LSL12;
3635 ins = insReverse(ins);
3638 assert((imm & 0xfff) == 0);
3640 assert(isValidUimm12(imm));
3646 assert(!"Instruction cannot be encoded: IF_DI_1A");
3654 } // end switch (ins)
3657 assert(fmt != IF_NONE);
3659 instrDesc* id = emitNewInstrSC(attr, imm);
3671 /*****************************************************************************
3673 * Add an instruction referencing a register and a floating point constant.
3676 void emitter::emitIns_R_F(
3677 instruction ins, emitAttr attr, regNumber reg, double immDbl, insOpts opt /* = INS_OPTS_NONE */)
3680 emitAttr size = EA_SIZE(attr);
3681 emitAttr elemsize = EA_UNKNOWN;
3682 insFormat fmt = IF_NONE;
3684 bool canEncode = false;
3686 /* Figure out the encoding format of the instruction */
3693 assert(insOptsNone(opt));
3694 assert(isValidVectorElemsizeFloat(size));
3695 assert(isVectorRegister(reg));
3704 assert(isVectorRegister(reg));
3706 canEncode = canEncodeFloatImm8(immDbl, &fpi);
3708 if (insOptsAnyArrangement(opt))
3711 assert(isValidVectorDatasize(size));
3712 assert(isValidArrangement(size, opt));
3713 elemsize = optGetElemsize(opt);
3714 assert(isValidVectorElemsizeFloat(elemsize));
3715 assert(opt != INS_OPTS_1D); // Reserved encoding
3719 imm = fpi.immFPIVal;
3720 assert((imm >= 0) && (imm <= 0xff));
3727 assert(insOptsNone(opt));
3728 assert(isValidVectorElemsizeFloat(size));
3732 imm = fpi.immFPIVal;
3733 assert((imm >= 0) && (imm <= 0xff));
3743 } // end switch (ins)
3746 assert(fmt != IF_NONE);
3748 instrDesc* id = emitNewInstrSC(attr, imm);
3760 /*****************************************************************************
3762 * Add an instruction referencing two registers
3765 void emitter::emitIns_R_R(
3766 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insOpts opt /* = INS_OPTS_NONE */)
3768 emitAttr size = EA_SIZE(attr);
3769 emitAttr elemsize = EA_UNKNOWN;
3770 insFormat fmt = IF_NONE;
3772 /* Figure out the encoding format of the instruction */
3776 assert(insOptsNone(opt));
3777 // Is the mov even necessary?
3780 // A mov with a EA_4BYTE has the side-effect of clearing the upper bits
3781 // So only eliminate mov instructions that are not clearing the upper bits
3783 if (isGeneralRegisterOrSP(reg1) && (size == EA_8BYTE))
3787 else if (isVectorRegister(reg1) && (size == EA_16BYTE))
3793 // Check for the 'mov' aliases for the vector registers
3794 if (isVectorRegister(reg1))
3796 if (isVectorRegister(reg2) && isValidVectorDatasize(size))
3798 return emitIns_R_R_R(INS_mov, size, reg1, reg2, reg2);
3802 return emitIns_R_R_I(INS_mov, size, reg1, reg2, 0);
3807 if (isVectorRegister(reg2))
3809 assert(isGeneralRegister(reg1));
3810 return emitIns_R_R_I(INS_mov, size, reg1, reg2, 0);
3814 // Is this a MOV to/from SP instruction?
3815 if ((reg1 == REG_SP) || (reg2 == REG_SP))
3817 assert(isGeneralRegisterOrSP(reg1));
3818 assert(isGeneralRegisterOrSP(reg2));
3819 reg1 = encodingSPtoZR(reg1);
3820 reg2 = encodingSPtoZR(reg2);
3825 assert(insOptsNone(opt));
3826 assert(isGeneralRegister(reg1));
3827 assert(isGeneralRegisterOrZR(reg2));
3834 assert(insOptsAnyArrangement(opt));
3835 assert(isVectorRegister(reg1));
3836 assert(isGeneralRegisterOrZR(reg2));
3837 assert(isValidVectorDatasize(size));
3838 assert(isValidArrangement(size, opt));
3844 assert(isVectorRegister(reg1));
3845 assert(isVectorRegister(reg2));
3848 assert(isValidVectorDatasize(size));
3849 // Bitwise behavior is independent of element size, but is always encoded as 1 Byte
3850 opt = optMakeArrangement(size, EA_1BYTE);
3852 if (insOptsNone(opt))
3855 assert(size == EA_8BYTE); // Only type D is supported
3861 assert(insOptsAnyArrangement(opt));
3862 assert(isValidVectorDatasize(size));
3863 assert(isValidArrangement(size, opt));
3864 elemsize = optGetElemsize(opt);
3871 if (isVectorRegister(reg1))
3873 assert(isVectorRegister(reg2));
3876 assert(isValidVectorDatasize(size));
3877 // Bitwise behavior is independent of element size, but is always encoded as 1 Byte
3878 opt = optMakeArrangement(size, EA_1BYTE);
3880 if (insOptsNone(opt))
3883 assert(size == EA_8BYTE); // Only type D is supported
3889 assert(isValidVectorDatasize(size));
3890 assert(isValidArrangement(size, opt));
3891 elemsize = optGetElemsize(opt);
3899 assert(insOptsNone(opt));
3900 assert(isGeneralRegister(reg1));
3901 assert(isGeneralRegisterOrZR(reg2));
3906 assert(size == EA_8BYTE);
3913 assert(insOptsNone(opt));
3914 assert(isValidGeneralDatasize(size));
3915 assert(isGeneralRegister(reg1));
3916 assert(isGeneralRegister(reg2));
3924 return emitIns_R_R_I(ins, size, reg1, reg2, 0, opt);
3932 if (isVectorRegister(reg1))
3934 assert(isVectorRegister(reg2));
3935 assert(isValidVectorDatasize(size));
3936 assert(isValidArrangement(size, opt));
3937 elemsize = optGetElemsize(opt);
3938 if ((ins == INS_cls) || (ins == INS_clz))
3940 assert(elemsize != EA_8BYTE); // No encoding for type D
3942 else if (ins == INS_rev32)
3944 assert((elemsize == EA_2BYTE) || (elemsize == EA_1BYTE));
3948 assert(elemsize == EA_1BYTE); // Only supports 8B or 16B
3955 // Doesn't have general register version(s)
3962 assert(insOptsNone(opt));
3963 assert(isGeneralRegister(reg1));
3964 assert(isGeneralRegister(reg2));
3965 if (ins == INS_rev32)
3967 assert(size == EA_8BYTE);
3971 assert(isValidGeneralDatasize(size));
3984 assert(isVectorRegister(reg1));
3985 assert(isVectorRegister(reg2));
3986 assert(isValidVectorDatasize(size));
3987 assert(isValidArrangement(size, opt));
3988 elemsize = optGetElemsize(opt);
3989 assert(elemsize != EA_8BYTE); // No encoding for type D
3995 assert(isVectorRegister(reg1));
3996 assert(isVectorRegister(reg2));
3997 assert(isValidVectorDatasize(size));
3998 assert(isValidArrangement(size, opt));
3999 elemsize = optGetElemsize(opt);
4000 // size is determined by instruction
4003 assert(size == EA_8BYTE);
4005 else // ins == INS_xtn2
4007 assert(size == EA_16BYTE);
4009 assert(elemsize != EA_8BYTE); // Narrowing must not end with 8 byte data
4017 assert(isValidGeneralDatasize(size));
4029 assert(isValidGeneralLSDatasize(size));
4030 assert(isGeneralRegisterOrZR(reg1));
4031 assert(isGeneralRegisterOrSP(reg2));
4032 assert(insOptsNone(opt));
4034 reg2 = encodingSPtoZR(reg2);
4052 assert(insOptsNone(opt));
4053 emitIns_R_R_I(ins, attr, reg1, reg2, 0, INS_OPTS_NONE);
4057 assert(isValidVectorElemsizeFloat(size));
4059 // Is the mov even necessary?
4065 if (isVectorRegister(reg1))
4067 if (isVectorRegister(reg2))
4069 assert(insOptsNone(opt));
4074 assert(isGeneralRegister(reg2));
4076 // if the optional conversion specifier is not present we calculate it
4077 if (opt == INS_OPTS_NONE)
4079 opt = (size == EA_4BYTE) ? INS_OPTS_4BYTE_TO_S : INS_OPTS_8BYTE_TO_D;
4081 assert(insOptsConvertIntToFloat(opt));
4088 assert(isGeneralRegister(reg1));
4089 assert(isVectorRegister(reg2));
4091 // if the optional conversion specifier is not present we calculate it
4092 if (opt == INS_OPTS_NONE)
4094 opt = (size == EA_4BYTE) ? INS_OPTS_S_TO_4BYTE : INS_OPTS_D_TO_8BYTE;
4096 assert(insOptsConvertFloatToInt(opt));
4104 assert(insOptsNone(opt));
4105 assert(isValidVectorElemsizeFloat(size));
4106 assert(isVectorRegister(reg1));
4107 assert(isVectorRegister(reg2));
4121 if (insOptsAnyArrangement(opt))
4124 assert(isVectorRegister(reg1));
4125 assert(isVectorRegister(reg2));
4126 assert(isValidVectorDatasize(size));
4127 assert(isValidArrangement(size, opt));
4128 elemsize = optGetElemsize(opt);
4129 assert(isValidVectorElemsizeFloat(elemsize));
4130 assert(opt != INS_OPTS_1D); // Reserved encoding
4136 assert(isVectorRegister(reg2));
4137 if (isVectorRegister(reg1))
4139 assert(insOptsNone(opt));
4140 assert(isValidVectorElemsizeFloat(size));
4145 assert(isGeneralRegister(reg1));
4146 assert(insOptsConvertFloatToInt(opt));
4147 assert(isValidVectorElemsizeFloat(size));
4157 assert(isVectorRegister(reg1));
4158 assert(isVectorRegister(reg2));
4159 assert(isValidVectorDatasize(size));
4160 assert(insOptsNone(opt));
4161 assert(size == EA_8BYTE); // Narrowing from Double or Widening to Double (Half not supported)
4167 if (insOptsAnyArrangement(opt))
4170 assert(isVectorRegister(reg1));
4171 assert(isVectorRegister(reg2));
4172 assert(isValidVectorDatasize(size));
4173 assert(isValidArrangement(size, opt));
4174 elemsize = optGetElemsize(opt);
4175 assert(isValidVectorElemsizeFloat(elemsize));
4176 assert(opt != INS_OPTS_1D); // Reserved encoding
4182 assert(isVectorRegister(reg1));
4183 if (isVectorRegister(reg2))
4185 assert(insOptsNone(opt));
4186 assert(isValidVectorElemsizeFloat(size));
4191 assert(isGeneralRegister(reg2));
4192 assert(insOptsConvertIntToFloat(opt));
4193 assert(isValidVectorElemsizeFloat(size));
4209 if (insOptsAnyArrangement(opt))
4212 assert(isVectorRegister(reg1));
4213 assert(isVectorRegister(reg2));
4214 assert(isValidVectorDatasize(size));
4215 assert(isValidArrangement(size, opt));
4216 elemsize = optGetElemsize(opt);
4217 assert(isValidVectorElemsizeFloat(elemsize));
4218 assert(opt != INS_OPTS_1D); // Reserved encoding
4224 assert(insOptsNone(opt));
4225 assert(isValidVectorElemsizeFloat(size));
4226 assert(isVectorRegister(reg1));
4227 assert(isVectorRegister(reg2));
4234 assert(insOptsNone(opt));
4235 assert(isValidVectorElemsizeFloat(size));
4236 assert(isVectorRegister(reg1));
4237 assert(isVectorRegister(reg2));
4242 assert(insOptsConvertFloatToFloat(opt));
4243 assert(isValidVectorFcvtsize(size));
4244 assert(isVectorRegister(reg1));
4245 assert(isVectorRegister(reg2));
4254 assert(isVectorRegister(reg1));
4255 assert(isVectorRegister(reg2));
4257 if (isValidVectorDatasize(size))
4260 assert(insOptsAnyArrangement(opt));
4261 assert(isValidArrangement(size, opt));
4262 elemsize = optGetElemsize(opt);
4269 assert(size == EA_8BYTE); // Only Double supported
4279 assert(isVectorRegister(reg1));
4280 assert(isVectorRegister(reg2));
4282 if (isValidVectorDatasize(size))
4285 assert(insOptsAnyArrangement(opt));
4286 assert(isValidArrangement(size, opt));
4287 elemsize = optGetElemsize(opt);
4288 assert((elemsize == EA_8BYTE) || (elemsize == EA_4BYTE)); // Only Double/Float supported
4289 assert(opt != INS_OPTS_1D); // Reserved encoding
4296 assert((size == EA_8BYTE) || (size == EA_4BYTE)); // Only Double/Float supported
4304 assert(isVectorRegister(reg1));
4305 assert(isVectorRegister(reg2));
4306 assert(isValidVectorDatasize(size));
4307 elemsize = optGetElemsize(opt);
4308 assert(elemsize == EA_1BYTE);
4313 assert(insOptsNone(opt));
4314 assert(isVectorRegister(reg1));
4315 assert(isVectorRegister(reg2));
4321 assert(isVectorRegister(reg1));
4322 assert(isVectorRegister(reg2));
4323 assert(isValidVectorDatasize(size));
4324 elemsize = optGetElemsize(opt);
4325 assert(elemsize == EA_4BYTE);
4333 } // end switch (ins)
4335 assert(fmt != IF_NONE);
4337 instrDesc* id = emitNewInstrSmall(attr);
4350 /*****************************************************************************
4352 * Add an instruction referencing a register and two constants.
4355 void emitter::emitIns_R_I_I(
4356 instruction ins, emitAttr attr, regNumber reg, ssize_t imm1, ssize_t imm2, insOpts opt /* = INS_OPTS_NONE */)
4358 emitAttr size = EA_SIZE(attr);
4359 insFormat fmt = IF_NONE;
4360 size_t immOut = 0; // composed from imm1 and imm2 and stored in the instrDesc
4362 /* Figure out the encoding format of the instruction */
4369 ins = INS_movz; // INS_mov with LSL is an alias for INS_movz LSL
4375 assert(isValidGeneralDatasize(size));
4376 assert(isGeneralRegister(reg));
4377 assert(isValidUimm16(imm1));
4378 assert(insOptsLSL(opt)); // Must be INS_OPTS_LSL
4380 if (size == EA_8BYTE)
4382 assert((imm2 == 0) || (imm2 == 16) || // shift amount: 0, 16, 32 or 48
4383 (imm2 == 32) || (imm2 == 48));
4387 assert((imm2 == 0) || (imm2 == 16)); // shift amount: 0 or 16
4422 immOut = hwi.immHWVal;
4423 assert(isValidImmHWVal(immOut, size));
4432 } // end switch (ins)
4434 assert(fmt != IF_NONE);
4436 instrDesc* id = emitNewInstrSC(attr, immOut);
4447 /*****************************************************************************
4449 * Add an instruction referencing two registers and a constant.
4452 void emitter::emitIns_R_R_I(
4453 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm, insOpts opt /* = INS_OPTS_NONE */)
4455 emitAttr size = EA_SIZE(attr);
4456 emitAttr elemsize = EA_UNKNOWN;
4457 insFormat fmt = IF_NONE;
4458 bool isLdSt = false;
4459 bool isSIMD = false;
4460 bool isAddSub = false;
4461 bool setFlags = false;
4463 bool unscaledOp = false;
4465 /* Figure out the encoding format of the instruction */
4472 // Check for the 'mov' aliases for the vector registers
4473 assert(insOptsNone(opt));
4474 assert(isValidVectorElemsize(size));
4476 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4478 if (isVectorRegister(reg1))
4480 if (isGeneralRegisterOrZR(reg2))
4482 fmt = IF_DV_2C; // Alias for 'ins'
4485 else if (isVectorRegister(reg2))
4487 fmt = IF_DV_2E; // Alias for 'dup'
4491 else // isGeneralRegister(reg1)
4493 assert(isGeneralRegister(reg1));
4494 if (isVectorRegister(reg2))
4496 fmt = IF_DV_2B; // Alias for 'umov'
4500 assert(!" invalid INS_mov operands");
4506 assert(insOptsNone(opt));
4507 assert(isValidGeneralDatasize(size));
4508 assert(isGeneralRegister(reg1));
4509 assert(isGeneralRegister(reg2));
4510 assert(isValidImmShift(imm, size));
4515 assert(insOptsNone(opt));
4516 assert(isValidGeneralDatasize(size));
4517 assert(isGeneralRegister(reg1));
4518 assert(isGeneralRegister(reg2));
4519 assert(isValidImmShift(imm, size));
4534 assert(isVectorRegister(reg1));
4535 assert(isVectorRegister(reg2));
4536 if (insOptsAnyArrangement(opt))
4539 assert(isValidVectorDatasize(size));
4540 assert(isValidArrangement(size, opt));
4541 elemsize = optGetElemsize(opt);
4542 assert(isValidVectorElemsize(elemsize));
4543 assert(isValidImmShift(imm, elemsize));
4544 assert(opt != INS_OPTS_1D); // Reserved encoding
4551 assert(insOptsNone(opt));
4552 assert(size == EA_8BYTE); // only supported size
4553 assert(isValidImmShift(imm, size));
4567 assert(isVectorRegister(reg1));
4568 assert(isVectorRegister(reg2));
4570 assert(size == EA_8BYTE);
4571 assert(isValidArrangement(size, opt));
4572 elemsize = optGetElemsize(opt);
4573 assert(elemsize != EA_8BYTE); // Reserved encodings
4574 assert(isValidVectorElemsize(elemsize));
4575 assert(isValidImmShift(imm, elemsize));
4588 assert(isVectorRegister(reg1));
4589 assert(isVectorRegister(reg2));
4591 assert(size == EA_16BYTE);
4592 assert(isValidArrangement(size, opt));
4593 elemsize = optGetElemsize(opt);
4594 assert(elemsize != EA_8BYTE); // Reserved encodings
4595 assert(isValidVectorElemsize(elemsize));
4596 assert(isValidImmShift(imm, elemsize));
4603 assert(isValidGeneralDatasize(size));
4604 assert(isGeneralRegister(reg1));
4605 assert(isGeneralRegisterOrZR(reg2));
4609 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4617 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
4621 assert(insOptsAluShift(opt)); // a non-zero imm, must select shift kind, can't use ROR
4623 assert(isValidImmShift(imm, size));
4629 assert(isValidGeneralDatasize(size));
4630 assert(isGeneralRegisterOrZR(reg1));
4631 assert(isGeneralRegister(reg2));
4633 if (insOptsAnyShift(opt))
4635 assert(isValidImmShift(imm, size) && (imm != 0));
4640 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4648 assert(isValidGeneralDatasize(size));
4649 assert(isGeneralRegisterOrSP(reg1));
4650 assert(isGeneralRegister(reg2));
4652 reg1 = encodingSPtoZR(reg1);
4653 if (insOptsAnyExtend(opt))
4655 assert((imm >= 0) && (imm <= 4));
4661 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4667 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
4668 assert(isValidImmShift(imm, size));
4677 assert(insOptsNone(opt));
4678 assert(isGeneralRegister(reg2));
4679 if (ins == INS_ands)
4681 assert(isGeneralRegister(reg1));
4685 assert(isGeneralRegisterOrSP(reg1));
4686 reg1 = encodingSPtoZR(reg1);
4690 canEncode = canEncodeBitMaskImm(imm, size, &bmi);
4694 assert(isValidImmNRS(imm, size));
4699 case INS_dup: // by element, imm selects the element of reg2
4700 assert(isVectorRegister(reg1));
4701 if (isVectorRegister(reg2))
4703 if (insOptsAnyArrangement(opt))
4706 assert(isValidVectorDatasize(size));
4707 assert(isValidArrangement(size, opt));
4708 elemsize = optGetElemsize(opt);
4709 assert(isValidVectorElemsize(elemsize));
4710 assert(isValidVectorIndex(size, elemsize, imm));
4711 assert(opt != INS_OPTS_1D); // Reserved encoding
4718 assert(insOptsNone(opt));
4720 assert(isValidVectorElemsize(elemsize));
4721 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4728 case INS_ins: // (MOV from general)
4729 assert(insOptsNone(opt));
4730 assert(isValidVectorElemsize(size));
4731 assert(isVectorRegister(reg1));
4732 assert(isGeneralRegisterOrZR(reg2));
4734 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4738 case INS_umov: // (MOV to general)
4739 assert(insOptsNone(opt));
4740 assert(isValidVectorElemsize(size));
4741 assert(isGeneralRegister(reg1));
4742 assert(isVectorRegister(reg2));
4744 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4749 assert(insOptsNone(opt));
4750 assert(isValidVectorElemsize(size));
4751 assert(size != EA_8BYTE); // no encoding, use INS_umov
4752 assert(isGeneralRegister(reg1));
4753 assert(isVectorRegister(reg2));
4755 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4773 // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4774 assert(isValidGeneralDatasize(size));
4775 unscaledOp = (ins == INS_ldursb);
4782 // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4783 assert(isValidGeneralDatasize(size));
4784 unscaledOp = (ins == INS_ldursh);
4791 // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4792 assert(size == EA_8BYTE);
4793 unscaledOp = (ins == INS_ldursw);
4832 // Is the target a vector register?
4833 if (isVectorRegister(reg1))
4835 assert(isValidVectorLSDatasize(size));
4836 assert(isGeneralRegisterOrSP(reg2));
4841 assert(isValidGeneralDatasize(size));
4844 scale = NaturalScale_helper(size);
4850 // Is the target a vector register?
4851 if (isVectorRegister(reg1))
4853 assert(isValidVectorLSDatasize(size));
4854 assert(isGeneralRegisterOrSP(reg2));
4859 assert(isValidGeneralDatasize(size));
4870 } // end switch (ins)
4878 assert(isValidVectorLSDatasize(size));
4879 assert(isVectorRegister(reg1));
4880 assert((scale >= 0) && (scale <= 4));
4884 assert(isValidGeneralLSDatasize(size));
4885 assert(isGeneralRegisterOrZR(reg1));
4886 assert((scale >= 0) && (scale <= 3));
4889 assert(isGeneralRegisterOrSP(reg2));
4891 // Load/Store reserved encodings:
4892 if (insOptsIndexed(opt))
4894 assert(reg1 != reg2);
4897 reg2 = encodingSPtoZR(reg2);
4899 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
4902 assert(insOptsNone(opt)); // PRE/POST Index doesn't make sense with an immediate of zero
4906 else if (insOptsIndexed(opt) || unscaledOp || (imm < 0) || ((imm & mask) != 0))
4908 if ((imm >= -256) && (imm <= 255))
4914 assert(!"Instruction cannot be encoded: IF_LS_2C");
4919 assert(insOptsNone(opt));
4920 assert(!unscaledOp);
4922 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
4924 imm >>= scale; // The immediate is scaled by the size of the ld/st
4930 assert(!"Instruction cannot be encoded: IF_LS_2B");
4937 assert(insOptsNone(opt));
4939 if (setFlags) // Can't encode SP with setFlags
4941 assert(isGeneralRegister(reg1));
4942 assert(isGeneralRegister(reg2));
4946 assert(isGeneralRegisterOrSP(reg1));
4947 assert(isGeneralRegisterOrSP(reg2));
4949 // Is it just a mov?
4952 // Is the mov even necessary?
4955 emitIns_R_R(INS_mov, attr, reg1, reg2);
4960 reg1 = encodingSPtoZR(reg1);
4961 reg2 = encodingSPtoZR(reg2);
4964 if (unsigned_abs(imm) <= 0x0fff)
4968 ins = insReverse(ins);
4971 assert(isValidUimm12(imm));
4974 else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
4976 // Encoding will use a 12-bit left shift of the immediate
4977 opt = INS_OPTS_LSL12;
4980 ins = insReverse(ins);
4983 assert((imm & 0xfff) == 0);
4985 assert(isValidUimm12(imm));
4990 assert(!"Instruction cannot be encoded: IF_DI_2A");
4994 assert(fmt != IF_NONE);
4996 instrDesc* id = emitNewInstrSC(attr, imm);
5009 /*****************************************************************************
5011 * Add an instruction referencing two registers and a constant.
5012 * Also checks for a large immediate that needs a second instruction
5013 * and will load it in reg1
5015 * - Supports instructions: add, adds, sub, subs, and, ands, eor and orr
5016 * - Requires that reg1 is a general register and not SP or ZR
5017 * - Requires that reg1 != reg2
5019 void emitter::emitIns_R_R_Imm(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm)
5021 assert(isGeneralRegister(reg1));
5022 assert(reg1 != reg2);
5024 bool immFits = true;
5032 immFits = emitter::emitIns_valid_imm_for_add(imm, attr);
5039 immFits = emitter::emitIns_valid_imm_for_alu(imm, attr);
5043 assert(!"Unsupported instruction in emitIns_R_R_Imm");
5048 emitIns_R_R_I(ins, attr, reg1, reg2, imm);
5052 // Load 'imm' into the reg1 register
5053 // then issue: 'ins' reg1, reg2, reg1
5055 codeGen->instGen_Set_Reg_To_Imm(attr, reg1, imm);
5056 emitIns_R_R_R(ins, attr, reg1, reg2, reg1);
5060 /*****************************************************************************
5062 * Add an instruction referencing three registers.
5065 void emitter::emitIns_R_R_R(
5066 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insOpts opt) /* = INS_OPTS_NONE */
5068 emitAttr size = EA_SIZE(attr);
5069 emitAttr elemsize = EA_UNKNOWN;
5070 insFormat fmt = IF_NONE;
5072 /* Figure out the encoding format of the instruction */
5096 assert(insOptsNone(opt));
5097 assert(isValidGeneralDatasize(size));
5098 assert(isGeneralRegister(reg1));
5099 assert(isGeneralRegister(reg2));
5100 assert(isGeneralRegister(reg3));
5105 if (insOptsNone(opt))
5108 assert(isValidGeneralDatasize(size));
5109 assert(isGeneralRegister(reg1));
5110 assert(isGeneralRegister(reg2));
5111 assert(isGeneralRegister(reg3));
5120 assert(insOptsAnyArrangement(opt));
5121 assert(isVectorRegister(reg1));
5122 assert(isVectorRegister(reg2));
5123 assert(isVectorRegister(reg3));
5124 assert(isValidVectorDatasize(size));
5125 assert(isValidArrangement(size, opt));
5126 elemsize = optGetElemsize(opt);
5127 if (ins == INS_pmul)
5129 assert(elemsize == EA_1BYTE); // only supports 8B or 16B
5131 else // INS_mul, INS_mla, INS_mls
5133 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
5140 if (isVectorRegister(reg1))
5142 assert(isVectorRegister(reg2));
5143 assert(isVectorRegister(reg3));
5145 if (insOptsAnyArrangement(opt))
5148 assert(opt != INS_OPTS_1D); // Reserved encoding
5149 assert(isValidVectorDatasize(size));
5150 assert(isValidArrangement(size, opt));
5156 assert(insOptsNone(opt));
5157 assert(size == EA_8BYTE);
5166 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, INS_OPTS_NONE);
5175 assert(isVectorRegister(reg1));
5176 assert(isVectorRegister(reg2));
5177 assert(isVectorRegister(reg3));
5179 if (isValidVectorDatasize(size))
5182 assert(insOptsAnyArrangement(opt));
5183 assert(isValidArrangement(size, opt));
5184 elemsize = optGetElemsize(opt);
5191 assert(size == EA_8BYTE); // Only Double supported
5199 assert(isVectorRegister(reg1));
5200 assert(isVectorRegister(reg2));
5201 assert(isVectorRegister(reg3));
5203 if (isValidVectorDatasize(size))
5206 assert(insOptsAnyArrangement(opt));
5207 assert(isValidArrangement(size, opt));
5208 elemsize = optGetElemsize(opt);
5209 assert((elemsize == EA_8BYTE) || (elemsize == EA_4BYTE)); // Only Double/Float supported
5210 assert(opt != INS_OPTS_1D); // Reserved encoding
5217 assert((size == EA_8BYTE) || (size == EA_4BYTE)); // Only Double/Float supported
5230 assert(isVectorRegister(reg1));
5231 assert(isVectorRegister(reg2));
5232 assert(isVectorRegister(reg3));
5233 assert(insOptsAnyArrangement(opt));
5236 assert(isValidVectorDatasize(size));
5237 assert(isValidArrangement(size, opt));
5238 elemsize = optGetElemsize(opt);
5239 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
5245 assert(isVectorRegister(reg1));
5246 assert(isVectorRegister(reg2));
5247 assert(reg2 == reg3);
5248 assert(isValidVectorDatasize(size));
5249 // INS_mov is an alias for INS_orr (vector register)
5250 if (opt == INS_OPTS_NONE)
5252 elemsize = EA_1BYTE;
5253 opt = optMakeArrangement(size, elemsize);
5255 assert(isValidArrangement(size, opt));
5264 if (isVectorRegister(reg1))
5266 assert(isValidVectorDatasize(size));
5267 assert(isVectorRegister(reg2));
5268 assert(isVectorRegister(reg3));
5269 if (opt == INS_OPTS_NONE)
5271 elemsize = EA_1BYTE;
5272 opt = optMakeArrangement(size, elemsize);
5274 assert(isValidArrangement(size, opt));
5283 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, INS_OPTS_NONE);
5289 assert(isValidVectorDatasize(size));
5290 assert(isVectorRegister(reg1));
5291 assert(isVectorRegister(reg2));
5292 assert(isVectorRegister(reg3));
5293 if (opt == INS_OPTS_NONE)
5295 elemsize = EA_1BYTE;
5296 opt = optMakeArrangement(size, elemsize);
5298 assert(isValidArrangement(size, opt));
5310 assert(isVectorRegister(reg1));
5311 assert(isVectorRegister(reg2));
5312 assert(isVectorRegister(reg3));
5313 if (insOptsAnyArrangement(opt))
5316 assert(isValidVectorDatasize(size));
5317 assert(isValidArrangement(size, opt));
5318 elemsize = optGetElemsize(opt);
5319 assert(isValidVectorElemsizeFloat(elemsize));
5320 assert(opt != INS_OPTS_1D); // Reserved encoding
5326 assert(insOptsNone(opt));
5327 assert(isValidScalarDatasize(size));
5334 assert(insOptsNone(opt));
5335 assert(isVectorRegister(reg1));
5336 assert(isVectorRegister(reg2));
5337 assert(isVectorRegister(reg3));
5338 assert(isValidScalarDatasize(size));
5345 assert(isVectorRegister(reg1));
5346 assert(isVectorRegister(reg2));
5347 assert(isVectorRegister(reg3));
5348 assert(insOptsAnyArrangement(opt)); // no scalar encoding, use 4-operand 'fmadd' or 'fmsub'
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
5368 emitIns_R_R_R_Ext(ins, attr, reg1, reg2, reg3, opt);
5376 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0);
5385 assert(isGeneralRegisterOrZR(reg1));
5386 assert(isGeneralRegisterOrZR(reg2));
5387 assert(isGeneralRegisterOrSP(reg3));
5398 assert(isValidVectorDatasize(size));
5399 assert(isVectorRegister(reg1));
5400 assert(isVectorRegister(reg2));
5401 assert(isVectorRegister(reg3));
5402 if (opt == INS_OPTS_NONE)
5404 elemsize = EA_4BYTE;
5405 opt = optMakeArrangement(size, elemsize);
5407 assert(isValidArrangement(size, opt));
5415 } // end switch (ins)
5417 assert(fmt != IF_NONE);
5419 instrDesc* id = emitNewInstr(attr);
5433 /*****************************************************************************
5435 * Add an instruction referencing three registers and a constant.
5438 void emitter::emitIns_R_R_R_I(instruction ins,
5444 insOpts opt /* = INS_OPTS_NONE */,
5445 emitAttr attrReg2 /* = EA_UNKNOWN */)
5447 emitAttr size = EA_SIZE(attr);
5448 emitAttr elemsize = EA_UNKNOWN;
5449 insFormat fmt = IF_NONE;
5450 bool isLdSt = false;
5451 bool isSIMD = false;
5452 bool isAddSub = false;
5453 bool setFlags = false;
5456 /* Figure out the encoding format of the instruction */
5460 assert(insOptsNone(opt));
5461 assert(isValidGeneralDatasize(size));
5462 assert(isGeneralRegister(reg1));
5463 assert(isGeneralRegister(reg2));
5464 assert(isGeneralRegister(reg3));
5465 assert(isValidImmShift(imm, size));
5477 assert(isValidGeneralDatasize(size));
5478 assert(isGeneralRegister(reg1));
5479 assert(isGeneralRegister(reg2));
5480 assert(isGeneralRegister(reg3));
5481 assert(isValidImmShift(imm, size));
5484 assert(insOptsNone(opt)); // a zero imm, means no shift kind
5489 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
5494 case INS_fmul: // by element, imm[0..3] selects the element of reg3
5498 assert(isVectorRegister(reg1));
5499 assert(isVectorRegister(reg2));
5500 assert(isVectorRegister(reg3));
5501 if (insOptsAnyArrangement(opt))
5504 assert(isValidVectorDatasize(size));
5505 assert(isValidArrangement(size, opt));
5506 elemsize = optGetElemsize(opt);
5507 assert(isValidVectorElemsizeFloat(elemsize));
5508 assert(isValidVectorIndex(size, elemsize, imm));
5509 assert(opt != INS_OPTS_1D); // Reserved encoding
5515 assert(insOptsNone(opt));
5516 assert(isValidScalarDatasize(size));
5518 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
5523 case INS_mul: // by element, imm[0..7] selects the element of reg3
5526 assert(isVectorRegister(reg1));
5527 assert(isVectorRegister(reg2));
5528 assert(isVectorRegister(reg3));
5530 assert(insOptsAnyArrangement(opt));
5531 assert(isValidVectorDatasize(size));
5532 assert(isValidArrangement(size, opt));
5533 elemsize = optGetElemsize(opt);
5534 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
5535 // Only has encodings for H or S elemsize
5536 assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE));
5537 // Only has encodings for V0..V15
5538 if ((elemsize == EA_2BYTE) && (reg3 >= REG_V16))
5540 noway_assert(!"Invalid reg3");
5564 assert(insOptsNone(opt)); // Can't use Pre/Post index on these two instructions
5569 // Is the target a vector register?
5570 if (isVectorRegister(reg1))
5572 scale = NaturalScale_helper(size);
5577 scale = (size == EA_8BYTE) ? 3 : 2;
5586 } // end switch (ins)
5591 assert(isGeneralRegisterOrSP(reg3));
5592 assert(insOptsNone(opt) || insOptsIndexed(opt));
5596 assert(isValidVectorLSPDatasize(size));
5597 assert(isVectorRegister(reg1));
5598 assert(isVectorRegister(reg2));
5599 assert((scale >= 2) && (scale <= 4));
5603 assert(isValidGeneralDatasize(size));
5604 assert(isGeneralRegisterOrZR(reg1));
5605 assert(isGeneralRegisterOrZR(reg2));
5606 assert((scale == 2) || (scale == 3));
5609 // Load/Store Pair reserved encodings:
5610 if (emitInsIsLoad(ins))
5612 assert(reg1 != reg2);
5614 if (insOptsIndexed(opt))
5616 assert(reg1 != reg3);
5617 assert(reg2 != reg3);
5620 reg3 = encodingSPtoZR(reg3);
5622 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
5625 assert(insOptsNone(opt)); // PRE/POST Index doesn't make sense with an immediate of zero
5631 if ((imm & mask) == 0)
5633 imm >>= scale; // The immediate is scaled by the size of the ld/st
5635 if ((imm >= -64) && (imm <= 63))
5641 if (fmt != IF_LS_3C)
5643 assert(!"Instruction cannot be encoded: IF_LS_3C");
5650 bool reg2IsSP = (reg2 == REG_SP);
5652 assert(isValidGeneralDatasize(size));
5653 assert(isGeneralRegister(reg3));
5655 if (setFlags || insOptsAluShift(opt)) // Can't encode SP in reg1 with setFlags or AluShift option
5657 assert(isGeneralRegisterOrZR(reg1));
5661 assert(isGeneralRegisterOrSP(reg1));
5662 reg1 = encodingSPtoZR(reg1);
5665 if (insOptsAluShift(opt)) // Can't encode SP in reg2 with AluShift option
5667 assert(isGeneralRegister(reg2));
5671 assert(isGeneralRegisterOrSP(reg2));
5672 reg2 = encodingSPtoZR(reg2);
5675 if (insOptsAnyExtend(opt))
5677 assert((imm >= 0) && (imm <= 4));
5681 else if (insOptsAluShift(opt))
5683 // imm should be non-zero and in [1..63]
5684 assert(isValidImmShift(imm, size) && (imm != 0));
5689 assert(insOptsNone(opt));
5693 // To encode the SP register as reg2 we must use the IF_DR_3C encoding
5694 // and also specify a LSL of zero (imm == 0)
5705 assert(!"Instruction cannot be encoded: Add/Sub IF_DR_3A");
5708 assert(fmt != IF_NONE);
5710 instrDesc* id = emitNewInstrCns(attr, imm);
5720 // Record the attribute for the second register in the pair
5721 id->idGCrefReg2(GCT_NONE);
5722 if (attrReg2 != EA_UNKNOWN)
5724 // Record the attribute for the second register in the pair
5725 assert((fmt == IF_LS_3B) || (fmt == IF_LS_3C));
5726 if (EA_IS_GCREF(attrReg2))
5728 id->idGCrefReg2(GCT_GCREF);
5730 else if (EA_IS_BYREF(attrReg2))
5732 id->idGCrefReg2(GCT_BYREF);
5740 /*****************************************************************************
5742 * Add an instruction referencing three registers, with an extend option
5745 void emitter::emitIns_R_R_R_Ext(instruction ins,
5750 insOpts opt, /* = INS_OPTS_NONE */
5751 int shiftAmount) /* = -1 -- unset */
5753 emitAttr size = EA_SIZE(attr);
5754 insFormat fmt = IF_NONE;
5755 bool isSIMD = false;
5758 /* Figure out the encoding format of the instruction */
5779 // Is the target a vector register?
5780 if (isVectorRegister(reg1))
5782 assert(isValidVectorLSDatasize(size));
5783 scale = NaturalScale_helper(size);
5788 assert(isValidGeneralDatasize(size));
5789 scale = (size == EA_8BYTE) ? 3 : 2;
5798 } // end switch (ins)
5800 assert(scale != -1);
5801 assert(insOptsLSExtend(opt));
5805 assert(isValidVectorLSDatasize(size));
5806 assert(isVectorRegister(reg1));
5810 assert(isValidGeneralLSDatasize(size));
5811 assert(isGeneralRegisterOrZR(reg1));
5814 assert(isGeneralRegisterOrSP(reg2));
5815 assert(isGeneralRegister(reg3));
5817 // Load/Store reserved encodings:
5818 if (insOptsIndexed(opt))
5820 assert(reg1 != reg2);
5823 if (shiftAmount == -1)
5825 shiftAmount = insOptsLSL(opt) ? scale : 0;
5827 assert((shiftAmount == scale) || (shiftAmount == 0));
5829 reg2 = encodingSPtoZR(reg2);
5832 instrDesc* id = emitNewInstr(attr);
5841 id->idReg3Scaled(shiftAmount == scale);
5847 /*****************************************************************************
5849 * Add an instruction referencing two registers and two constants.
5852 void emitter::emitIns_R_R_I_I(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, int imm1, int imm2)
5854 emitAttr size = EA_SIZE(attr);
5855 emitAttr elemsize = EA_UNKNOWN;
5856 insFormat fmt = IF_NONE;
5857 size_t immOut = 0; // composed from imm1 and imm2 and stored in the instrDesc
5859 /* Figure out the encoding format of the instruction */
5869 assert(isGeneralRegister(reg1));
5870 assert(isGeneralRegister(reg2));
5871 assert(isValidImmShift(imm1, size));
5872 assert(isValidImmShift(imm2, size));
5874 bmi.immN = (size == EA_8BYTE);
5877 immOut = bmi.immNRS;
5884 assert(isGeneralRegister(reg1));
5885 assert(isGeneralRegister(reg2));
5886 lsb = getBitWidth(size) - imm1;
5888 assert(isValidImmShift(lsb, size));
5889 assert(isValidImmShift(width, size));
5891 bmi.immN = (size == EA_8BYTE);
5894 immOut = bmi.immNRS;
5901 assert(isGeneralRegister(reg1));
5902 assert(isGeneralRegister(reg2));
5904 width = imm2 + imm1 - 1;
5905 assert(isValidImmShift(lsb, size));
5906 assert(isValidImmShift(width, size));
5908 bmi.immN = (size == EA_8BYTE);
5910 bmi.immS = imm2 + imm1 - 1;
5911 immOut = bmi.immNRS;
5917 assert(isVectorRegister(reg1));
5918 assert(isVectorRegister(reg2));
5920 assert(isValidVectorElemsize(elemsize));
5921 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm1));
5922 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm2));
5923 immOut = (imm1 << 4) + imm2;
5931 assert(fmt != IF_NONE);
5933 instrDesc* id = emitNewInstrSC(attr, immOut);
5945 /*****************************************************************************
5947 * Add an instruction referencing four registers.
5950 void emitter::emitIns_R_R_R_R(
5951 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, regNumber reg4)
5953 emitAttr size = EA_SIZE(attr);
5954 insFormat fmt = IF_NONE;
5956 /* Figure out the encoding format of the instruction */
5965 assert(isValidGeneralDatasize(size));
5966 assert(isGeneralRegister(reg1));
5967 assert(isGeneralRegister(reg2));
5968 assert(isGeneralRegister(reg3));
5969 assert(isGeneralRegister(reg4));
5978 assert(isValidScalarDatasize(size));
5979 assert(isVectorRegister(reg1));
5980 assert(isVectorRegister(reg2));
5981 assert(isVectorRegister(reg3));
5982 assert(isVectorRegister(reg4));
5994 assert(fmt != IF_NONE);
5996 instrDesc* id = emitNewInstr(attr);
6010 /*****************************************************************************
6012 * Add an instruction referencing a register and a condition code
6015 void emitter::emitIns_R_COND(instruction ins, emitAttr attr, regNumber reg, insCond cond)
6017 emitAttr size = EA_SIZE(attr);
6018 insFormat fmt = IF_NONE;
6022 /* Figure out the encoding format of the instruction */
6027 assert(isGeneralRegister(reg));
6036 } // end switch (ins)
6038 assert(fmt != IF_NONE);
6039 assert(isValidImmCond(cfi.immCFVal));
6041 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6045 id->idInsOpt(INS_OPTS_NONE);
6053 /*****************************************************************************
6055 * Add an instruction referencing two registers and a condition code
6058 void emitter::emitIns_R_R_COND(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insCond cond)
6060 emitAttr size = EA_SIZE(attr);
6061 insFormat fmt = IF_NONE;
6065 /* Figure out the encoding format of the instruction */
6071 assert(isGeneralRegister(reg1));
6072 assert(isGeneralRegister(reg2));
6080 } // end switch (ins)
6082 assert(fmt != IF_NONE);
6083 assert(isValidImmCond(cfi.immCFVal));
6085 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6089 id->idInsOpt(INS_OPTS_NONE);
6098 /*****************************************************************************
6100 * Add an instruction referencing two registers and a condition code
6103 void emitter::emitIns_R_R_R_COND(
6104 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insCond cond)
6106 emitAttr size = EA_SIZE(attr);
6107 insFormat fmt = IF_NONE;
6111 /* Figure out the encoding format of the instruction */
6118 assert(isGeneralRegister(reg1));
6119 assert(isGeneralRegister(reg2));
6120 assert(isGeneralRegister(reg3));
6129 } // end switch (ins)
6131 assert(fmt != IF_NONE);
6132 assert(isValidImmCond(cfi.immCFVal));
6134 instrDesc* id = emitNewInstr(attr);
6138 id->idInsOpt(INS_OPTS_NONE);
6143 id->idSmallCns(cfi.immCFVal);
6149 /*****************************************************************************
6151 * Add an instruction referencing two registers the flags and a condition code
6154 void emitter::emitIns_R_R_FLAGS_COND(
6155 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insCflags flags, insCond cond)
6157 emitAttr size = EA_SIZE(attr);
6158 insFormat fmt = IF_NONE;
6162 /* Figure out the encoding format of the instruction */
6167 assert(isGeneralRegister(reg1));
6168 assert(isGeneralRegister(reg2));
6176 } // end switch (ins)
6178 assert(fmt != IF_NONE);
6179 assert(isValidImmCondFlags(cfi.immCFVal));
6181 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6185 id->idInsOpt(INS_OPTS_NONE);
6194 /*****************************************************************************
6196 * Add an instruction referencing a register, an immediate, the flags and a condition code
6199 void emitter::emitIns_R_I_FLAGS_COND(
6200 instruction ins, emitAttr attr, regNumber reg, int imm, insCflags flags, insCond cond)
6202 emitAttr size = EA_SIZE(attr);
6203 insFormat fmt = IF_NONE;
6207 /* Figure out the encoding format of the instruction */
6212 assert(isGeneralRegister(reg));
6215 ins = insReverse(ins);
6218 if ((imm >= 0) && (imm <= 31))
6227 assert(!"Instruction cannot be encoded: ccmp/ccmn imm5");
6233 } // end switch (ins)
6235 assert(fmt != IF_NONE);
6236 assert(isValidImmCondFlagsImm5(cfi.immCFVal));
6238 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6242 id->idInsOpt(INS_OPTS_NONE);
6250 /*****************************************************************************
6252 * Add a memory barrier instruction with a 'barrier' immediate
6255 void emitter::emitIns_BARR(instruction ins, insBarrier barrier)
6257 insFormat fmt = IF_NONE;
6260 /* Figure out the encoding format of the instruction */
6268 imm = (ssize_t)barrier;
6273 } // end switch (ins)
6275 assert(fmt != IF_NONE);
6277 instrDesc* id = emitNewInstrSC(EA_8BYTE, imm);
6281 id->idInsOpt(INS_OPTS_NONE);
6287 /*****************************************************************************
6289 * Add an instruction with a static data member operand. If 'size' is 0, the
6290 * instruction operates on the address of the static member instead of its
6291 * value (e.g. "push offset clsvar", rather than "push dword ptr [clsvar]").
6294 void emitter::emitIns_C(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, int offs)
6299 /*****************************************************************************
6301 * Add an instruction referencing stack-based local variable.
6304 void emitter::emitIns_S(instruction ins, emitAttr attr, int varx, int offs)
6309 /*****************************************************************************
6311 * Add an instruction referencing a register and a stack-based local variable.
6313 void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
6315 emitAttr size = EA_SIZE(attr);
6316 insFormat fmt = IF_NONE;
6322 // TODO-ARM64-CQ: use unscaled loads?
6323 /* Figure out the encoding format of the instruction */
6344 assert(isValidGeneralDatasize(size) || isValidVectorDatasize(size));
6345 scale = genLog2(EA_SIZE_IN_BYTES(size));
6349 assert(size == EA_8BYTE);
6354 NYI("emitIns_R_S"); // FP locals?
6357 } // end switch (ins)
6359 /* Figure out the variable's frame position */
6364 base = emitComp->lvaFrameAddress(varx, &FPbased);
6366 assert((scale >= 0) && (scale <= 4));
6368 regNumber reg2 = FPbased ? REG_FPBASE : REG_SPBASE;
6369 reg2 = encodingSPtoZR(reg2);
6386 fmt = IF_DI_2A; // add reg1,reg2,#disp
6390 regNumber rsvdReg = codeGen->rsGetRsvdReg();
6391 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6392 fmt = IF_DR_3A; // add reg1,reg2,rsvdReg
6397 bool useRegForImm = false;
6398 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6405 else if ((imm < 0) || ((imm & mask) != 0))
6407 if ((imm >= -256) && (imm <= 255))
6413 useRegForImm = true;
6418 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
6420 imm >>= scale; // The immediate is scaled by the size of the ld/st
6426 useRegForImm = true;
6432 regNumber rsvdReg = codeGen->rsGetRsvdReg();
6433 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6438 assert(fmt != IF_NONE);
6440 instrDesc* id = emitNewInstrCns(attr, imm);
6444 id->idInsOpt(INS_OPTS_NONE);
6448 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6449 id->idSetIsLclVar();
6452 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6459 /*****************************************************************************
6461 * Add an instruction referencing two register and consectutive stack-based local variable slots.
6463 void emitter::emitIns_R_R_S_S(
6464 instruction ins, emitAttr attr1, emitAttr attr2, regNumber reg1, regNumber reg2, int varx, int offs)
6466 assert((ins == INS_ldp) || (ins == INS_ldnp));
6467 assert(EA_8BYTE == EA_SIZE(attr1));
6468 assert(EA_8BYTE == EA_SIZE(attr2));
6469 assert(isGeneralRegisterOrZR(reg1));
6470 assert(isGeneralRegisterOrZR(reg2));
6473 insFormat fmt = IF_LS_3B;
6475 const unsigned scale = 3;
6477 /* Figure out the variable's frame position */
6481 base = emitComp->lvaFrameAddress(varx, &FPbased);
6484 // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6485 regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE;
6486 reg3 = encodingSPtoZR(reg3);
6488 bool useRegForAdr = true;
6490 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6493 useRegForAdr = false;
6497 if ((imm & mask) == 0)
6499 ssize_t immShift = imm >> scale; // The immediate is scaled by the size of the ld/st
6501 if ((immShift >= -64) && (immShift <= 63))
6504 useRegForAdr = false;
6512 regNumber rsvd = codeGen->rsGetRsvdReg();
6513 emitIns_R_R_Imm(INS_add, EA_PTRSIZE, rsvd, reg3, imm);
6518 assert(fmt != IF_NONE);
6520 instrDesc* id = emitNewInstrCns(attr1, imm);
6524 id->idInsOpt(INS_OPTS_NONE);
6526 // Record the attribute for the second register in the pair
6527 if (EA_IS_GCREF(attr2))
6529 id->idGCrefReg2(GCT_GCREF);
6531 else if (EA_IS_BYREF(attr2))
6533 id->idGCrefReg2(GCT_BYREF);
6537 id->idGCrefReg2(GCT_NONE);
6543 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6544 id->idSetIsLclVar();
6547 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6554 /*****************************************************************************
6556 * Add an instruction referencing a stack-based local variable and a register
6558 void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
6561 emitAttr size = EA_SIZE(attr);
6562 insFormat fmt = IF_NONE;
6565 bool isVectorStore = false;
6567 // TODO-ARM64-CQ: use unscaled loads?
6568 /* Figure out the encoding format of the instruction */
6573 assert(isGeneralRegisterOrZR(reg1));
6578 assert(isGeneralRegisterOrZR(reg1));
6582 if (isGeneralRegisterOrZR(reg1))
6584 assert(isValidGeneralDatasize(size));
6585 scale = (size == EA_8BYTE) ? 3 : 2;
6589 assert(isVectorRegister(reg1));
6590 assert(isValidVectorLSDatasize(size));
6591 scale = NaturalScale_helper(size);
6592 isVectorStore = true;
6597 NYI("emitIns_S_R"); // FP locals?
6600 } // end switch (ins)
6602 /* Figure out the variable's frame position */
6606 base = emitComp->lvaFrameAddress(varx, &FPbased);
6618 // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6619 regNumber reg2 = FPbased ? REG_FPBASE : REG_SPBASE;
6620 reg2 = encodingSPtoZR(reg2);
6622 bool useRegForImm = false;
6624 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6629 else if ((imm < 0) || ((imm & mask) != 0))
6631 if ((imm >= -256) && (imm <= 255))
6637 useRegForImm = true;
6642 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
6644 imm >>= scale; // The immediate is scaled by the size of the ld/st
6650 useRegForImm = true;
6656 // The reserved register is not stored in idReg3() since that field overlaps with iiaLclVar.
6657 // It is instead implicit when idSetIsLclVar() is set, with this encoding format.
6658 regNumber rsvdReg = codeGen->rsGetRsvdReg();
6659 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6663 assert(fmt != IF_NONE);
6665 instrDesc* id = emitNewInstrCns(attr, imm);
6669 id->idInsOpt(INS_OPTS_NONE);
6673 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6674 id->idSetIsLclVar();
6677 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6684 /*****************************************************************************
6686 * Add an instruction referencing consecutive stack-based local variable slots and two registers
6688 void emitter::emitIns_S_S_R_R(
6689 instruction ins, emitAttr attr1, emitAttr attr2, regNumber reg1, regNumber reg2, int varx, int offs)
6691 assert((ins == INS_stp) || (ins == INS_stnp));
6692 assert(EA_8BYTE == EA_SIZE(attr1));
6693 assert(EA_8BYTE == EA_SIZE(attr2));
6694 assert(isGeneralRegisterOrZR(reg1));
6695 assert(isGeneralRegisterOrZR(reg2));
6698 insFormat fmt = IF_LS_3B;
6700 const unsigned scale = 3;
6702 /* Figure out the variable's frame position */
6706 base = emitComp->lvaFrameAddress(varx, &FPbased);
6709 // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6710 regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE;
6711 reg3 = encodingSPtoZR(reg3);
6713 bool useRegForAdr = true;
6715 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6718 useRegForAdr = false;
6722 if ((imm & mask) == 0)
6724 ssize_t immShift = imm >> scale; // The immediate is scaled by the size of the ld/st
6726 if ((immShift >= -64) && (immShift <= 63))
6729 useRegForAdr = false;
6737 regNumber rsvd = codeGen->rsGetRsvdReg();
6738 emitIns_R_R_Imm(INS_add, EA_PTRSIZE, rsvd, reg3, imm);
6743 assert(fmt != IF_NONE);
6745 instrDesc* id = emitNewInstrCns(attr1, imm);
6749 id->idInsOpt(INS_OPTS_NONE);
6751 // Record the attribute for the second register in the pair
6752 if (EA_IS_GCREF(attr2))
6754 id->idGCrefReg2(GCT_GCREF);
6756 else if (EA_IS_BYREF(attr2))
6758 id->idGCrefReg2(GCT_BYREF);
6762 id->idGCrefReg2(GCT_NONE);
6768 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6769 id->idSetIsLclVar();
6772 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6779 /*****************************************************************************
6781 * Add an instruction referencing stack-based local variable and an immediate
6783 void emitter::emitIns_S_I(instruction ins, emitAttr attr, int varx, int offs, int val)
6788 /*****************************************************************************
6790 * Add an instruction with a register + static member operands.
6791 * Constant is stored into JIT data which is adjacent to code.
6792 * No relocation is needed. PC-relative offset will be encoded directly into instruction.
6795 void emitter::emitIns_R_C(
6796 instruction ins, emitAttr attr, regNumber reg, regNumber addrReg, CORINFO_FIELD_HANDLE fldHnd, int offs)
6799 assert(instrDesc::fitsInSmallCns(offs));
6801 emitAttr size = EA_SIZE(attr);
6802 insFormat fmt = IF_NONE;
6804 instrDescJmp* id = emitNewInstrJmp();
6809 // This is case to get address to the constant data.
6811 assert(isGeneralRegister(reg));
6812 assert(isValidGeneralDatasize(size));
6817 if (isVectorRegister(reg))
6819 assert(isValidScalarDatasize(size));
6820 // For vector (float/double) register, we should have an integer address reg to
6821 // compute long address which consists of page address and page offset.
6822 // For integer constant, this is not needed since the dest reg can be used to
6823 // compute address as well as contain the final contents.
6824 assert(isGeneralRegister(reg) || (addrReg != REG_NA));
6828 assert(isGeneralRegister(reg));
6829 assert(isValidGeneralDatasize(size));
6836 assert(fmt != IF_NONE);
6840 id->idInsOpt(INS_OPTS_NONE);
6841 id->idSmallCns(offs);
6843 id->idAddr()->iiaFieldHnd = fldHnd;
6844 id->idSetIsBound(); // We won't patch address since we will know the exact distance once JIT code and data are
6845 // allocated together.
6847 id->idReg1(reg); // destination register that will get the constant value.
6848 if (addrReg != REG_NA)
6850 id->idReg2(addrReg); // integer register to compute long address (used for vector dest when we end up with long
6853 id->idjShort = false; // Assume loading constant from long address
6855 // Keep it long if it's in cold code.
6856 id->idjKeepLong = emitComp->fgIsBlockCold(emitComp->compCurBB);
6859 if (emitComp->opts.compLongAddress)
6860 id->idjKeepLong = 1;
6863 // If it's possible to be shortened, then put it in jump list
6864 // to be revisited by emitJumpDistBind.
6865 if (!id->idjKeepLong)
6867 /* Record the jump's IG and offset within it */
6868 id->idjIG = emitCurIG;
6869 id->idjOffs = emitCurIGsize;
6871 /* Append this jump to this IG's jump list */
6872 id->idjNext = emitCurIGjmpList;
6873 emitCurIGjmpList = id;
6884 /*****************************************************************************
6886 * Add an instruction with a static member + constant.
6889 void emitter::emitIns_C_I(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, ssize_t offs, ssize_t val)
6894 /*****************************************************************************
6896 * Add an instruction with a static member + register operands.
6899 void emitter::emitIns_C_R(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, regNumber reg, int offs)
6901 assert(!"emitIns_C_R not supported for RyuJIT backend");
6904 void emitter::emitIns_R_AR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
6906 NYI("emitIns_R_AR");
6909 // This computes address from the immediate which is relocatable.
6910 void emitter::emitIns_R_AI(instruction ins, emitAttr attr, regNumber ireg, ssize_t addr)
6912 assert(EA_IS_RELOC(attr));
6913 emitAttr size = EA_SIZE(attr);
6914 insFormat fmt = IF_DI_1E;
6915 bool needAdd = false;
6916 instrDescJmp* id = emitNewInstrJmp();
6921 // This computes page address.
6922 // page offset is needed using add.
6933 id->idInsOpt(INS_OPTS_NONE);
6935 id->idAddr()->iiaAddr = (BYTE*)addr;
6937 id->idSetIsDspReloc();
6944 // add reg, reg, imm
6947 instrDesc* id = emitAllocInstr(attr);
6948 assert(id->idIsReloc());
6952 id->idInsOpt(INS_OPTS_NONE);
6954 id->idAddr()->iiaAddr = (BYTE*)addr;
6963 void emitter::emitIns_AR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
6965 NYI("emitIns_AR_R");
6968 void emitter::emitIns_R_ARR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
6970 NYI("emitIns_R_ARR");
6973 void emitter::emitIns_ARR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
6975 NYI("emitIns_R_ARR");
6978 void emitter::emitIns_R_ARX(
6979 instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, unsigned mul, int disp)
6981 NYI("emitIns_R_ARR");
6984 /*****************************************************************************
6986 * Record that a jump instruction uses the short encoding
6989 void emitter::emitSetShortJump(instrDescJmp* id)
6991 if (id->idjKeepLong)
6994 insFormat fmt = IF_NONE;
6995 if (emitIsCondJump(id))
6997 switch (id->idIns())
7012 else if (emitIsLoadLabel(id))
7016 else if (emitIsLoadConstant(id))
7026 id->idjShort = true;
7029 /*****************************************************************************
7031 * Add a label instruction.
7034 void emitter::emitIns_R_L(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
7036 assert(dst->bbFlags & BBF_JMP_TARGET);
7038 insFormat fmt = IF_NONE;
7049 instrDescJmp* id = emitNewInstrJmp();
7053 id->idjShort = false;
7054 id->idAddr()->iiaBBlabel = dst;
7056 id->idOpSize(EA_PTRSIZE);
7059 // Mark the catch return
7060 if (emitComp->compCurBB->bbJumpKind == BBJ_EHCATCHRET)
7062 id->idDebugOnlyInfo()->idCatchRet = true;
7066 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7069 if (emitComp->opts.compLongAddress)
7070 id->idjKeepLong = 1;
7073 /* Record the jump's IG and offset within it */
7075 id->idjIG = emitCurIG;
7076 id->idjOffs = emitCurIGsize;
7078 /* Append this jump to this IG's jump list */
7080 id->idjNext = emitCurIGjmpList;
7081 emitCurIGjmpList = id;
7091 /*****************************************************************************
7093 * Add a data label instruction.
7096 void emitter::emitIns_R_D(instruction ins, emitAttr attr, unsigned offs, regNumber reg)
7101 void emitter::emitIns_J_R(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
7103 assert((ins == INS_cbz) || (ins == INS_cbnz));
7105 assert(dst != nullptr);
7106 assert((dst->bbFlags & BBF_JMP_TARGET) != 0);
7108 insFormat fmt = IF_LARGEJMP;
7110 instrDescJmp* id = emitNewInstrJmp();
7115 id->idjShort = false;
7116 id->idOpSize(EA_SIZE(attr));
7118 id->idAddr()->iiaBBlabel = dst;
7119 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7121 /* Record the jump's IG and offset within it */
7123 id->idjIG = emitCurIG;
7124 id->idjOffs = emitCurIGsize;
7126 /* Append this jump to this IG's jump list */
7128 id->idjNext = emitCurIGjmpList;
7129 emitCurIGjmpList = id;
7139 void emitter::emitIns_J_R_I(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg, int imm)
7141 assert((ins == INS_tbz) || (ins == INS_tbnz));
7143 assert(dst != nullptr);
7144 assert((dst->bbFlags & BBF_JMP_TARGET) != 0);
7145 assert((EA_SIZE(attr) == EA_4BYTE) || (EA_SIZE(attr) == EA_8BYTE));
7146 assert(imm < ((EA_SIZE(attr) == EA_4BYTE) ? 32 : 64));
7148 insFormat fmt = IF_LARGEJMP;
7150 instrDescJmp* id = emitNewInstrJmp();
7155 id->idjShort = false;
7156 id->idSmallCns(imm);
7157 id->idOpSize(EA_SIZE(attr));
7159 id->idAddr()->iiaBBlabel = dst;
7160 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7162 /* Record the jump's IG and offset within it */
7164 id->idjIG = emitCurIG;
7165 id->idjOffs = emitCurIGsize;
7167 /* Append this jump to this IG's jump list */
7169 id->idjNext = emitCurIGjmpList;
7170 emitCurIGjmpList = id;
7180 void emitter::emitIns_J(instruction ins, BasicBlock* dst, int instrCount)
7182 insFormat fmt = IF_NONE;
7186 assert(dst->bbFlags & BBF_JMP_TARGET);
7190 assert(instrCount != 0);
7193 /* Figure out the encoding format of the instruction */
7195 bool idjShort = false;
7200 // Unconditional jump is a single form.
7219 // Assume conditional jump is long.
7228 instrDescJmp* id = emitNewInstrJmp();
7232 id->idjShort = idjShort;
7235 // Mark the finally call
7236 if (ins == INS_bl_local && emitComp->compCurBB->bbJumpKind == BBJ_CALLFINALLY)
7238 id->idDebugOnlyInfo()->idFinallyCall = true;
7244 id->idAddr()->iiaBBlabel = dst;
7246 // Skip unconditional jump that has a single form.
7247 // TODO-ARM64-NYI: enable hot/cold splittingNYI.
7248 // The target needs to be relocated.
7251 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7254 if (emitComp->opts.compLongAddress) // Force long branches
7255 id->idjKeepLong = 1;
7261 id->idAddr()->iiaSetInstrCount(instrCount);
7262 id->idjKeepLong = false;
7263 /* This jump must be short */
7264 emitSetShortJump(id);
7268 /* Record the jump's IG and offset within it */
7270 id->idjIG = emitCurIG;
7271 id->idjOffs = emitCurIGsize;
7273 /* Append this jump to this IG's jump list */
7275 id->idjNext = emitCurIGjmpList;
7276 emitCurIGjmpList = id;
7286 /*****************************************************************************
7288 * Add a call instruction (direct or indirect).
7289 * argSize<0 means that the caller will pop the arguments
7291 * The other arguments are interpreted depending on callType as shown:
7292 * Unless otherwise specified, ireg,xreg,xmul,disp should have default values.
7294 * EC_FUNC_TOKEN : addr is the method address
7295 * EC_FUNC_ADDR : addr is the absolute address of the function
7297 * If callType is one of these emitCallTypes, addr has to be NULL.
7298 * EC_INDIR_R : "call ireg".
7300 * For ARM xreg, xmul and disp are never used and should always be 0/REG_NA.
7302 * Please consult the "debugger team notification" comment in genFnProlog().
7305 void emitter::emitIns_Call(EmitCallType callType,
7306 CORINFO_METHOD_HANDLE methHnd,
7307 INDEBUG_LDISASM_COMMA(CORINFO_SIG_INFO* sigInfo) // used to report call sites to the EE
7311 emitAttr secondRetSize,
7312 VARSET_VALARG_TP ptrVars,
7313 regMaskTP gcrefRegs,
7314 regMaskTP byrefRegs,
7315 IL_OFFSETX ilOffset /* = BAD_IL_OFFSET */,
7316 regNumber ireg /* = REG_NA */,
7317 regNumber xreg /* = REG_NA */,
7318 unsigned xmul /* = 0 */,
7319 ssize_t disp /* = 0 */,
7320 bool isJump /* = false */,
7321 bool isNoGC /* = false */,
7322 bool isProfLeaveCB /* = false */)
7324 /* Sanity check the arguments depending on callType */
7326 assert(callType < EC_COUNT);
7327 assert((callType != EC_FUNC_TOKEN && callType != EC_FUNC_ADDR) ||
7328 (ireg == REG_NA && xreg == REG_NA && xmul == 0 && disp == 0));
7329 assert(callType < EC_INDIR_R || addr == NULL);
7330 assert(callType != EC_INDIR_R || (ireg < REG_COUNT && xreg == REG_NA && xmul == 0 && disp == 0));
7332 // ARM never uses these
7333 assert(xreg == REG_NA && xmul == 0 && disp == 0);
7335 // Our stack level should be always greater than the bytes of arguments we push. Just
7337 assert((unsigned)abs(argSize) <= codeGen->genStackLevel);
7342 /* This is the saved set of registers after a normal call */
7343 regMaskTP savedSet = RBM_CALLEE_SAVED;
7345 /* some special helper calls have a different saved set registers */
7349 assert(emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
7351 // Get the set of registers that this call kills and remove it from the saved set.
7352 savedSet = RBM_ALLINT & ~emitComp->compNoGCHelperCallKillSet(Compiler::eeGetHelperNum(methHnd));
7354 // In case of Leave profiler callback, we need to preserve liveness of REG_PROFILER_RET_SCRATCH
7357 savedSet |= RBM_PROFILER_RET_SCRATCH;
7362 assert(!emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
7365 /* Trim out any callee-trashed registers from the live set */
7367 gcrefRegs &= savedSet;
7368 byrefRegs &= savedSet;
7371 if (EMIT_GC_VERBOSE)
7373 printf("Call: GCvars=%s ", VarSetOps::ToString(emitComp, ptrVars));
7374 dumpConvertedVarSet(emitComp, ptrVars);
7375 printf(", gcrefRegs=");
7376 printRegMaskInt(gcrefRegs);
7377 emitDispRegSet(gcrefRegs);
7378 printf(", byrefRegs=");
7379 printRegMaskInt(byrefRegs);
7380 emitDispRegSet(byrefRegs);
7385 assert(argSize % REGSIZE_BYTES == 0);
7386 argCnt = (int)(argSize / (int)REGSIZE_BYTES);
7388 /* Managed RetVal: emit sequence point for the call */
7389 if (emitComp->opts.compDbgInfo && ilOffset != BAD_IL_OFFSET)
7391 codeGen->genIPmappingAdd(ilOffset, false);
7395 We need to allocate the appropriate instruction descriptor based
7396 on whether this is a direct/indirect call, and whether we need to
7397 record an updated set of live GC variables.
7400 if (callType >= EC_INDIR_R)
7402 /* Indirect call, virtual calls */
7404 assert(callType == EC_INDIR_R);
7406 id = emitNewInstrCallInd(argCnt, disp, ptrVars, gcrefRegs, byrefRegs, retSize, secondRetSize);
7410 /* Helper/static/nonvirtual/function calls (direct or through handle),
7411 and calls to an absolute addr. */
7413 assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
7415 id = emitNewInstrCallDir(argCnt, ptrVars, gcrefRegs, byrefRegs, retSize, secondRetSize);
7418 /* Update the emitter's live GC ref sets */
7420 VarSetOps::Assign(emitComp, emitThisGCrefVars, ptrVars);
7421 emitThisGCrefRegs = gcrefRegs;
7422 emitThisByrefRegs = byrefRegs;
7424 /* Set the instruction - special case jumping a function */
7426 insFormat fmt = IF_NONE;
7428 id->idSetIsNoGC(isNoGC);
7430 /* Record the address: method, indirection, or funcptr */
7432 if (callType > EC_FUNC_ADDR)
7434 /* This is an indirect call (either a virtual call or func ptr call) */
7438 case EC_INDIR_R: // the address is in a register
7440 id->idSetIsCallRegPtr();
7444 ins = INS_br_tail; // INS_br_tail Reg
7448 ins = INS_blr; // INS_blr Reg
7456 assert(xreg == REG_NA);
7460 NO_WAY("unexpected instruction");
7466 /* This is a simple direct call: "call helper/method/addr" */
7468 assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
7470 assert(addr != NULL);
7474 ins = INS_b_tail; // INS_b_tail imm28
7478 ins = INS_bl; // INS_bl imm28
7485 id->idAddr()->iiaAddr = (BYTE*)addr;
7487 if (callType == EC_FUNC_ADDR)
7489 id->idSetIsCallAddr();
7492 if (emitComp->opts.compReloc)
7494 id->idSetIsDspReloc();
7499 if (EMIT_GC_VERBOSE)
7501 if (id->idIsLargeCall())
7503 printf("[%02u] Rec call GC vars = %s\n", id->idDebugOnlyInfo()->idNum,
7504 VarSetOps::ToString(emitComp, ((instrDescCGCA*)id)->idcGCvars));
7508 id->idDebugOnlyInfo()->idMemCookie = (size_t)methHnd; // method token
7509 id->idDebugOnlyInfo()->idCallSig = sigInfo;
7513 if (addr != nullptr)
7515 codeGen->getDisAssembler().disSetMethod((size_t)addr, methHnd);
7517 #endif // LATE_DISASM
7523 /*****************************************************************************
7525 * Returns true if 'imm' is valid Cond encoding
7528 /*static*/ bool emitter::isValidImmCond(ssize_t imm)
7530 // range check the ssize_t value, to make sure it is a small unsigned value
7531 // and that only the bits in the cfi.cond are set
7532 if ((imm < 0) || (imm > 0xF))
7536 cfi.immCFVal = (unsigned)imm;
7538 return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7541 /*****************************************************************************
7543 * Returns true if 'imm' is valid Cond/Flags encoding
7546 /*static*/ bool emitter::isValidImmCondFlags(ssize_t imm)
7548 // range check the ssize_t value, to make sure it is a small unsigned value
7549 // and that only the bits in the cfi.cond or cfi.flags are set
7550 if ((imm < 0) || (imm > 0xFF))
7554 cfi.immCFVal = (unsigned)imm;
7556 return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7559 /*****************************************************************************
7561 * Returns true if 'imm' is valid Cond/Flags/Imm5 encoding
7564 /*static*/ bool emitter::isValidImmCondFlagsImm5(ssize_t imm)
7566 // range check the ssize_t value, to make sure it is a small unsigned value
7567 // and that only the bits in the cfi.cond, cfi.flags or cfi.imm5 are set
7568 if ((imm < 0) || (imm > 0x1FFF))
7572 cfi.immCFVal = (unsigned)imm;
7574 return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7577 /*****************************************************************************
7579 * Returns an encoding for the specified register used in the 'Rd' position
7582 /*static*/ emitter::code_t emitter::insEncodeReg_Rd(regNumber reg)
7584 assert(isIntegerRegister(reg));
7585 emitter::code_t ureg = (emitter::code_t)reg;
7586 assert((ureg >= 0) && (ureg <= 31));
7590 /*****************************************************************************
7592 * Returns an encoding for the specified register used in the 'Rt' position
7595 /*static*/ emitter::code_t emitter::insEncodeReg_Rt(regNumber reg)
7597 assert(isIntegerRegister(reg));
7598 emitter::code_t ureg = (emitter::code_t)reg;
7599 assert((ureg >= 0) && (ureg <= 31));
7603 /*****************************************************************************
7605 * Returns an encoding for the specified register used in the 'Rn' position
7608 /*static*/ emitter::code_t emitter::insEncodeReg_Rn(regNumber reg)
7610 assert(isIntegerRegister(reg));
7611 emitter::code_t ureg = (emitter::code_t)reg;
7612 assert((ureg >= 0) && (ureg <= 31));
7616 /*****************************************************************************
7618 * Returns an encoding for the specified register used in the 'Rm' position
7621 /*static*/ emitter::code_t emitter::insEncodeReg_Rm(regNumber reg)
7623 assert(isIntegerRegister(reg));
7624 emitter::code_t ureg = (emitter::code_t)reg;
7625 assert((ureg >= 0) && (ureg <= 31));
7629 /*****************************************************************************
7631 * Returns an encoding for the specified register used in the 'Ra' position
7634 /*static*/ emitter::code_t emitter::insEncodeReg_Ra(regNumber reg)
7636 assert(isIntegerRegister(reg));
7637 emitter::code_t ureg = (emitter::code_t)reg;
7638 assert((ureg >= 0) && (ureg <= 31));
7642 /*****************************************************************************
7644 * Returns an encoding for the specified register used in the 'Vd' position
7647 /*static*/ emitter::code_t emitter::insEncodeReg_Vd(regNumber reg)
7649 assert(emitter::isVectorRegister(reg));
7650 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7651 assert((ureg >= 0) && (ureg <= 31));
7655 /*****************************************************************************
7657 * Returns an encoding for the specified register used in the 'Vt' position
7660 /*static*/ emitter::code_t emitter::insEncodeReg_Vt(regNumber reg)
7662 assert(emitter::isVectorRegister(reg));
7663 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7664 assert((ureg >= 0) && (ureg <= 31));
7668 /*****************************************************************************
7670 * Returns an encoding for the specified register used in the 'Vn' position
7673 /*static*/ emitter::code_t emitter::insEncodeReg_Vn(regNumber reg)
7675 assert(emitter::isVectorRegister(reg));
7676 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7677 assert((ureg >= 0) && (ureg <= 31));
7681 /*****************************************************************************
7683 * Returns an encoding for the specified register used in the 'Vm' position
7686 /*static*/ emitter::code_t emitter::insEncodeReg_Vm(regNumber reg)
7688 assert(emitter::isVectorRegister(reg));
7689 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7690 assert((ureg >= 0) && (ureg <= 31));
7694 /*****************************************************************************
7696 * Returns an encoding for the specified register used in the 'Va' position
7699 /*static*/ emitter::code_t emitter::insEncodeReg_Va(regNumber reg)
7701 assert(emitter::isVectorRegister(reg));
7702 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7703 assert((ureg >= 0) && (ureg <= 31));
7707 /*****************************************************************************
7709 * Returns an encoding for the specified condition code.
7712 /*static*/ emitter::code_t emitter::insEncodeCond(insCond cond)
7714 emitter::code_t uimm = (emitter::code_t)cond;
7718 /*****************************************************************************
7720 * Returns an encoding for the condition code with the lowest bit inverted (marked by invert(<cond>) in the
7721 * architecture manual).
7724 /*static*/ emitter::code_t emitter::insEncodeInvertedCond(insCond cond)
7726 emitter::code_t uimm = (emitter::code_t)cond;
7727 uimm ^= 1; // invert the lowest bit
7731 /*****************************************************************************
7733 * Returns an encoding for the specified flags.
7736 /*static*/ emitter::code_t emitter::insEncodeFlags(insCflags flags)
7738 emitter::code_t uimm = (emitter::code_t)flags;
7742 /*****************************************************************************
7744 * Returns the encoding for the Shift Count bits to be used for Arm64 encodings
7747 /*static*/ emitter::code_t emitter::insEncodeShiftCount(ssize_t imm, emitAttr size)
7749 assert((imm & 0x003F) == imm);
7750 assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
7752 return (emitter::code_t)imm << 10;
7755 /*****************************************************************************
7757 * Returns the encoding to select a 64-bit datasize for an Arm64 instruction
7760 /*static*/ emitter::code_t emitter::insEncodeDatasize(emitAttr size)
7762 if (size == EA_8BYTE)
7764 return 0x80000000; // set the bit at location 31
7768 assert(size == EA_4BYTE);
7773 /*****************************************************************************
7775 * Returns the encoding to select the datasize for the general load/store Arm64 instructions
7779 /*static*/ emitter::code_t emitter::insEncodeDatasizeLS(emitter::code_t code, emitAttr size)
7781 bool exclusive = ((code & 0x35000000) == 0);
7783 if ((code & 0x00800000) && !exclusive) // Is this a sign-extending opcode? (i.e. ldrsw, ldrsh, ldrsb)
7785 if ((code & 0x80000000) == 0) // Is it a ldrsh or ldrsb and not ldrsw ?
7787 if (EA_SIZE(size) != EA_8BYTE) // Do we need to encode the 32-bit Rt size bit?
7789 return 0x00400000; // set the bit at location 22
7793 else if (code & 0x80000000) // Is this a ldr/str/ldur/stur opcode?
7795 if (EA_SIZE(size) == EA_8BYTE) // Do we need to encode the 64-bit size bit?
7797 return 0x40000000; // set the bit at location 30
7803 /*****************************************************************************
7805 * Returns the encoding to select the datasize for the vector load/store Arm64 instructions
7809 /*static*/ emitter::code_t emitter::insEncodeDatasizeVLS(emitter::code_t code, emitAttr size)
7814 if ((code & 0x20000000) == 0)
7818 if (size == EA_16BYTE)
7820 // set the operation size in bit 31
7821 result = 0x80000000;
7823 else if (size == EA_8BYTE)
7825 // set the operation size in bit 30
7826 result = 0x40000000;
7830 assert(size == EA_4BYTE);
7832 result = 0x00000000;
7839 if (size == EA_16BYTE)
7841 // The operation size in bits 31 and 30 are zero
7842 // Bit 23 specifies a 128-bit Load/Store
7843 result = 0x00800000;
7845 else if (size == EA_8BYTE)
7847 // set the operation size in bits 31 and 30
7848 result = 0xC0000000;
7850 else if (size == EA_4BYTE)
7852 // set the operation size in bit 31
7853 result = 0x80000000;
7855 else if (size == EA_2BYTE)
7857 // set the operation size in bit 30
7858 result = 0x40000000;
7862 assert(size == EA_1BYTE);
7863 // The operation size in bits 31 and 30 are zero
7864 result = 0x00000000;
7868 // Or in bit 26 to indicate a Vector register is used as 'target'
7869 result |= 0x04000000;
7874 /*****************************************************************************
7876 * Returns the encoding to select the datasize for the vector load/store Arm64 instructions
7880 /*static*/ emitter::code_t emitter::insEncodeDatasizeVPLS(emitter::code_t code, emitAttr size)
7884 if (size == EA_16BYTE)
7886 // The operation size in bits 31 and 30 are zero
7887 // Bit 23 specifies a 128-bit Load/Store
7888 result = 0x80000000;
7890 else if (size == EA_8BYTE)
7892 // set the operation size in bits 31 and 30
7893 result = 0x40000000;
7895 else if (size == EA_4BYTE)
7897 // set the operation size in bit 31
7898 result = 0x00000000;
7901 // Or in bit 26 to indicate a Vector register is used as 'target'
7902 result |= 0x04000000;
7907 /*****************************************************************************
7909 * Returns the encoding to set the size bit and the N bits for a 'bitfield' instruction
7913 /*static*/ emitter::code_t emitter::insEncodeDatasizeBF(emitter::code_t code, emitAttr size)
7915 // is bit 30 equal to 0?
7916 if ((code & 0x40000000) == 0) // is the opcode one of extr, sxtb, sxth or sxtw
7918 if (size == EA_8BYTE) // Do we need to set the sf and N bits?
7920 return 0x80400000; // set the sf-bit at location 31 and the N-bit at location 22
7923 return 0; // don't set any bits
7926 /*****************************************************************************
7928 * Returns the encoding to select the 64/128-bit datasize for an Arm64 vector instruction
7931 /*static*/ emitter::code_t emitter::insEncodeVectorsize(emitAttr size)
7933 if (size == EA_16BYTE)
7935 return 0x40000000; // set the bit at location 30
7939 assert(size == EA_8BYTE);
7944 /*****************************************************************************
7946 * Returns the encoding to select 'index' for an Arm64 vector elem instruction
7948 /*static*/ emitter::code_t emitter::insEncodeVectorIndex(emitAttr elemsize, ssize_t index)
7950 code_t bits = (code_t)index;
7951 if (elemsize == EA_1BYTE)
7956 else if (elemsize == EA_2BYTE)
7961 else if (elemsize == EA_4BYTE)
7968 assert(elemsize == EA_8BYTE);
7972 assert((bits >= 1) && (bits <= 0x1f));
7974 return (bits << 16); // bits at locations [20,19,18,17,16]
7977 /*****************************************************************************
7979 * Returns the encoding to select 'index2' for an Arm64 'ins' elem instruction
7981 /*static*/ emitter::code_t emitter::insEncodeVectorIndex2(emitAttr elemsize, ssize_t index2)
7983 code_t bits = (code_t)index2;
7984 if (elemsize == EA_1BYTE)
7988 else if (elemsize == EA_2BYTE)
7992 else if (elemsize == EA_4BYTE)
7998 assert(elemsize == EA_8BYTE);
8001 assert((bits >= 0) && (bits <= 0xf));
8003 return (bits << 11); // bits at locations [14,13,12,11]
8006 /*****************************************************************************
8008 * Returns the encoding to select the 'index' for an Arm64 'mul' by elem instruction
8010 /*static*/ emitter::code_t emitter::insEncodeVectorIndexLMH(emitAttr elemsize, ssize_t index)
8014 if (elemsize == EA_2BYTE)
8016 assert((index >= 0) && (index <= 7));
8019 bits |= (1 << 11); // set bit 11 'H'
8023 bits |= (1 << 21); // set bit 21 'L'
8027 bits |= (1 << 20); // set bit 20 'M'
8030 else if (elemsize == EA_4BYTE)
8032 assert((index >= 0) && (index <= 3));
8035 bits |= (1 << 11); // set bit 11 'H'
8039 bits |= (1 << 21); // set bit 21 'L'
8044 assert(!"Invalid 'elemsize' value");
8050 /*****************************************************************************
8052 * Returns the encoding to shift by 'shift' for an Arm64 vector or scalar instruction
8055 /*static*/ emitter::code_t emitter::insEncodeVectorShift(emitAttr size, ssize_t shift)
8057 assert(shift < getBitWidth(size));
8059 code_t imm = (code_t)(getBitWidth(size) + shift);
8064 /*****************************************************************************
8066 * Returns the encoding to select the 1/2/4/8 byte elemsize for an Arm64 vector instruction
8069 /*static*/ emitter::code_t emitter::insEncodeElemsize(emitAttr size)
8071 if (size == EA_8BYTE)
8073 return 0x00C00000; // set the bit at location 23 and 22
8075 else if (size == EA_4BYTE)
8077 return 0x00800000; // set the bit at location 23
8079 else if (size == EA_2BYTE)
8081 return 0x00400000; // set the bit at location 22
8083 assert(size == EA_1BYTE);
8087 /*****************************************************************************
8089 * Returns the encoding to select the 4/8 byte elemsize for an Arm64 float vector instruction
8092 /*static*/ emitter::code_t emitter::insEncodeFloatElemsize(emitAttr size)
8094 if (size == EA_8BYTE)
8096 return 0x00400000; // set the bit at location 22
8098 assert(size == EA_4BYTE);
8102 // Returns the encoding to select the index for an Arm64 float vector by elem instruction
8103 /*static*/ emitter::code_t emitter::insEncodeFloatIndex(emitAttr elemsize, ssize_t index)
8105 code_t result = 0x00000000;
8106 if (elemsize == EA_8BYTE)
8108 assert((index >= 0) && (index <= 1));
8111 result |= 0x00000800; // 'H' - set the bit at location 11
8116 assert(elemsize == EA_4BYTE);
8117 assert((index >= 0) && (index <= 3));
8120 result |= 0x00000800; // 'H' - set the bit at location 11
8124 result |= 0x00200000; // 'L' - set the bit at location 21
8130 /*****************************************************************************
8132 * Returns the encoding to select the fcvt operation for Arm64 instructions
8134 /*static*/ emitter::code_t emitter::insEncodeConvertOpt(insFormat fmt, insOpts conversion)
8139 case INS_OPTS_S_TO_D: // Single to Double
8140 assert(fmt == IF_DV_2J);
8141 result = 0x00008000; // type=00, opc=01
8144 case INS_OPTS_D_TO_S: // Double to Single
8145 assert(fmt == IF_DV_2J);
8146 result = 0x00400000; // type=01, opc=00
8149 case INS_OPTS_H_TO_S: // Half to Single
8150 assert(fmt == IF_DV_2J);
8151 result = 0x00C00000; // type=11, opc=00
8154 case INS_OPTS_H_TO_D: // Half to Double
8155 assert(fmt == IF_DV_2J);
8156 result = 0x00C08000; // type=11, opc=01
8159 case INS_OPTS_S_TO_H: // Single to Half
8160 assert(fmt == IF_DV_2J);
8161 result = 0x00018000; // type=00, opc=11
8164 case INS_OPTS_D_TO_H: // Double to Half
8165 assert(fmt == IF_DV_2J);
8166 result = 0x00418000; // type=01, opc=11
8169 case INS_OPTS_S_TO_4BYTE: // Single to INT32
8170 assert(fmt == IF_DV_2H);
8171 result = 0x00000000; // sf=0, type=00
8174 case INS_OPTS_D_TO_4BYTE: // Double to INT32
8175 assert(fmt == IF_DV_2H);
8176 result = 0x00400000; // sf=0, type=01
8179 case INS_OPTS_S_TO_8BYTE: // Single to INT64
8180 assert(fmt == IF_DV_2H);
8181 result = 0x80000000; // sf=1, type=00
8184 case INS_OPTS_D_TO_8BYTE: // Double to INT64
8185 assert(fmt == IF_DV_2H);
8186 result = 0x80400000; // sf=1, type=01
8189 case INS_OPTS_4BYTE_TO_S: // INT32 to Single
8190 assert(fmt == IF_DV_2I);
8191 result = 0x00000000; // sf=0, type=00
8194 case INS_OPTS_4BYTE_TO_D: // INT32 to Double
8195 assert(fmt == IF_DV_2I);
8196 result = 0x00400000; // sf=0, type=01
8199 case INS_OPTS_8BYTE_TO_S: // INT64 to Single
8200 assert(fmt == IF_DV_2I);
8201 result = 0x80000000; // sf=1, type=00
8204 case INS_OPTS_8BYTE_TO_D: // INT64 to Double
8205 assert(fmt == IF_DV_2I);
8206 result = 0x80400000; // sf=1, type=01
8210 assert(!"Invalid 'conversion' value");
8216 /*****************************************************************************
8218 * Returns the encoding to have the Rn register be updated Pre/Post indexed
8222 /*static*/ emitter::code_t emitter::insEncodeIndexedOpt(insOpts opt)
8224 assert(emitter::insOptsNone(opt) || emitter::insOptsIndexed(opt));
8226 if (emitter::insOptsIndexed(opt))
8228 if (emitter::insOptsPostIndex(opt))
8230 return 0x00000400; // set the bit at location 10
8234 assert(emitter::insOptsPreIndex(opt));
8235 return 0x00000C00; // set the bit at location 10 and 11
8240 assert(emitter::insOptsNone(opt));
8241 return 0; // bits 10 and 11 are zero
8245 /*****************************************************************************
8247 * Returns the encoding for a ldp/stp instruction to have the Rn register
8248 * be updated Pre/Post indexed or not updated
8251 /*static*/ emitter::code_t emitter::insEncodePairIndexedOpt(instruction ins, insOpts opt)
8253 assert(emitter::insOptsNone(opt) || emitter::insOptsIndexed(opt));
8255 if ((ins == INS_ldnp) || (ins == INS_stnp))
8257 assert(emitter::insOptsNone(opt));
8258 return 0; // bits 23 and 24 are zero
8262 if (emitter::insOptsIndexed(opt))
8264 if (emitter::insOptsPostIndex(opt))
8266 return 0x00800000; // set the bit at location 23
8270 assert(emitter::insOptsPreIndex(opt));
8271 return 0x01800000; // set the bit at location 24 and 23
8276 assert(emitter::insOptsNone(opt));
8277 return 0x01000000; // set the bit at location 24
8282 /*****************************************************************************
8284 * Returns the encoding to apply a Shift Type on the Rm register
8287 /*static*/ emitter::code_t emitter::insEncodeShiftType(insOpts opt)
8289 if (emitter::insOptsNone(opt))
8291 // None implies the we encode LSL (with a zero immediate)
8294 assert(emitter::insOptsAnyShift(opt));
8296 emitter::code_t option = (emitter::code_t)opt - (emitter::code_t)INS_OPTS_LSL;
8297 assert(option <= 3);
8299 return option << 22; // bits 23, 22
8302 /*****************************************************************************
8304 * Returns the encoding to apply a 12 bit left shift to the immediate
8307 /*static*/ emitter::code_t emitter::insEncodeShiftImm12(insOpts opt)
8309 if (emitter::insOptsLSL12(opt))
8311 return 0x00400000; // set the bit at location 22
8316 /*****************************************************************************
8318 * Returns the encoding to have the Rm register use an extend operation
8321 /*static*/ emitter::code_t emitter::insEncodeExtend(insOpts opt)
8323 if (emitter::insOptsNone(opt) || (opt == INS_OPTS_LSL))
8325 // None or LSL implies the we encode UXTX
8326 opt = INS_OPTS_UXTX;
8328 assert(emitter::insOptsAnyExtend(opt));
8330 emitter::code_t option = (emitter::code_t)opt - (emitter::code_t)INS_OPTS_UXTB;
8331 assert(option <= 7);
8333 return option << 13; // bits 15,14,13
8336 /*****************************************************************************
8338 * Returns the encoding to scale the Rm register by {0,1,2,3,4}
8339 * when using an extend operation
8342 /*static*/ emitter::code_t emitter::insEncodeExtendScale(ssize_t imm)
8344 assert((imm >= 0) && (imm <= 4));
8346 return (emitter::code_t)imm << 10; // bits 12,11,10
8349 /*****************************************************************************
8351 * Returns the encoding to have the Rm register be auto scaled by the ld/st size
8354 /*static*/ emitter::code_t emitter::insEncodeReg3Scale(bool isScaled)
8358 return 0x00001000; // set the bit at location 12
8366 BYTE* emitter::emitOutputLoadLabel(BYTE* dst, BYTE* srcAddr, BYTE* dstAddr, instrDescJmp* id)
8368 instruction ins = id->idIns();
8369 insFormat fmt = id->idInsFmt();
8370 regNumber dstReg = id->idReg1();
8373 // adr x, [rel addr] -- compute address: current addr(ip) + rel addr.
8374 assert(ins == INS_adr);
8375 assert(fmt == IF_DI_1E);
8376 ssize_t distVal = (ssize_t)(dstAddr - srcAddr);
8377 dst = emitOutputShortAddress(dst, ins, fmt, distVal, dstReg);
8381 // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8382 assert(fmt == IF_LARGEADR);
8383 ssize_t relPageAddr =
8384 (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8385 dst = emitOutputShortAddress(dst, INS_adrp, IF_DI_1E, relPageAddr, dstReg);
8387 // add x, x, page offs -- compute address = page addr + page offs
8388 ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8389 assert(isValidUimm12(imm12));
8391 emitInsCode(INS_add, IF_DI_2A); // DI_2A X0010001shiiiiii iiiiiinnnnnddddd 1100 0000 imm(i12, sh)
8392 code |= insEncodeDatasize(EA_8BYTE); // X
8393 code |= ((code_t)imm12 << 10); // iiiiiiiiiiii
8394 code |= insEncodeReg_Rd(dstReg); // ddddd
8395 code |= insEncodeReg_Rn(dstReg); // nnnnn
8396 dst += emitOutput_Instr(dst, code);
8401 /*****************************************************************************
8403 * Output a local jump or other instruction with a pc-relative immediate.
8404 * Note that this may be invoked to overwrite an existing jump instruction at 'dst'
8405 * to handle forward branch patching.
8408 BYTE* emitter::emitOutputLJ(insGroup* ig, BYTE* dst, instrDesc* i)
8410 instrDescJmp* id = (instrDescJmp*)i;
8419 // Set default ins/fmt from id.
8420 instruction ins = id->idIns();
8421 insFormat fmt = id->idInsFmt();
8423 bool loadLabel = false;
8424 bool isJump = false;
8425 bool loadConstant = false;
8442 loadConstant = true;
8451 /* Figure out the distance to the target */
8453 srcOffs = emitCurCodeOffs(dst);
8454 srcAddr = emitOffsetToPtr(srcOffs);
8456 if (id->idAddr()->iiaIsJitDataOffset())
8458 assert(loadConstant || loadLabel);
8459 int doff = id->idAddr()->iiaGetJitDataOffset();
8461 ssize_t imm = emitGetInsSC(id);
8462 assert((imm >= 0) && (imm < 0x1000)); // 0x1000 is arbitrary, currently 'imm' is always 0
8464 unsigned dataOffs = (unsigned)(doff + imm);
8465 assert(dataOffs < emitDataSize());
8466 dstAddr = emitDataOffsetToPtr(dataOffs);
8468 regNumber dstReg = id->idReg1();
8469 regNumber addrReg = dstReg; // an integer register to compute long address.
8470 emitAttr opSize = id->idOpSize();
8476 // ldr x/v, [rel addr] -- load constant from current addr(ip) + rel addr.
8477 assert(ins == INS_ldr);
8478 assert(fmt == IF_LS_1A);
8479 distVal = (ssize_t)(dstAddr - srcAddr);
8480 dst = emitOutputShortConstant(dst, ins, fmt, distVal, dstReg, opSize);
8484 // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8485 assert(fmt == IF_LARGELDC);
8486 ssize_t relPageAddr =
8487 (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8488 if (isVectorRegister(dstReg))
8490 // Update addrReg with the reserved integer register
8491 // since we cannot use dstReg (vector) to load constant directly from memory.
8492 addrReg = id->idReg2();
8493 assert(isGeneralRegister(addrReg));
8497 dst = emitOutputShortAddress(dst, ins, fmt, relPageAddr, addrReg);
8499 // ldr x, [x, page offs] -- load constant from page address + page offset into integer register.
8500 ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8501 assert(isValidUimm12(imm12));
8504 dst = emitOutputShortConstant(dst, ins, fmt, imm12, addrReg, opSize);
8506 // fmov v, d -- copy constant in integer register to vector register.
8507 // This is needed only for vector constant.
8508 if (addrReg != dstReg)
8510 // fmov Vd,Rn DV_2I X00111100X100111 000000nnnnnddddd 1E27 0000 Vd,Rn
8511 // (scalar, from general)
8512 assert(isVectorRegister(dstReg) && isGeneralRegister(addrReg));
8515 code_t code = emitInsCode(ins, fmt);
8517 code |= insEncodeReg_Vd(dstReg); // ddddd
8518 code |= insEncodeReg_Rn(addrReg); // nnnnn
8519 if (id->idOpSize() == EA_8BYTE)
8521 code |= 0x80400000; // X ... X
8523 dst += emitOutput_Instr(dst, code);
8530 dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8536 assert(loadLabel || isJump);
8538 if (id->idAddr()->iiaHasInstrCount())
8541 int instrCount = id->idAddr()->iiaGetInstrCount();
8542 unsigned insNum = emitFindInsNum(ig, id);
8545 // Backward branches using instruction count must be within the same instruction group.
8546 assert(insNum + 1 >= (unsigned)(-instrCount));
8548 dstOffs = ig->igOffs + emitFindOffset(ig, (insNum + 1 + instrCount));
8549 dstAddr = emitOffsetToPtr(dstOffs);
8553 dstOffs = id->idAddr()->iiaIGlabel->igOffs;
8554 dstAddr = emitOffsetToPtr(dstOffs);
8557 distVal = (ssize_t)(dstAddr - srcAddr);
8559 if (dstOffs <= srcOffs)
8562 /* This is a backward jump - distance is known at this point */
8564 if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8566 size_t blkOffs = id->idjIG->igOffs;
8568 if (INTERESTING_JUMP_NUM == 0)
8569 printf("[3] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8570 printf("[3] Jump block is at %08X - %02X = %08X\n", blkOffs, emitOffsAdj, blkOffs - emitOffsAdj);
8571 printf("[3] Jump is at %08X - %02X = %08X\n", srcOffs, emitOffsAdj, srcOffs - emitOffsAdj);
8572 printf("[3] Label block is at %08X - %02X = %08X\n", dstOffs, emitOffsAdj, dstOffs - emitOffsAdj);
8578 /* This is a forward jump - distance will be an upper limit */
8580 emitFwdJumps = true;
8582 /* The target offset will be closer by at least 'emitOffsAdj', but only if this
8583 jump doesn't cross the hot-cold boundary. */
8585 if (!emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8587 dstOffs -= emitOffsAdj;
8588 distVal -= emitOffsAdj;
8591 /* Record the location of the jump for later patching */
8593 id->idjOffs = dstOffs;
8595 /* Are we overflowing the id->idjOffs bitfield? */
8596 if (id->idjOffs != dstOffs)
8597 IMPL_LIMITATION("Method is too large");
8600 if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8602 size_t blkOffs = id->idjIG->igOffs;
8604 if (INTERESTING_JUMP_NUM == 0)
8605 printf("[4] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8606 printf("[4] Jump block is at %08X\n", blkOffs);
8607 printf("[4] Jump is at %08X\n", srcOffs);
8608 printf("[4] Label block is at %08X - %02X = %08X\n", dstOffs + emitOffsAdj, emitOffsAdj, dstOffs);
8614 if (0 && emitComp->verbose)
8617 int distValSize = id->idjShort ? 4 : 8;
8618 printf("; %s jump [%08X/%03u] from %0*X to %0*X: dist = %08XH\n", (dstOffs <= srcOffs) ? "Fwd" : "Bwd",
8619 dspPtr(id), id->idDebugOnlyInfo()->idNum, distValSize, srcOffs + sz, distValSize, dstOffs, distVal);
8623 /* For forward jumps, record the address of the distance value */
8624 id->idjTemp.idjAddr = (distVal > 0) ? dst : NULL;
8626 if (emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8628 assert(!id->idjShort);
8629 NYI_ARM64("Relocation Support for long address");
8632 assert(insOptsNone(id->idInsOpt()));
8638 // Short conditional/unconditional jump
8639 assert(!id->idjKeepLong);
8640 assert(emitJumpCrossHotColdBoundary(srcOffs, dstOffs) == false);
8641 assert((fmt == IF_BI_0A) || (fmt == IF_BI_0B) || (fmt == IF_BI_1A) || (fmt == IF_BI_1B));
8645 // Long conditional jump
8646 assert(fmt == IF_LARGEJMP);
8647 // This is a pseudo-instruction format representing a large conditional branch, to allow
8648 // us to get a greater branch target range than we can get by using a straightforward conditional
8649 // branch. It is encoded as a short conditional branch that branches around a long unconditional
8652 // Conceptually, we have:
8656 // The code we emit is:
8658 // b<!cond> L_not // 4 bytes. Note that we reverse the condition.
8659 // b L_target // 4 bytes
8662 // Note that we don't actually insert any blocks: we simply encode "b <!cond> L_not" as a branch with
8663 // the correct offset. Note also that this works for both integer and floating-point conditions, because
8664 // the condition inversion takes ordered/unordered into account, preserving NaN behavior. For example,
8665 // "GT" (greater than) is inverted to "LE" (less than, equal, or unordered).
8667 instruction reverseIns;
8668 insFormat reverseFmt;
8673 reverseIns = INS_cbnz;
8674 reverseFmt = IF_BI_1A;
8677 reverseIns = INS_cbz;
8678 reverseFmt = IF_BI_1A;
8681 reverseIns = INS_tbnz;
8682 reverseFmt = IF_BI_1B;
8685 reverseIns = INS_tbz;
8686 reverseFmt = IF_BI_1B;
8689 reverseIns = emitJumpKindToIns(emitReverseJumpKind(emitInsToJumpKind(ins)));
8690 reverseFmt = IF_BI_0B;
8694 emitOutputShortBranch(dst,
8695 reverseIns, // reverse the conditional instruction
8697 8, /* 8 bytes from start of this large conditional pseudo-instruction to L_not. */
8700 // Now, pretend we've got a normal unconditional branch, and fall through to the code to emit that.
8704 // The distVal was computed based on the beginning of the pseudo-instruction,
8705 // So subtract the size of the conditional branch so that it is relative to the
8706 // unconditional branch.
8710 dst = emitOutputShortBranch(dst, ins, fmt, distVal, id);
8714 dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8720 /*****************************************************************************
8722 * Output a short branch instruction.
8724 BYTE* emitter::emitOutputShortBranch(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, instrDescJmp* id)
8726 code_t code = emitInsCode(ins, fmt);
8728 ssize_t loBits = (distVal & 3);
8729 noway_assert(loBits == 0);
8730 distVal >>= 2; // branch offset encodings are scaled by 4.
8732 if (fmt == IF_BI_0A)
8734 // INS_b or INS_bl_local
8735 noway_assert(isValidSimm26(distVal));
8736 distVal &= 0x3FFFFFFLL;
8739 else if (fmt == IF_BI_0B) // BI_0B 01010100iiiiiiii iiiiiiiiiiiXXXXX simm19:00
8741 // INS_beq, INS_bne, etc...
8742 noway_assert(isValidSimm19(distVal));
8743 distVal &= 0x7FFFFLL;
8744 code |= distVal << 5;
8746 else if (fmt == IF_BI_1A) // BI_1A X.......iiiiiiii iiiiiiiiiiittttt Rt simm19:00
8748 // INS_cbz or INS_cbnz
8749 assert(id != nullptr);
8750 code |= insEncodeDatasize(id->idOpSize()); // X
8751 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
8753 noway_assert(isValidSimm19(distVal));
8754 distVal &= 0x7FFFFLL; // 19 bits
8755 code |= distVal << 5;
8757 else if (fmt == IF_BI_1B) // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
8759 // INS_tbz or INS_tbnz
8760 assert(id != nullptr);
8761 ssize_t imm = emitGetInsSC(id);
8762 assert(isValidImmShift(imm, id->idOpSize()));
8764 if (imm & 0x20) // test bit 32-63 ?
8766 code |= 0x80000000; // B
8768 code |= ((imm & 0x1F) << 19); // bbbbb
8769 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
8771 noway_assert(isValidSimm14(distVal));
8772 distVal &= 0x3FFFLL; // 14 bits
8773 code |= distVal << 5;
8777 assert(!"Unknown fmt for emitOutputShortBranch");
8780 dst += emitOutput_Instr(dst, code);
8785 /*****************************************************************************
8787 * Output a short address instruction.
8789 BYTE* emitter::emitOutputShortAddress(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, regNumber reg)
8791 ssize_t loBits = (distVal & 3);
8794 code_t code = emitInsCode(ins, fmt);
8795 if (fmt == IF_DI_1E) // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
8797 // INS_adr or INS_adrp
8798 code |= insEncodeReg_Rd(reg); // ddddd
8800 noway_assert(isValidSimm19(distVal));
8801 distVal &= 0x7FFFFLL; // 19 bits
8802 code |= distVal << 5;
8803 code |= loBits << 29; // 2 bits
8807 assert(!"Unknown fmt for emitOutputShortAddress");
8810 dst += emitOutput_Instr(dst, code);
8815 /*****************************************************************************
8817 * Output a short constant instruction.
8819 BYTE* emitter::emitOutputShortConstant(
8820 BYTE* dst, instruction ins, insFormat fmt, ssize_t imm, regNumber reg, emitAttr opSize)
8822 code_t code = emitInsCode(ins, fmt);
8824 if (fmt == IF_LS_1A)
8826 // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt simm21
8827 // INS_ldr or INS_ldrsw (PC-Relative)
8829 ssize_t loBits = (imm & 3);
8830 noway_assert(loBits == 0);
8831 ssize_t distVal = imm >>= 2; // load offset encodings are scaled by 4.
8833 noway_assert(isValidSimm19(distVal));
8835 // Is the target a vector register?
8836 if (isVectorRegister(reg))
8838 code |= insEncodeDatasizeVLS(code, opSize); // XX V
8839 code |= insEncodeReg_Vt(reg); // ttttt
8843 assert(isGeneralRegister(reg));
8844 // insEncodeDatasizeLS is not quite right for this case.
8845 // So just specialize it.
8846 if ((ins == INS_ldr) && (opSize == EA_8BYTE))
8848 // set the operation size in bit 30
8852 code |= insEncodeReg_Rt(reg); // ttttt
8855 distVal &= 0x7FFFFLL; // 19 bits
8856 code |= distVal << 5;
8858 else if (fmt == IF_LS_2B)
8860 // ldr Rt,[Xn+pimm12] LS_2B 1X11100101iiiiii iiiiiinnnnnttttt B940 0000 imm(0-4095<<{2,3})
8861 // INS_ldr or INS_ldrsw (PC-Relative)
8862 noway_assert(isValidUimm12(imm));
8863 assert(isGeneralRegister(reg));
8865 if (opSize == EA_8BYTE)
8867 // insEncodeDatasizeLS is not quite right for this case.
8868 // So just specialize it.
8871 // set the operation size in bit 30
8874 // Low 3 bits should be 0 -- 8 byte JIT data should be aligned on 8 byte.
8875 assert((imm & 7) == 0);
8880 assert(opSize == EA_4BYTE);
8881 // Low 2 bits should be 0 -- 4 byte aligned data.
8882 assert((imm & 3) == 0);
8886 code |= insEncodeReg_Rt(reg); // ttttt
8887 code |= insEncodeReg_Rn(reg); // nnnnn
8892 assert(!"Unknown fmt for emitOutputShortConstant");
8895 dst += emitOutput_Instr(dst, code);
8899 /*****************************************************************************
8901 * Output a call instruction.
8904 unsigned emitter::emitOutputCall(insGroup* ig, BYTE* dst, instrDesc* id, code_t code)
8906 const unsigned char callInstrSize = sizeof(code_t); // 4 bytes
8907 regMaskTP gcrefRegs;
8908 regMaskTP byrefRegs;
8910 VARSET_TP GCvars(VarSetOps::UninitVal());
8912 // Is this a "fat" call descriptor?
8913 if (id->idIsLargeCall())
8915 instrDescCGCA* idCall = (instrDescCGCA*)id;
8916 gcrefRegs = idCall->idcGcrefRegs;
8917 byrefRegs = idCall->idcByrefRegs;
8918 VarSetOps::Assign(emitComp, GCvars, idCall->idcGCvars);
8922 assert(!id->idIsLargeDsp());
8923 assert(!id->idIsLargeCns());
8925 gcrefRegs = emitDecodeCallGCregs(id);
8927 VarSetOps::AssignNoCopy(emitComp, GCvars, VarSetOps::MakeEmpty(emitComp));
8930 /* We update the GC info before the call as the variables cannot be
8931 used by the call. Killing variables before the call helps with
8932 boundary conditions if the call is CORINFO_HELP_THROW - see bug 50029.
8933 If we ever track aliased variables (which could be used by the
8934 call), we would have to keep them alive past the call. */
8936 emitUpdateLiveGCvars(GCvars, dst);
8938 // Now output the call instruction and update the 'dst' pointer
8940 unsigned outputInstrSize = emitOutput_Instr(dst, code);
8941 dst += outputInstrSize;
8943 // All call instructions are 4-byte in size on ARM64
8945 assert(outputInstrSize == callInstrSize);
8947 // If the method returns a GC ref, mark INTRET (R0) appropriately.
8948 if (id->idGCref() == GCT_GCREF)
8950 gcrefRegs |= RBM_INTRET;
8952 else if (id->idGCref() == GCT_BYREF)
8954 byrefRegs |= RBM_INTRET;
8957 // If is a multi-register return method is called, mark INTRET_1 (X1) appropriately
8958 if (id->idIsLargeCall())
8960 instrDescCGCA* idCall = (instrDescCGCA*)id;
8961 if (idCall->idSecondGCref() == GCT_GCREF)
8963 gcrefRegs |= RBM_INTRET_1;
8965 else if (idCall->idSecondGCref() == GCT_BYREF)
8967 byrefRegs |= RBM_INTRET_1;
8971 // If the GC register set has changed, report the new set.
8972 if (gcrefRegs != emitThisGCrefRegs)
8974 emitUpdateLiveGCregs(GCT_GCREF, gcrefRegs, dst);
8976 // If the Byref register set has changed, report the new set.
8977 if (byrefRegs != emitThisByrefRegs)
8979 emitUpdateLiveGCregs(GCT_BYREF, byrefRegs, dst);
8982 // Some helper calls may be marked as not requiring GC info to be recorded.
8983 if ((!id->idIsNoGC()))
8985 // On ARM64, as on AMD64, we don't change the stack pointer to push/pop args.
8986 // So we're not really doing a "stack pop" here (note that "args" is 0), but we use this mechanism
8987 // to record the call for GC info purposes. (It might be best to use an alternate call,
8988 // and protect "emitStackPop" under the EMIT_TRACK_STACK_DEPTH preprocessor variable.)
8989 emitStackPop(dst, /*isCall*/ true, callInstrSize, /*args*/ 0);
8991 // Do we need to record a call location for GC purposes?
8993 if (!emitFullGCinfo)
8995 emitRecordGCcall(dst, callInstrSize);
8998 return callInstrSize;
9001 /*****************************************************************************
9003 * Emit a 32-bit Arm64 instruction
9006 /*static*/ unsigned emitter::emitOutput_Instr(BYTE* dst, code_t code)
9008 assert(sizeof(code_t) == 4);
9009 *((code_t*)dst) = code;
9011 return sizeof(code_t);
9014 /*****************************************************************************
9016 * Append the machine code corresponding to the given instruction descriptor
9017 * to the code block at '*dp'; the base of the code block is 'bp', and 'ig'
9018 * is the instruction group that contains the instruction. Updates '*dp' to
9019 * point past the generated code, and returns the size of the instruction
9020 * descriptor in bytes.
9023 size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
9028 size_t sz = emitGetInstrDescSize(id); // TODO-ARM64-Cleanup: on ARM, this is set in each case. why?
9029 instruction ins = id->idIns();
9030 insFormat fmt = id->idInsFmt();
9031 emitAttr size = id->idOpSize();
9032 unsigned char callInstrSize = 0;
9037 bool dspOffs = emitComp->opts.dspGCtbls;
9039 bool dspOffs = !emitComp->opts.disDiffable;
9043 assert(REG_NA == (int)REG_NA);
9045 VARSET_TP GCvars(VarSetOps::UninitVal());
9047 /* What instruction format have we got? */
9062 case IF_BI_0A: // BI_0A ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
9063 case IF_BI_0B: // BI_0B ......iiiiiiiiii iiiiiiiiiii..... simm19:00
9065 assert(id->idGCref() == GCT_NONE);
9066 assert(id->idIsBound());
9067 dst = emitOutputLJ(ig, dst, id);
9068 sz = sizeof(instrDescJmp);
9071 case IF_BI_0C: // BI_0C ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
9072 code = emitInsCode(ins, fmt);
9073 sz = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
9074 dst += emitOutputCall(ig, dst, id, code);
9075 // Always call RecordRelocation so that we wire in a JumpStub when we don't reach
9076 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_BRANCH26);
9079 case IF_BI_1A: // BI_1A ......iiiiiiiiii iiiiiiiiiiittttt Rt simm19:00
9080 assert(insOptsNone(id->idInsOpt()));
9081 assert(id->idIsBound());
9083 dst = emitOutputLJ(ig, dst, id);
9084 sz = sizeof(instrDescJmp);
9087 case IF_BI_1B: // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
9088 assert(insOptsNone(id->idInsOpt()));
9089 assert(id->idIsBound());
9091 dst = emitOutputLJ(ig, dst, id);
9092 sz = sizeof(instrDescJmp);
9095 case IF_BR_1A: // BR_1A ................ ......nnnnn..... Rn
9096 assert(insOptsNone(id->idInsOpt()));
9097 assert((ins == INS_ret) || (ins == INS_br));
9098 code = emitInsCode(ins, fmt);
9099 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9101 dst += emitOutput_Instr(dst, code);
9104 case IF_BR_1B: // BR_1B ................ ......nnnnn..... Rn
9105 assert(insOptsNone(id->idInsOpt()));
9106 assert((ins == INS_br_tail) || (ins == INS_blr));
9107 code = emitInsCode(ins, fmt);
9108 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9110 sz = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
9111 dst += emitOutputCall(ig, dst, id, code);
9114 case IF_LS_1A: // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB)
9116 assert(insOptsNone(id->idInsOpt()));
9117 assert(id->idIsBound());
9119 dst = emitOutputLJ(ig, dst, id);
9120 sz = sizeof(instrDescJmp);
9123 case IF_LS_2A: // LS_2A .X.......X...... ......nnnnnttttt Rt Rn
9124 assert(insOptsNone(id->idInsOpt()));
9125 code = emitInsCode(ins, fmt);
9126 // Is the target a vector register?
9127 if (isVectorRegister(id->idReg1()))
9129 code &= 0x3FFFFFFF; // clear the size bits
9130 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9131 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9135 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9136 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9138 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9139 dst += emitOutput_Instr(dst, code);
9142 case IF_LS_2B: // LS_2B .X.......Xiiiiii iiiiiinnnnnttttt Rt Rn imm(0-4095)
9143 assert(insOptsNone(id->idInsOpt()));
9144 imm = emitGetInsSC(id);
9145 assert(isValidUimm12(imm));
9146 code = emitInsCode(ins, fmt);
9147 // Is the target a vector register?
9148 if (isVectorRegister(id->idReg1()))
9150 code &= 0x3FFFFFFF; // clear the size bits
9151 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9152 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9156 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9157 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9159 code |= ((code_t)imm << 10); // iiiiiiiiiiii
9160 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9161 dst += emitOutput_Instr(dst, code);
9164 case IF_LS_2C: // LS_2C .X.......X.iiiii iiiiPPnnnnnttttt Rt Rn imm(-256..+255) no/pre/post inc
9165 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9166 imm = emitGetInsSC(id);
9167 assert((imm >= -256) && (imm <= 255)); // signed 9 bits
9168 imm &= 0x1ff; // force into unsigned 9 bit representation
9169 code = emitInsCode(ins, fmt);
9170 // Is the target a vector register?
9171 if (isVectorRegister(id->idReg1()))
9173 code &= 0x3FFFFFFF; // clear the size bits
9174 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9175 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9179 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9180 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9182 code |= insEncodeIndexedOpt(id->idInsOpt()); // PP
9183 code |= ((code_t)imm << 12); // iiiiiiiii
9184 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9185 dst += emitOutput_Instr(dst, code);
9188 case IF_LS_3A: // LS_3A .X.......X.mmmmm oooS..nnnnnttttt Rt Rn Rm ext(Rm) LSL {}
9189 assert(insOptsLSExtend(id->idInsOpt()));
9190 code = emitInsCode(ins, fmt);
9191 // Is the target a vector register?
9192 if (isVectorRegister(id->idReg1()))
9194 code &= 0x3FFFFFFF; // clear the size bits
9195 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9196 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9200 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9201 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9203 code |= insEncodeExtend(id->idInsOpt()); // ooo
9204 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9205 if (id->idIsLclVar())
9207 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9211 code |= insEncodeReg3Scale(id->idReg3Scaled()); // S
9212 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9214 dst += emitOutput_Instr(dst, code);
9217 case IF_LS_3B: // LS_3B X............... .aaaaannnnnddddd Rd Ra Rn
9218 assert(insOptsNone(id->idInsOpt()));
9219 code = emitInsCode(ins, fmt);
9220 // Is the target a vector register?
9221 if (isVectorRegister(id->idReg1()))
9223 code &= 0x3FFFFFFF; // clear the size bits
9224 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9225 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9226 code |= insEncodeReg_Va(id->idReg2()); // aaaaa
9230 code |= insEncodeDatasize(id->idOpSize()); // X
9231 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9232 code |= insEncodeReg_Ra(id->idReg2()); // aaaaa
9234 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9235 dst += emitOutput_Instr(dst, code);
9238 case IF_LS_3C: // LS_3C X......PP.iiiiii iaaaaannnnnddddd Rd Ra Rn imm(im7,sh)
9239 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9240 imm = emitGetInsSC(id);
9241 assert((imm >= -64) && (imm <= 63)); // signed 7 bits
9242 imm &= 0x7f; // force into unsigned 7 bit representation
9243 code = emitInsCode(ins, fmt);
9244 // Is the target a vector register?
9245 if (isVectorRegister(id->idReg1()))
9247 code &= 0x3FFFFFFF; // clear the size bits
9248 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9249 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9250 code |= insEncodeReg_Va(id->idReg2()); // aaaaa
9254 code |= insEncodeDatasize(id->idOpSize()); // X
9255 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9256 code |= insEncodeReg_Ra(id->idReg2()); // aaaaa
9258 code |= insEncodePairIndexedOpt(ins, id->idInsOpt()); // PP
9259 code |= ((code_t)imm << 15); // iiiiiiiii
9260 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9261 dst += emitOutput_Instr(dst, code);
9264 case IF_LS_3D: // LS_3D .X.......X.mmmmm ......nnnnnttttt Wm Rt Rn
9265 code = emitInsCode(ins, fmt);
9266 // Arm64 store exclusive unpredictable cases
9267 assert(id->idReg1() != id->idReg2());
9268 assert(id->idReg1() != id->idReg3());
9269 code |= insEncodeDatasizeLS(code, id->idOpSize()); // X
9270 code |= insEncodeReg_Rm(id->idReg1()); // mmmmm
9271 code |= insEncodeReg_Rt(id->idReg2()); // ttttt
9272 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9273 dst += emitOutput_Instr(dst, code);
9276 case IF_DI_1A: // DI_1A X.......shiiiiii iiiiiinnnnn..... Rn imm(i12,sh)
9277 assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9278 imm = emitGetInsSC(id);
9279 assert(isValidUimm12(imm));
9280 code = emitInsCode(ins, fmt);
9281 code |= insEncodeDatasize(id->idOpSize()); // X
9282 code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9283 code |= ((code_t)imm << 10); // iiiiiiiiiiii
9284 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9285 dst += emitOutput_Instr(dst, code);
9288 case IF_DI_1B: // DI_1B X........hwiiiii iiiiiiiiiiiddddd Rd imm(i16,hw)
9289 imm = emitGetInsSC(id);
9290 assert(isValidImmHWVal(imm, id->idOpSize()));
9291 code = emitInsCode(ins, fmt);
9292 code |= insEncodeDatasize(id->idOpSize()); // X
9293 code |= ((code_t)imm << 5); // hwiiiii iiiiiiiiiii
9294 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9295 dst += emitOutput_Instr(dst, code);
9298 case IF_DI_1C: // DI_1C X........Nrrrrrr ssssssnnnnn..... Rn imm(N,r,s)
9299 imm = emitGetInsSC(id);
9300 assert(isValidImmNRS(imm, id->idOpSize()));
9301 code = emitInsCode(ins, fmt);
9302 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9303 code |= insEncodeDatasize(id->idOpSize()); // X
9304 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9305 dst += emitOutput_Instr(dst, code);
9308 case IF_DI_1D: // DI_1D X........Nrrrrrr ssssss.....ddddd Rd imm(N,r,s)
9309 imm = emitGetInsSC(id);
9310 assert(isValidImmNRS(imm, id->idOpSize()));
9311 code = emitInsCode(ins, fmt);
9312 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9313 code |= insEncodeDatasize(id->idOpSize()); // X
9314 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9315 dst += emitOutput_Instr(dst, code);
9318 case IF_DI_1E: // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
9320 assert(insOptsNone(id->idInsOpt()));
9321 if (id->idIsReloc())
9323 code = emitInsCode(ins, fmt);
9324 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9325 dst += emitOutput_Instr(dst, code);
9326 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEBASE_REL21);
9330 // Local jmp/load case which does not need a relocation.
9331 assert(id->idIsBound());
9332 dst = emitOutputLJ(ig, dst, id);
9334 sz = sizeof(instrDescJmp);
9337 case IF_DI_1F: // DI_1F X..........iiiii cccc..nnnnn.nzcv Rn imm5 nzcv cond
9338 imm = emitGetInsSC(id);
9339 assert(isValidImmCondFlagsImm5(imm));
9342 cfi.immCFVal = (unsigned)imm;
9343 code = emitInsCode(ins, fmt);
9344 code |= insEncodeDatasize(id->idOpSize()); // X
9345 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9346 code |= ((code_t)cfi.imm5 << 16); // iiiii
9347 code |= insEncodeFlags(cfi.flags); // nzcv
9348 code |= insEncodeCond(cfi.cond); // cccc
9349 dst += emitOutput_Instr(dst, code);
9353 case IF_DI_2A: // DI_2A X.......shiiiiii iiiiiinnnnnddddd Rd Rn imm(i12,sh)
9354 assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9355 imm = emitGetInsSC(id);
9356 assert(isValidUimm12(imm));
9357 code = emitInsCode(ins, fmt);
9358 code |= insEncodeDatasize(id->idOpSize()); // X
9359 code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9360 code |= ((code_t)imm << 10); // iiiiiiiiiiii
9361 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9362 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9363 dst += emitOutput_Instr(dst, code);
9365 if (id->idIsReloc())
9367 assert(sz == sizeof(instrDesc));
9368 assert(id->idAddr()->iiaAddr != nullptr);
9369 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEOFFSET_12A);
9373 case IF_DI_2B: // DI_2B X.........Xnnnnn ssssssnnnnnddddd Rd Rn imm(0-63)
9374 code = emitInsCode(ins, fmt);
9375 imm = emitGetInsSC(id);
9376 assert(isValidImmShift(imm, id->idOpSize()));
9377 code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9378 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9379 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9380 code |= insEncodeReg_Rm(id->idReg2()); // Reg2 also in mmmmm
9381 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9382 dst += emitOutput_Instr(dst, code);
9385 case IF_DI_2C: // DI_2C X........Nrrrrrr ssssssnnnnnddddd Rd Rn imm(N,r,s)
9386 imm = emitGetInsSC(id);
9387 assert(isValidImmNRS(imm, id->idOpSize()));
9388 code = emitInsCode(ins, fmt);
9389 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9390 code |= insEncodeDatasize(id->idOpSize()); // X
9391 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9392 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9393 dst += emitOutput_Instr(dst, code);
9396 case IF_DI_2D: // DI_2D X........Nrrrrrr ssssssnnnnnddddd Rd Rn imr, imms (N,r,s)
9397 if (ins == INS_asr || ins == INS_lsl || ins == INS_lsr)
9399 imm = emitGetInsSC(id);
9400 assert(isValidImmShift(imm, id->idOpSize()));
9402 // Shift immediates are aliases of the SBFM/UBFM instructions
9403 // that actually take 2 registers and 2 constants,
9404 // Since we stored the shift immediate value
9405 // we need to calculate the N,R and S values here.
9410 bmi.immN = (size == EA_8BYTE) ? 1 : 0;
9412 bmi.immS = (size == EA_8BYTE) ? 0x3f : 0x1f;
9414 // immR and immS are now set correctly for INS_asr and INS_lsr
9415 // but for INS_lsl we have to adjust the values for immR and immS
9419 bmi.immR = -imm & bmi.immS;
9420 bmi.immS = bmi.immS - imm;
9423 // setup imm with the proper 13 bit value N:R:S
9429 // The other instructions have already have encoded N,R and S values
9430 imm = emitGetInsSC(id);
9432 assert(isValidImmNRS(imm, id->idOpSize()));
9434 code = emitInsCode(ins, fmt);
9435 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9436 code |= insEncodeDatasize(id->idOpSize()); // X
9437 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9438 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9439 dst += emitOutput_Instr(dst, code);
9442 case IF_DR_1D: // DR_1D X............... cccc.......ddddd Rd cond
9443 imm = emitGetInsSC(id);
9444 assert(isValidImmCond(imm));
9447 cfi.immCFVal = (unsigned)imm;
9448 code = emitInsCode(ins, fmt);
9449 code |= insEncodeDatasize(id->idOpSize()); // X
9450 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9451 code |= insEncodeInvertedCond(cfi.cond); // cccc
9452 dst += emitOutput_Instr(dst, code);
9456 case IF_DR_2A: // DR_2A X..........mmmmm ......nnnnn..... Rn Rm
9457 assert(insOptsNone(id->idInsOpt()));
9458 code = emitInsCode(ins, fmt);
9459 code |= insEncodeDatasize(id->idOpSize()); // X
9460 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9461 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9462 dst += emitOutput_Instr(dst, code);
9465 case IF_DR_2B: // DR_2B X.......sh.mmmmm ssssssnnnnn..... Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
9466 code = emitInsCode(ins, fmt);
9467 imm = emitGetInsSC(id);
9468 assert(isValidImmShift(imm, id->idOpSize()));
9469 code |= insEncodeDatasize(id->idOpSize()); // X
9470 code |= insEncodeShiftType(id->idInsOpt()); // sh
9471 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9472 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9473 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9474 dst += emitOutput_Instr(dst, code);
9477 case IF_DR_2C: // DR_2C X..........mmmmm ooosssnnnnn..... Rn Rm ext(Rm) LSL imm(0-4)
9478 code = emitInsCode(ins, fmt);
9479 imm = emitGetInsSC(id);
9480 assert((imm >= 0) && (imm <= 4)); // imm [0..4]
9481 code |= insEncodeDatasize(id->idOpSize()); // X
9482 code |= insEncodeExtend(id->idInsOpt()); // ooo
9483 code |= insEncodeExtendScale(imm); // sss
9484 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9485 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9486 dst += emitOutput_Instr(dst, code);
9489 case IF_DR_2D: // DR_2D X..........nnnnn cccc..nnnnnddddd Rd Rn cond
9490 imm = emitGetInsSC(id);
9491 assert(isValidImmCond(imm));
9494 cfi.immCFVal = (unsigned)imm;
9495 code = emitInsCode(ins, fmt);
9496 code |= insEncodeDatasize(id->idOpSize()); // X
9497 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9498 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9499 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9500 code |= insEncodeInvertedCond(cfi.cond); // cccc
9501 dst += emitOutput_Instr(dst, code);
9505 case IF_DR_2E: // DR_2E X..........mmmmm ...........ddddd Rd Rm
9506 code = emitInsCode(ins, fmt);
9507 code |= insEncodeDatasize(id->idOpSize()); // X
9508 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9509 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9510 dst += emitOutput_Instr(dst, code);
9513 case IF_DR_2F: // DR_2F X.......sh.mmmmm ssssss.....ddddd Rd Rm {LSL,LSR,ASR} imm(0-63)
9514 code = emitInsCode(ins, fmt);
9515 imm = emitGetInsSC(id);
9516 assert(isValidImmShift(imm, id->idOpSize()));
9517 code |= insEncodeDatasize(id->idOpSize()); // X
9518 code |= insEncodeShiftType(id->idInsOpt()); // sh
9519 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9520 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9521 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9522 dst += emitOutput_Instr(dst, code);
9525 case IF_DR_2G: // DR_2G X............... .....xnnnnnddddd Rd Rn
9526 code = emitInsCode(ins, fmt);
9527 code |= insEncodeDatasize(id->idOpSize()); // X
9530 if (size == EA_8BYTE)
9532 code |= 0x00000400; // x - bit at location 10
9535 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9536 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9537 dst += emitOutput_Instr(dst, code);
9540 case IF_DR_2H: // DR_2H X........X...... ......nnnnnddddd Rd Rn
9541 code = emitInsCode(ins, fmt);
9542 code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9543 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9544 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9545 dst += emitOutput_Instr(dst, code);
9548 case IF_DR_2I: // DR_2I X..........mmmmm cccc..nnnnn.nzcv Rn Rm nzcv cond
9549 imm = emitGetInsSC(id);
9550 assert(isValidImmCondFlags(imm));
9553 cfi.immCFVal = (unsigned)imm;
9554 code = emitInsCode(ins, fmt);
9555 code |= insEncodeDatasize(id->idOpSize()); // X
9556 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9557 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9558 code |= insEncodeFlags(cfi.flags); // nzcv
9559 code |= insEncodeCond(cfi.cond); // cccc
9560 dst += emitOutput_Instr(dst, code);
9564 case IF_DR_2J: // DR_2J ................ ......nnnnnddddd Sd Sn (sha1h)
9565 code = emitInsCode(ins, fmt);
9566 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9567 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9568 dst += emitOutput_Instr(dst, code);
9571 case IF_DR_3A: // DR_3A X..........mmmmm ......nnnnnmmmmm Rd Rn Rm
9572 code = emitInsCode(ins, fmt);
9573 code |= insEncodeDatasize(id->idOpSize()); // X
9574 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9575 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9576 if (id->idIsLclVar())
9578 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9582 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9584 dst += emitOutput_Instr(dst, code);
9587 case IF_DR_3B: // DR_3B X.......sh.mmmmm ssssssnnnnnddddd Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
9588 code = emitInsCode(ins, fmt);
9589 imm = emitGetInsSC(id);
9590 assert(isValidImmShift(imm, id->idOpSize()));
9591 code |= insEncodeDatasize(id->idOpSize()); // X
9592 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9593 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9594 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9595 code |= insEncodeShiftType(id->idInsOpt()); // sh
9596 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9597 dst += emitOutput_Instr(dst, code);
9600 case IF_DR_3C: // DR_3C X..........mmmmm ooosssnnnnnddddd Rd Rn Rm ext(Rm) LSL imm(0-4)
9601 code = emitInsCode(ins, fmt);
9602 imm = emitGetInsSC(id);
9603 assert((imm >= 0) && (imm <= 4)); // imm [0..4]
9604 code |= insEncodeDatasize(id->idOpSize()); // X
9605 code |= insEncodeExtend(id->idInsOpt()); // ooo
9606 code |= insEncodeExtendScale(imm); // sss
9607 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9608 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9609 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9610 dst += emitOutput_Instr(dst, code);
9613 case IF_DR_3D: // DR_3D X..........mmmmm cccc..nnnnnddddd Rd Rn Rm cond
9614 imm = emitGetInsSC(id);
9615 assert(isValidImmCond(imm));
9618 cfi.immCFVal = (unsigned)imm;
9619 code = emitInsCode(ins, fmt);
9620 code |= insEncodeDatasize(id->idOpSize()); // X
9621 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9622 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9623 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9624 code |= insEncodeCond(cfi.cond); // cccc
9625 dst += emitOutput_Instr(dst, code);
9629 case IF_DR_3E: // DR_3E X........X.mmmmm ssssssnnnnnddddd Rd Rn Rm imm(0-63)
9630 code = emitInsCode(ins, fmt);
9631 imm = emitGetInsSC(id);
9632 assert(isValidImmShift(imm, id->idOpSize()));
9633 code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9634 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9635 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9636 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9637 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9638 dst += emitOutput_Instr(dst, code);
9641 case IF_DR_4A: // DR_4A X..........mmmmm .aaaaannnnnmmmmm Rd Rn Rm Ra
9642 code = emitInsCode(ins, fmt);
9643 code |= insEncodeDatasize(id->idOpSize()); // X
9644 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9645 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9646 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9647 code |= insEncodeReg_Ra(id->idReg4()); // aaaaa
9648 dst += emitOutput_Instr(dst, code);
9651 case IF_DV_1A: // DV_1A .........X.iiiii iii........ddddd Vd imm8 (fmov - immediate scalar)
9652 imm = emitGetInsSC(id);
9653 elemsize = id->idOpSize();
9654 code = emitInsCode(ins, fmt);
9655 code |= insEncodeFloatElemsize(elemsize); // X
9656 code |= ((code_t)imm << 13); // iiiii iii
9657 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9658 dst += emitOutput_Instr(dst, code);
9661 case IF_DV_1B: // DV_1B .QX..........iii cmod..iiiiiddddd Vd imm8 (immediate vector)
9662 imm = emitGetInsSC(id) & 0x0ff;
9663 immShift = (emitGetInsSC(id) & 0x700) >> 8;
9664 elemsize = optGetElemsize(id->idInsOpt());
9669 cmode = 0xE; // 1110
9673 cmode |= (immShift << 1); // 10x0
9679 cmode |= (immShift << 1); // 0xx0
9689 cmode = 0xE; // 1110
9696 code = emitInsCode(ins, fmt);
9697 code |= insEncodeVectorsize(id->idOpSize()); // Q
9698 if ((ins == INS_fmov) || (ins == INS_movi))
9700 if (elemsize == EA_8BYTE)
9702 code |= 0x20000000; // X
9705 if (ins != INS_fmov)
9707 assert((cmode >= 0) && (cmode <= 0xF));
9708 code |= (cmode << 12); // cmod
9710 code |= (((code_t)imm >> 5) << 16); // iii
9711 code |= (((code_t)imm & 0x1f) << 5); // iiiii
9712 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9713 dst += emitOutput_Instr(dst, code);
9716 case IF_DV_1C: // DV_1C .........X...... ......nnnnn..... Vn #0.0 (fcmp - with zero)
9717 elemsize = id->idOpSize();
9718 code = emitInsCode(ins, fmt);
9719 code |= insEncodeFloatElemsize(elemsize); // X
9720 code |= insEncodeReg_Vn(id->idReg1()); // nnnnn
9721 dst += emitOutput_Instr(dst, code);
9724 case IF_DV_2A: // DV_2A .Q.......X...... ......nnnnnddddd Vd Vn (fabs, fcvt - vector)
9725 elemsize = optGetElemsize(id->idInsOpt());
9726 code = emitInsCode(ins, fmt);
9727 code |= insEncodeVectorsize(id->idOpSize()); // Q
9728 code |= insEncodeFloatElemsize(elemsize); // X
9729 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9730 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9731 dst += emitOutput_Instr(dst, code);
9734 case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov/smov - to general)
9735 elemsize = id->idOpSize();
9736 index = emitGetInsSC(id);
9737 datasize = (elemsize == EA_8BYTE) ? EA_16BYTE : EA_8BYTE;
9738 if (ins == INS_smov)
9740 datasize = EA_16BYTE;
9742 code = emitInsCode(ins, fmt);
9743 code |= insEncodeVectorsize(datasize); // Q
9744 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9745 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9746 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9747 dst += emitOutput_Instr(dst, code);
9750 case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
9753 datasize = id->idOpSize();
9754 elemsize = optGetElemsize(id->idInsOpt());
9759 datasize = EA_16BYTE;
9760 elemsize = id->idOpSize();
9761 index = emitGetInsSC(id);
9763 code = emitInsCode(ins, fmt);
9764 code |= insEncodeVectorsize(datasize); // Q
9765 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9766 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9767 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9768 dst += emitOutput_Instr(dst, code);
9771 case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
9772 index = emitGetInsSC(id);
9773 elemsize = optGetElemsize(id->idInsOpt());
9774 code = emitInsCode(ins, fmt);
9775 code |= insEncodeVectorsize(id->idOpSize()); // Q
9776 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9777 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9778 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9779 dst += emitOutput_Instr(dst, code);
9782 case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
9783 index = emitGetInsSC(id);
9784 elemsize = id->idOpSize();
9785 code = emitInsCode(ins, fmt);
9786 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9787 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9788 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9789 dst += emitOutput_Instr(dst, code);
9792 case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
9793 elemsize = id->idOpSize();
9794 imm = emitGetInsSC(id);
9795 index = (imm >> 4) & 0xf;
9797 code = emitInsCode(ins, fmt);
9798 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9799 code |= insEncodeVectorIndex2(elemsize, index2); // jjjj
9800 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9801 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9802 dst += emitOutput_Instr(dst, code);
9805 case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov,fcvtXX - register)
9806 elemsize = id->idOpSize();
9807 code = emitInsCode(ins, fmt);
9808 code |= insEncodeFloatElemsize(elemsize); // X
9809 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9810 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9811 dst += emitOutput_Instr(dst, code);
9814 case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov - to general)
9815 elemsize = id->idOpSize();
9816 code = emitInsCode(ins, fmt);
9817 code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X X
9818 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9819 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9820 dst += emitOutput_Instr(dst, code);
9823 case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov - from general)
9824 elemsize = id->idOpSize();
9825 code = emitInsCode(ins, fmt);
9826 code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X X
9827 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9828 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9829 dst += emitOutput_Instr(dst, code);
9832 case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
9833 code = emitInsCode(ins, fmt);
9834 code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // SS DD
9835 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9836 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9837 dst += emitOutput_Instr(dst, code);
9840 case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
9841 elemsize = id->idOpSize();
9842 code = emitInsCode(ins, fmt);
9843 code |= insEncodeFloatElemsize(elemsize); // X
9844 code |= insEncodeReg_Vn(id->idReg1()); // nnnnn
9845 code |= insEncodeReg_Vm(id->idReg2()); // mmmmm
9846 dst += emitOutput_Instr(dst, code);
9849 case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
9850 elemsize = id->idOpSize();
9851 code = emitInsCode(ins, fmt);
9852 code |= insEncodeElemsize(elemsize); // XX
9853 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9854 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9855 dst += emitOutput_Instr(dst, code);
9858 case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
9859 elemsize = optGetElemsize(id->idInsOpt());
9860 code = emitInsCode(ins, fmt);
9861 code |= insEncodeVectorsize(id->idOpSize()); // Q
9862 code |= insEncodeElemsize(elemsize); // XX
9863 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9864 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9865 dst += emitOutput_Instr(dst, code);
9868 case IF_DV_2N: // DV_2N .........iiiiiii ......nnnnnddddd Vd Vn imm (shift - scalar)
9869 imm = emitGetInsSC(id);
9870 code = emitInsCode(ins, fmt);
9871 code |= insEncodeVectorShift(EA_8BYTE, imm); // iiiiiii
9872 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9873 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9874 dst += emitOutput_Instr(dst, code);
9877 case IF_DV_2O: // DV_2O .Q.......iiiiiii ......nnnnnddddd Vd Vn imm (shift - vector)
9878 imm = emitGetInsSC(id);
9879 elemsize = optGetElemsize(id->idInsOpt());
9880 code = emitInsCode(ins, fmt);
9881 code |= insEncodeVectorsize(id->idOpSize()); // Q
9882 code |= insEncodeVectorShift(elemsize, imm); // iiiiiii
9883 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9884 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9885 dst += emitOutput_Instr(dst, code);
9888 case IF_DV_2P: // DV_2P ............... ......nnnnnddddd Vd Vn (aes*, sha1su1)
9889 elemsize = optGetElemsize(id->idInsOpt());
9890 code = emitInsCode(ins, fmt);
9891 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9892 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9893 dst += emitOutput_Instr(dst, code);
9896 case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
9897 code = emitInsCode(ins, fmt);
9898 elemsize = optGetElemsize(id->idInsOpt());
9899 code |= insEncodeVectorsize(id->idOpSize()); // Q
9900 code |= insEncodeElemsize(elemsize); // XX
9901 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9902 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9903 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9904 dst += emitOutput_Instr(dst, code);
9907 case IF_DV_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector)
9908 code = emitInsCode(ins, fmt);
9909 imm = emitGetInsSC(id);
9910 elemsize = optGetElemsize(id->idInsOpt());
9911 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
9912 code |= insEncodeVectorsize(id->idOpSize()); // Q
9913 code |= insEncodeElemsize(elemsize); // XX
9914 code |= insEncodeVectorIndexLMH(elemsize, imm); // LM H
9915 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9916 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9917 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9918 dst += emitOutput_Instr(dst, code);
9921 case IF_DV_3B: // DV_3B .Q.......X.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
9922 code = emitInsCode(ins, fmt);
9923 elemsize = optGetElemsize(id->idInsOpt());
9924 code |= insEncodeVectorsize(id->idOpSize()); // Q
9925 code |= insEncodeFloatElemsize(elemsize); // X
9926 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9927 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9928 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9929 dst += emitOutput_Instr(dst, code);
9932 case IF_DV_3BI: // DV_3BI .Q.......XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
9933 code = emitInsCode(ins, fmt);
9934 imm = emitGetInsSC(id);
9935 elemsize = optGetElemsize(id->idInsOpt());
9936 assert(isValidVectorIndex(id->idOpSize(), elemsize, imm));
9937 code |= insEncodeVectorsize(id->idOpSize()); // Q
9938 code |= insEncodeFloatElemsize(elemsize); // X
9939 code |= insEncodeFloatIndex(elemsize, imm); // L H
9940 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9941 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9942 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9943 dst += emitOutput_Instr(dst, code);
9946 case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
9947 code = emitInsCode(ins, fmt);
9948 code |= insEncodeVectorsize(id->idOpSize()); // Q
9949 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9950 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9951 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9952 dst += emitOutput_Instr(dst, code);
9955 case IF_DV_3D: // DV_3D .........X.mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
9956 code = emitInsCode(ins, fmt);
9957 code |= insEncodeFloatElemsize(id->idOpSize()); // X
9958 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9959 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9960 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9961 dst += emitOutput_Instr(dst, code);
9964 case IF_DV_3DI: // DV_3DI .........XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (scalar by elem)
9965 code = emitInsCode(ins, fmt);
9966 imm = emitGetInsSC(id);
9967 elemsize = id->idOpSize();
9968 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
9969 code |= insEncodeFloatElemsize(elemsize); // X
9970 code |= insEncodeFloatIndex(elemsize, imm); // L H
9971 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9972 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9973 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9974 dst += emitOutput_Instr(dst, code);
9977 case IF_DV_3E: // DV_3E ...........mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
9978 case IF_DV_3F: // DV_3F ...........mmmmm ......nnnnnddddd Vd Vn Vm (vector) - source dest regs overlap
9979 code = emitInsCode(ins, fmt);
9980 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9981 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9982 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9983 dst += emitOutput_Instr(dst, code);
9986 case IF_DV_4A: // DV_4A .........X.mmmmm .aaaaannnnnddddd Vd Va Vn Vm (scalar)
9987 code = emitInsCode(ins, fmt);
9988 elemsize = id->idOpSize();
9989 code |= insEncodeFloatElemsize(elemsize); // X
9990 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9991 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9992 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9993 code |= insEncodeReg_Va(id->idReg4()); // aaaaa
9994 dst += emitOutput_Instr(dst, code);
9997 case IF_SN_0A: // SN_0A ................ ................
9998 code = emitInsCode(ins, fmt);
9999 dst += emitOutput_Instr(dst, code);
10002 case IF_SI_0A: // SI_0A ...........iiiii iiiiiiiiiii..... imm16
10003 imm = emitGetInsSC(id);
10004 assert(isValidUimm16(imm));
10005 code = emitInsCode(ins, fmt);
10006 code |= ((code_t)imm << 5); // iiiii iiiiiiiiiii
10007 dst += emitOutput_Instr(dst, code);
10010 case IF_SI_0B: // SI_0B ................ ....bbbb........ imm4 - barrier
10011 imm = emitGetInsSC(id);
10012 assert((imm >= 0) && (imm <= 15));
10013 code = emitInsCode(ins, fmt);
10014 code |= ((code_t)imm << 8); // bbbb
10015 dst += emitOutput_Instr(dst, code);
10019 assert(!"Unexpected format");
10023 // Determine if any registers now hold GC refs, or whether a register that was overwritten held a GC ref.
10024 // We assume here that "id->idGCref()" is not GC_NONE only if the instruction described by "id" writes a
10025 // GC ref to register "id->idReg1()". (It may, apparently, also not be GC_NONE in other cases, such as
10026 // for stores, but we ignore those cases here.)
10027 if (emitInsMayWriteToGCReg(id)) // True if "id->idIns()" writes to a register than can hold GC ref.
10029 // We assume that "idReg1" is the primary destination register for all instructions
10030 if (id->idGCref() != GCT_NONE)
10032 emitGCregLiveUpd(id->idGCref(), id->idReg1(), dst);
10036 emitGCregDeadUpd(id->idReg1(), dst);
10039 if (emitInsMayWriteMultipleRegs(id))
10042 // "idReg2" is the secondary destination register
10043 if (id->idGCrefReg2() != GCT_NONE)
10045 emitGCregLiveUpd(id->idGCrefReg2(), id->idReg2(), dst);
10049 emitGCregDeadUpd(id->idReg2(), dst);
10054 // Now we determine if the instruction has written to a (local variable) stack location, and either written a GC
10055 // ref or overwritten one.
10056 if (emitInsWritesToLclVarStackLoc(id) || emitInsWritesToLclVarStackLocPair(id))
10058 int varNum = id->idAddr()->iiaLclVar.lvaVarNum();
10059 unsigned ofs = AlignDown(id->idAddr()->iiaLclVar.lvaOffset(), TARGET_POINTER_SIZE);
10061 int adr = emitComp->lvaFrameAddress(varNum, &FPbased);
10062 if (id->idGCref() != GCT_NONE)
10064 emitGCvarLiveUpd(adr + ofs, varNum, id->idGCref(), dst);
10068 // If the type of the local is a gc ref type, update the liveness.
10072 // "Regular" (non-spill-temp) local.
10073 vt = var_types(emitComp->lvaTable[varNum].lvType);
10077 TempDsc* tmpDsc = emitComp->tmpFindNum(varNum);
10078 vt = tmpDsc->tdTempType();
10080 if (vt == TYP_REF || vt == TYP_BYREF)
10081 emitGCvarDeadUpd(adr + ofs, dst);
10083 if (emitInsWritesToLclVarStackLocPair(id))
10085 unsigned ofs2 = ofs + TARGET_POINTER_SIZE;
10086 if (id->idGCrefReg2() != GCT_NONE)
10088 emitGCvarLiveUpd(adr + ofs2, varNum, id->idGCrefReg2(), dst);
10092 // If the type of the local is a gc ref type, update the liveness.
10096 // "Regular" (non-spill-temp) local.
10097 vt = var_types(emitComp->lvaTable[varNum].lvType);
10101 TempDsc* tmpDsc = emitComp->tmpFindNum(varNum);
10102 vt = tmpDsc->tdTempType();
10104 if (vt == TYP_REF || vt == TYP_BYREF)
10105 emitGCvarDeadUpd(adr + ofs2, dst);
10111 /* Make sure we set the instruction descriptor size correctly */
10113 size_t expected = emitSizeOfInsDsc(id);
10114 assert(sz == expected);
10116 if (emitComp->opts.disAsm || emitComp->opts.dspEmit || emitComp->verbose)
10118 emitDispIns(id, false, dspOffs, true, emitCurCodeOffs(odst), *dp, (dst - *dp), ig);
10121 if (emitComp->compDebugBreak)
10123 // For example, set JitBreakEmitOutputInstr=a6 will break when this method is called for
10124 // emitting instruction a6, (i.e. IN00a6 in jitdump).
10125 if ((unsigned)JitConfig.JitBreakEmitOutputInstr() == id->idDebugOnlyInfo()->idNum)
10127 assert(!"JitBreakEmitOutputInstr reached");
10132 /* All instructions are expected to generate code */
10134 assert(*dp != dst);
10141 /*****************************************************************************/
10142 /*****************************************************************************/
10146 /*****************************************************************************
10148 * Display the instruction name
10150 void emitter::emitDispInst(instruction ins)
10152 const char* insstr = codeGen->genInsName(ins);
10153 size_t len = strlen(insstr);
10155 /* Display the instruction name */
10157 printf("%s", insstr);
10160 // Add at least one space after the instruction name
10161 // and add spaces until we have reach the normal size of 8
10169 /*****************************************************************************
10171 * Display an reloc value
10172 * If we are formatting for an assembly listing don't print the hex value
10173 * since it will prevent us from doing assembly diffs
10175 void emitter::emitDispReloc(int value, bool addComma)
10177 if (emitComp->opts.disAsm)
10183 printf("(reloc 0x%x)", dspPtr(value));
10190 /*****************************************************************************
10192 * Display an immediate value
10194 void emitter::emitDispImm(ssize_t imm, bool addComma, bool alwaysHex /* =false */)
10201 // Munge any pointers if we want diff-able disassembly.
10202 // Since some may be emitted as partial words, print as diffable anything that has
10203 // significant bits beyond the lowest 8-bits.
10204 if (emitComp->opts.disDiffable)
10206 ssize_t top56bits = (imm >> 8);
10207 if ((top56bits != 0) && (top56bits != -1))
10211 if (!alwaysHex && (imm > -1000) && (imm < 1000))
10217 if ((imm < 0) && ((imm & 0xFFFFFFFF00000000LL) == 0xFFFFFFFF00000000LL))
10223 if ((imm & 0xFFFFFFFF00000000LL) != 0)
10225 printf("0x%llx", imm);
10229 printf("0x%02x", imm);
10237 /*****************************************************************************
10239 * Display a float zero constant
10241 void emitter::emitDispFloatZero()
10250 /*****************************************************************************
10252 * Display an encoded float constant value
10254 void emitter::emitDispFloatImm(ssize_t imm8)
10256 assert((0 <= imm8) && (imm8 <= 0x0ff));
10263 fpImm.immFPIVal = (unsigned)imm8;
10264 double result = emitDecodeFloatImm8(fpImm);
10266 printf("%.4f", result);
10269 /*****************************************************************************
10271 * Display an immediate that is optionally LSL12.
10273 void emitter::emitDispImmOptsLSL12(ssize_t imm, insOpts opt)
10275 if (!strictArmAsm && insOptsLSL12(opt))
10279 emitDispImm(imm, false);
10280 if (strictArmAsm && insOptsLSL12(opt))
10282 printf(", LSL #12");
10286 /*****************************************************************************
10288 * Display an ARM64 condition code for the conditional instructions
10290 void emitter::emitDispCond(insCond cond)
10292 const static char* armCond[16] = {"eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc",
10293 "hi", "ls", "ge", "lt", "gt", "le", "AL", "NV"}; // The last two are invalid
10294 unsigned imm = (unsigned)cond;
10295 assert((0 <= imm) && (imm < ArrLen(armCond)));
10296 printf(armCond[imm]);
10299 /*****************************************************************************
10301 * Display an ARM64 flags for the conditional instructions
10303 void emitter::emitDispFlags(insCflags flags)
10305 const static char* armFlags[16] = {"0", "v", "c", "cv", "z", "zv", "zc", "zcv",
10306 "n", "nv", "nc", "ncv", "nz", "nzv", "nzc", "nzcv"};
10307 unsigned imm = (unsigned)flags;
10308 assert((0 <= imm) && (imm < ArrLen(armFlags)));
10309 printf(armFlags[imm]);
10312 /*****************************************************************************
10314 * Display an ARM64 'barrier' for the memory barrier instructions
10316 void emitter::emitDispBarrier(insBarrier barrier)
10318 const static char* armBarriers[16] = {"#0", "oshld", "oshst", "osh", "#4", "nshld", "nshst", "nsh",
10319 "#8", "ishld", "ishst", "ish", "#12", "ld", "st", "sy"};
10320 unsigned imm = (unsigned)barrier;
10321 assert((0 <= imm) && (imm < ArrLen(armBarriers)));
10322 printf(armBarriers[imm]);
10325 /*****************************************************************************
10327 * Prints the encoding for the Shift Type encoding
10330 void emitter::emitDispShiftOpts(insOpts opt)
10332 if (opt == INS_OPTS_LSL)
10334 else if (opt == INS_OPTS_LSR)
10336 else if (opt == INS_OPTS_ASR)
10338 else if (opt == INS_OPTS_ROR)
10340 else if (opt == INS_OPTS_MSL)
10343 assert(!"Bad value");
10346 /*****************************************************************************
10348 * Prints the encoding for the Extend Type encoding
10351 void emitter::emitDispExtendOpts(insOpts opt)
10353 if (opt == INS_OPTS_UXTB)
10355 else if (opt == INS_OPTS_UXTH)
10357 else if (opt == INS_OPTS_UXTW)
10359 else if (opt == INS_OPTS_UXTX)
10361 else if (opt == INS_OPTS_SXTB)
10363 else if (opt == INS_OPTS_SXTH)
10365 else if (opt == INS_OPTS_SXTW)
10367 else if (opt == INS_OPTS_SXTX)
10370 assert(!"Bad value");
10373 /*****************************************************************************
10375 * Prints the encoding for the Extend Type encoding in loads/stores
10378 void emitter::emitDispLSExtendOpts(insOpts opt)
10380 if (opt == INS_OPTS_LSL)
10382 else if (opt == INS_OPTS_UXTW)
10384 else if (opt == INS_OPTS_UXTX)
10386 else if (opt == INS_OPTS_SXTW)
10388 else if (opt == INS_OPTS_SXTX)
10391 assert(!"Bad value");
10394 /*****************************************************************************
10396 * Display a register
10398 void emitter::emitDispReg(regNumber reg, emitAttr attr, bool addComma)
10400 emitAttr size = EA_SIZE(attr);
10401 printf(emitRegName(reg, size));
10407 /*****************************************************************************
10409 * Display a vector register with an arrangement suffix
10411 void emitter::emitDispVectorReg(regNumber reg, insOpts opt, bool addComma)
10413 assert(isVectorRegister(reg));
10414 printf(emitVectorRegName(reg));
10415 emitDispArrangement(opt);
10421 /*****************************************************************************
10423 * Display an vector register index suffix
10425 void emitter::emitDispVectorRegIndex(regNumber reg, emitAttr elemsize, ssize_t index, bool addComma)
10427 assert(isVectorRegister(reg));
10428 printf(emitVectorRegName(reg));
10445 assert(!"invalid elemsize");
10449 printf("[%d]", index);
10455 /*****************************************************************************
10457 * Display an arrangement suffix
10459 void emitter::emitDispArrangement(insOpts opt)
10461 const char* str = "???";
10491 assert(!"Invalid insOpt for vector register");
10497 /*****************************************************************************
10499 * Display a register with an optional shift operation
10501 void emitter::emitDispShiftedReg(regNumber reg, insOpts opt, ssize_t imm, emitAttr attr)
10503 emitAttr size = EA_SIZE(attr);
10504 assert((imm & 0x003F) == imm);
10505 assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
10507 printf(emitRegName(reg, size));
10515 emitDispShiftOpts(opt);
10516 emitDispImm(imm, false);
10520 /*****************************************************************************
10522 * Display a register with an optional extend and scale operations
10524 void emitter::emitDispExtendReg(regNumber reg, insOpts opt, ssize_t imm)
10526 assert((imm >= 0) && (imm <= 4));
10527 assert(insOptsNone(opt) || insOptsAnyExtend(opt) || (opt == INS_OPTS_LSL));
10529 // size is based on the extend option, not the instr size.
10530 emitAttr size = insOpts32BitExtend(opt) ? EA_4BYTE : EA_8BYTE;
10534 if (insOptsNone(opt))
10536 emitDispReg(reg, size, false);
10540 emitDispReg(reg, size, true);
10541 if (opt == INS_OPTS_LSL)
10544 emitDispExtendOpts(opt);
10545 if ((imm > 0) || (opt == INS_OPTS_LSL))
10548 emitDispImm(imm, false);
10552 else // !strictArmAsm
10554 if (insOptsNone(opt))
10556 emitDispReg(reg, size, false);
10560 if (opt != INS_OPTS_LSL)
10562 emitDispExtendOpts(opt);
10564 emitDispReg(reg, size, false);
10571 emitDispImm(1 << imm, false);
10576 /*****************************************************************************
10578 * Display an addressing operand [reg + imm]
10580 void emitter::emitDispAddrRI(regNumber reg, insOpts opt, ssize_t imm)
10582 reg = encodingZRtoSP(reg); // ZR (R31) encodes the SP register
10588 emitDispReg(reg, EA_8BYTE, false);
10590 if (!insOptsPostIndex(opt) && (imm != 0))
10593 emitDispImm(imm, false);
10597 if (insOptsPreIndex(opt))
10601 else if (insOptsPostIndex(opt))
10604 emitDispImm(imm, false);
10607 else // !strictArmAsm
10611 const char* operStr = "++";
10618 if (insOptsPreIndex(opt))
10623 emitDispReg(reg, EA_8BYTE, false);
10625 if (insOptsPostIndex(opt))
10630 if (insOptsIndexed(opt))
10636 printf("%c", operStr[1]);
10638 emitDispImm(imm, false);
10643 /*****************************************************************************
10645 * Display an addressing operand [reg + extended reg]
10647 void emitter::emitDispAddrRRExt(regNumber reg1, regNumber reg2, insOpts opt, bool isScaled, emitAttr size)
10649 reg1 = encodingZRtoSP(reg1); // ZR (R31) encodes the SP register
10651 unsigned scale = 0;
10654 scale = NaturalScale_helper(size);
10661 emitDispReg(reg1, EA_8BYTE, true);
10662 emitDispExtendReg(reg2, opt, scale);
10664 else // !strictArmAsm
10666 emitDispReg(reg1, EA_8BYTE, false);
10668 emitDispExtendReg(reg2, opt, scale);
10674 /*****************************************************************************
10676 * Display (optionally) the instruction encoding in hex
10679 void emitter::emitDispInsHex(BYTE* code, size_t sz)
10681 // We do not display the instruction hex if we want diff-able disassembly
10682 if (!emitComp->opts.disDiffable)
10686 printf(" %08X ", (*((code_t*)code)));
10695 /****************************************************************************
10697 * Display the given instruction.
10700 void emitter::emitDispIns(
10701 instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* pCode, size_t sz, insGroup* ig)
10706 id->idDebugOnlyInfo()->idNum; // Do not remove this! It is needed for VisualStudio conditional breakpoints
10708 printf("IN%04x: ", idNum);
10714 if (!emitComp->opts.dspEmit && !isNew && !asmfm && sz)
10717 /* Display the instruction offset */
10719 emitDispInsOffs(offset, doffs);
10721 /* Display the instruction hex code */
10723 emitDispInsHex(pCode, sz);
10727 /* Get the instruction and format */
10729 instruction ins = id->idIns();
10730 insFormat fmt = id->idInsFmt();
10734 /* If this instruction has just been added, check its size */
10736 assert(isNew == false || (int)emitSizeOfInsDsc(id) == emitCurIGfreeNext - (BYTE*)id);
10738 /* Figure out the operand size */
10739 emitAttr size = id->idOpSize();
10740 emitAttr attr = size;
10741 if (id->idGCref() == GCT_GCREF)
10743 else if (id->idGCref() == GCT_BYREF)
10751 bool isExtendAlias;
10760 const char* methodName;
10768 case IF_BI_0A: // BI_0A ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
10769 case IF_BI_0B: // BI_0B ......iiiiiiiiii iiiiiiiiiii..... simm19:00
10772 if (fmt == IF_LARGEJMP)
10774 printf("(LARGEJMP)");
10776 if (id->idAddr()->iiaHasInstrCount())
10778 int instrCount = id->idAddr()->iiaGetInstrCount();
10782 printf("pc%s%d instructions", (instrCount >= 0) ? "+" : "", instrCount);
10786 unsigned insNum = emitFindInsNum(ig, id);
10787 UNATIVE_OFFSET srcOffs = ig->igOffs + emitFindOffset(ig, insNum + 1);
10788 UNATIVE_OFFSET dstOffs = ig->igOffs + emitFindOffset(ig, insNum + 1 + instrCount);
10789 ssize_t relOffs = (ssize_t)(emitOffsetToPtr(dstOffs) - emitOffsetToPtr(srcOffs));
10790 printf("pc%s%d (%d instructions)", (relOffs >= 0) ? "+" : "", relOffs, instrCount);
10793 else if (id->idIsBound())
10795 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10799 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10804 case IF_BI_0C: // BI_0C ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
10805 if (id->idIsCallAddr())
10807 offs = (ssize_t)id->idAddr()->iiaAddr;
10813 methodName = emitComp->eeGetMethodFullName((CORINFO_METHOD_HANDLE)id->idDebugOnlyInfo()->idMemCookie);
10818 if (id->idIsDspReloc())
10820 printf("%08X", offs);
10824 printf("%s", methodName);
10828 case IF_BI_1A: // BI_1A ......iiiiiiiiii iiiiiiiiiiittttt Rt simm19:00
10829 assert(insOptsNone(id->idInsOpt()));
10830 emitDispReg(id->idReg1(), size, true);
10831 if (id->idIsBound())
10833 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10837 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10841 case IF_BI_1B: // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
10842 assert(insOptsNone(id->idInsOpt()));
10843 emitDispReg(id->idReg1(), size, true);
10844 emitDispImm(emitGetInsSC(id), true);
10845 if (id->idIsBound())
10847 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10851 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10855 case IF_BR_1A: // BR_1A ................ ......nnnnn..... Rn
10856 assert(insOptsNone(id->idInsOpt()));
10857 emitDispReg(id->idReg1(), size, false);
10860 case IF_BR_1B: // BR_1B ................ ......nnnnn..... Rn
10861 assert(insOptsNone(id->idInsOpt()));
10862 emitDispReg(id->idReg3(), size, false);
10865 case IF_LS_1A: // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB)
10866 case IF_DI_1E: // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
10869 assert(insOptsNone(id->idInsOpt()));
10870 emitDispReg(id->idReg1(), size, true);
10871 imm = emitGetInsSC(id);
10873 /* Is this actually a reference to a data section? */
10874 if (fmt == IF_LARGEADR)
10876 printf("(LARGEADR)");
10878 else if (fmt == IF_LARGELDC)
10880 printf("(LARGELDC)");
10884 if (id->idAddr()->iiaIsJitDataOffset())
10886 doffs = Compiler::eeGetJitDataOffs(id->idAddr()->iiaFieldHnd);
10887 /* Display a data section reference */
10890 printf("@CNS%02u", doffs - 1);
10892 printf("@RWD%02u", doffs);
10895 printf("%+Id", imm);
10900 if (id->idIsReloc())
10903 emitDispImm((ssize_t)id->idAddr()->iiaAddr, false);
10905 else if (id->idIsBound())
10907 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10911 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10917 case IF_LS_2A: // LS_2A .X.......X...... ......nnnnnttttt Rt Rn
10918 assert(insOptsNone(id->idInsOpt()));
10919 assert(emitGetInsSC(id) == 0);
10920 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10921 emitDispAddrRI(id->idReg2(), id->idInsOpt(), 0);
10924 case IF_LS_2B: // LS_2B .X.......Xiiiiii iiiiiinnnnnttttt Rt Rn imm(0-4095)
10925 assert(insOptsNone(id->idInsOpt()));
10926 imm = emitGetInsSC(id);
10927 scale = NaturalScale_helper(emitInsLoadStoreSize(id));
10928 imm <<= scale; // The immediate is scaled by the size of the ld/st
10929 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10930 emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
10933 case IF_LS_2C: // LS_2C .X.......X.iiiii iiiiPPnnnnnttttt Rt Rn imm(-256..+255) no/pre/post inc
10934 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
10935 imm = emitGetInsSC(id);
10936 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10937 emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
10940 case IF_LS_3A: // LS_3A .X.......X.mmmmm oooS..nnnnnttttt Rt Rn Rm ext(Rm) LSL {}
10941 assert(insOptsLSExtend(id->idInsOpt()));
10942 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10943 if (id->idIsLclVar())
10945 emitDispAddrRRExt(id->idReg2(), codeGen->rsGetRsvdReg(), id->idInsOpt(), false, size);
10949 emitDispAddrRRExt(id->idReg2(), id->idReg3(), id->idInsOpt(), id->idReg3Scaled(), size);
10953 case IF_LS_3B: // LS_3B X............... .aaaaannnnnddddd Rt Ra Rn
10954 assert(insOptsNone(id->idInsOpt()));
10955 assert(emitGetInsSC(id) == 0);
10956 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10957 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10958 emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
10961 case IF_LS_3C: // LS_3C X.........iiiiii iaaaaannnnnddddd Rt Ra Rn imm(im7,sh)
10962 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
10963 imm = emitGetInsSC(id);
10964 scale = NaturalScale_helper(emitInsLoadStoreSize(id));
10966 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10967 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10968 emitDispAddrRI(id->idReg3(), id->idInsOpt(), imm);
10971 case IF_LS_3D: // LS_3D .X.......X.mmmmm ......nnnnnttttt Wm Rt Rn
10972 assert(insOptsNone(id->idInsOpt()));
10973 emitDispReg(id->idReg1(), EA_4BYTE, true);
10974 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10975 emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
10978 case IF_DI_1A: // DI_1A X.......shiiiiii iiiiiinnnnn..... Rn imm(i12,sh)
10979 emitDispReg(id->idReg1(), size, true);
10980 emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
10983 case IF_DI_1B: // DI_1B X........hwiiiii iiiiiiiiiiiddddd Rd imm(i16,hw)
10984 emitDispReg(id->idReg1(), size, true);
10985 hwi.immHWVal = (unsigned)emitGetInsSC(id);
10986 if (ins == INS_mov)
10988 emitDispImm(emitDecodeHalfwordImm(hwi, size), false);
10990 else // movz, movn, movk
10992 emitDispImm(hwi.immVal, false);
10993 if (hwi.immHW != 0)
10995 emitDispShiftOpts(INS_OPTS_LSL);
10996 emitDispImm(hwi.immHW * 16, false);
11001 case IF_DI_1C: // DI_1C X........Nrrrrrr ssssssnnnnn..... Rn imm(N,r,s)
11002 emitDispReg(id->idReg1(), size, true);
11003 bmi.immNRS = (unsigned)emitGetInsSC(id);
11004 emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
11007 case IF_DI_1D: // DI_1D X........Nrrrrrr ssssss.....ddddd Rd imm(N,r,s)
11008 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11009 bmi.immNRS = (unsigned)emitGetInsSC(id);
11010 emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
11013 case IF_DI_2A: // DI_2A X.......shiiiiii iiiiiinnnnnddddd Rd Rn imm(i12,sh)
11014 if ((ins == INS_add) || (ins == INS_sub))
11016 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11017 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11021 emitDispReg(id->idReg1(), size, true);
11022 emitDispReg(id->idReg2(), size, true);
11024 emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
11027 case IF_DI_2B: // DI_2B X........X.nnnnn ssssssnnnnnddddd Rd Rn imm(0-63)
11028 emitDispReg(id->idReg1(), size, true);
11029 emitDispReg(id->idReg2(), size, true);
11030 emitDispImm(emitGetInsSC(id), false);
11033 case IF_DI_2C: // DI_2C X........Nrrrrrr ssssssnnnnnddddd Rd Rn imm(N,r,s)
11034 if (ins == INS_ands)
11036 emitDispReg(id->idReg1(), size, true);
11040 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11042 emitDispReg(id->idReg2(), size, true);
11043 bmi.immNRS = (unsigned)emitGetInsSC(id);
11044 emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
11047 case IF_DI_2D: // DI_2D X........Nrrrrrr ssssssnnnnnddddd Rd Rn imr, ims (N,r,s)
11048 emitDispReg(id->idReg1(), size, true);
11049 emitDispReg(id->idReg2(), size, true);
11051 imm = emitGetInsSC(id);
11052 bmi.immNRS = (unsigned)imm;
11059 emitDispImm(bmi.immR, true);
11060 emitDispImm(bmi.immS, false);
11066 emitDispImm(getBitWidth(size) - bmi.immR, true);
11067 emitDispImm(bmi.immS + 1, false);
11073 emitDispImm(bmi.immR, true);
11074 emitDispImm(bmi.immS - bmi.immR + 1, false);
11080 emitDispImm(imm, false);
11084 assert(!"Unexpected instruction in IF_DI_2D");
11089 case IF_DI_1F: // DI_1F X..........iiiii cccc..nnnnn.nzcv Rn imm5 nzcv cond
11090 emitDispReg(id->idReg1(), size, true);
11091 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11092 emitDispImm(cfi.imm5, true);
11093 emitDispFlags(cfi.flags);
11095 emitDispCond(cfi.cond);
11098 case IF_DR_1D: // DR_1D X............... cccc.......mmmmm Rd cond
11099 emitDispReg(id->idReg1(), size, true);
11100 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11101 emitDispCond(cfi.cond);
11104 case IF_DR_2A: // DR_2A X..........mmmmm ......nnnnn..... Rn Rm
11105 emitDispReg(id->idReg1(), size, true);
11106 emitDispReg(id->idReg2(), size, false);
11109 case IF_DR_2B: // DR_2B X.......sh.mmmmm ssssssnnnnn..... Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
11110 emitDispReg(id->idReg1(), size, true);
11111 emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
11114 case IF_DR_2C: // DR_2C X..........mmmmm ooosssnnnnn..... Rn Rm ext(Rm) LSL imm(0-4)
11115 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11116 imm = emitGetInsSC(id);
11117 emitDispExtendReg(id->idReg2(), id->idInsOpt(), imm);
11120 case IF_DR_2D: // DR_2D X..........nnnnn cccc..nnnnnddddd Rd Rn cond
11121 emitDispReg(id->idReg1(), size, true);
11122 emitDispReg(id->idReg2(), size, true);
11123 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11124 emitDispCond(cfi.cond);
11127 case IF_DR_2E: // DR_2E X..........mmmmm ...........ddddd Rd Rm
11128 case IF_DR_2J: // DR_2J ................ ......nnnnnddddd Sd Sn
11129 emitDispReg(id->idReg1(), size, true);
11130 emitDispReg(id->idReg2(), size, false);
11133 case IF_DR_2F: // DR_2F X.......sh.mmmmm ssssss.....ddddd Rd Rm {LSL,LSR,ASR} imm(0-63)
11134 emitDispReg(id->idReg1(), size, true);
11135 emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
11138 case IF_DR_2G: // DR_2G X............... ......nnnnnddddd Rd Rn
11139 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11140 emitDispReg(encodingZRtoSP(id->idReg2()), size, false);
11143 case IF_DR_2H: // DR_2H X........X...... ......nnnnnddddd Rd Rn
11144 emitDispReg(id->idReg1(), size, true);
11145 emitDispReg(id->idReg2(), size, false);
11148 case IF_DR_2I: // DR_2I X..........mmmmm cccc..nnnnn.nzcv Rn Rm nzcv cond
11149 emitDispReg(id->idReg1(), size, true);
11150 emitDispReg(id->idReg2(), size, true);
11151 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11152 emitDispFlags(cfi.flags);
11154 emitDispCond(cfi.cond);
11157 case IF_DR_3A: // DR_3A X..........mmmmm ......nnnnnmmmmm Rd Rn Rm
11158 if ((ins == INS_add) || (ins == INS_sub))
11160 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11161 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11163 else if ((ins == INS_smull) || (ins == INS_smulh))
11165 // Rd is always 8 bytes
11166 emitDispReg(id->idReg1(), EA_8BYTE, true);
11168 // Rn, Rm effective size depends on instruction type
11169 size = (ins == INS_smulh) ? EA_8BYTE : EA_4BYTE;
11170 emitDispReg(id->idReg2(), size, true);
11174 emitDispReg(id->idReg1(), size, true);
11175 emitDispReg(id->idReg2(), size, true);
11177 if (id->idIsLclVar())
11179 emitDispReg(codeGen->rsGetRsvdReg(), size, false);
11183 emitDispReg(id->idReg3(), size, false);
11188 case IF_DR_3B: // DR_3B X.......sh.mmmmm ssssssnnnnnddddd Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
11189 emitDispReg(id->idReg1(), size, true);
11190 emitDispReg(id->idReg2(), size, true);
11191 emitDispShiftedReg(id->idReg3(), id->idInsOpt(), emitGetInsSC(id), size);
11194 case IF_DR_3C: // DR_3C X..........mmmmm ooosssnnnnnddddd Rd Rn Rm ext(Rm) LSL imm(0-4)
11195 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11196 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11197 imm = emitGetInsSC(id);
11198 emitDispExtendReg(id->idReg3(), id->idInsOpt(), imm);
11201 case IF_DR_3D: // DR_3D X..........mmmmm cccc..nnnnnmmmmm Rd Rn Rm cond
11202 emitDispReg(id->idReg1(), size, true);
11203 emitDispReg(id->idReg2(), size, true);
11204 emitDispReg(id->idReg3(), size, true);
11205 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11206 emitDispCond(cfi.cond);
11209 case IF_DR_3E: // DR_3E X........X.mmmmm ssssssnnnnnddddd Rd Rn Rm imm(0-63)
11210 emitDispReg(id->idReg1(), size, true);
11211 emitDispReg(id->idReg2(), size, true);
11212 emitDispReg(id->idReg3(), size, true);
11213 emitDispImm(emitGetInsSC(id), false);
11216 case IF_DR_4A: // DR_4A X..........mmmmm .aaaaannnnnmmmmm Rd Rn Rm Ra
11217 emitDispReg(id->idReg1(), size, true);
11218 emitDispReg(id->idReg2(), size, true);
11219 emitDispReg(id->idReg3(), size, true);
11220 emitDispReg(id->idReg4(), size, false);
11223 case IF_DV_1A: // DV_1A .........X.iiiii iii........ddddd Vd imm8 (fmov - immediate scalar)
11224 elemsize = id->idOpSize();
11225 emitDispReg(id->idReg1(), elemsize, true);
11226 emitDispFloatImm(emitGetInsSC(id));
11229 case IF_DV_1B: // DV_1B .QX..........iii cmod..iiiiiddddd Vd imm8 (immediate vector)
11230 imm = emitGetInsSC(id) & 0x0ff;
11231 immShift = (emitGetInsSC(id) & 0x700) >> 8;
11232 hasShift = (immShift != 0);
11233 elemsize = optGetElemsize(id->idInsOpt());
11234 if (id->idInsOpt() == INS_OPTS_1D)
11236 assert(elemsize == size);
11237 emitDispReg(id->idReg1(), size, true);
11241 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11243 if (ins == INS_fmov)
11245 emitDispFloatImm(imm);
11246 assert(hasShift == false);
11250 if (elemsize == EA_8BYTE)
11252 assert(ins == INS_movi);
11254 const ssize_t mask8 = 0xFF;
11255 for (unsigned b = 0; b < 8; b++)
11257 if (imm & (1 << b))
11259 imm64 |= (mask8 << (b * 8));
11262 emitDispImm(imm64, hasShift, true);
11266 emitDispImm(imm, hasShift, true);
11270 insOpts opt = (immShift & 0x4) ? INS_OPTS_MSL : INS_OPTS_LSL;
11271 unsigned shift = (immShift & 0x3) * 8;
11272 emitDispShiftOpts(opt);
11273 emitDispImm(shift, false);
11278 case IF_DV_1C: // DV_1C .........X...... ......nnnnn..... Vn #0.0 (fcmp - with zero)
11279 elemsize = id->idOpSize();
11280 emitDispReg(id->idReg1(), elemsize, true);
11281 emitDispFloatZero();
11284 case IF_DV_2A: // DV_2A .Q.......X...... ......nnnnnddddd Vd Vn (fabs, fcvt - vector)
11285 case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
11286 case IF_DV_2P: // DV_2P ................ ......nnnnnddddd Vd Vn (aes*, sha1su1)
11287 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11288 emitDispVectorReg(id->idReg2(), id->idInsOpt(), false);
11291 case IF_DV_2N: // DV_2N .........iiiiiii ......nnnnnddddd Vd Vn imm (shift - scalar)
11292 elemsize = id->idOpSize();
11293 emitDispReg(id->idReg1(), elemsize, true);
11294 emitDispReg(id->idReg2(), elemsize, true);
11295 emitDispImm(emitGetInsSC(id), false);
11298 case IF_DV_2O: // DV_2O .Q.......iiiiiii ......nnnnnddddd Vd Vn imm (shift - vector)
11299 imm = emitGetInsSC(id);
11300 // Do we have a sxtl or uxtl instruction?
11301 isExtendAlias = ((ins == INS_sxtl) || (ins == INS_sxtl2) || (ins == INS_uxtl) || (ins == INS_uxtl2));
11302 code = emitInsCode(ins, fmt);
11303 if (code & 0x00008000) // widen/narrow opcodes
11305 if (code & 0x00002000) // SHL opcodes
11307 emitDispVectorReg(id->idReg1(), optWidenElemsize(id->idInsOpt()), true);
11308 emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11310 else // SHR opcodes
11312 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11313 emitDispVectorReg(id->idReg2(), optWidenElemsize(id->idInsOpt()), !isExtendAlias);
11318 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11319 emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11321 // Print the immediate unless we have a sxtl or uxtl instruction
11322 if (!isExtendAlias)
11324 emitDispImm(imm, false);
11328 case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov/smov - to general)
11329 srcsize = id->idOpSize();
11330 index = emitGetInsSC(id);
11331 if (ins == INS_smov)
11333 dstsize = EA_8BYTE;
11335 else // INS_umov or INS_mov
11337 dstsize = (srcsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE;
11339 emitDispReg(id->idReg1(), dstsize, true);
11340 emitDispVectorRegIndex(id->idReg2(), srcsize, index, false);
11343 case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
11344 if (ins == INS_dup)
11346 datasize = id->idOpSize();
11347 assert(isValidVectorDatasize(datasize));
11348 assert(isValidArrangement(datasize, id->idInsOpt()));
11349 elemsize = optGetElemsize(id->idInsOpt());
11350 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11354 elemsize = id->idOpSize();
11355 index = emitGetInsSC(id);
11356 assert(isValidVectorElemsize(elemsize));
11357 emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11359 emitDispReg(id->idReg2(), (elemsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE, false);
11362 case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
11363 datasize = id->idOpSize();
11364 assert(isValidVectorDatasize(datasize));
11365 assert(isValidArrangement(datasize, id->idInsOpt()));
11366 elemsize = optGetElemsize(id->idInsOpt());
11367 index = emitGetInsSC(id);
11368 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11369 emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11372 case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
11373 elemsize = id->idOpSize();
11374 index = emitGetInsSC(id);
11375 emitDispReg(id->idReg1(), elemsize, true);
11376 emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11379 case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
11380 imm = emitGetInsSC(id);
11381 index = (imm >> 4) & 0xf;
11382 index2 = imm & 0xf;
11383 elemsize = id->idOpSize();
11384 emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11385 emitDispVectorRegIndex(id->idReg2(), elemsize, index2, false);
11388 case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov, fcvtXX - register)
11389 case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
11390 case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
11391 elemsize = id->idOpSize();
11392 emitDispReg(id->idReg1(), elemsize, true);
11393 emitDispReg(id->idReg2(), elemsize, false);
11396 case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov, fcvtXX - to general)
11397 case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov, Xcvtf - from general)
11398 case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
11399 dstsize = optGetDstsize(id->idInsOpt());
11400 srcsize = optGetSrcsize(id->idInsOpt());
11402 emitDispReg(id->idReg1(), dstsize, true);
11403 emitDispReg(id->idReg2(), srcsize, false);
11406 case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11407 case IF_DV_3B: // DV_3B .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11408 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11409 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11410 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11413 case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11414 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11415 if (ins != INS_mov)
11417 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11419 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11422 case IF_DV_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
11423 case IF_DV_3BI: // DV_3BI .Q........Lmmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
11424 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11425 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11426 elemsize = optGetElemsize(id->idInsOpt());
11427 emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11430 case IF_DV_3D: // DV_3D .........X.mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
11431 case IF_DV_3E: // DV_3E ...........mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
11432 emitDispReg(id->idReg1(), size, true);
11433 emitDispReg(id->idReg2(), size, true);
11434 emitDispReg(id->idReg3(), size, false);
11437 case IF_DV_3F: // DV_3F ..........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11438 if ((ins == INS_sha1c) || (ins == INS_sha1m) || (ins == INS_sha1p))
11440 // Qd, Sn, Vm (vector)
11441 emitDispReg(id->idReg1(), size, true);
11442 emitDispReg(id->idReg2(), EA_4BYTE, true);
11443 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11445 else if ((ins == INS_sha256h) || (ins == INS_sha256h2))
11447 // Qd Qn Vm (vector)
11448 emitDispReg(id->idReg1(), size, true);
11449 emitDispReg(id->idReg2(), size, true);
11450 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11454 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11455 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11456 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11460 case IF_DV_3DI: // DV_3DI .........XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (scalar by elem)
11461 emitDispReg(id->idReg1(), size, true);
11462 emitDispReg(id->idReg2(), size, true);
11464 emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11467 case IF_DV_4A: // DV_4A .........X.mmmmm .aaaaannnnnddddd Vd Va Vn Vm (scalar)
11468 emitDispReg(id->idReg1(), size, true);
11469 emitDispReg(id->idReg2(), size, true);
11470 emitDispReg(id->idReg3(), size, true);
11471 emitDispReg(id->idReg4(), size, false);
11474 case IF_SN_0A: // SN_0A ................ ................
11477 case IF_SI_0A: // SI_0A ...........iiiii iiiiiiiiiii..... imm16
11478 emitDispImm(emitGetInsSC(id), false);
11481 case IF_SI_0B: // SI_0B ................ ....bbbb........ imm4 - barrier
11482 emitDispBarrier((insBarrier)emitGetInsSC(id));
11486 printf("unexpected format %s", emitIfName(id->idInsFmt()));
11487 assert(!"unexpectedFormat");
11491 if (id->idDebugOnlyInfo()->idVarRefOffs)
11494 emitDispFrameRef(id->idAddr()->iiaLclVar.lvaVarNum(), id->idAddr()->iiaLclVar.lvaOffset(),
11495 id->idDebugOnlyInfo()->idVarRefOffs, asmfm);
11501 /*****************************************************************************
11503 * Display a stack frame reference.
11506 void emitter::emitDispFrameRef(int varx, int disp, int offs, bool asmfm)
11511 printf("TEMP_%02u", -varx);
11513 emitComp->gtDispLclVar(+varx, false);
11516 printf("-0x%02x", -disp);
11518 printf("+0x%02x", +disp);
11522 if (varx >= 0 && emitComp->opts.varNames)
11525 const char* varName;
11527 assert((unsigned)varx < emitComp->lvaCount);
11528 varDsc = emitComp->lvaTable + varx;
11529 varName = emitComp->compLocalVarName(varx, offs);
11533 printf("'%s", varName);
11536 printf("-%d", -disp);
11538 printf("+%d", +disp);
11547 // Generate code for a load or store operation with a potentially complex addressing mode
11548 // This method handles the case of a GT_IND with contained GT_LEA op1 of the x86 form [base + index*sccale + offset]
11549 // Since Arm64 does not directly support this complex of an addressing mode
11550 // we may generates up to three instructions for this for Arm64
11552 void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataReg, GenTreeIndir* indir)
11554 emitAttr ldstAttr = isVectorRegister(dataReg) ? attr : emitInsAdjustLoadStoreAttr(ins, attr);
11556 GenTree* addr = indir->Addr();
11558 if (addr->isContained())
11560 assert(addr->OperGet() == GT_LCL_VAR_ADDR || addr->OperGet() == GT_LEA);
11565 if (addr->OperGet() == GT_LEA)
11567 offset = addr->AsAddrMode()->Offset();
11568 if (addr->AsAddrMode()->gtScale > 0)
11570 assert(isPow2(addr->AsAddrMode()->gtScale));
11571 BitScanForward(&lsl, addr->AsAddrMode()->gtScale);
11575 GenTree* memBase = indir->Base();
11577 if (indir->HasIndex())
11579 GenTree* index = indir->Index();
11583 regNumber tmpReg = indir->GetSingleTempReg();
11585 emitAttr addType = varTypeIsGC(memBase) ? EA_BYREF : EA_PTRSIZE;
11587 if (emitIns_valid_imm_for_add(offset, EA_8BYTE))
11591 // Generate code to set tmpReg = base + index*scale
11592 emitIns_R_R_R_I(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum, lsl,
11597 // Generate code to set tmpReg = base + index
11598 emitIns_R_R_R(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum);
11601 noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11603 // Then load/store dataReg from/to [tmpReg + offset]
11604 emitIns_R_R_I(ins, ldstAttr, dataReg, tmpReg, offset);
11606 else // large offset
11608 // First load/store tmpReg with the large offset constant
11609 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11610 // Then add the base register
11612 emitIns_R_R_R(INS_add, addType, tmpReg, tmpReg, memBase->gtRegNum);
11614 noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11615 noway_assert(tmpReg != index->gtRegNum);
11617 // Then load/store dataReg from/to [tmpReg + index*scale]
11618 emitIns_R_R_R_I(ins, ldstAttr, dataReg, tmpReg, index->gtRegNum, lsl, INS_OPTS_LSL);
11621 else // (offset == 0)
11625 // Then load/store dataReg from/to [memBase + index*scale]
11626 emitIns_R_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum, lsl, INS_OPTS_LSL);
11630 // Then load/store dataReg from/to [memBase + index]
11631 emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum);
11635 else // no Index register
11637 if (emitIns_valid_imm_for_ldst_offset(offset, EA_SIZE(attr)))
11639 // Then load/store dataReg from/to [memBase + offset]
11640 emitIns_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, offset);
11644 // We require a tmpReg to hold the offset
11645 regNumber tmpReg = indir->GetSingleTempReg();
11647 // First load/store tmpReg with the large offset constant
11648 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11650 // Then load/store dataReg from/to [memBase + tmpReg]
11651 emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, tmpReg);
11655 else // addr is not contained, so we evaluate it into a register
11657 // Then load/store dataReg from/to [addrReg]
11658 emitIns_R_R(ins, ldstAttr, dataReg, addr->gtRegNum);
11662 // The callee must call genConsumeReg() for any non-contained srcs
11663 // and genProduceReg() for any non-contained dsts.
11665 regNumber emitter::emitInsBinary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src)
11667 regNumber result = REG_NA;
11669 // dst can only be a reg
11670 assert(!dst->isContained());
11672 // src can be immed or reg
11673 assert(!src->isContained() || src->isContainedIntOrIImmed());
11675 // find immed (if any) - it cannot be a dst
11676 GenTreeIntConCommon* intConst = nullptr;
11677 if (src->isContainedIntOrIImmed())
11679 intConst = src->AsIntConCommon();
11684 emitIns_R_I(ins, attr, dst->gtRegNum, intConst->IconValue());
11685 return dst->gtRegNum;
11689 emitIns_R_R(ins, attr, dst->gtRegNum, src->gtRegNum);
11690 return dst->gtRegNum;
11694 // The callee must call genConsumeReg() for any non-contained srcs
11695 // and genProduceReg() for any non-contained dsts.
11697 regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src1, GenTree* src2)
11699 regNumber result = REG_NA;
11701 // dst can only be a reg
11702 assert(!dst->isContained());
11704 // find immed (if any) - it cannot be a dst
11705 // Only one src can be an int.
11706 GenTreeIntConCommon* intConst = nullptr;
11707 GenTree* nonIntReg = nullptr;
11709 if (varTypeIsFloating(dst))
11711 // src1 can only be a reg
11712 assert(!src1->isContained());
11713 // src2 can only be a reg
11714 assert(!src2->isContained());
11716 else // not floating point
11718 // src2 can be immed or reg
11719 assert(!src2->isContained() || src2->isContainedIntOrIImmed());
11721 // Check src2 first as we can always allow it to be a contained immediate
11722 if (src2->isContainedIntOrIImmed())
11724 intConst = src2->AsIntConCommon();
11727 // Only for commutative operations do we check src1 and allow it to be a contained immediate
11728 else if (dst->OperIsCommutative())
11730 // src1 can be immed or reg
11731 assert(!src1->isContained() || src1->isContainedIntOrIImmed());
11733 // Check src1 and allow it to be a contained immediate
11734 if (src1->isContainedIntOrIImmed())
11736 assert(!src2->isContainedIntOrIImmed());
11737 intConst = src1->AsIntConCommon();
11743 // src1 can only be a reg
11744 assert(!src1->isContained());
11748 bool isMulOverflow = false;
11749 if (dst->gtOverflowEx())
11751 if ((ins == INS_add) || (ins == INS_adds))
11755 else if ((ins == INS_sub) || (ins == INS_subs))
11759 else if (ins == INS_mul)
11761 isMulOverflow = true;
11762 assert(intConst == nullptr); // overflow format doesn't support an int constant operand
11766 assert(!"Invalid ins for overflow check");
11769 if (intConst != nullptr)
11771 emitIns_R_R_I(ins, attr, dst->gtRegNum, nonIntReg->gtRegNum, intConst->IconValue());
11777 regNumber extraReg = dst->GetSingleTempReg();
11778 assert(extraReg != dst->gtRegNum);
11780 if ((dst->gtFlags & GTF_UNSIGNED) != 0)
11782 if (attr == EA_4BYTE)
11784 // Compute 8 byte results from 4 byte by 4 byte multiplication.
11785 emitIns_R_R_R(INS_umull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11787 // Get the high result by shifting dst.
11788 emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11792 assert(attr == EA_8BYTE);
11793 // Compute the high result.
11794 emitIns_R_R_R(INS_umulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11796 // Now multiply without skewing the high result.
11797 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11800 // zero-sign bit comparison to detect overflow.
11801 emitIns_R_I(INS_cmp, attr, extraReg, 0);
11806 if (attr == EA_4BYTE)
11808 // Compute 8 byte results from 4 byte by 4 byte multiplication.
11809 emitIns_R_R_R(INS_smull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11811 // Get the high result by shifting dst.
11812 emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11818 assert(attr == EA_8BYTE);
11819 // Save the high result in a temporary register.
11820 emitIns_R_R_R(INS_smulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11822 // Now multiply without skewing the high result.
11823 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11828 // Sign bit comparison to detect overflow.
11829 emitIns_R_R_I(INS_cmp, attr, extraReg, dst->gtRegNum, bitShift, INS_OPTS_ASR);
11834 // We can just multiply.
11835 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11839 if (dst->gtOverflowEx())
11841 assert(!varTypeIsFloating(dst));
11842 codeGen->genCheckOverflow(dst);
11845 return dst->gtRegNum;
11848 #endif // defined(_TARGET_ARM64_)