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));
4320 assert(isVectorRegister(reg1));
4321 assert(isVectorRegister(reg2));
4322 assert(isValidVectorDatasize(size));
4323 elemsize = optGetElemsize(opt);
4324 assert(elemsize == EA_4BYTE);
4332 } // end switch (ins)
4334 assert(fmt != IF_NONE);
4336 instrDesc* id = emitNewInstrSmall(attr);
4349 /*****************************************************************************
4351 * Add an instruction referencing a register and two constants.
4354 void emitter::emitIns_R_I_I(
4355 instruction ins, emitAttr attr, regNumber reg, ssize_t imm1, ssize_t imm2, insOpts opt /* = INS_OPTS_NONE */)
4357 emitAttr size = EA_SIZE(attr);
4358 insFormat fmt = IF_NONE;
4359 size_t immOut = 0; // composed from imm1 and imm2 and stored in the instrDesc
4361 /* Figure out the encoding format of the instruction */
4368 ins = INS_movz; // INS_mov with LSL is an alias for INS_movz LSL
4374 assert(isValidGeneralDatasize(size));
4375 assert(isGeneralRegister(reg));
4376 assert(isValidUimm16(imm1));
4377 assert(insOptsLSL(opt)); // Must be INS_OPTS_LSL
4379 if (size == EA_8BYTE)
4381 assert((imm2 == 0) || (imm2 == 16) || // shift amount: 0, 16, 32 or 48
4382 (imm2 == 32) || (imm2 == 48));
4386 assert((imm2 == 0) || (imm2 == 16)); // shift amount: 0 or 16
4421 immOut = hwi.immHWVal;
4422 assert(isValidImmHWVal(immOut, size));
4431 } // end switch (ins)
4433 assert(fmt != IF_NONE);
4435 instrDesc* id = emitNewInstrSC(attr, immOut);
4446 /*****************************************************************************
4448 * Add an instruction referencing two registers and a constant.
4451 void emitter::emitIns_R_R_I(
4452 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm, insOpts opt /* = INS_OPTS_NONE */)
4454 emitAttr size = EA_SIZE(attr);
4455 emitAttr elemsize = EA_UNKNOWN;
4456 insFormat fmt = IF_NONE;
4457 bool isLdSt = false;
4458 bool isSIMD = false;
4459 bool isAddSub = false;
4460 bool setFlags = false;
4462 bool unscaledOp = false;
4464 /* Figure out the encoding format of the instruction */
4471 // Check for the 'mov' aliases for the vector registers
4472 assert(insOptsNone(opt));
4473 assert(isValidVectorElemsize(size));
4475 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4477 if (isVectorRegister(reg1))
4479 if (isGeneralRegisterOrZR(reg2))
4481 fmt = IF_DV_2C; // Alias for 'ins'
4484 else if (isVectorRegister(reg2))
4486 fmt = IF_DV_2E; // Alias for 'dup'
4490 else // isGeneralRegister(reg1)
4492 assert(isGeneralRegister(reg1));
4493 if (isVectorRegister(reg2))
4495 fmt = IF_DV_2B; // Alias for 'umov'
4499 assert(!" invalid INS_mov operands");
4505 assert(insOptsNone(opt));
4506 assert(isValidGeneralDatasize(size));
4507 assert(isGeneralRegister(reg1));
4508 assert(isGeneralRegister(reg2));
4509 assert(isValidImmShift(imm, size));
4514 assert(insOptsNone(opt));
4515 assert(isValidGeneralDatasize(size));
4516 assert(isGeneralRegister(reg1));
4517 assert(isGeneralRegister(reg2));
4518 assert(isValidImmShift(imm, size));
4533 assert(isVectorRegister(reg1));
4534 assert(isVectorRegister(reg2));
4535 if (insOptsAnyArrangement(opt))
4538 assert(isValidVectorDatasize(size));
4539 assert(isValidArrangement(size, opt));
4540 elemsize = optGetElemsize(opt);
4541 assert(isValidVectorElemsize(elemsize));
4542 assert(isValidImmShift(imm, elemsize));
4543 assert(opt != INS_OPTS_1D); // Reserved encoding
4550 assert(insOptsNone(opt));
4551 assert(size == EA_8BYTE); // only supported size
4552 assert(isValidImmShift(imm, size));
4566 assert(isVectorRegister(reg1));
4567 assert(isVectorRegister(reg2));
4569 assert(size == EA_8BYTE);
4570 assert(isValidArrangement(size, opt));
4571 elemsize = optGetElemsize(opt);
4572 assert(elemsize != EA_8BYTE); // Reserved encodings
4573 assert(isValidVectorElemsize(elemsize));
4574 assert(isValidImmShift(imm, elemsize));
4587 assert(isVectorRegister(reg1));
4588 assert(isVectorRegister(reg2));
4590 assert(size == EA_16BYTE);
4591 assert(isValidArrangement(size, opt));
4592 elemsize = optGetElemsize(opt);
4593 assert(elemsize != EA_8BYTE); // Reserved encodings
4594 assert(isValidVectorElemsize(elemsize));
4595 assert(isValidImmShift(imm, elemsize));
4602 assert(isValidGeneralDatasize(size));
4603 assert(isGeneralRegister(reg1));
4604 assert(isGeneralRegisterOrZR(reg2));
4608 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4616 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
4620 assert(insOptsAluShift(opt)); // a non-zero imm, must select shift kind, can't use ROR
4622 assert(isValidImmShift(imm, size));
4628 assert(isValidGeneralDatasize(size));
4629 assert(isGeneralRegisterOrZR(reg1));
4630 assert(isGeneralRegister(reg2));
4632 if (insOptsAnyShift(opt))
4634 assert(isValidImmShift(imm, size) && (imm != 0));
4639 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4647 assert(isValidGeneralDatasize(size));
4648 assert(isGeneralRegisterOrSP(reg1));
4649 assert(isGeneralRegister(reg2));
4651 reg1 = encodingSPtoZR(reg1);
4652 if (insOptsAnyExtend(opt))
4654 assert((imm >= 0) && (imm <= 4));
4660 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4666 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
4667 assert(isValidImmShift(imm, size));
4676 assert(insOptsNone(opt));
4677 assert(isGeneralRegister(reg2));
4678 if (ins == INS_ands)
4680 assert(isGeneralRegister(reg1));
4684 assert(isGeneralRegisterOrSP(reg1));
4685 reg1 = encodingSPtoZR(reg1);
4689 canEncode = canEncodeBitMaskImm(imm, size, &bmi);
4693 assert(isValidImmNRS(imm, size));
4698 case INS_dup: // by element, imm selects the element of reg2
4699 assert(isVectorRegister(reg1));
4700 if (isVectorRegister(reg2))
4702 if (insOptsAnyArrangement(opt))
4705 assert(isValidVectorDatasize(size));
4706 assert(isValidArrangement(size, opt));
4707 elemsize = optGetElemsize(opt);
4708 assert(isValidVectorElemsize(elemsize));
4709 assert(isValidVectorIndex(size, elemsize, imm));
4710 assert(opt != INS_OPTS_1D); // Reserved encoding
4717 assert(insOptsNone(opt));
4719 assert(isValidVectorElemsize(elemsize));
4720 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4727 case INS_ins: // (MOV from general)
4728 assert(insOptsNone(opt));
4729 assert(isValidVectorElemsize(size));
4730 assert(isVectorRegister(reg1));
4731 assert(isGeneralRegisterOrZR(reg2));
4733 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4737 case INS_umov: // (MOV to general)
4738 assert(insOptsNone(opt));
4739 assert(isValidVectorElemsize(size));
4740 assert(isGeneralRegister(reg1));
4741 assert(isVectorRegister(reg2));
4743 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4748 assert(insOptsNone(opt));
4749 assert(isValidVectorElemsize(size));
4750 assert(size != EA_8BYTE); // no encoding, use INS_umov
4751 assert(isGeneralRegister(reg1));
4752 assert(isVectorRegister(reg2));
4754 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4772 // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4773 assert(isValidGeneralDatasize(size));
4774 unscaledOp = (ins == INS_ldursb);
4781 // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4782 assert(isValidGeneralDatasize(size));
4783 unscaledOp = (ins == INS_ldursh);
4790 // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4791 assert(size == EA_8BYTE);
4792 unscaledOp = (ins == INS_ldursw);
4831 // Is the target a vector register?
4832 if (isVectorRegister(reg1))
4834 assert(isValidVectorLSDatasize(size));
4835 assert(isGeneralRegisterOrSP(reg2));
4840 assert(isValidGeneralDatasize(size));
4843 scale = NaturalScale_helper(size);
4849 // Is the target a vector register?
4850 if (isVectorRegister(reg1))
4852 assert(isValidVectorLSDatasize(size));
4853 assert(isGeneralRegisterOrSP(reg2));
4858 assert(isValidGeneralDatasize(size));
4869 } // end switch (ins)
4877 assert(isValidVectorLSDatasize(size));
4878 assert(isVectorRegister(reg1));
4879 assert((scale >= 0) && (scale <= 4));
4883 assert(isValidGeneralLSDatasize(size));
4884 assert(isGeneralRegisterOrZR(reg1));
4885 assert((scale >= 0) && (scale <= 3));
4888 assert(isGeneralRegisterOrSP(reg2));
4890 // Load/Store reserved encodings:
4891 if (insOptsIndexed(opt))
4893 assert(reg1 != reg2);
4896 reg2 = encodingSPtoZR(reg2);
4898 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
4901 assert(insOptsNone(opt)); // PRE/POST Index doesn't make sense with an immediate of zero
4905 else if (insOptsIndexed(opt) || unscaledOp || (imm < 0) || ((imm & mask) != 0))
4907 if ((imm >= -256) && (imm <= 255))
4913 assert(!"Instruction cannot be encoded: IF_LS_2C");
4918 assert(insOptsNone(opt));
4919 assert(!unscaledOp);
4921 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
4923 imm >>= scale; // The immediate is scaled by the size of the ld/st
4929 assert(!"Instruction cannot be encoded: IF_LS_2B");
4936 assert(insOptsNone(opt));
4938 if (setFlags) // Can't encode SP with setFlags
4940 assert(isGeneralRegister(reg1));
4941 assert(isGeneralRegister(reg2));
4945 assert(isGeneralRegisterOrSP(reg1));
4946 assert(isGeneralRegisterOrSP(reg2));
4948 // Is it just a mov?
4951 // Is the mov even necessary?
4954 emitIns_R_R(INS_mov, attr, reg1, reg2);
4959 reg1 = encodingSPtoZR(reg1);
4960 reg2 = encodingSPtoZR(reg2);
4963 if (unsigned_abs(imm) <= 0x0fff)
4967 ins = insReverse(ins);
4970 assert(isValidUimm12(imm));
4973 else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
4975 // Encoding will use a 12-bit left shift of the immediate
4976 opt = INS_OPTS_LSL12;
4979 ins = insReverse(ins);
4982 assert((imm & 0xfff) == 0);
4984 assert(isValidUimm12(imm));
4989 assert(!"Instruction cannot be encoded: IF_DI_2A");
4993 assert(fmt != IF_NONE);
4995 instrDesc* id = emitNewInstrSC(attr, imm);
5008 /*****************************************************************************
5010 * Add an instruction referencing two registers and a constant.
5011 * Also checks for a large immediate that needs a second instruction
5012 * and will load it in reg1
5014 * - Supports instructions: add, adds, sub, subs, and, ands, eor and orr
5015 * - Requires that reg1 is a general register and not SP or ZR
5016 * - Requires that reg1 != reg2
5018 void emitter::emitIns_R_R_Imm(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm)
5020 assert(isGeneralRegister(reg1));
5021 assert(reg1 != reg2);
5023 bool immFits = true;
5031 immFits = emitter::emitIns_valid_imm_for_add(imm, attr);
5038 immFits = emitter::emitIns_valid_imm_for_alu(imm, attr);
5042 assert(!"Unsupported instruction in emitIns_R_R_Imm");
5047 emitIns_R_R_I(ins, attr, reg1, reg2, imm);
5051 // Load 'imm' into the reg1 register
5052 // then issue: 'ins' reg1, reg2, reg1
5054 codeGen->instGen_Set_Reg_To_Imm(attr, reg1, imm);
5055 emitIns_R_R_R(ins, attr, reg1, reg2, reg1);
5059 /*****************************************************************************
5061 * Add an instruction referencing three registers.
5064 void emitter::emitIns_R_R_R(
5065 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insOpts opt) /* = INS_OPTS_NONE */
5067 emitAttr size = EA_SIZE(attr);
5068 emitAttr elemsize = EA_UNKNOWN;
5069 insFormat fmt = IF_NONE;
5071 /* Figure out the encoding format of the instruction */
5095 assert(insOptsNone(opt));
5096 assert(isValidGeneralDatasize(size));
5097 assert(isGeneralRegister(reg1));
5098 assert(isGeneralRegister(reg2));
5099 assert(isGeneralRegister(reg3));
5104 if (insOptsNone(opt))
5107 assert(isValidGeneralDatasize(size));
5108 assert(isGeneralRegister(reg1));
5109 assert(isGeneralRegister(reg2));
5110 assert(isGeneralRegister(reg3));
5119 assert(insOptsAnyArrangement(opt));
5120 assert(isVectorRegister(reg1));
5121 assert(isVectorRegister(reg2));
5122 assert(isVectorRegister(reg3));
5123 assert(isValidVectorDatasize(size));
5124 assert(isValidArrangement(size, opt));
5125 elemsize = optGetElemsize(opt);
5126 if (ins == INS_pmul)
5128 assert(elemsize == EA_1BYTE); // only supports 8B or 16B
5130 else // INS_mul, INS_mla, INS_mls
5132 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
5139 if (isVectorRegister(reg1))
5141 assert(isVectorRegister(reg2));
5142 assert(isVectorRegister(reg3));
5144 if (insOptsAnyArrangement(opt))
5147 assert(opt != INS_OPTS_1D); // Reserved encoding
5148 assert(isValidVectorDatasize(size));
5149 assert(isValidArrangement(size, opt));
5155 assert(insOptsNone(opt));
5156 assert(size == EA_8BYTE);
5165 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, INS_OPTS_NONE);
5174 assert(isVectorRegister(reg1));
5175 assert(isVectorRegister(reg2));
5176 assert(isVectorRegister(reg3));
5178 if (isValidVectorDatasize(size))
5181 assert(insOptsAnyArrangement(opt));
5182 assert(isValidArrangement(size, opt));
5183 elemsize = optGetElemsize(opt);
5190 assert(size == EA_8BYTE); // Only Double supported
5198 assert(isVectorRegister(reg1));
5199 assert(isVectorRegister(reg2));
5200 assert(isVectorRegister(reg3));
5202 if (isValidVectorDatasize(size))
5205 assert(insOptsAnyArrangement(opt));
5206 assert(isValidArrangement(size, opt));
5207 elemsize = optGetElemsize(opt);
5208 assert((elemsize == EA_8BYTE) || (elemsize == EA_4BYTE)); // Only Double/Float supported
5209 assert(opt != INS_OPTS_1D); // Reserved encoding
5216 assert((size == EA_8BYTE) || (size == EA_4BYTE)); // Only Double/Float supported
5229 assert(isVectorRegister(reg1));
5230 assert(isVectorRegister(reg2));
5231 assert(isVectorRegister(reg3));
5232 assert(insOptsAnyArrangement(opt));
5235 assert(isValidVectorDatasize(size));
5236 assert(isValidArrangement(size, opt));
5237 elemsize = optGetElemsize(opt);
5238 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
5244 assert(isVectorRegister(reg1));
5245 assert(isVectorRegister(reg2));
5246 assert(reg2 == reg3);
5247 assert(isValidVectorDatasize(size));
5248 // INS_mov is an alias for INS_orr (vector register)
5249 if (opt == INS_OPTS_NONE)
5251 elemsize = EA_1BYTE;
5252 opt = optMakeArrangement(size, elemsize);
5254 assert(isValidArrangement(size, opt));
5263 if (isVectorRegister(reg1))
5265 assert(isValidVectorDatasize(size));
5266 assert(isVectorRegister(reg2));
5267 assert(isVectorRegister(reg3));
5268 if (opt == INS_OPTS_NONE)
5270 elemsize = EA_1BYTE;
5271 opt = optMakeArrangement(size, elemsize);
5273 assert(isValidArrangement(size, opt));
5282 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, INS_OPTS_NONE);
5288 assert(isValidVectorDatasize(size));
5289 assert(isVectorRegister(reg1));
5290 assert(isVectorRegister(reg2));
5291 assert(isVectorRegister(reg3));
5292 if (opt == INS_OPTS_NONE)
5294 elemsize = EA_1BYTE;
5295 opt = optMakeArrangement(size, elemsize);
5297 assert(isValidArrangement(size, opt));
5309 assert(isVectorRegister(reg1));
5310 assert(isVectorRegister(reg2));
5311 assert(isVectorRegister(reg3));
5312 if (insOptsAnyArrangement(opt))
5315 assert(isValidVectorDatasize(size));
5316 assert(isValidArrangement(size, opt));
5317 elemsize = optGetElemsize(opt);
5318 assert(isValidVectorElemsizeFloat(elemsize));
5319 assert(opt != INS_OPTS_1D); // Reserved encoding
5325 assert(insOptsNone(opt));
5326 assert(isValidScalarDatasize(size));
5333 assert(insOptsNone(opt));
5334 assert(isVectorRegister(reg1));
5335 assert(isVectorRegister(reg2));
5336 assert(isVectorRegister(reg3));
5337 assert(isValidScalarDatasize(size));
5344 assert(isVectorRegister(reg1));
5345 assert(isVectorRegister(reg2));
5346 assert(isVectorRegister(reg3));
5347 assert(insOptsAnyArrangement(opt)); // no scalar encoding, use 4-operand 'fmadd' or 'fmsub'
5350 assert(isValidVectorDatasize(size));
5351 assert(isValidArrangement(size, opt));
5352 elemsize = optGetElemsize(opt);
5353 assert(isValidVectorElemsizeFloat(elemsize));
5354 assert(opt != INS_OPTS_1D); // Reserved encoding
5367 emitIns_R_R_R_Ext(ins, attr, reg1, reg2, reg3, opt);
5375 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0);
5384 assert(isGeneralRegisterOrZR(reg1));
5385 assert(isGeneralRegisterOrZR(reg2));
5386 assert(isGeneralRegisterOrSP(reg3));
5394 assert(isValidVectorDatasize(size));
5395 assert(isVectorRegister(reg1));
5396 assert(isVectorRegister(reg2));
5397 assert(isVectorRegister(reg3));
5398 if (opt == INS_OPTS_NONE)
5400 elemsize = EA_4BYTE;
5401 opt = optMakeArrangement(size, elemsize);
5403 assert(isValidArrangement(size, opt));
5411 } // end switch (ins)
5413 assert(fmt != IF_NONE);
5415 instrDesc* id = emitNewInstr(attr);
5429 /*****************************************************************************
5431 * Add an instruction referencing three registers and a constant.
5434 void emitter::emitIns_R_R_R_I(instruction ins,
5440 insOpts opt /* = INS_OPTS_NONE */,
5441 emitAttr attrReg2 /* = EA_UNKNOWN */)
5443 emitAttr size = EA_SIZE(attr);
5444 emitAttr elemsize = EA_UNKNOWN;
5445 insFormat fmt = IF_NONE;
5446 bool isLdSt = false;
5447 bool isSIMD = false;
5448 bool isAddSub = false;
5449 bool setFlags = false;
5452 /* Figure out the encoding format of the instruction */
5456 assert(insOptsNone(opt));
5457 assert(isValidGeneralDatasize(size));
5458 assert(isGeneralRegister(reg1));
5459 assert(isGeneralRegister(reg2));
5460 assert(isGeneralRegister(reg3));
5461 assert(isValidImmShift(imm, size));
5473 assert(isValidGeneralDatasize(size));
5474 assert(isGeneralRegister(reg1));
5475 assert(isGeneralRegister(reg2));
5476 assert(isGeneralRegister(reg3));
5477 assert(isValidImmShift(imm, size));
5480 assert(insOptsNone(opt)); // a zero imm, means no shift kind
5485 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
5490 case INS_fmul: // by element, imm[0..3] selects the element of reg3
5494 assert(isVectorRegister(reg1));
5495 assert(isVectorRegister(reg2));
5496 assert(isVectorRegister(reg3));
5497 if (insOptsAnyArrangement(opt))
5500 assert(isValidVectorDatasize(size));
5501 assert(isValidArrangement(size, opt));
5502 elemsize = optGetElemsize(opt);
5503 assert(isValidVectorElemsizeFloat(elemsize));
5504 assert(isValidVectorIndex(size, elemsize, imm));
5505 assert(opt != INS_OPTS_1D); // Reserved encoding
5511 assert(insOptsNone(opt));
5512 assert(isValidScalarDatasize(size));
5514 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
5519 case INS_mul: // by element, imm[0..7] selects the element of reg3
5522 assert(isVectorRegister(reg1));
5523 assert(isVectorRegister(reg2));
5524 assert(isVectorRegister(reg3));
5526 assert(insOptsAnyArrangement(opt));
5527 assert(isValidVectorDatasize(size));
5528 assert(isValidArrangement(size, opt));
5529 elemsize = optGetElemsize(opt);
5530 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
5531 // Only has encodings for H or S elemsize
5532 assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE));
5533 // Only has encodings for V0..V15
5534 if ((elemsize == EA_2BYTE) && (reg3 >= REG_V16))
5536 noway_assert(!"Invalid reg3");
5560 assert(insOptsNone(opt)); // Can't use Pre/Post index on these two instructions
5565 // Is the target a vector register?
5566 if (isVectorRegister(reg1))
5568 scale = NaturalScale_helper(size);
5573 scale = (size == EA_8BYTE) ? 3 : 2;
5582 } // end switch (ins)
5587 assert(isGeneralRegisterOrSP(reg3));
5588 assert(insOptsNone(opt) || insOptsIndexed(opt));
5592 assert(isValidVectorLSPDatasize(size));
5593 assert(isVectorRegister(reg1));
5594 assert(isVectorRegister(reg2));
5595 assert((scale >= 2) && (scale <= 4));
5599 assert(isValidGeneralDatasize(size));
5600 assert(isGeneralRegisterOrZR(reg1));
5601 assert(isGeneralRegisterOrZR(reg2));
5602 assert((scale == 2) || (scale == 3));
5605 // Load/Store Pair reserved encodings:
5606 if (emitInsIsLoad(ins))
5608 assert(reg1 != reg2);
5610 if (insOptsIndexed(opt))
5612 assert(reg1 != reg3);
5613 assert(reg2 != reg3);
5616 reg3 = encodingSPtoZR(reg3);
5618 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
5621 assert(insOptsNone(opt)); // PRE/POST Index doesn't make sense with an immediate of zero
5627 if ((imm & mask) == 0)
5629 imm >>= scale; // The immediate is scaled by the size of the ld/st
5631 if ((imm >= -64) && (imm <= 63))
5637 if (fmt != IF_LS_3C)
5639 assert(!"Instruction cannot be encoded: IF_LS_3C");
5646 bool reg2IsSP = (reg2 == REG_SP);
5648 assert(isValidGeneralDatasize(size));
5649 assert(isGeneralRegister(reg3));
5651 if (setFlags || insOptsAluShift(opt)) // Can't encode SP in reg1 with setFlags or AluShift option
5653 assert(isGeneralRegisterOrZR(reg1));
5657 assert(isGeneralRegisterOrSP(reg1));
5658 reg1 = encodingSPtoZR(reg1);
5661 if (insOptsAluShift(opt)) // Can't encode SP in reg2 with AluShift option
5663 assert(isGeneralRegister(reg2));
5667 assert(isGeneralRegisterOrSP(reg2));
5668 reg2 = encodingSPtoZR(reg2);
5671 if (insOptsAnyExtend(opt))
5673 assert((imm >= 0) && (imm <= 4));
5677 else if (insOptsAluShift(opt))
5679 // imm should be non-zero and in [1..63]
5680 assert(isValidImmShift(imm, size) && (imm != 0));
5685 assert(insOptsNone(opt));
5689 // To encode the SP register as reg2 we must use the IF_DR_3C encoding
5690 // and also specify a LSL of zero (imm == 0)
5701 assert(!"Instruction cannot be encoded: Add/Sub IF_DR_3A");
5704 assert(fmt != IF_NONE);
5706 instrDesc* id = emitNewInstrCns(attr, imm);
5716 // Record the attribute for the second register in the pair
5717 id->idGCrefReg2(GCT_NONE);
5718 if (attrReg2 != EA_UNKNOWN)
5720 // Record the attribute for the second register in the pair
5721 assert((fmt == IF_LS_3B) || (fmt == IF_LS_3C));
5722 if (EA_IS_GCREF(attrReg2))
5724 id->idGCrefReg2(GCT_GCREF);
5726 else if (EA_IS_BYREF(attrReg2))
5728 id->idGCrefReg2(GCT_BYREF);
5736 /*****************************************************************************
5738 * Add an instruction referencing three registers, with an extend option
5741 void emitter::emitIns_R_R_R_Ext(instruction ins,
5746 insOpts opt, /* = INS_OPTS_NONE */
5747 int shiftAmount) /* = -1 -- unset */
5749 emitAttr size = EA_SIZE(attr);
5750 insFormat fmt = IF_NONE;
5751 bool isSIMD = false;
5754 /* Figure out the encoding format of the instruction */
5775 // Is the target a vector register?
5776 if (isVectorRegister(reg1))
5778 assert(isValidVectorLSDatasize(size));
5779 scale = NaturalScale_helper(size);
5784 assert(isValidGeneralDatasize(size));
5785 scale = (size == EA_8BYTE) ? 3 : 2;
5794 } // end switch (ins)
5796 assert(scale != -1);
5797 assert(insOptsLSExtend(opt));
5801 assert(isValidVectorLSDatasize(size));
5802 assert(isVectorRegister(reg1));
5806 assert(isValidGeneralLSDatasize(size));
5807 assert(isGeneralRegisterOrZR(reg1));
5810 assert(isGeneralRegisterOrSP(reg2));
5811 assert(isGeneralRegister(reg3));
5813 // Load/Store reserved encodings:
5814 if (insOptsIndexed(opt))
5816 assert(reg1 != reg2);
5819 if (shiftAmount == -1)
5821 shiftAmount = insOptsLSL(opt) ? scale : 0;
5823 assert((shiftAmount == scale) || (shiftAmount == 0));
5825 reg2 = encodingSPtoZR(reg2);
5828 instrDesc* id = emitNewInstr(attr);
5837 id->idReg3Scaled(shiftAmount == scale);
5843 /*****************************************************************************
5845 * Add an instruction referencing two registers and two constants.
5848 void emitter::emitIns_R_R_I_I(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, int imm1, int imm2)
5850 emitAttr size = EA_SIZE(attr);
5851 emitAttr elemsize = EA_UNKNOWN;
5852 insFormat fmt = IF_NONE;
5853 size_t immOut = 0; // composed from imm1 and imm2 and stored in the instrDesc
5855 /* Figure out the encoding format of the instruction */
5865 assert(isGeneralRegister(reg1));
5866 assert(isGeneralRegister(reg2));
5867 assert(isValidImmShift(imm1, size));
5868 assert(isValidImmShift(imm2, size));
5870 bmi.immN = (size == EA_8BYTE);
5873 immOut = bmi.immNRS;
5880 assert(isGeneralRegister(reg1));
5881 assert(isGeneralRegister(reg2));
5882 lsb = getBitWidth(size) - imm1;
5884 assert(isValidImmShift(lsb, size));
5885 assert(isValidImmShift(width, size));
5887 bmi.immN = (size == EA_8BYTE);
5890 immOut = bmi.immNRS;
5897 assert(isGeneralRegister(reg1));
5898 assert(isGeneralRegister(reg2));
5900 width = imm2 + imm1 - 1;
5901 assert(isValidImmShift(lsb, size));
5902 assert(isValidImmShift(width, size));
5904 bmi.immN = (size == EA_8BYTE);
5906 bmi.immS = imm2 + imm1 - 1;
5907 immOut = bmi.immNRS;
5913 assert(isVectorRegister(reg1));
5914 assert(isVectorRegister(reg2));
5916 assert(isValidVectorElemsize(elemsize));
5917 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm1));
5918 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm2));
5919 immOut = (imm1 << 4) + imm2;
5927 assert(fmt != IF_NONE);
5929 instrDesc* id = emitNewInstrSC(attr, immOut);
5941 /*****************************************************************************
5943 * Add an instruction referencing four registers.
5946 void emitter::emitIns_R_R_R_R(
5947 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, regNumber reg4)
5949 emitAttr size = EA_SIZE(attr);
5950 insFormat fmt = IF_NONE;
5952 /* Figure out the encoding format of the instruction */
5961 assert(isValidGeneralDatasize(size));
5962 assert(isGeneralRegister(reg1));
5963 assert(isGeneralRegister(reg2));
5964 assert(isGeneralRegister(reg3));
5965 assert(isGeneralRegister(reg4));
5974 assert(isValidScalarDatasize(size));
5975 assert(isVectorRegister(reg1));
5976 assert(isVectorRegister(reg2));
5977 assert(isVectorRegister(reg3));
5978 assert(isVectorRegister(reg4));
5990 assert(fmt != IF_NONE);
5992 instrDesc* id = emitNewInstr(attr);
6006 /*****************************************************************************
6008 * Add an instruction referencing a register and a condition code
6011 void emitter::emitIns_R_COND(instruction ins, emitAttr attr, regNumber reg, insCond cond)
6013 emitAttr size = EA_SIZE(attr);
6014 insFormat fmt = IF_NONE;
6018 /* Figure out the encoding format of the instruction */
6023 assert(isGeneralRegister(reg));
6032 } // end switch (ins)
6034 assert(fmt != IF_NONE);
6035 assert(isValidImmCond(cfi.immCFVal));
6037 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6041 id->idInsOpt(INS_OPTS_NONE);
6049 /*****************************************************************************
6051 * Add an instruction referencing two registers and a condition code
6054 void emitter::emitIns_R_R_COND(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insCond cond)
6056 emitAttr size = EA_SIZE(attr);
6057 insFormat fmt = IF_NONE;
6061 /* Figure out the encoding format of the instruction */
6067 assert(isGeneralRegister(reg1));
6068 assert(isGeneralRegister(reg2));
6076 } // end switch (ins)
6078 assert(fmt != IF_NONE);
6079 assert(isValidImmCond(cfi.immCFVal));
6081 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6085 id->idInsOpt(INS_OPTS_NONE);
6094 /*****************************************************************************
6096 * Add an instruction referencing two registers and a condition code
6099 void emitter::emitIns_R_R_R_COND(
6100 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insCond cond)
6102 emitAttr size = EA_SIZE(attr);
6103 insFormat fmt = IF_NONE;
6107 /* Figure out the encoding format of the instruction */
6114 assert(isGeneralRegister(reg1));
6115 assert(isGeneralRegister(reg2));
6116 assert(isGeneralRegister(reg3));
6125 } // end switch (ins)
6127 assert(fmt != IF_NONE);
6128 assert(isValidImmCond(cfi.immCFVal));
6130 instrDesc* id = emitNewInstr(attr);
6134 id->idInsOpt(INS_OPTS_NONE);
6139 id->idSmallCns(cfi.immCFVal);
6145 /*****************************************************************************
6147 * Add an instruction referencing two registers the flags and a condition code
6150 void emitter::emitIns_R_R_FLAGS_COND(
6151 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insCflags flags, insCond cond)
6153 emitAttr size = EA_SIZE(attr);
6154 insFormat fmt = IF_NONE;
6158 /* Figure out the encoding format of the instruction */
6163 assert(isGeneralRegister(reg1));
6164 assert(isGeneralRegister(reg2));
6172 } // end switch (ins)
6174 assert(fmt != IF_NONE);
6175 assert(isValidImmCondFlags(cfi.immCFVal));
6177 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6181 id->idInsOpt(INS_OPTS_NONE);
6190 /*****************************************************************************
6192 * Add an instruction referencing a register, an immediate, the flags and a condition code
6195 void emitter::emitIns_R_I_FLAGS_COND(
6196 instruction ins, emitAttr attr, regNumber reg, int imm, insCflags flags, insCond cond)
6198 emitAttr size = EA_SIZE(attr);
6199 insFormat fmt = IF_NONE;
6203 /* Figure out the encoding format of the instruction */
6208 assert(isGeneralRegister(reg));
6211 ins = insReverse(ins);
6214 if ((imm >= 0) && (imm <= 31))
6223 assert(!"Instruction cannot be encoded: ccmp/ccmn imm5");
6229 } // end switch (ins)
6231 assert(fmt != IF_NONE);
6232 assert(isValidImmCondFlagsImm5(cfi.immCFVal));
6234 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6238 id->idInsOpt(INS_OPTS_NONE);
6246 /*****************************************************************************
6248 * Add a memory barrier instruction with a 'barrier' immediate
6251 void emitter::emitIns_BARR(instruction ins, insBarrier barrier)
6253 insFormat fmt = IF_NONE;
6256 /* Figure out the encoding format of the instruction */
6264 imm = (ssize_t)barrier;
6269 } // end switch (ins)
6271 assert(fmt != IF_NONE);
6273 instrDesc* id = emitNewInstrSC(EA_8BYTE, imm);
6277 id->idInsOpt(INS_OPTS_NONE);
6283 /*****************************************************************************
6285 * Add an instruction with a static data member operand. If 'size' is 0, the
6286 * instruction operates on the address of the static member instead of its
6287 * value (e.g. "push offset clsvar", rather than "push dword ptr [clsvar]").
6290 void emitter::emitIns_C(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, int offs)
6295 /*****************************************************************************
6297 * Add an instruction referencing stack-based local variable.
6300 void emitter::emitIns_S(instruction ins, emitAttr attr, int varx, int offs)
6305 /*****************************************************************************
6307 * Add an instruction referencing a register and a stack-based local variable.
6309 void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
6311 emitAttr size = EA_SIZE(attr);
6312 insFormat fmt = IF_NONE;
6318 // TODO-ARM64-CQ: use unscaled loads?
6319 /* Figure out the encoding format of the instruction */
6340 assert(isValidGeneralDatasize(size) || isValidVectorDatasize(size));
6341 scale = genLog2(EA_SIZE_IN_BYTES(size));
6345 assert(size == EA_8BYTE);
6350 NYI("emitIns_R_S"); // FP locals?
6353 } // end switch (ins)
6355 /* Figure out the variable's frame position */
6360 base = emitComp->lvaFrameAddress(varx, &FPbased);
6362 assert((scale >= 0) && (scale <= 4));
6364 regNumber reg2 = FPbased ? REG_FPBASE : REG_SPBASE;
6365 reg2 = encodingSPtoZR(reg2);
6382 fmt = IF_DI_2A; // add reg1,reg2,#disp
6386 regNumber rsvdReg = codeGen->rsGetRsvdReg();
6387 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6388 fmt = IF_DR_3A; // add reg1,reg2,rsvdReg
6393 bool useRegForImm = false;
6394 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6401 else if ((imm < 0) || ((imm & mask) != 0))
6403 if ((imm >= -256) && (imm <= 255))
6409 useRegForImm = true;
6414 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
6416 imm >>= scale; // The immediate is scaled by the size of the ld/st
6422 useRegForImm = true;
6428 regNumber rsvdReg = codeGen->rsGetRsvdReg();
6429 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6434 assert(fmt != IF_NONE);
6436 instrDesc* id = emitNewInstrCns(attr, imm);
6440 id->idInsOpt(INS_OPTS_NONE);
6444 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6445 id->idSetIsLclVar();
6448 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6455 /*****************************************************************************
6457 * Add an instruction referencing two register and consectutive stack-based local variable slots.
6459 void emitter::emitIns_R_R_S_S(
6460 instruction ins, emitAttr attr1, emitAttr attr2, regNumber reg1, regNumber reg2, int varx, int offs)
6462 assert((ins == INS_ldp) || (ins == INS_ldnp));
6463 assert(EA_8BYTE == EA_SIZE(attr1));
6464 assert(EA_8BYTE == EA_SIZE(attr2));
6465 assert(isGeneralRegisterOrZR(reg1));
6466 assert(isGeneralRegisterOrZR(reg2));
6469 insFormat fmt = IF_LS_3B;
6471 const unsigned scale = 3;
6473 /* Figure out the variable's frame position */
6477 base = emitComp->lvaFrameAddress(varx, &FPbased);
6480 // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6481 regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE;
6482 reg3 = encodingSPtoZR(reg3);
6484 bool useRegForAdr = true;
6486 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6489 useRegForAdr = false;
6493 if ((imm & mask) == 0)
6495 ssize_t immShift = imm >> scale; // The immediate is scaled by the size of the ld/st
6497 if ((immShift >= -64) && (immShift <= 63))
6500 useRegForAdr = false;
6508 regNumber rsvd = codeGen->rsGetRsvdReg();
6509 emitIns_R_R_Imm(INS_add, EA_PTRSIZE, rsvd, reg3, imm);
6514 assert(fmt != IF_NONE);
6516 instrDesc* id = emitNewInstrCns(attr1, imm);
6520 id->idInsOpt(INS_OPTS_NONE);
6522 // Record the attribute for the second register in the pair
6523 if (EA_IS_GCREF(attr2))
6525 id->idGCrefReg2(GCT_GCREF);
6527 else if (EA_IS_BYREF(attr2))
6529 id->idGCrefReg2(GCT_BYREF);
6533 id->idGCrefReg2(GCT_NONE);
6539 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6540 id->idSetIsLclVar();
6543 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6550 /*****************************************************************************
6552 * Add an instruction referencing a stack-based local variable and a register
6554 void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
6557 emitAttr size = EA_SIZE(attr);
6558 insFormat fmt = IF_NONE;
6561 bool isVectorStore = false;
6563 // TODO-ARM64-CQ: use unscaled loads?
6564 /* Figure out the encoding format of the instruction */
6569 assert(isGeneralRegisterOrZR(reg1));
6574 assert(isGeneralRegisterOrZR(reg1));
6578 if (isGeneralRegisterOrZR(reg1))
6580 assert(isValidGeneralDatasize(size));
6581 scale = (size == EA_8BYTE) ? 3 : 2;
6585 assert(isVectorRegister(reg1));
6586 assert(isValidVectorLSDatasize(size));
6587 scale = NaturalScale_helper(size);
6588 isVectorStore = true;
6593 NYI("emitIns_S_R"); // FP locals?
6596 } // end switch (ins)
6598 /* Figure out the variable's frame position */
6602 base = emitComp->lvaFrameAddress(varx, &FPbased);
6614 // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6615 regNumber reg2 = FPbased ? REG_FPBASE : REG_SPBASE;
6616 reg2 = encodingSPtoZR(reg2);
6618 bool useRegForImm = false;
6620 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6625 else if ((imm < 0) || ((imm & mask) != 0))
6627 if ((imm >= -256) && (imm <= 255))
6633 useRegForImm = true;
6638 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
6640 imm >>= scale; // The immediate is scaled by the size of the ld/st
6646 useRegForImm = true;
6652 // The reserved register is not stored in idReg3() since that field overlaps with iiaLclVar.
6653 // It is instead implicit when idSetIsLclVar() is set, with this encoding format.
6654 regNumber rsvdReg = codeGen->rsGetRsvdReg();
6655 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6659 assert(fmt != IF_NONE);
6661 instrDesc* id = emitNewInstrCns(attr, imm);
6665 id->idInsOpt(INS_OPTS_NONE);
6669 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6670 id->idSetIsLclVar();
6673 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6680 /*****************************************************************************
6682 * Add an instruction referencing consecutive stack-based local variable slots and two registers
6684 void emitter::emitIns_S_S_R_R(
6685 instruction ins, emitAttr attr1, emitAttr attr2, regNumber reg1, regNumber reg2, int varx, int offs)
6687 assert((ins == INS_stp) || (ins == INS_stnp));
6688 assert(EA_8BYTE == EA_SIZE(attr1));
6689 assert(EA_8BYTE == EA_SIZE(attr2));
6690 assert(isGeneralRegisterOrZR(reg1));
6691 assert(isGeneralRegisterOrZR(reg2));
6694 insFormat fmt = IF_LS_3B;
6696 const unsigned scale = 3;
6698 /* Figure out the variable's frame position */
6702 base = emitComp->lvaFrameAddress(varx, &FPbased);
6705 // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6706 regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE;
6707 reg3 = encodingSPtoZR(reg3);
6709 bool useRegForAdr = true;
6711 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6714 useRegForAdr = false;
6718 if ((imm & mask) == 0)
6720 ssize_t immShift = imm >> scale; // The immediate is scaled by the size of the ld/st
6722 if ((immShift >= -64) && (immShift <= 63))
6725 useRegForAdr = false;
6733 regNumber rsvd = codeGen->rsGetRsvdReg();
6734 emitIns_R_R_Imm(INS_add, EA_PTRSIZE, rsvd, reg3, imm);
6739 assert(fmt != IF_NONE);
6741 instrDesc* id = emitNewInstrCns(attr1, imm);
6745 id->idInsOpt(INS_OPTS_NONE);
6747 // Record the attribute for the second register in the pair
6748 if (EA_IS_GCREF(attr2))
6750 id->idGCrefReg2(GCT_GCREF);
6752 else if (EA_IS_BYREF(attr2))
6754 id->idGCrefReg2(GCT_BYREF);
6758 id->idGCrefReg2(GCT_NONE);
6764 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6765 id->idSetIsLclVar();
6768 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6775 /*****************************************************************************
6777 * Add an instruction referencing stack-based local variable and an immediate
6779 void emitter::emitIns_S_I(instruction ins, emitAttr attr, int varx, int offs, int val)
6784 /*****************************************************************************
6786 * Add an instruction with a register + static member operands.
6787 * Constant is stored into JIT data which is adjacent to code.
6788 * No relocation is needed. PC-relative offset will be encoded directly into instruction.
6791 void emitter::emitIns_R_C(
6792 instruction ins, emitAttr attr, regNumber reg, regNumber addrReg, CORINFO_FIELD_HANDLE fldHnd, int offs)
6795 assert(instrDesc::fitsInSmallCns(offs));
6797 emitAttr size = EA_SIZE(attr);
6798 insFormat fmt = IF_NONE;
6800 instrDescJmp* id = emitNewInstrJmp();
6805 // This is case to get address to the constant data.
6807 assert(isGeneralRegister(reg));
6808 assert(isValidGeneralDatasize(size));
6813 if (isVectorRegister(reg))
6815 assert(isValidScalarDatasize(size));
6816 // For vector (float/double) register, we should have an integer address reg to
6817 // compute long address which consists of page address and page offset.
6818 // For integer constant, this is not needed since the dest reg can be used to
6819 // compute address as well as contain the final contents.
6820 assert(isGeneralRegister(reg) || (addrReg != REG_NA));
6824 assert(isGeneralRegister(reg));
6825 assert(isValidGeneralDatasize(size));
6832 assert(fmt != IF_NONE);
6836 id->idInsOpt(INS_OPTS_NONE);
6837 id->idSmallCns(offs);
6839 id->idAddr()->iiaFieldHnd = fldHnd;
6840 id->idSetIsBound(); // We won't patch address since we will know the exact distance once JIT code and data are
6841 // allocated together.
6843 id->idReg1(reg); // destination register that will get the constant value.
6844 if (addrReg != REG_NA)
6846 id->idReg2(addrReg); // integer register to compute long address (used for vector dest when we end up with long
6849 id->idjShort = false; // Assume loading constant from long address
6851 // Keep it long if it's in cold code.
6852 id->idjKeepLong = emitComp->fgIsBlockCold(emitComp->compCurBB);
6855 if (emitComp->opts.compLongAddress)
6856 id->idjKeepLong = 1;
6859 // If it's possible to be shortened, then put it in jump list
6860 // to be revisited by emitJumpDistBind.
6861 if (!id->idjKeepLong)
6863 /* Record the jump's IG and offset within it */
6864 id->idjIG = emitCurIG;
6865 id->idjOffs = emitCurIGsize;
6867 /* Append this jump to this IG's jump list */
6868 id->idjNext = emitCurIGjmpList;
6869 emitCurIGjmpList = id;
6880 /*****************************************************************************
6882 * Add an instruction with a static member + constant.
6885 void emitter::emitIns_C_I(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, ssize_t offs, ssize_t val)
6890 /*****************************************************************************
6892 * Add an instruction with a static member + register operands.
6895 void emitter::emitIns_C_R(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, regNumber reg, int offs)
6897 assert(!"emitIns_C_R not supported for RyuJIT backend");
6900 void emitter::emitIns_R_AR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
6902 NYI("emitIns_R_AR");
6905 // This computes address from the immediate which is relocatable.
6906 void emitter::emitIns_R_AI(instruction ins, emitAttr attr, regNumber ireg, ssize_t addr)
6908 assert(EA_IS_RELOC(attr));
6909 emitAttr size = EA_SIZE(attr);
6910 insFormat fmt = IF_DI_1E;
6911 bool needAdd = false;
6912 instrDescJmp* id = emitNewInstrJmp();
6917 // This computes page address.
6918 // page offset is needed using add.
6929 id->idInsOpt(INS_OPTS_NONE);
6931 id->idAddr()->iiaAddr = (BYTE*)addr;
6933 id->idSetIsDspReloc();
6940 // add reg, reg, imm
6943 instrDesc* id = emitAllocInstr(attr);
6944 assert(id->idIsReloc());
6948 id->idInsOpt(INS_OPTS_NONE);
6950 id->idAddr()->iiaAddr = (BYTE*)addr;
6959 void emitter::emitIns_AR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
6961 NYI("emitIns_AR_R");
6964 void emitter::emitIns_R_ARR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
6966 NYI("emitIns_R_ARR");
6969 void emitter::emitIns_ARR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
6971 NYI("emitIns_R_ARR");
6974 void emitter::emitIns_R_ARX(
6975 instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, unsigned mul, int disp)
6977 NYI("emitIns_R_ARR");
6980 /*****************************************************************************
6982 * Record that a jump instruction uses the short encoding
6985 void emitter::emitSetShortJump(instrDescJmp* id)
6987 if (id->idjKeepLong)
6990 insFormat fmt = IF_NONE;
6991 if (emitIsCondJump(id))
6993 switch (id->idIns())
7008 else if (emitIsLoadLabel(id))
7012 else if (emitIsLoadConstant(id))
7022 id->idjShort = true;
7025 /*****************************************************************************
7027 * Add a label instruction.
7030 void emitter::emitIns_R_L(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
7032 assert(dst->bbFlags & BBF_JMP_TARGET);
7034 insFormat fmt = IF_NONE;
7045 instrDescJmp* id = emitNewInstrJmp();
7049 id->idjShort = false;
7050 id->idAddr()->iiaBBlabel = dst;
7052 id->idOpSize(EA_PTRSIZE);
7055 // Mark the catch return
7056 if (emitComp->compCurBB->bbJumpKind == BBJ_EHCATCHRET)
7058 id->idDebugOnlyInfo()->idCatchRet = true;
7062 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7065 if (emitComp->opts.compLongAddress)
7066 id->idjKeepLong = 1;
7069 /* Record the jump's IG and offset within it */
7071 id->idjIG = emitCurIG;
7072 id->idjOffs = emitCurIGsize;
7074 /* Append this jump to this IG's jump list */
7076 id->idjNext = emitCurIGjmpList;
7077 emitCurIGjmpList = id;
7087 /*****************************************************************************
7089 * Add a data label instruction.
7092 void emitter::emitIns_R_D(instruction ins, emitAttr attr, unsigned offs, regNumber reg)
7097 void emitter::emitIns_J_R(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
7099 assert((ins == INS_cbz) || (ins == INS_cbnz));
7101 assert(dst != nullptr);
7102 assert((dst->bbFlags & BBF_JMP_TARGET) != 0);
7104 insFormat fmt = IF_LARGEJMP;
7106 instrDescJmp* id = emitNewInstrJmp();
7111 id->idjShort = false;
7112 id->idOpSize(EA_SIZE(attr));
7114 id->idAddr()->iiaBBlabel = dst;
7115 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7117 /* Record the jump's IG and offset within it */
7119 id->idjIG = emitCurIG;
7120 id->idjOffs = emitCurIGsize;
7122 /* Append this jump to this IG's jump list */
7124 id->idjNext = emitCurIGjmpList;
7125 emitCurIGjmpList = id;
7135 void emitter::emitIns_J_R_I(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg, int imm)
7137 assert((ins == INS_tbz) || (ins == INS_tbnz));
7139 assert(dst != nullptr);
7140 assert((dst->bbFlags & BBF_JMP_TARGET) != 0);
7141 assert((EA_SIZE(attr) == EA_4BYTE) || (EA_SIZE(attr) == EA_8BYTE));
7142 assert(imm < ((EA_SIZE(attr) == EA_4BYTE) ? 32 : 64));
7144 insFormat fmt = IF_LARGEJMP;
7146 instrDescJmp* id = emitNewInstrJmp();
7151 id->idjShort = false;
7152 id->idSmallCns(imm);
7153 id->idOpSize(EA_SIZE(attr));
7155 id->idAddr()->iiaBBlabel = dst;
7156 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7158 /* Record the jump's IG and offset within it */
7160 id->idjIG = emitCurIG;
7161 id->idjOffs = emitCurIGsize;
7163 /* Append this jump to this IG's jump list */
7165 id->idjNext = emitCurIGjmpList;
7166 emitCurIGjmpList = id;
7176 void emitter::emitIns_J(instruction ins, BasicBlock* dst, int instrCount)
7178 insFormat fmt = IF_NONE;
7182 assert(dst->bbFlags & BBF_JMP_TARGET);
7186 assert(instrCount != 0);
7189 /* Figure out the encoding format of the instruction */
7191 bool idjShort = false;
7196 // Unconditional jump is a single form.
7215 // Assume conditional jump is long.
7224 instrDescJmp* id = emitNewInstrJmp();
7228 id->idjShort = idjShort;
7231 // Mark the finally call
7232 if (ins == INS_bl_local && emitComp->compCurBB->bbJumpKind == BBJ_CALLFINALLY)
7234 id->idDebugOnlyInfo()->idFinallyCall = true;
7240 id->idAddr()->iiaBBlabel = dst;
7242 // Skip unconditional jump that has a single form.
7243 // TODO-ARM64-NYI: enable hot/cold splittingNYI.
7244 // The target needs to be relocated.
7247 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7250 if (emitComp->opts.compLongAddress) // Force long branches
7251 id->idjKeepLong = 1;
7257 id->idAddr()->iiaSetInstrCount(instrCount);
7258 id->idjKeepLong = false;
7259 /* This jump must be short */
7260 emitSetShortJump(id);
7264 /* Record the jump's IG and offset within it */
7266 id->idjIG = emitCurIG;
7267 id->idjOffs = emitCurIGsize;
7269 /* Append this jump to this IG's jump list */
7271 id->idjNext = emitCurIGjmpList;
7272 emitCurIGjmpList = id;
7282 /*****************************************************************************
7284 * Add a call instruction (direct or indirect).
7285 * argSize<0 means that the caller will pop the arguments
7287 * The other arguments are interpreted depending on callType as shown:
7288 * Unless otherwise specified, ireg,xreg,xmul,disp should have default values.
7290 * EC_FUNC_TOKEN : addr is the method address
7291 * EC_FUNC_ADDR : addr is the absolute address of the function
7293 * If callType is one of these emitCallTypes, addr has to be NULL.
7294 * EC_INDIR_R : "call ireg".
7296 * For ARM xreg, xmul and disp are never used and should always be 0/REG_NA.
7298 * Please consult the "debugger team notification" comment in genFnProlog().
7301 void emitter::emitIns_Call(EmitCallType callType,
7302 CORINFO_METHOD_HANDLE methHnd,
7303 INDEBUG_LDISASM_COMMA(CORINFO_SIG_INFO* sigInfo) // used to report call sites to the EE
7307 emitAttr secondRetSize,
7308 VARSET_VALARG_TP ptrVars,
7309 regMaskTP gcrefRegs,
7310 regMaskTP byrefRegs,
7311 IL_OFFSETX ilOffset /* = BAD_IL_OFFSET */,
7312 regNumber ireg /* = REG_NA */,
7313 regNumber xreg /* = REG_NA */,
7314 unsigned xmul /* = 0 */,
7315 ssize_t disp /* = 0 */,
7316 bool isJump /* = false */,
7317 bool isNoGC /* = false */,
7318 bool isProfLeaveCB /* = false */)
7320 /* Sanity check the arguments depending on callType */
7322 assert(callType < EC_COUNT);
7323 assert((callType != EC_FUNC_TOKEN && callType != EC_FUNC_ADDR) ||
7324 (ireg == REG_NA && xreg == REG_NA && xmul == 0 && disp == 0));
7325 assert(callType < EC_INDIR_R || addr == NULL);
7326 assert(callType != EC_INDIR_R || (ireg < REG_COUNT && xreg == REG_NA && xmul == 0 && disp == 0));
7328 // ARM never uses these
7329 assert(xreg == REG_NA && xmul == 0 && disp == 0);
7331 // Our stack level should be always greater than the bytes of arguments we push. Just
7333 assert((unsigned)abs(argSize) <= codeGen->genStackLevel);
7338 /* This is the saved set of registers after a normal call */
7339 regMaskTP savedSet = RBM_CALLEE_SAVED;
7341 /* some special helper calls have a different saved set registers */
7345 assert(emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
7347 // Get the set of registers that this call kills and remove it from the saved set.
7348 savedSet = RBM_ALLINT & ~emitComp->compNoGCHelperCallKillSet(Compiler::eeGetHelperNum(methHnd));
7350 // In case of Leave profiler callback, we need to preserve liveness of REG_PROFILER_RET_SCRATCH
7353 savedSet |= RBM_PROFILER_RET_SCRATCH;
7358 assert(!emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
7361 /* Trim out any callee-trashed registers from the live set */
7363 gcrefRegs &= savedSet;
7364 byrefRegs &= savedSet;
7367 if (EMIT_GC_VERBOSE)
7369 printf("Call: GCvars=%s ", VarSetOps::ToString(emitComp, ptrVars));
7370 dumpConvertedVarSet(emitComp, ptrVars);
7371 printf(", gcrefRegs=");
7372 printRegMaskInt(gcrefRegs);
7373 emitDispRegSet(gcrefRegs);
7374 printf(", byrefRegs=");
7375 printRegMaskInt(byrefRegs);
7376 emitDispRegSet(byrefRegs);
7381 assert(argSize % REGSIZE_BYTES == 0);
7382 argCnt = (int)(argSize / (int)REGSIZE_BYTES);
7384 /* Managed RetVal: emit sequence point for the call */
7385 if (emitComp->opts.compDbgInfo && ilOffset != BAD_IL_OFFSET)
7387 codeGen->genIPmappingAdd(ilOffset, false);
7391 We need to allocate the appropriate instruction descriptor based
7392 on whether this is a direct/indirect call, and whether we need to
7393 record an updated set of live GC variables.
7396 if (callType >= EC_INDIR_R)
7398 /* Indirect call, virtual calls */
7400 assert(callType == EC_INDIR_R);
7402 id = emitNewInstrCallInd(argCnt, disp, ptrVars, gcrefRegs, byrefRegs, retSize, secondRetSize);
7406 /* Helper/static/nonvirtual/function calls (direct or through handle),
7407 and calls to an absolute addr. */
7409 assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
7411 id = emitNewInstrCallDir(argCnt, ptrVars, gcrefRegs, byrefRegs, retSize, secondRetSize);
7414 /* Update the emitter's live GC ref sets */
7416 VarSetOps::Assign(emitComp, emitThisGCrefVars, ptrVars);
7417 emitThisGCrefRegs = gcrefRegs;
7418 emitThisByrefRegs = byrefRegs;
7420 /* Set the instruction - special case jumping a function */
7422 insFormat fmt = IF_NONE;
7424 id->idSetIsNoGC(isNoGC);
7426 /* Record the address: method, indirection, or funcptr */
7428 if (callType > EC_FUNC_ADDR)
7430 /* This is an indirect call (either a virtual call or func ptr call) */
7434 case EC_INDIR_R: // the address is in a register
7436 id->idSetIsCallRegPtr();
7440 ins = INS_br_tail; // INS_br_tail Reg
7444 ins = INS_blr; // INS_blr Reg
7452 assert(xreg == REG_NA);
7456 NO_WAY("unexpected instruction");
7462 /* This is a simple direct call: "call helper/method/addr" */
7464 assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
7466 assert(addr != NULL);
7470 ins = INS_b_tail; // INS_b_tail imm28
7474 ins = INS_bl; // INS_bl imm28
7481 id->idAddr()->iiaAddr = (BYTE*)addr;
7483 if (callType == EC_FUNC_ADDR)
7485 id->idSetIsCallAddr();
7488 if (emitComp->opts.compReloc)
7490 id->idSetIsDspReloc();
7495 if (EMIT_GC_VERBOSE)
7497 if (id->idIsLargeCall())
7499 printf("[%02u] Rec call GC vars = %s\n", id->idDebugOnlyInfo()->idNum,
7500 VarSetOps::ToString(emitComp, ((instrDescCGCA*)id)->idcGCvars));
7504 id->idDebugOnlyInfo()->idMemCookie = (size_t)methHnd; // method token
7505 id->idDebugOnlyInfo()->idCallSig = sigInfo;
7509 if (addr != nullptr)
7511 codeGen->getDisAssembler().disSetMethod((size_t)addr, methHnd);
7513 #endif // LATE_DISASM
7519 /*****************************************************************************
7521 * Returns true if 'imm' is valid Cond encoding
7524 /*static*/ bool emitter::isValidImmCond(ssize_t imm)
7526 // range check the ssize_t value, to make sure it is a small unsigned value
7527 // and that only the bits in the cfi.cond are set
7528 if ((imm < 0) || (imm > 0xF))
7532 cfi.immCFVal = (unsigned)imm;
7534 return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7537 /*****************************************************************************
7539 * Returns true if 'imm' is valid Cond/Flags encoding
7542 /*static*/ bool emitter::isValidImmCondFlags(ssize_t imm)
7544 // range check the ssize_t value, to make sure it is a small unsigned value
7545 // and that only the bits in the cfi.cond or cfi.flags are set
7546 if ((imm < 0) || (imm > 0xFF))
7550 cfi.immCFVal = (unsigned)imm;
7552 return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7555 /*****************************************************************************
7557 * Returns true if 'imm' is valid Cond/Flags/Imm5 encoding
7560 /*static*/ bool emitter::isValidImmCondFlagsImm5(ssize_t imm)
7562 // range check the ssize_t value, to make sure it is a small unsigned value
7563 // and that only the bits in the cfi.cond, cfi.flags or cfi.imm5 are set
7564 if ((imm < 0) || (imm > 0x1FFF))
7568 cfi.immCFVal = (unsigned)imm;
7570 return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7573 /*****************************************************************************
7575 * Returns an encoding for the specified register used in the 'Rd' position
7578 /*static*/ emitter::code_t emitter::insEncodeReg_Rd(regNumber reg)
7580 assert(isIntegerRegister(reg));
7581 emitter::code_t ureg = (emitter::code_t)reg;
7582 assert((ureg >= 0) && (ureg <= 31));
7586 /*****************************************************************************
7588 * Returns an encoding for the specified register used in the 'Rt' position
7591 /*static*/ emitter::code_t emitter::insEncodeReg_Rt(regNumber reg)
7593 assert(isIntegerRegister(reg));
7594 emitter::code_t ureg = (emitter::code_t)reg;
7595 assert((ureg >= 0) && (ureg <= 31));
7599 /*****************************************************************************
7601 * Returns an encoding for the specified register used in the 'Rn' position
7604 /*static*/ emitter::code_t emitter::insEncodeReg_Rn(regNumber reg)
7606 assert(isIntegerRegister(reg));
7607 emitter::code_t ureg = (emitter::code_t)reg;
7608 assert((ureg >= 0) && (ureg <= 31));
7612 /*****************************************************************************
7614 * Returns an encoding for the specified register used in the 'Rm' position
7617 /*static*/ emitter::code_t emitter::insEncodeReg_Rm(regNumber reg)
7619 assert(isIntegerRegister(reg));
7620 emitter::code_t ureg = (emitter::code_t)reg;
7621 assert((ureg >= 0) && (ureg <= 31));
7625 /*****************************************************************************
7627 * Returns an encoding for the specified register used in the 'Ra' position
7630 /*static*/ emitter::code_t emitter::insEncodeReg_Ra(regNumber reg)
7632 assert(isIntegerRegister(reg));
7633 emitter::code_t ureg = (emitter::code_t)reg;
7634 assert((ureg >= 0) && (ureg <= 31));
7638 /*****************************************************************************
7640 * Returns an encoding for the specified register used in the 'Vd' position
7643 /*static*/ emitter::code_t emitter::insEncodeReg_Vd(regNumber reg)
7645 assert(emitter::isVectorRegister(reg));
7646 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7647 assert((ureg >= 0) && (ureg <= 31));
7651 /*****************************************************************************
7653 * Returns an encoding for the specified register used in the 'Vt' position
7656 /*static*/ emitter::code_t emitter::insEncodeReg_Vt(regNumber reg)
7658 assert(emitter::isVectorRegister(reg));
7659 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7660 assert((ureg >= 0) && (ureg <= 31));
7664 /*****************************************************************************
7666 * Returns an encoding for the specified register used in the 'Vn' position
7669 /*static*/ emitter::code_t emitter::insEncodeReg_Vn(regNumber reg)
7671 assert(emitter::isVectorRegister(reg));
7672 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7673 assert((ureg >= 0) && (ureg <= 31));
7677 /*****************************************************************************
7679 * Returns an encoding for the specified register used in the 'Vm' position
7682 /*static*/ emitter::code_t emitter::insEncodeReg_Vm(regNumber reg)
7684 assert(emitter::isVectorRegister(reg));
7685 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7686 assert((ureg >= 0) && (ureg <= 31));
7690 /*****************************************************************************
7692 * Returns an encoding for the specified register used in the 'Va' position
7695 /*static*/ emitter::code_t emitter::insEncodeReg_Va(regNumber reg)
7697 assert(emitter::isVectorRegister(reg));
7698 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7699 assert((ureg >= 0) && (ureg <= 31));
7703 /*****************************************************************************
7705 * Returns an encoding for the specified condition code.
7708 /*static*/ emitter::code_t emitter::insEncodeCond(insCond cond)
7710 emitter::code_t uimm = (emitter::code_t)cond;
7714 /*****************************************************************************
7716 * Returns an encoding for the condition code with the lowest bit inverted (marked by invert(<cond>) in the
7717 * architecture manual).
7720 /*static*/ emitter::code_t emitter::insEncodeInvertedCond(insCond cond)
7722 emitter::code_t uimm = (emitter::code_t)cond;
7723 uimm ^= 1; // invert the lowest bit
7727 /*****************************************************************************
7729 * Returns an encoding for the specified flags.
7732 /*static*/ emitter::code_t emitter::insEncodeFlags(insCflags flags)
7734 emitter::code_t uimm = (emitter::code_t)flags;
7738 /*****************************************************************************
7740 * Returns the encoding for the Shift Count bits to be used for Arm64 encodings
7743 /*static*/ emitter::code_t emitter::insEncodeShiftCount(ssize_t imm, emitAttr size)
7745 assert((imm & 0x003F) == imm);
7746 assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
7748 return (emitter::code_t)imm << 10;
7751 /*****************************************************************************
7753 * Returns the encoding to select a 64-bit datasize for an Arm64 instruction
7756 /*static*/ emitter::code_t emitter::insEncodeDatasize(emitAttr size)
7758 if (size == EA_8BYTE)
7760 return 0x80000000; // set the bit at location 31
7764 assert(size == EA_4BYTE);
7769 /*****************************************************************************
7771 * Returns the encoding to select the datasize for the general load/store Arm64 instructions
7775 /*static*/ emitter::code_t emitter::insEncodeDatasizeLS(emitter::code_t code, emitAttr size)
7777 bool exclusive = ((code & 0x35000000) == 0);
7779 if ((code & 0x00800000) && !exclusive) // Is this a sign-extending opcode? (i.e. ldrsw, ldrsh, ldrsb)
7781 if ((code & 0x80000000) == 0) // Is it a ldrsh or ldrsb and not ldrsw ?
7783 if (EA_SIZE(size) != EA_8BYTE) // Do we need to encode the 32-bit Rt size bit?
7785 return 0x00400000; // set the bit at location 22
7789 else if (code & 0x80000000) // Is this a ldr/str/ldur/stur opcode?
7791 if (EA_SIZE(size) == EA_8BYTE) // Do we need to encode the 64-bit size bit?
7793 return 0x40000000; // set the bit at location 30
7799 /*****************************************************************************
7801 * Returns the encoding to select the datasize for the vector load/store Arm64 instructions
7805 /*static*/ emitter::code_t emitter::insEncodeDatasizeVLS(emitter::code_t code, emitAttr size)
7810 if ((code & 0x20000000) == 0)
7814 if (size == EA_16BYTE)
7816 // set the operation size in bit 31
7817 result = 0x80000000;
7819 else if (size == EA_8BYTE)
7821 // set the operation size in bit 30
7822 result = 0x40000000;
7826 assert(size == EA_4BYTE);
7828 result = 0x00000000;
7835 if (size == EA_16BYTE)
7837 // The operation size in bits 31 and 30 are zero
7838 // Bit 23 specifies a 128-bit Load/Store
7839 result = 0x00800000;
7841 else if (size == EA_8BYTE)
7843 // set the operation size in bits 31 and 30
7844 result = 0xC0000000;
7846 else if (size == EA_4BYTE)
7848 // set the operation size in bit 31
7849 result = 0x80000000;
7851 else if (size == EA_2BYTE)
7853 // set the operation size in bit 30
7854 result = 0x40000000;
7858 assert(size == EA_1BYTE);
7859 // The operation size in bits 31 and 30 are zero
7860 result = 0x00000000;
7864 // Or in bit 26 to indicate a Vector register is used as 'target'
7865 result |= 0x04000000;
7870 /*****************************************************************************
7872 * Returns the encoding to select the datasize for the vector load/store Arm64 instructions
7876 /*static*/ emitter::code_t emitter::insEncodeDatasizeVPLS(emitter::code_t code, emitAttr size)
7880 if (size == EA_16BYTE)
7882 // The operation size in bits 31 and 30 are zero
7883 // Bit 23 specifies a 128-bit Load/Store
7884 result = 0x80000000;
7886 else if (size == EA_8BYTE)
7888 // set the operation size in bits 31 and 30
7889 result = 0x40000000;
7891 else if (size == EA_4BYTE)
7893 // set the operation size in bit 31
7894 result = 0x00000000;
7897 // Or in bit 26 to indicate a Vector register is used as 'target'
7898 result |= 0x04000000;
7903 /*****************************************************************************
7905 * Returns the encoding to set the size bit and the N bits for a 'bitfield' instruction
7909 /*static*/ emitter::code_t emitter::insEncodeDatasizeBF(emitter::code_t code, emitAttr size)
7911 // is bit 30 equal to 0?
7912 if ((code & 0x40000000) == 0) // is the opcode one of extr, sxtb, sxth or sxtw
7914 if (size == EA_8BYTE) // Do we need to set the sf and N bits?
7916 return 0x80400000; // set the sf-bit at location 31 and the N-bit at location 22
7919 return 0; // don't set any bits
7922 /*****************************************************************************
7924 * Returns the encoding to select the 64/128-bit datasize for an Arm64 vector instruction
7927 /*static*/ emitter::code_t emitter::insEncodeVectorsize(emitAttr size)
7929 if (size == EA_16BYTE)
7931 return 0x40000000; // set the bit at location 30
7935 assert(size == EA_8BYTE);
7940 /*****************************************************************************
7942 * Returns the encoding to select 'index' for an Arm64 vector elem instruction
7944 /*static*/ emitter::code_t emitter::insEncodeVectorIndex(emitAttr elemsize, ssize_t index)
7946 code_t bits = (code_t)index;
7947 if (elemsize == EA_1BYTE)
7952 else if (elemsize == EA_2BYTE)
7957 else if (elemsize == EA_4BYTE)
7964 assert(elemsize == EA_8BYTE);
7968 assert((bits >= 1) && (bits <= 0x1f));
7970 return (bits << 16); // bits at locations [20,19,18,17,16]
7973 /*****************************************************************************
7975 * Returns the encoding to select 'index2' for an Arm64 'ins' elem instruction
7977 /*static*/ emitter::code_t emitter::insEncodeVectorIndex2(emitAttr elemsize, ssize_t index2)
7979 code_t bits = (code_t)index2;
7980 if (elemsize == EA_1BYTE)
7984 else if (elemsize == EA_2BYTE)
7988 else if (elemsize == EA_4BYTE)
7994 assert(elemsize == EA_8BYTE);
7997 assert((bits >= 0) && (bits <= 0xf));
7999 return (bits << 11); // bits at locations [14,13,12,11]
8002 /*****************************************************************************
8004 * Returns the encoding to select the 'index' for an Arm64 'mul' by elem instruction
8006 /*static*/ emitter::code_t emitter::insEncodeVectorIndexLMH(emitAttr elemsize, ssize_t index)
8010 if (elemsize == EA_2BYTE)
8012 assert((index >= 0) && (index <= 7));
8015 bits |= (1 << 11); // set bit 11 'H'
8019 bits |= (1 << 21); // set bit 21 'L'
8023 bits |= (1 << 20); // set bit 20 'M'
8026 else if (elemsize == EA_4BYTE)
8028 assert((index >= 0) && (index <= 3));
8031 bits |= (1 << 11); // set bit 11 'H'
8035 bits |= (1 << 21); // set bit 21 'L'
8040 assert(!"Invalid 'elemsize' value");
8046 /*****************************************************************************
8048 * Returns the encoding to shift by 'shift' for an Arm64 vector or scalar instruction
8051 /*static*/ emitter::code_t emitter::insEncodeVectorShift(emitAttr size, ssize_t shift)
8053 assert(shift < getBitWidth(size));
8055 code_t imm = (code_t)(getBitWidth(size) + shift);
8060 /*****************************************************************************
8062 * Returns the encoding to select the 1/2/4/8 byte elemsize for an Arm64 vector instruction
8065 /*static*/ emitter::code_t emitter::insEncodeElemsize(emitAttr size)
8067 if (size == EA_8BYTE)
8069 return 0x00C00000; // set the bit at location 23 and 22
8071 else if (size == EA_4BYTE)
8073 return 0x00800000; // set the bit at location 23
8075 else if (size == EA_2BYTE)
8077 return 0x00400000; // set the bit at location 22
8079 assert(size == EA_1BYTE);
8083 /*****************************************************************************
8085 * Returns the encoding to select the 4/8 byte elemsize for an Arm64 float vector instruction
8088 /*static*/ emitter::code_t emitter::insEncodeFloatElemsize(emitAttr size)
8090 if (size == EA_8BYTE)
8092 return 0x00400000; // set the bit at location 22
8094 assert(size == EA_4BYTE);
8098 // Returns the encoding to select the index for an Arm64 float vector by elem instruction
8099 /*static*/ emitter::code_t emitter::insEncodeFloatIndex(emitAttr elemsize, ssize_t index)
8101 code_t result = 0x00000000;
8102 if (elemsize == EA_8BYTE)
8104 assert((index >= 0) && (index <= 1));
8107 result |= 0x00000800; // 'H' - set the bit at location 11
8112 assert(elemsize == EA_4BYTE);
8113 assert((index >= 0) && (index <= 3));
8116 result |= 0x00000800; // 'H' - set the bit at location 11
8120 result |= 0x00200000; // 'L' - set the bit at location 21
8126 /*****************************************************************************
8128 * Returns the encoding to select the fcvt operation for Arm64 instructions
8130 /*static*/ emitter::code_t emitter::insEncodeConvertOpt(insFormat fmt, insOpts conversion)
8135 case INS_OPTS_S_TO_D: // Single to Double
8136 assert(fmt == IF_DV_2J);
8137 result = 0x00008000; // type=00, opc=01
8140 case INS_OPTS_D_TO_S: // Double to Single
8141 assert(fmt == IF_DV_2J);
8142 result = 0x00400000; // type=01, opc=00
8145 case INS_OPTS_H_TO_S: // Half to Single
8146 assert(fmt == IF_DV_2J);
8147 result = 0x00C00000; // type=11, opc=00
8150 case INS_OPTS_H_TO_D: // Half to Double
8151 assert(fmt == IF_DV_2J);
8152 result = 0x00C08000; // type=11, opc=01
8155 case INS_OPTS_S_TO_H: // Single to Half
8156 assert(fmt == IF_DV_2J);
8157 result = 0x00018000; // type=00, opc=11
8160 case INS_OPTS_D_TO_H: // Double to Half
8161 assert(fmt == IF_DV_2J);
8162 result = 0x00418000; // type=01, opc=11
8165 case INS_OPTS_S_TO_4BYTE: // Single to INT32
8166 assert(fmt == IF_DV_2H);
8167 result = 0x00000000; // sf=0, type=00
8170 case INS_OPTS_D_TO_4BYTE: // Double to INT32
8171 assert(fmt == IF_DV_2H);
8172 result = 0x00400000; // sf=0, type=01
8175 case INS_OPTS_S_TO_8BYTE: // Single to INT64
8176 assert(fmt == IF_DV_2H);
8177 result = 0x80000000; // sf=1, type=00
8180 case INS_OPTS_D_TO_8BYTE: // Double to INT64
8181 assert(fmt == IF_DV_2H);
8182 result = 0x80400000; // sf=1, type=01
8185 case INS_OPTS_4BYTE_TO_S: // INT32 to Single
8186 assert(fmt == IF_DV_2I);
8187 result = 0x00000000; // sf=0, type=00
8190 case INS_OPTS_4BYTE_TO_D: // INT32 to Double
8191 assert(fmt == IF_DV_2I);
8192 result = 0x00400000; // sf=0, type=01
8195 case INS_OPTS_8BYTE_TO_S: // INT64 to Single
8196 assert(fmt == IF_DV_2I);
8197 result = 0x80000000; // sf=1, type=00
8200 case INS_OPTS_8BYTE_TO_D: // INT64 to Double
8201 assert(fmt == IF_DV_2I);
8202 result = 0x80400000; // sf=1, type=01
8206 assert(!"Invalid 'conversion' value");
8212 /*****************************************************************************
8214 * Returns the encoding to have the Rn register be updated Pre/Post indexed
8218 /*static*/ emitter::code_t emitter::insEncodeIndexedOpt(insOpts opt)
8220 assert(emitter::insOptsNone(opt) || emitter::insOptsIndexed(opt));
8222 if (emitter::insOptsIndexed(opt))
8224 if (emitter::insOptsPostIndex(opt))
8226 return 0x00000400; // set the bit at location 10
8230 assert(emitter::insOptsPreIndex(opt));
8231 return 0x00000C00; // set the bit at location 10 and 11
8236 assert(emitter::insOptsNone(opt));
8237 return 0; // bits 10 and 11 are zero
8241 /*****************************************************************************
8243 * Returns the encoding for a ldp/stp instruction to have the Rn register
8244 * be updated Pre/Post indexed or not updated
8247 /*static*/ emitter::code_t emitter::insEncodePairIndexedOpt(instruction ins, insOpts opt)
8249 assert(emitter::insOptsNone(opt) || emitter::insOptsIndexed(opt));
8251 if ((ins == INS_ldnp) || (ins == INS_stnp))
8253 assert(emitter::insOptsNone(opt));
8254 return 0; // bits 23 and 24 are zero
8258 if (emitter::insOptsIndexed(opt))
8260 if (emitter::insOptsPostIndex(opt))
8262 return 0x00800000; // set the bit at location 23
8266 assert(emitter::insOptsPreIndex(opt));
8267 return 0x01800000; // set the bit at location 24 and 23
8272 assert(emitter::insOptsNone(opt));
8273 return 0x01000000; // set the bit at location 24
8278 /*****************************************************************************
8280 * Returns the encoding to apply a Shift Type on the Rm register
8283 /*static*/ emitter::code_t emitter::insEncodeShiftType(insOpts opt)
8285 if (emitter::insOptsNone(opt))
8287 // None implies the we encode LSL (with a zero immediate)
8290 assert(emitter::insOptsAnyShift(opt));
8292 emitter::code_t option = (emitter::code_t)opt - (emitter::code_t)INS_OPTS_LSL;
8293 assert(option <= 3);
8295 return option << 22; // bits 23, 22
8298 /*****************************************************************************
8300 * Returns the encoding to apply a 12 bit left shift to the immediate
8303 /*static*/ emitter::code_t emitter::insEncodeShiftImm12(insOpts opt)
8305 if (emitter::insOptsLSL12(opt))
8307 return 0x00400000; // set the bit at location 22
8312 /*****************************************************************************
8314 * Returns the encoding to have the Rm register use an extend operation
8317 /*static*/ emitter::code_t emitter::insEncodeExtend(insOpts opt)
8319 if (emitter::insOptsNone(opt) || (opt == INS_OPTS_LSL))
8321 // None or LSL implies the we encode UXTX
8322 opt = INS_OPTS_UXTX;
8324 assert(emitter::insOptsAnyExtend(opt));
8326 emitter::code_t option = (emitter::code_t)opt - (emitter::code_t)INS_OPTS_UXTB;
8327 assert(option <= 7);
8329 return option << 13; // bits 15,14,13
8332 /*****************************************************************************
8334 * Returns the encoding to scale the Rm register by {0,1,2,3,4}
8335 * when using an extend operation
8338 /*static*/ emitter::code_t emitter::insEncodeExtendScale(ssize_t imm)
8340 assert((imm >= 0) && (imm <= 4));
8342 return (emitter::code_t)imm << 10; // bits 12,11,10
8345 /*****************************************************************************
8347 * Returns the encoding to have the Rm register be auto scaled by the ld/st size
8350 /*static*/ emitter::code_t emitter::insEncodeReg3Scale(bool isScaled)
8354 return 0x00001000; // set the bit at location 12
8362 BYTE* emitter::emitOutputLoadLabel(BYTE* dst, BYTE* srcAddr, BYTE* dstAddr, instrDescJmp* id)
8364 instruction ins = id->idIns();
8365 insFormat fmt = id->idInsFmt();
8366 regNumber dstReg = id->idReg1();
8369 // adr x, [rel addr] -- compute address: current addr(ip) + rel addr.
8370 assert(ins == INS_adr);
8371 assert(fmt == IF_DI_1E);
8372 ssize_t distVal = (ssize_t)(dstAddr - srcAddr);
8373 dst = emitOutputShortAddress(dst, ins, fmt, distVal, dstReg);
8377 // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8378 assert(fmt == IF_LARGEADR);
8379 ssize_t relPageAddr =
8380 (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8381 dst = emitOutputShortAddress(dst, INS_adrp, IF_DI_1E, relPageAddr, dstReg);
8383 // add x, x, page offs -- compute address = page addr + page offs
8384 ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8385 assert(isValidUimm12(imm12));
8387 emitInsCode(INS_add, IF_DI_2A); // DI_2A X0010001shiiiiii iiiiiinnnnnddddd 1100 0000 imm(i12, sh)
8388 code |= insEncodeDatasize(EA_8BYTE); // X
8389 code |= ((code_t)imm12 << 10); // iiiiiiiiiiii
8390 code |= insEncodeReg_Rd(dstReg); // ddddd
8391 code |= insEncodeReg_Rn(dstReg); // nnnnn
8392 dst += emitOutput_Instr(dst, code);
8397 /*****************************************************************************
8399 * Output a local jump or other instruction with a pc-relative immediate.
8400 * Note that this may be invoked to overwrite an existing jump instruction at 'dst'
8401 * to handle forward branch patching.
8404 BYTE* emitter::emitOutputLJ(insGroup* ig, BYTE* dst, instrDesc* i)
8406 instrDescJmp* id = (instrDescJmp*)i;
8415 // Set default ins/fmt from id.
8416 instruction ins = id->idIns();
8417 insFormat fmt = id->idInsFmt();
8419 bool loadLabel = false;
8420 bool isJump = false;
8421 bool loadConstant = false;
8438 loadConstant = true;
8447 /* Figure out the distance to the target */
8449 srcOffs = emitCurCodeOffs(dst);
8450 srcAddr = emitOffsetToPtr(srcOffs);
8452 if (id->idAddr()->iiaIsJitDataOffset())
8454 assert(loadConstant || loadLabel);
8455 int doff = id->idAddr()->iiaGetJitDataOffset();
8457 ssize_t imm = emitGetInsSC(id);
8458 assert((imm >= 0) && (imm < 0x1000)); // 0x1000 is arbitrary, currently 'imm' is always 0
8460 unsigned dataOffs = (unsigned)(doff + imm);
8461 assert(dataOffs < emitDataSize());
8462 dstAddr = emitDataOffsetToPtr(dataOffs);
8464 regNumber dstReg = id->idReg1();
8465 regNumber addrReg = dstReg; // an integer register to compute long address.
8466 emitAttr opSize = id->idOpSize();
8472 // ldr x/v, [rel addr] -- load constant from current addr(ip) + rel addr.
8473 assert(ins == INS_ldr);
8474 assert(fmt == IF_LS_1A);
8475 distVal = (ssize_t)(dstAddr - srcAddr);
8476 dst = emitOutputShortConstant(dst, ins, fmt, distVal, dstReg, opSize);
8480 // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8481 assert(fmt == IF_LARGELDC);
8482 ssize_t relPageAddr =
8483 (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8484 if (isVectorRegister(dstReg))
8486 // Update addrReg with the reserved integer register
8487 // since we cannot use dstReg (vector) to load constant directly from memory.
8488 addrReg = id->idReg2();
8489 assert(isGeneralRegister(addrReg));
8493 dst = emitOutputShortAddress(dst, ins, fmt, relPageAddr, addrReg);
8495 // ldr x, [x, page offs] -- load constant from page address + page offset into integer register.
8496 ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8497 assert(isValidUimm12(imm12));
8500 dst = emitOutputShortConstant(dst, ins, fmt, imm12, addrReg, opSize);
8502 // fmov v, d -- copy constant in integer register to vector register.
8503 // This is needed only for vector constant.
8504 if (addrReg != dstReg)
8506 // fmov Vd,Rn DV_2I X00111100X100111 000000nnnnnddddd 1E27 0000 Vd,Rn
8507 // (scalar, from general)
8508 assert(isVectorRegister(dstReg) && isGeneralRegister(addrReg));
8511 code_t code = emitInsCode(ins, fmt);
8513 code |= insEncodeReg_Vd(dstReg); // ddddd
8514 code |= insEncodeReg_Rn(addrReg); // nnnnn
8515 if (id->idOpSize() == EA_8BYTE)
8517 code |= 0x80400000; // X ... X
8519 dst += emitOutput_Instr(dst, code);
8526 dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8532 assert(loadLabel || isJump);
8534 if (id->idAddr()->iiaHasInstrCount())
8537 int instrCount = id->idAddr()->iiaGetInstrCount();
8538 unsigned insNum = emitFindInsNum(ig, id);
8541 // Backward branches using instruction count must be within the same instruction group.
8542 assert(insNum + 1 >= (unsigned)(-instrCount));
8544 dstOffs = ig->igOffs + emitFindOffset(ig, (insNum + 1 + instrCount));
8545 dstAddr = emitOffsetToPtr(dstOffs);
8549 dstOffs = id->idAddr()->iiaIGlabel->igOffs;
8550 dstAddr = emitOffsetToPtr(dstOffs);
8553 distVal = (ssize_t)(dstAddr - srcAddr);
8555 if (dstOffs <= srcOffs)
8558 /* This is a backward jump - distance is known at this point */
8560 if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8562 size_t blkOffs = id->idjIG->igOffs;
8564 if (INTERESTING_JUMP_NUM == 0)
8565 printf("[3] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8566 printf("[3] Jump block is at %08X - %02X = %08X\n", blkOffs, emitOffsAdj, blkOffs - emitOffsAdj);
8567 printf("[3] Jump is at %08X - %02X = %08X\n", srcOffs, emitOffsAdj, srcOffs - emitOffsAdj);
8568 printf("[3] Label block is at %08X - %02X = %08X\n", dstOffs, emitOffsAdj, dstOffs - emitOffsAdj);
8574 /* This is a forward jump - distance will be an upper limit */
8576 emitFwdJumps = true;
8578 /* The target offset will be closer by at least 'emitOffsAdj', but only if this
8579 jump doesn't cross the hot-cold boundary. */
8581 if (!emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8583 dstOffs -= emitOffsAdj;
8584 distVal -= emitOffsAdj;
8587 /* Record the location of the jump for later patching */
8589 id->idjOffs = dstOffs;
8591 /* Are we overflowing the id->idjOffs bitfield? */
8592 if (id->idjOffs != dstOffs)
8593 IMPL_LIMITATION("Method is too large");
8596 if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8598 size_t blkOffs = id->idjIG->igOffs;
8600 if (INTERESTING_JUMP_NUM == 0)
8601 printf("[4] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8602 printf("[4] Jump block is at %08X\n", blkOffs);
8603 printf("[4] Jump is at %08X\n", srcOffs);
8604 printf("[4] Label block is at %08X - %02X = %08X\n", dstOffs + emitOffsAdj, emitOffsAdj, dstOffs);
8610 if (0 && emitComp->verbose)
8613 int distValSize = id->idjShort ? 4 : 8;
8614 printf("; %s jump [%08X/%03u] from %0*X to %0*X: dist = %08XH\n", (dstOffs <= srcOffs) ? "Fwd" : "Bwd",
8615 dspPtr(id), id->idDebugOnlyInfo()->idNum, distValSize, srcOffs + sz, distValSize, dstOffs, distVal);
8619 /* For forward jumps, record the address of the distance value */
8620 id->idjTemp.idjAddr = (distVal > 0) ? dst : NULL;
8622 if (emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8624 assert(!id->idjShort);
8625 NYI_ARM64("Relocation Support for long address");
8628 assert(insOptsNone(id->idInsOpt()));
8634 // Short conditional/unconditional jump
8635 assert(!id->idjKeepLong);
8636 assert(emitJumpCrossHotColdBoundary(srcOffs, dstOffs) == false);
8637 assert((fmt == IF_BI_0A) || (fmt == IF_BI_0B) || (fmt == IF_BI_1A) || (fmt == IF_BI_1B));
8641 // Long conditional jump
8642 assert(fmt == IF_LARGEJMP);
8643 // This is a pseudo-instruction format representing a large conditional branch, to allow
8644 // us to get a greater branch target range than we can get by using a straightforward conditional
8645 // branch. It is encoded as a short conditional branch that branches around a long unconditional
8648 // Conceptually, we have:
8652 // The code we emit is:
8654 // b<!cond> L_not // 4 bytes. Note that we reverse the condition.
8655 // b L_target // 4 bytes
8658 // Note that we don't actually insert any blocks: we simply encode "b <!cond> L_not" as a branch with
8659 // the correct offset. Note also that this works for both integer and floating-point conditions, because
8660 // the condition inversion takes ordered/unordered into account, preserving NaN behavior. For example,
8661 // "GT" (greater than) is inverted to "LE" (less than, equal, or unordered).
8663 instruction reverseIns;
8664 insFormat reverseFmt;
8669 reverseIns = INS_cbnz;
8670 reverseFmt = IF_BI_1A;
8673 reverseIns = INS_cbz;
8674 reverseFmt = IF_BI_1A;
8677 reverseIns = INS_tbnz;
8678 reverseFmt = IF_BI_1B;
8681 reverseIns = INS_tbz;
8682 reverseFmt = IF_BI_1B;
8685 reverseIns = emitJumpKindToIns(emitReverseJumpKind(emitInsToJumpKind(ins)));
8686 reverseFmt = IF_BI_0B;
8690 emitOutputShortBranch(dst,
8691 reverseIns, // reverse the conditional instruction
8693 8, /* 8 bytes from start of this large conditional pseudo-instruction to L_not. */
8696 // Now, pretend we've got a normal unconditional branch, and fall through to the code to emit that.
8700 // The distVal was computed based on the beginning of the pseudo-instruction,
8701 // So subtract the size of the conditional branch so that it is relative to the
8702 // unconditional branch.
8706 dst = emitOutputShortBranch(dst, ins, fmt, distVal, id);
8710 dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8716 /*****************************************************************************
8718 * Output a short branch instruction.
8720 BYTE* emitter::emitOutputShortBranch(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, instrDescJmp* id)
8722 code_t code = emitInsCode(ins, fmt);
8724 ssize_t loBits = (distVal & 3);
8725 noway_assert(loBits == 0);
8726 distVal >>= 2; // branch offset encodings are scaled by 4.
8728 if (fmt == IF_BI_0A)
8730 // INS_b or INS_bl_local
8731 noway_assert(isValidSimm26(distVal));
8732 distVal &= 0x3FFFFFFLL;
8735 else if (fmt == IF_BI_0B) // BI_0B 01010100iiiiiiii iiiiiiiiiiiXXXXX simm19:00
8737 // INS_beq, INS_bne, etc...
8738 noway_assert(isValidSimm19(distVal));
8739 distVal &= 0x7FFFFLL;
8740 code |= distVal << 5;
8742 else if (fmt == IF_BI_1A) // BI_1A X.......iiiiiiii iiiiiiiiiiittttt Rt simm19:00
8744 // INS_cbz or INS_cbnz
8745 assert(id != nullptr);
8746 code |= insEncodeDatasize(id->idOpSize()); // X
8747 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
8749 noway_assert(isValidSimm19(distVal));
8750 distVal &= 0x7FFFFLL; // 19 bits
8751 code |= distVal << 5;
8753 else if (fmt == IF_BI_1B) // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
8755 // INS_tbz or INS_tbnz
8756 assert(id != nullptr);
8757 ssize_t imm = emitGetInsSC(id);
8758 assert(isValidImmShift(imm, id->idOpSize()));
8760 if (imm & 0x20) // test bit 32-63 ?
8762 code |= 0x80000000; // B
8764 code |= ((imm & 0x1F) << 19); // bbbbb
8765 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
8767 noway_assert(isValidSimm14(distVal));
8768 distVal &= 0x3FFFLL; // 14 bits
8769 code |= distVal << 5;
8773 assert(!"Unknown fmt for emitOutputShortBranch");
8776 dst += emitOutput_Instr(dst, code);
8781 /*****************************************************************************
8783 * Output a short address instruction.
8785 BYTE* emitter::emitOutputShortAddress(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, regNumber reg)
8787 ssize_t loBits = (distVal & 3);
8790 code_t code = emitInsCode(ins, fmt);
8791 if (fmt == IF_DI_1E) // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
8793 // INS_adr or INS_adrp
8794 code |= insEncodeReg_Rd(reg); // ddddd
8796 noway_assert(isValidSimm19(distVal));
8797 distVal &= 0x7FFFFLL; // 19 bits
8798 code |= distVal << 5;
8799 code |= loBits << 29; // 2 bits
8803 assert(!"Unknown fmt for emitOutputShortAddress");
8806 dst += emitOutput_Instr(dst, code);
8811 /*****************************************************************************
8813 * Output a short constant instruction.
8815 BYTE* emitter::emitOutputShortConstant(
8816 BYTE* dst, instruction ins, insFormat fmt, ssize_t imm, regNumber reg, emitAttr opSize)
8818 code_t code = emitInsCode(ins, fmt);
8820 if (fmt == IF_LS_1A)
8822 // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt simm21
8823 // INS_ldr or INS_ldrsw (PC-Relative)
8825 ssize_t loBits = (imm & 3);
8826 noway_assert(loBits == 0);
8827 ssize_t distVal = imm >>= 2; // load offset encodings are scaled by 4.
8829 noway_assert(isValidSimm19(distVal));
8831 // Is the target a vector register?
8832 if (isVectorRegister(reg))
8834 code |= insEncodeDatasizeVLS(code, opSize); // XX V
8835 code |= insEncodeReg_Vt(reg); // ttttt
8839 assert(isGeneralRegister(reg));
8840 // insEncodeDatasizeLS is not quite right for this case.
8841 // So just specialize it.
8842 if ((ins == INS_ldr) && (opSize == EA_8BYTE))
8844 // set the operation size in bit 30
8848 code |= insEncodeReg_Rt(reg); // ttttt
8851 distVal &= 0x7FFFFLL; // 19 bits
8852 code |= distVal << 5;
8854 else if (fmt == IF_LS_2B)
8856 // ldr Rt,[Xn+pimm12] LS_2B 1X11100101iiiiii iiiiiinnnnnttttt B940 0000 imm(0-4095<<{2,3})
8857 // INS_ldr or INS_ldrsw (PC-Relative)
8858 noway_assert(isValidUimm12(imm));
8859 assert(isGeneralRegister(reg));
8861 if (opSize == EA_8BYTE)
8863 // insEncodeDatasizeLS is not quite right for this case.
8864 // So just specialize it.
8867 // set the operation size in bit 30
8870 // Low 3 bits should be 0 -- 8 byte JIT data should be aligned on 8 byte.
8871 assert((imm & 7) == 0);
8876 assert(opSize == EA_4BYTE);
8877 // Low 2 bits should be 0 -- 4 byte aligned data.
8878 assert((imm & 3) == 0);
8882 code |= insEncodeReg_Rt(reg); // ttttt
8883 code |= insEncodeReg_Rn(reg); // nnnnn
8888 assert(!"Unknown fmt for emitOutputShortConstant");
8891 dst += emitOutput_Instr(dst, code);
8895 /*****************************************************************************
8897 * Output a call instruction.
8900 unsigned emitter::emitOutputCall(insGroup* ig, BYTE* dst, instrDesc* id, code_t code)
8902 const unsigned char callInstrSize = sizeof(code_t); // 4 bytes
8903 regMaskTP gcrefRegs;
8904 regMaskTP byrefRegs;
8906 VARSET_TP GCvars(VarSetOps::UninitVal());
8908 // Is this a "fat" call descriptor?
8909 if (id->idIsLargeCall())
8911 instrDescCGCA* idCall = (instrDescCGCA*)id;
8912 gcrefRegs = idCall->idcGcrefRegs;
8913 byrefRegs = idCall->idcByrefRegs;
8914 VarSetOps::Assign(emitComp, GCvars, idCall->idcGCvars);
8918 assert(!id->idIsLargeDsp());
8919 assert(!id->idIsLargeCns());
8921 gcrefRegs = emitDecodeCallGCregs(id);
8923 VarSetOps::AssignNoCopy(emitComp, GCvars, VarSetOps::MakeEmpty(emitComp));
8926 /* We update the GC info before the call as the variables cannot be
8927 used by the call. Killing variables before the call helps with
8928 boundary conditions if the call is CORINFO_HELP_THROW - see bug 50029.
8929 If we ever track aliased variables (which could be used by the
8930 call), we would have to keep them alive past the call. */
8932 emitUpdateLiveGCvars(GCvars, dst);
8934 // Now output the call instruction and update the 'dst' pointer
8936 unsigned outputInstrSize = emitOutput_Instr(dst, code);
8937 dst += outputInstrSize;
8939 // All call instructions are 4-byte in size on ARM64
8941 assert(outputInstrSize == callInstrSize);
8943 // If the method returns a GC ref, mark INTRET (R0) appropriately.
8944 if (id->idGCref() == GCT_GCREF)
8946 gcrefRegs |= RBM_INTRET;
8948 else if (id->idGCref() == GCT_BYREF)
8950 byrefRegs |= RBM_INTRET;
8953 // If is a multi-register return method is called, mark INTRET_1 (X1) appropriately
8954 if (id->idIsLargeCall())
8956 instrDescCGCA* idCall = (instrDescCGCA*)id;
8957 if (idCall->idSecondGCref() == GCT_GCREF)
8959 gcrefRegs |= RBM_INTRET_1;
8961 else if (idCall->idSecondGCref() == GCT_BYREF)
8963 byrefRegs |= RBM_INTRET_1;
8967 // If the GC register set has changed, report the new set.
8968 if (gcrefRegs != emitThisGCrefRegs)
8970 emitUpdateLiveGCregs(GCT_GCREF, gcrefRegs, dst);
8972 // If the Byref register set has changed, report the new set.
8973 if (byrefRegs != emitThisByrefRegs)
8975 emitUpdateLiveGCregs(GCT_BYREF, byrefRegs, dst);
8978 // Some helper calls may be marked as not requiring GC info to be recorded.
8979 if ((!id->idIsNoGC()))
8981 // On ARM64, as on AMD64, we don't change the stack pointer to push/pop args.
8982 // So we're not really doing a "stack pop" here (note that "args" is 0), but we use this mechanism
8983 // to record the call for GC info purposes. (It might be best to use an alternate call,
8984 // and protect "emitStackPop" under the EMIT_TRACK_STACK_DEPTH preprocessor variable.)
8985 emitStackPop(dst, /*isCall*/ true, callInstrSize, /*args*/ 0);
8987 // Do we need to record a call location for GC purposes?
8989 if (!emitFullGCinfo)
8991 emitRecordGCcall(dst, callInstrSize);
8994 return callInstrSize;
8997 /*****************************************************************************
8999 * Emit a 32-bit Arm64 instruction
9002 /*static*/ unsigned emitter::emitOutput_Instr(BYTE* dst, code_t code)
9004 assert(sizeof(code_t) == 4);
9005 *((code_t*)dst) = code;
9007 return sizeof(code_t);
9010 /*****************************************************************************
9012 * Append the machine code corresponding to the given instruction descriptor
9013 * to the code block at '*dp'; the base of the code block is 'bp', and 'ig'
9014 * is the instruction group that contains the instruction. Updates '*dp' to
9015 * point past the generated code, and returns the size of the instruction
9016 * descriptor in bytes.
9019 size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
9024 size_t sz = emitGetInstrDescSize(id); // TODO-ARM64-Cleanup: on ARM, this is set in each case. why?
9025 instruction ins = id->idIns();
9026 insFormat fmt = id->idInsFmt();
9027 emitAttr size = id->idOpSize();
9028 unsigned char callInstrSize = 0;
9033 bool dspOffs = emitComp->opts.dspGCtbls;
9035 bool dspOffs = !emitComp->opts.disDiffable;
9039 assert(REG_NA == (int)REG_NA);
9041 VARSET_TP GCvars(VarSetOps::UninitVal());
9043 /* What instruction format have we got? */
9058 case IF_BI_0A: // BI_0A ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
9059 case IF_BI_0B: // BI_0B ......iiiiiiiiii iiiiiiiiiii..... simm19:00
9061 assert(id->idGCref() == GCT_NONE);
9062 assert(id->idIsBound());
9063 dst = emitOutputLJ(ig, dst, id);
9064 sz = sizeof(instrDescJmp);
9067 case IF_BI_0C: // BI_0C ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
9068 code = emitInsCode(ins, fmt);
9069 sz = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
9070 dst += emitOutputCall(ig, dst, id, code);
9071 // Always call RecordRelocation so that we wire in a JumpStub when we don't reach
9072 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_BRANCH26);
9075 case IF_BI_1A: // BI_1A ......iiiiiiiiii iiiiiiiiiiittttt Rt simm19:00
9076 assert(insOptsNone(id->idInsOpt()));
9077 assert(id->idIsBound());
9079 dst = emitOutputLJ(ig, dst, id);
9080 sz = sizeof(instrDescJmp);
9083 case IF_BI_1B: // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
9084 assert(insOptsNone(id->idInsOpt()));
9085 assert(id->idIsBound());
9087 dst = emitOutputLJ(ig, dst, id);
9088 sz = sizeof(instrDescJmp);
9091 case IF_BR_1A: // BR_1A ................ ......nnnnn..... Rn
9092 assert(insOptsNone(id->idInsOpt()));
9093 assert((ins == INS_ret) || (ins == INS_br));
9094 code = emitInsCode(ins, fmt);
9095 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9097 dst += emitOutput_Instr(dst, code);
9100 case IF_BR_1B: // BR_1B ................ ......nnnnn..... Rn
9101 assert(insOptsNone(id->idInsOpt()));
9102 assert((ins == INS_br_tail) || (ins == INS_blr));
9103 code = emitInsCode(ins, fmt);
9104 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9106 sz = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
9107 dst += emitOutputCall(ig, dst, id, code);
9110 case IF_LS_1A: // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB)
9112 assert(insOptsNone(id->idInsOpt()));
9113 assert(id->idIsBound());
9115 dst = emitOutputLJ(ig, dst, id);
9116 sz = sizeof(instrDescJmp);
9119 case IF_LS_2A: // LS_2A .X.......X...... ......nnnnnttttt Rt Rn
9120 assert(insOptsNone(id->idInsOpt()));
9121 code = emitInsCode(ins, fmt);
9122 // Is the target a vector register?
9123 if (isVectorRegister(id->idReg1()))
9125 code &= 0x3FFFFFFF; // clear the size bits
9126 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9127 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9131 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9132 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9134 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9135 dst += emitOutput_Instr(dst, code);
9138 case IF_LS_2B: // LS_2B .X.......Xiiiiii iiiiiinnnnnttttt Rt Rn imm(0-4095)
9139 assert(insOptsNone(id->idInsOpt()));
9140 imm = emitGetInsSC(id);
9141 assert(isValidUimm12(imm));
9142 code = emitInsCode(ins, fmt);
9143 // Is the target a vector register?
9144 if (isVectorRegister(id->idReg1()))
9146 code &= 0x3FFFFFFF; // clear the size bits
9147 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9148 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9152 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9153 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9155 code |= ((code_t)imm << 10); // iiiiiiiiiiii
9156 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9157 dst += emitOutput_Instr(dst, code);
9160 case IF_LS_2C: // LS_2C .X.......X.iiiii iiiiPPnnnnnttttt Rt Rn imm(-256..+255) no/pre/post inc
9161 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9162 imm = emitGetInsSC(id);
9163 assert((imm >= -256) && (imm <= 255)); // signed 9 bits
9164 imm &= 0x1ff; // force into unsigned 9 bit representation
9165 code = emitInsCode(ins, fmt);
9166 // Is the target a vector register?
9167 if (isVectorRegister(id->idReg1()))
9169 code &= 0x3FFFFFFF; // clear the size bits
9170 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9171 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9175 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9176 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9178 code |= insEncodeIndexedOpt(id->idInsOpt()); // PP
9179 code |= ((code_t)imm << 12); // iiiiiiiii
9180 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9181 dst += emitOutput_Instr(dst, code);
9184 case IF_LS_3A: // LS_3A .X.......X.mmmmm oooS..nnnnnttttt Rt Rn Rm ext(Rm) LSL {}
9185 assert(insOptsLSExtend(id->idInsOpt()));
9186 code = emitInsCode(ins, fmt);
9187 // Is the target a vector register?
9188 if (isVectorRegister(id->idReg1()))
9190 code &= 0x3FFFFFFF; // clear the size bits
9191 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9192 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9196 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9197 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9199 code |= insEncodeExtend(id->idInsOpt()); // ooo
9200 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9201 if (id->idIsLclVar())
9203 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9207 code |= insEncodeReg3Scale(id->idReg3Scaled()); // S
9208 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9210 dst += emitOutput_Instr(dst, code);
9213 case IF_LS_3B: // LS_3B X............... .aaaaannnnnddddd Rd Ra Rn
9214 assert(insOptsNone(id->idInsOpt()));
9215 code = emitInsCode(ins, fmt);
9216 // Is the target a vector register?
9217 if (isVectorRegister(id->idReg1()))
9219 code &= 0x3FFFFFFF; // clear the size bits
9220 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9221 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9222 code |= insEncodeReg_Va(id->idReg2()); // aaaaa
9226 code |= insEncodeDatasize(id->idOpSize()); // X
9227 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9228 code |= insEncodeReg_Ra(id->idReg2()); // aaaaa
9230 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9231 dst += emitOutput_Instr(dst, code);
9234 case IF_LS_3C: // LS_3C X......PP.iiiiii iaaaaannnnnddddd Rd Ra Rn imm(im7,sh)
9235 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9236 imm = emitGetInsSC(id);
9237 assert((imm >= -64) && (imm <= 63)); // signed 7 bits
9238 imm &= 0x7f; // force into unsigned 7 bit representation
9239 code = emitInsCode(ins, fmt);
9240 // Is the target a vector register?
9241 if (isVectorRegister(id->idReg1()))
9243 code &= 0x3FFFFFFF; // clear the size bits
9244 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9245 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9246 code |= insEncodeReg_Va(id->idReg2()); // aaaaa
9250 code |= insEncodeDatasize(id->idOpSize()); // X
9251 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9252 code |= insEncodeReg_Ra(id->idReg2()); // aaaaa
9254 code |= insEncodePairIndexedOpt(ins, id->idInsOpt()); // PP
9255 code |= ((code_t)imm << 15); // iiiiiiiii
9256 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9257 dst += emitOutput_Instr(dst, code);
9260 case IF_LS_3D: // LS_3D .X.......X.mmmmm ......nnnnnttttt Wm Rt Rn
9261 code = emitInsCode(ins, fmt);
9262 // Arm64 store exclusive unpredictable cases
9263 assert(id->idReg1() != id->idReg2());
9264 assert(id->idReg1() != id->idReg3());
9265 code |= insEncodeDatasizeLS(code, id->idOpSize()); // X
9266 code |= insEncodeReg_Rm(id->idReg1()); // mmmmm
9267 code |= insEncodeReg_Rt(id->idReg2()); // ttttt
9268 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9269 dst += emitOutput_Instr(dst, code);
9272 case IF_DI_1A: // DI_1A X.......shiiiiii iiiiiinnnnn..... Rn imm(i12,sh)
9273 assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9274 imm = emitGetInsSC(id);
9275 assert(isValidUimm12(imm));
9276 code = emitInsCode(ins, fmt);
9277 code |= insEncodeDatasize(id->idOpSize()); // X
9278 code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9279 code |= ((code_t)imm << 10); // iiiiiiiiiiii
9280 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9281 dst += emitOutput_Instr(dst, code);
9284 case IF_DI_1B: // DI_1B X........hwiiiii iiiiiiiiiiiddddd Rd imm(i16,hw)
9285 imm = emitGetInsSC(id);
9286 assert(isValidImmHWVal(imm, id->idOpSize()));
9287 code = emitInsCode(ins, fmt);
9288 code |= insEncodeDatasize(id->idOpSize()); // X
9289 code |= ((code_t)imm << 5); // hwiiiii iiiiiiiiiii
9290 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9291 dst += emitOutput_Instr(dst, code);
9294 case IF_DI_1C: // DI_1C X........Nrrrrrr ssssssnnnnn..... Rn imm(N,r,s)
9295 imm = emitGetInsSC(id);
9296 assert(isValidImmNRS(imm, id->idOpSize()));
9297 code = emitInsCode(ins, fmt);
9298 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9299 code |= insEncodeDatasize(id->idOpSize()); // X
9300 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9301 dst += emitOutput_Instr(dst, code);
9304 case IF_DI_1D: // DI_1D X........Nrrrrrr ssssss.....ddddd Rd imm(N,r,s)
9305 imm = emitGetInsSC(id);
9306 assert(isValidImmNRS(imm, id->idOpSize()));
9307 code = emitInsCode(ins, fmt);
9308 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9309 code |= insEncodeDatasize(id->idOpSize()); // X
9310 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9311 dst += emitOutput_Instr(dst, code);
9314 case IF_DI_1E: // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
9316 assert(insOptsNone(id->idInsOpt()));
9317 if (id->idIsReloc())
9319 code = emitInsCode(ins, fmt);
9320 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9321 dst += emitOutput_Instr(dst, code);
9322 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEBASE_REL21);
9326 // Local jmp/load case which does not need a relocation.
9327 assert(id->idIsBound());
9328 dst = emitOutputLJ(ig, dst, id);
9330 sz = sizeof(instrDescJmp);
9333 case IF_DI_1F: // DI_1F X..........iiiii cccc..nnnnn.nzcv Rn imm5 nzcv cond
9334 imm = emitGetInsSC(id);
9335 assert(isValidImmCondFlagsImm5(imm));
9338 cfi.immCFVal = (unsigned)imm;
9339 code = emitInsCode(ins, fmt);
9340 code |= insEncodeDatasize(id->idOpSize()); // X
9341 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9342 code |= ((code_t)cfi.imm5 << 16); // iiiii
9343 code |= insEncodeFlags(cfi.flags); // nzcv
9344 code |= insEncodeCond(cfi.cond); // cccc
9345 dst += emitOutput_Instr(dst, code);
9349 case IF_DI_2A: // DI_2A X.......shiiiiii iiiiiinnnnnddddd Rd Rn imm(i12,sh)
9350 assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9351 imm = emitGetInsSC(id);
9352 assert(isValidUimm12(imm));
9353 code = emitInsCode(ins, fmt);
9354 code |= insEncodeDatasize(id->idOpSize()); // X
9355 code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9356 code |= ((code_t)imm << 10); // iiiiiiiiiiii
9357 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9358 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9359 dst += emitOutput_Instr(dst, code);
9361 if (id->idIsReloc())
9363 assert(sz == sizeof(instrDesc));
9364 assert(id->idAddr()->iiaAddr != nullptr);
9365 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEOFFSET_12A);
9369 case IF_DI_2B: // DI_2B X.........Xnnnnn ssssssnnnnnddddd Rd Rn imm(0-63)
9370 code = emitInsCode(ins, fmt);
9371 imm = emitGetInsSC(id);
9372 assert(isValidImmShift(imm, id->idOpSize()));
9373 code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9374 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9375 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9376 code |= insEncodeReg_Rm(id->idReg2()); // Reg2 also in mmmmm
9377 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9378 dst += emitOutput_Instr(dst, code);
9381 case IF_DI_2C: // DI_2C X........Nrrrrrr ssssssnnnnnddddd Rd Rn imm(N,r,s)
9382 imm = emitGetInsSC(id);
9383 assert(isValidImmNRS(imm, id->idOpSize()));
9384 code = emitInsCode(ins, fmt);
9385 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9386 code |= insEncodeDatasize(id->idOpSize()); // X
9387 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9388 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9389 dst += emitOutput_Instr(dst, code);
9392 case IF_DI_2D: // DI_2D X........Nrrrrrr ssssssnnnnnddddd Rd Rn imr, imms (N,r,s)
9393 if (ins == INS_asr || ins == INS_lsl || ins == INS_lsr)
9395 imm = emitGetInsSC(id);
9396 assert(isValidImmShift(imm, id->idOpSize()));
9398 // Shift immediates are aliases of the SBFM/UBFM instructions
9399 // that actually take 2 registers and 2 constants,
9400 // Since we stored the shift immediate value
9401 // we need to calculate the N,R and S values here.
9406 bmi.immN = (size == EA_8BYTE) ? 1 : 0;
9408 bmi.immS = (size == EA_8BYTE) ? 0x3f : 0x1f;
9410 // immR and immS are now set correctly for INS_asr and INS_lsr
9411 // but for INS_lsl we have to adjust the values for immR and immS
9415 bmi.immR = -imm & bmi.immS;
9416 bmi.immS = bmi.immS - imm;
9419 // setup imm with the proper 13 bit value N:R:S
9425 // The other instructions have already have encoded N,R and S values
9426 imm = emitGetInsSC(id);
9428 assert(isValidImmNRS(imm, id->idOpSize()));
9430 code = emitInsCode(ins, fmt);
9431 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9432 code |= insEncodeDatasize(id->idOpSize()); // X
9433 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9434 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9435 dst += emitOutput_Instr(dst, code);
9438 case IF_DR_1D: // DR_1D X............... cccc.......ddddd Rd cond
9439 imm = emitGetInsSC(id);
9440 assert(isValidImmCond(imm));
9443 cfi.immCFVal = (unsigned)imm;
9444 code = emitInsCode(ins, fmt);
9445 code |= insEncodeDatasize(id->idOpSize()); // X
9446 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9447 code |= insEncodeInvertedCond(cfi.cond); // cccc
9448 dst += emitOutput_Instr(dst, code);
9452 case IF_DR_2A: // DR_2A X..........mmmmm ......nnnnn..... Rn Rm
9453 assert(insOptsNone(id->idInsOpt()));
9454 code = emitInsCode(ins, fmt);
9455 code |= insEncodeDatasize(id->idOpSize()); // X
9456 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9457 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9458 dst += emitOutput_Instr(dst, code);
9461 case IF_DR_2B: // DR_2B X.......sh.mmmmm ssssssnnnnn..... Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
9462 code = emitInsCode(ins, fmt);
9463 imm = emitGetInsSC(id);
9464 assert(isValidImmShift(imm, id->idOpSize()));
9465 code |= insEncodeDatasize(id->idOpSize()); // X
9466 code |= insEncodeShiftType(id->idInsOpt()); // sh
9467 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9468 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9469 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9470 dst += emitOutput_Instr(dst, code);
9473 case IF_DR_2C: // DR_2C X..........mmmmm ooosssnnnnn..... Rn Rm ext(Rm) LSL imm(0-4)
9474 code = emitInsCode(ins, fmt);
9475 imm = emitGetInsSC(id);
9476 assert((imm >= 0) && (imm <= 4)); // imm [0..4]
9477 code |= insEncodeDatasize(id->idOpSize()); // X
9478 code |= insEncodeExtend(id->idInsOpt()); // ooo
9479 code |= insEncodeExtendScale(imm); // sss
9480 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9481 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9482 dst += emitOutput_Instr(dst, code);
9485 case IF_DR_2D: // DR_2D X..........nnnnn cccc..nnnnnddddd Rd Rn cond
9486 imm = emitGetInsSC(id);
9487 assert(isValidImmCond(imm));
9490 cfi.immCFVal = (unsigned)imm;
9491 code = emitInsCode(ins, fmt);
9492 code |= insEncodeDatasize(id->idOpSize()); // X
9493 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9494 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9495 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9496 code |= insEncodeInvertedCond(cfi.cond); // cccc
9497 dst += emitOutput_Instr(dst, code);
9501 case IF_DR_2E: // DR_2E X..........mmmmm ...........ddddd Rd Rm
9502 code = emitInsCode(ins, fmt);
9503 code |= insEncodeDatasize(id->idOpSize()); // X
9504 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9505 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9506 dst += emitOutput_Instr(dst, code);
9509 case IF_DR_2F: // DR_2F X.......sh.mmmmm ssssss.....ddddd Rd Rm {LSL,LSR,ASR} imm(0-63)
9510 code = emitInsCode(ins, fmt);
9511 imm = emitGetInsSC(id);
9512 assert(isValidImmShift(imm, id->idOpSize()));
9513 code |= insEncodeDatasize(id->idOpSize()); // X
9514 code |= insEncodeShiftType(id->idInsOpt()); // sh
9515 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9516 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9517 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9518 dst += emitOutput_Instr(dst, code);
9521 case IF_DR_2G: // DR_2G X............... .....xnnnnnddddd Rd Rn
9522 code = emitInsCode(ins, fmt);
9523 code |= insEncodeDatasize(id->idOpSize()); // X
9526 if (size == EA_8BYTE)
9528 code |= 0x00000400; // x - bit at location 10
9531 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9532 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9533 dst += emitOutput_Instr(dst, code);
9536 case IF_DR_2H: // DR_2H X........X...... ......nnnnnddddd Rd Rn
9537 code = emitInsCode(ins, fmt);
9538 code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9539 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9540 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9541 dst += emitOutput_Instr(dst, code);
9544 case IF_DR_2I: // DR_2I X..........mmmmm cccc..nnnnn.nzcv Rn Rm nzcv cond
9545 imm = emitGetInsSC(id);
9546 assert(isValidImmCondFlags(imm));
9549 cfi.immCFVal = (unsigned)imm;
9550 code = emitInsCode(ins, fmt);
9551 code |= insEncodeDatasize(id->idOpSize()); // X
9552 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9553 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9554 code |= insEncodeFlags(cfi.flags); // nzcv
9555 code |= insEncodeCond(cfi.cond); // cccc
9556 dst += emitOutput_Instr(dst, code);
9560 case IF_DR_2J: // DR_2J ................ ......nnnnnddddd Sd Sn (sha1h)
9561 code = emitInsCode(ins, fmt);
9562 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9563 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9564 dst += emitOutput_Instr(dst, code);
9567 case IF_DR_3A: // DR_3A X..........mmmmm ......nnnnnmmmmm Rd Rn Rm
9568 code = emitInsCode(ins, fmt);
9569 code |= insEncodeDatasize(id->idOpSize()); // X
9570 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9571 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9572 if (id->idIsLclVar())
9574 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9578 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9580 dst += emitOutput_Instr(dst, code);
9583 case IF_DR_3B: // DR_3B X.......sh.mmmmm ssssssnnnnnddddd Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
9584 code = emitInsCode(ins, fmt);
9585 imm = emitGetInsSC(id);
9586 assert(isValidImmShift(imm, id->idOpSize()));
9587 code |= insEncodeDatasize(id->idOpSize()); // X
9588 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9589 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9590 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9591 code |= insEncodeShiftType(id->idInsOpt()); // sh
9592 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9593 dst += emitOutput_Instr(dst, code);
9596 case IF_DR_3C: // DR_3C X..........mmmmm ooosssnnnnnddddd Rd Rn Rm ext(Rm) LSL imm(0-4)
9597 code = emitInsCode(ins, fmt);
9598 imm = emitGetInsSC(id);
9599 assert((imm >= 0) && (imm <= 4)); // imm [0..4]
9600 code |= insEncodeDatasize(id->idOpSize()); // X
9601 code |= insEncodeExtend(id->idInsOpt()); // ooo
9602 code |= insEncodeExtendScale(imm); // sss
9603 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9604 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9605 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9606 dst += emitOutput_Instr(dst, code);
9609 case IF_DR_3D: // DR_3D X..........mmmmm cccc..nnnnnddddd Rd Rn Rm cond
9610 imm = emitGetInsSC(id);
9611 assert(isValidImmCond(imm));
9614 cfi.immCFVal = (unsigned)imm;
9615 code = emitInsCode(ins, fmt);
9616 code |= insEncodeDatasize(id->idOpSize()); // X
9617 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9618 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9619 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9620 code |= insEncodeCond(cfi.cond); // cccc
9621 dst += emitOutput_Instr(dst, code);
9625 case IF_DR_3E: // DR_3E X........X.mmmmm ssssssnnnnnddddd Rd Rn Rm imm(0-63)
9626 code = emitInsCode(ins, fmt);
9627 imm = emitGetInsSC(id);
9628 assert(isValidImmShift(imm, id->idOpSize()));
9629 code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9630 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9631 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9632 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9633 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9634 dst += emitOutput_Instr(dst, code);
9637 case IF_DR_4A: // DR_4A X..........mmmmm .aaaaannnnnmmmmm Rd Rn Rm Ra
9638 code = emitInsCode(ins, fmt);
9639 code |= insEncodeDatasize(id->idOpSize()); // X
9640 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9641 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9642 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9643 code |= insEncodeReg_Ra(id->idReg4()); // aaaaa
9644 dst += emitOutput_Instr(dst, code);
9647 case IF_DV_1A: // DV_1A .........X.iiiii iii........ddddd Vd imm8 (fmov - immediate scalar)
9648 imm = emitGetInsSC(id);
9649 elemsize = id->idOpSize();
9650 code = emitInsCode(ins, fmt);
9651 code |= insEncodeFloatElemsize(elemsize); // X
9652 code |= ((code_t)imm << 13); // iiiii iii
9653 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9654 dst += emitOutput_Instr(dst, code);
9657 case IF_DV_1B: // DV_1B .QX..........iii cmod..iiiiiddddd Vd imm8 (immediate vector)
9658 imm = emitGetInsSC(id) & 0x0ff;
9659 immShift = (emitGetInsSC(id) & 0x700) >> 8;
9660 elemsize = optGetElemsize(id->idInsOpt());
9665 cmode = 0xE; // 1110
9669 cmode |= (immShift << 1); // 10x0
9675 cmode |= (immShift << 1); // 0xx0
9685 cmode = 0xE; // 1110
9692 code = emitInsCode(ins, fmt);
9693 code |= insEncodeVectorsize(id->idOpSize()); // Q
9694 if ((ins == INS_fmov) || (ins == INS_movi))
9696 if (elemsize == EA_8BYTE)
9698 code |= 0x20000000; // X
9701 if (ins != INS_fmov)
9703 assert((cmode >= 0) && (cmode <= 0xF));
9704 code |= (cmode << 12); // cmod
9706 code |= (((code_t)imm >> 5) << 16); // iii
9707 code |= (((code_t)imm & 0x1f) << 5); // iiiii
9708 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9709 dst += emitOutput_Instr(dst, code);
9712 case IF_DV_1C: // DV_1C .........X...... ......nnnnn..... Vn #0.0 (fcmp - with zero)
9713 elemsize = id->idOpSize();
9714 code = emitInsCode(ins, fmt);
9715 code |= insEncodeFloatElemsize(elemsize); // X
9716 code |= insEncodeReg_Vn(id->idReg1()); // nnnnn
9717 dst += emitOutput_Instr(dst, code);
9720 case IF_DV_2A: // DV_2A .Q.......X...... ......nnnnnddddd Vd Vn (fabs, fcvt - vector)
9721 elemsize = optGetElemsize(id->idInsOpt());
9722 code = emitInsCode(ins, fmt);
9723 code |= insEncodeVectorsize(id->idOpSize()); // Q
9724 code |= insEncodeFloatElemsize(elemsize); // X
9725 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9726 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9727 dst += emitOutput_Instr(dst, code);
9730 case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov/smov - to general)
9731 elemsize = id->idOpSize();
9732 index = emitGetInsSC(id);
9733 datasize = (elemsize == EA_8BYTE) ? EA_16BYTE : EA_8BYTE;
9734 if (ins == INS_smov)
9736 datasize = EA_16BYTE;
9738 code = emitInsCode(ins, fmt);
9739 code |= insEncodeVectorsize(datasize); // Q
9740 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9741 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9742 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9743 dst += emitOutput_Instr(dst, code);
9746 case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
9749 datasize = id->idOpSize();
9750 elemsize = optGetElemsize(id->idInsOpt());
9755 datasize = EA_16BYTE;
9756 elemsize = id->idOpSize();
9757 index = emitGetInsSC(id);
9759 code = emitInsCode(ins, fmt);
9760 code |= insEncodeVectorsize(datasize); // Q
9761 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9762 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9763 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9764 dst += emitOutput_Instr(dst, code);
9767 case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
9768 index = emitGetInsSC(id);
9769 elemsize = optGetElemsize(id->idInsOpt());
9770 code = emitInsCode(ins, fmt);
9771 code |= insEncodeVectorsize(id->idOpSize()); // Q
9772 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9773 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9774 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9775 dst += emitOutput_Instr(dst, code);
9778 case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
9779 index = emitGetInsSC(id);
9780 elemsize = id->idOpSize();
9781 code = emitInsCode(ins, fmt);
9782 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9783 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9784 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9785 dst += emitOutput_Instr(dst, code);
9788 case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
9789 elemsize = id->idOpSize();
9790 imm = emitGetInsSC(id);
9791 index = (imm >> 4) & 0xf;
9793 code = emitInsCode(ins, fmt);
9794 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9795 code |= insEncodeVectorIndex2(elemsize, index2); // jjjj
9796 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9797 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9798 dst += emitOutput_Instr(dst, code);
9801 case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov,fcvtXX - register)
9802 elemsize = id->idOpSize();
9803 code = emitInsCode(ins, fmt);
9804 code |= insEncodeFloatElemsize(elemsize); // X
9805 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9806 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9807 dst += emitOutput_Instr(dst, code);
9810 case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov - to general)
9811 elemsize = id->idOpSize();
9812 code = emitInsCode(ins, fmt);
9813 code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X X
9814 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9815 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9816 dst += emitOutput_Instr(dst, code);
9819 case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov - from general)
9820 elemsize = id->idOpSize();
9821 code = emitInsCode(ins, fmt);
9822 code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X X
9823 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9824 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9825 dst += emitOutput_Instr(dst, code);
9828 case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
9829 code = emitInsCode(ins, fmt);
9830 code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // SS DD
9831 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9832 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9833 dst += emitOutput_Instr(dst, code);
9836 case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
9837 elemsize = id->idOpSize();
9838 code = emitInsCode(ins, fmt);
9839 code |= insEncodeFloatElemsize(elemsize); // X
9840 code |= insEncodeReg_Vn(id->idReg1()); // nnnnn
9841 code |= insEncodeReg_Vm(id->idReg2()); // mmmmm
9842 dst += emitOutput_Instr(dst, code);
9845 case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
9846 elemsize = id->idOpSize();
9847 code = emitInsCode(ins, fmt);
9848 code |= insEncodeElemsize(elemsize); // XX
9849 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9850 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9851 dst += emitOutput_Instr(dst, code);
9854 case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
9855 elemsize = optGetElemsize(id->idInsOpt());
9856 code = emitInsCode(ins, fmt);
9857 code |= insEncodeVectorsize(id->idOpSize()); // Q
9858 code |= insEncodeElemsize(elemsize); // XX
9859 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9860 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9861 dst += emitOutput_Instr(dst, code);
9864 case IF_DV_2N: // DV_2N .........iiiiiii ......nnnnnddddd Vd Vn imm (shift - scalar)
9865 imm = emitGetInsSC(id);
9866 code = emitInsCode(ins, fmt);
9867 code |= insEncodeVectorShift(EA_8BYTE, imm); // iiiiiii
9868 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9869 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9870 dst += emitOutput_Instr(dst, code);
9873 case IF_DV_2O: // DV_2O .Q.......iiiiiii ......nnnnnddddd Vd Vn imm (shift - vector)
9874 imm = emitGetInsSC(id);
9875 elemsize = optGetElemsize(id->idInsOpt());
9876 code = emitInsCode(ins, fmt);
9877 code |= insEncodeVectorsize(id->idOpSize()); // Q
9878 code |= insEncodeVectorShift(elemsize, imm); // iiiiiii
9879 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9880 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9881 dst += emitOutput_Instr(dst, code);
9884 case IF_DV_2P: // DV_2P ............... ......nnnnnddddd Vd Vn (aes*, sha1su1)
9885 elemsize = optGetElemsize(id->idInsOpt());
9886 code = emitInsCode(ins, fmt);
9887 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9888 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9889 dst += emitOutput_Instr(dst, code);
9892 case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
9893 code = emitInsCode(ins, fmt);
9894 elemsize = optGetElemsize(id->idInsOpt());
9895 code |= insEncodeVectorsize(id->idOpSize()); // Q
9896 code |= insEncodeElemsize(elemsize); // XX
9897 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9898 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9899 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9900 dst += emitOutput_Instr(dst, code);
9903 case IF_DV_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector)
9904 code = emitInsCode(ins, fmt);
9905 imm = emitGetInsSC(id);
9906 elemsize = optGetElemsize(id->idInsOpt());
9907 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
9908 code |= insEncodeVectorsize(id->idOpSize()); // Q
9909 code |= insEncodeElemsize(elemsize); // XX
9910 code |= insEncodeVectorIndexLMH(elemsize, imm); // LM H
9911 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9912 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9913 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9914 dst += emitOutput_Instr(dst, code);
9917 case IF_DV_3B: // DV_3B .Q.......X.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
9918 code = emitInsCode(ins, fmt);
9919 elemsize = optGetElemsize(id->idInsOpt());
9920 code |= insEncodeVectorsize(id->idOpSize()); // Q
9921 code |= insEncodeFloatElemsize(elemsize); // X
9922 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9923 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9924 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9925 dst += emitOutput_Instr(dst, code);
9928 case IF_DV_3BI: // DV_3BI .Q.......XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
9929 code = emitInsCode(ins, fmt);
9930 imm = emitGetInsSC(id);
9931 elemsize = optGetElemsize(id->idInsOpt());
9932 assert(isValidVectorIndex(id->idOpSize(), elemsize, imm));
9933 code |= insEncodeVectorsize(id->idOpSize()); // Q
9934 code |= insEncodeFloatElemsize(elemsize); // X
9935 code |= insEncodeFloatIndex(elemsize, imm); // L H
9936 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9937 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9938 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9939 dst += emitOutput_Instr(dst, code);
9942 case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
9943 code = emitInsCode(ins, fmt);
9944 code |= insEncodeVectorsize(id->idOpSize()); // Q
9945 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9946 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9947 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9948 dst += emitOutput_Instr(dst, code);
9951 case IF_DV_3D: // DV_3D .........X.mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
9952 code = emitInsCode(ins, fmt);
9953 code |= insEncodeFloatElemsize(id->idOpSize()); // X
9954 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9955 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9956 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9957 dst += emitOutput_Instr(dst, code);
9960 case IF_DV_3DI: // DV_3DI .........XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (scalar by elem)
9961 code = emitInsCode(ins, fmt);
9962 imm = emitGetInsSC(id);
9963 elemsize = id->idOpSize();
9964 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
9965 code |= insEncodeFloatElemsize(elemsize); // X
9966 code |= insEncodeFloatIndex(elemsize, imm); // L H
9967 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9968 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9969 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9970 dst += emitOutput_Instr(dst, code);
9973 case IF_DV_3E: // DV_3E ...........mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
9974 case IF_DV_3F: // DV_3F ...........mmmmm ......nnnnnddddd Vd Vn Vm (vector) - source dest regs overlap
9975 code = emitInsCode(ins, fmt);
9976 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9977 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9978 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9979 dst += emitOutput_Instr(dst, code);
9982 case IF_DV_4A: // DV_4A .........X.mmmmm .aaaaannnnnddddd Vd Va Vn Vm (scalar)
9983 code = emitInsCode(ins, fmt);
9984 elemsize = id->idOpSize();
9985 code |= insEncodeFloatElemsize(elemsize); // X
9986 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9987 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9988 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9989 code |= insEncodeReg_Va(id->idReg4()); // aaaaa
9990 dst += emitOutput_Instr(dst, code);
9993 case IF_SN_0A: // SN_0A ................ ................
9994 code = emitInsCode(ins, fmt);
9995 dst += emitOutput_Instr(dst, code);
9998 case IF_SI_0A: // SI_0A ...........iiiii iiiiiiiiiii..... imm16
9999 imm = emitGetInsSC(id);
10000 assert(isValidUimm16(imm));
10001 code = emitInsCode(ins, fmt);
10002 code |= ((code_t)imm << 5); // iiiii iiiiiiiiiii
10003 dst += emitOutput_Instr(dst, code);
10006 case IF_SI_0B: // SI_0B ................ ....bbbb........ imm4 - barrier
10007 imm = emitGetInsSC(id);
10008 assert((imm >= 0) && (imm <= 15));
10009 code = emitInsCode(ins, fmt);
10010 code |= ((code_t)imm << 8); // bbbb
10011 dst += emitOutput_Instr(dst, code);
10015 assert(!"Unexpected format");
10019 // Determine if any registers now hold GC refs, or whether a register that was overwritten held a GC ref.
10020 // We assume here that "id->idGCref()" is not GC_NONE only if the instruction described by "id" writes a
10021 // GC ref to register "id->idReg1()". (It may, apparently, also not be GC_NONE in other cases, such as
10022 // for stores, but we ignore those cases here.)
10023 if (emitInsMayWriteToGCReg(id)) // True if "id->idIns()" writes to a register than can hold GC ref.
10025 // We assume that "idReg1" is the primary destination register for all instructions
10026 if (id->idGCref() != GCT_NONE)
10028 emitGCregLiveUpd(id->idGCref(), id->idReg1(), dst);
10032 emitGCregDeadUpd(id->idReg1(), dst);
10035 if (emitInsMayWriteMultipleRegs(id))
10038 // "idReg2" is the secondary destination register
10039 if (id->idGCrefReg2() != GCT_NONE)
10041 emitGCregLiveUpd(id->idGCrefReg2(), id->idReg2(), dst);
10045 emitGCregDeadUpd(id->idReg2(), dst);
10050 // Now we determine if the instruction has written to a (local variable) stack location, and either written a GC
10051 // ref or overwritten one.
10052 if (emitInsWritesToLclVarStackLoc(id) || emitInsWritesToLclVarStackLocPair(id))
10054 int varNum = id->idAddr()->iiaLclVar.lvaVarNum();
10055 unsigned ofs = AlignDown(id->idAddr()->iiaLclVar.lvaOffset(), TARGET_POINTER_SIZE);
10057 int adr = emitComp->lvaFrameAddress(varNum, &FPbased);
10058 if (id->idGCref() != GCT_NONE)
10060 emitGCvarLiveUpd(adr + ofs, varNum, id->idGCref(), dst);
10064 // If the type of the local is a gc ref type, update the liveness.
10068 // "Regular" (non-spill-temp) local.
10069 vt = var_types(emitComp->lvaTable[varNum].lvType);
10073 TempDsc* tmpDsc = emitComp->tmpFindNum(varNum);
10074 vt = tmpDsc->tdTempType();
10076 if (vt == TYP_REF || vt == TYP_BYREF)
10077 emitGCvarDeadUpd(adr + ofs, dst);
10079 if (emitInsWritesToLclVarStackLocPair(id))
10081 unsigned ofs2 = ofs + TARGET_POINTER_SIZE;
10082 if (id->idGCrefReg2() != GCT_NONE)
10084 emitGCvarLiveUpd(adr + ofs2, varNum, id->idGCrefReg2(), dst);
10088 // If the type of the local is a gc ref type, update the liveness.
10092 // "Regular" (non-spill-temp) local.
10093 vt = var_types(emitComp->lvaTable[varNum].lvType);
10097 TempDsc* tmpDsc = emitComp->tmpFindNum(varNum);
10098 vt = tmpDsc->tdTempType();
10100 if (vt == TYP_REF || vt == TYP_BYREF)
10101 emitGCvarDeadUpd(adr + ofs2, dst);
10107 /* Make sure we set the instruction descriptor size correctly */
10109 size_t expected = emitSizeOfInsDsc(id);
10110 assert(sz == expected);
10112 if (emitComp->opts.disAsm || emitComp->opts.dspEmit || emitComp->verbose)
10114 emitDispIns(id, false, dspOffs, true, emitCurCodeOffs(odst), *dp, (dst - *dp), ig);
10117 if (emitComp->compDebugBreak)
10119 // For example, set JitBreakEmitOutputInstr=a6 will break when this method is called for
10120 // emitting instruction a6, (i.e. IN00a6 in jitdump).
10121 if ((unsigned)JitConfig.JitBreakEmitOutputInstr() == id->idDebugOnlyInfo()->idNum)
10123 assert(!"JitBreakEmitOutputInstr reached");
10128 /* All instructions are expected to generate code */
10130 assert(*dp != dst);
10137 /*****************************************************************************/
10138 /*****************************************************************************/
10142 /*****************************************************************************
10144 * Display the instruction name
10146 void emitter::emitDispInst(instruction ins)
10148 const char* insstr = codeGen->genInsName(ins);
10149 size_t len = strlen(insstr);
10151 /* Display the instruction name */
10153 printf("%s", insstr);
10156 // Add at least one space after the instruction name
10157 // and add spaces until we have reach the normal size of 8
10165 /*****************************************************************************
10167 * Display an reloc value
10168 * If we are formatting for an assembly listing don't print the hex value
10169 * since it will prevent us from doing assembly diffs
10171 void emitter::emitDispReloc(int value, bool addComma)
10173 if (emitComp->opts.disAsm)
10179 printf("(reloc 0x%x)", dspPtr(value));
10186 /*****************************************************************************
10188 * Display an immediate value
10190 void emitter::emitDispImm(ssize_t imm, bool addComma, bool alwaysHex /* =false */)
10197 // Munge any pointers if we want diff-able disassembly.
10198 // Since some may be emitted as partial words, print as diffable anything that has
10199 // significant bits beyond the lowest 8-bits.
10200 if (emitComp->opts.disDiffable)
10202 ssize_t top56bits = (imm >> 8);
10203 if ((top56bits != 0) && (top56bits != -1))
10207 if (!alwaysHex && (imm > -1000) && (imm < 1000))
10213 if ((imm < 0) && ((imm & 0xFFFFFFFF00000000LL) == 0xFFFFFFFF00000000LL))
10219 if ((imm & 0xFFFFFFFF00000000LL) != 0)
10221 printf("0x%llx", imm);
10225 printf("0x%02x", imm);
10233 /*****************************************************************************
10235 * Display a float zero constant
10237 void emitter::emitDispFloatZero()
10246 /*****************************************************************************
10248 * Display an encoded float constant value
10250 void emitter::emitDispFloatImm(ssize_t imm8)
10252 assert((0 <= imm8) && (imm8 <= 0x0ff));
10259 fpImm.immFPIVal = (unsigned)imm8;
10260 double result = emitDecodeFloatImm8(fpImm);
10262 printf("%.4f", result);
10265 /*****************************************************************************
10267 * Display an immediate that is optionally LSL12.
10269 void emitter::emitDispImmOptsLSL12(ssize_t imm, insOpts opt)
10271 if (!strictArmAsm && insOptsLSL12(opt))
10275 emitDispImm(imm, false);
10276 if (strictArmAsm && insOptsLSL12(opt))
10278 printf(", LSL #12");
10282 /*****************************************************************************
10284 * Display an ARM64 condition code for the conditional instructions
10286 void emitter::emitDispCond(insCond cond)
10288 const static char* armCond[16] = {"eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc",
10289 "hi", "ls", "ge", "lt", "gt", "le", "AL", "NV"}; // The last two are invalid
10290 unsigned imm = (unsigned)cond;
10291 assert((0 <= imm) && (imm < ArrLen(armCond)));
10292 printf(armCond[imm]);
10295 /*****************************************************************************
10297 * Display an ARM64 flags for the conditional instructions
10299 void emitter::emitDispFlags(insCflags flags)
10301 const static char* armFlags[16] = {"0", "v", "c", "cv", "z", "zv", "zc", "zcv",
10302 "n", "nv", "nc", "ncv", "nz", "nzv", "nzc", "nzcv"};
10303 unsigned imm = (unsigned)flags;
10304 assert((0 <= imm) && (imm < ArrLen(armFlags)));
10305 printf(armFlags[imm]);
10308 /*****************************************************************************
10310 * Display an ARM64 'barrier' for the memory barrier instructions
10312 void emitter::emitDispBarrier(insBarrier barrier)
10314 const static char* armBarriers[16] = {"#0", "oshld", "oshst", "osh", "#4", "nshld", "nshst", "nsh",
10315 "#8", "ishld", "ishst", "ish", "#12", "ld", "st", "sy"};
10316 unsigned imm = (unsigned)barrier;
10317 assert((0 <= imm) && (imm < ArrLen(armBarriers)));
10318 printf(armBarriers[imm]);
10321 /*****************************************************************************
10323 * Prints the encoding for the Shift Type encoding
10326 void emitter::emitDispShiftOpts(insOpts opt)
10328 if (opt == INS_OPTS_LSL)
10330 else if (opt == INS_OPTS_LSR)
10332 else if (opt == INS_OPTS_ASR)
10334 else if (opt == INS_OPTS_ROR)
10336 else if (opt == INS_OPTS_MSL)
10339 assert(!"Bad value");
10342 /*****************************************************************************
10344 * Prints the encoding for the Extend Type encoding
10347 void emitter::emitDispExtendOpts(insOpts opt)
10349 if (opt == INS_OPTS_UXTB)
10351 else if (opt == INS_OPTS_UXTH)
10353 else if (opt == INS_OPTS_UXTW)
10355 else if (opt == INS_OPTS_UXTX)
10357 else if (opt == INS_OPTS_SXTB)
10359 else if (opt == INS_OPTS_SXTH)
10361 else if (opt == INS_OPTS_SXTW)
10363 else if (opt == INS_OPTS_SXTX)
10366 assert(!"Bad value");
10369 /*****************************************************************************
10371 * Prints the encoding for the Extend Type encoding in loads/stores
10374 void emitter::emitDispLSExtendOpts(insOpts opt)
10376 if (opt == INS_OPTS_LSL)
10378 else if (opt == INS_OPTS_UXTW)
10380 else if (opt == INS_OPTS_UXTX)
10382 else if (opt == INS_OPTS_SXTW)
10384 else if (opt == INS_OPTS_SXTX)
10387 assert(!"Bad value");
10390 /*****************************************************************************
10392 * Display a register
10394 void emitter::emitDispReg(regNumber reg, emitAttr attr, bool addComma)
10396 emitAttr size = EA_SIZE(attr);
10397 printf(emitRegName(reg, size));
10403 /*****************************************************************************
10405 * Display a vector register with an arrangement suffix
10407 void emitter::emitDispVectorReg(regNumber reg, insOpts opt, bool addComma)
10409 assert(isVectorRegister(reg));
10410 printf(emitVectorRegName(reg));
10411 emitDispArrangement(opt);
10417 /*****************************************************************************
10419 * Display an vector register index suffix
10421 void emitter::emitDispVectorRegIndex(regNumber reg, emitAttr elemsize, ssize_t index, bool addComma)
10423 assert(isVectorRegister(reg));
10424 printf(emitVectorRegName(reg));
10441 assert(!"invalid elemsize");
10445 printf("[%d]", index);
10451 /*****************************************************************************
10453 * Display an arrangement suffix
10455 void emitter::emitDispArrangement(insOpts opt)
10457 const char* str = "???";
10487 assert(!"Invalid insOpt for vector register");
10493 /*****************************************************************************
10495 * Display a register with an optional shift operation
10497 void emitter::emitDispShiftedReg(regNumber reg, insOpts opt, ssize_t imm, emitAttr attr)
10499 emitAttr size = EA_SIZE(attr);
10500 assert((imm & 0x003F) == imm);
10501 assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
10503 printf(emitRegName(reg, size));
10511 emitDispShiftOpts(opt);
10512 emitDispImm(imm, false);
10516 /*****************************************************************************
10518 * Display a register with an optional extend and scale operations
10520 void emitter::emitDispExtendReg(regNumber reg, insOpts opt, ssize_t imm)
10522 assert((imm >= 0) && (imm <= 4));
10523 assert(insOptsNone(opt) || insOptsAnyExtend(opt) || (opt == INS_OPTS_LSL));
10525 // size is based on the extend option, not the instr size.
10526 emitAttr size = insOpts32BitExtend(opt) ? EA_4BYTE : EA_8BYTE;
10530 if (insOptsNone(opt))
10532 emitDispReg(reg, size, false);
10536 emitDispReg(reg, size, true);
10537 if (opt == INS_OPTS_LSL)
10540 emitDispExtendOpts(opt);
10541 if ((imm > 0) || (opt == INS_OPTS_LSL))
10544 emitDispImm(imm, false);
10548 else // !strictArmAsm
10550 if (insOptsNone(opt))
10552 emitDispReg(reg, size, false);
10556 if (opt != INS_OPTS_LSL)
10558 emitDispExtendOpts(opt);
10560 emitDispReg(reg, size, false);
10567 emitDispImm(1 << imm, false);
10572 /*****************************************************************************
10574 * Display an addressing operand [reg + imm]
10576 void emitter::emitDispAddrRI(regNumber reg, insOpts opt, ssize_t imm)
10578 reg = encodingZRtoSP(reg); // ZR (R31) encodes the SP register
10584 emitDispReg(reg, EA_8BYTE, false);
10586 if (!insOptsPostIndex(opt) && (imm != 0))
10589 emitDispImm(imm, false);
10593 if (insOptsPreIndex(opt))
10597 else if (insOptsPostIndex(opt))
10600 emitDispImm(imm, false);
10603 else // !strictArmAsm
10607 const char* operStr = "++";
10614 if (insOptsPreIndex(opt))
10619 emitDispReg(reg, EA_8BYTE, false);
10621 if (insOptsPostIndex(opt))
10626 if (insOptsIndexed(opt))
10632 printf("%c", operStr[1]);
10634 emitDispImm(imm, false);
10639 /*****************************************************************************
10641 * Display an addressing operand [reg + extended reg]
10643 void emitter::emitDispAddrRRExt(regNumber reg1, regNumber reg2, insOpts opt, bool isScaled, emitAttr size)
10645 reg1 = encodingZRtoSP(reg1); // ZR (R31) encodes the SP register
10647 unsigned scale = 0;
10650 scale = NaturalScale_helper(size);
10657 emitDispReg(reg1, EA_8BYTE, true);
10658 emitDispExtendReg(reg2, opt, scale);
10660 else // !strictArmAsm
10662 emitDispReg(reg1, EA_8BYTE, false);
10664 emitDispExtendReg(reg2, opt, scale);
10670 /*****************************************************************************
10672 * Display (optionally) the instruction encoding in hex
10675 void emitter::emitDispInsHex(BYTE* code, size_t sz)
10677 // We do not display the instruction hex if we want diff-able disassembly
10678 if (!emitComp->opts.disDiffable)
10682 printf(" %08X ", (*((code_t*)code)));
10691 /****************************************************************************
10693 * Display the given instruction.
10696 void emitter::emitDispIns(
10697 instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* pCode, size_t sz, insGroup* ig)
10702 id->idDebugOnlyInfo()->idNum; // Do not remove this! It is needed for VisualStudio conditional breakpoints
10704 printf("IN%04x: ", idNum);
10710 if (!emitComp->opts.dspEmit && !isNew && !asmfm && sz)
10713 /* Display the instruction offset */
10715 emitDispInsOffs(offset, doffs);
10717 /* Display the instruction hex code */
10719 emitDispInsHex(pCode, sz);
10723 /* Get the instruction and format */
10725 instruction ins = id->idIns();
10726 insFormat fmt = id->idInsFmt();
10730 /* If this instruction has just been added, check its size */
10732 assert(isNew == false || (int)emitSizeOfInsDsc(id) == emitCurIGfreeNext - (BYTE*)id);
10734 /* Figure out the operand size */
10735 emitAttr size = id->idOpSize();
10736 emitAttr attr = size;
10737 if (id->idGCref() == GCT_GCREF)
10739 else if (id->idGCref() == GCT_BYREF)
10747 bool isExtendAlias;
10756 const char* methodName;
10764 case IF_BI_0A: // BI_0A ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
10765 case IF_BI_0B: // BI_0B ......iiiiiiiiii iiiiiiiiiii..... simm19:00
10768 if (fmt == IF_LARGEJMP)
10770 printf("(LARGEJMP)");
10772 if (id->idAddr()->iiaHasInstrCount())
10774 int instrCount = id->idAddr()->iiaGetInstrCount();
10778 printf("pc%s%d instructions", (instrCount >= 0) ? "+" : "", instrCount);
10782 unsigned insNum = emitFindInsNum(ig, id);
10783 UNATIVE_OFFSET srcOffs = ig->igOffs + emitFindOffset(ig, insNum + 1);
10784 UNATIVE_OFFSET dstOffs = ig->igOffs + emitFindOffset(ig, insNum + 1 + instrCount);
10785 ssize_t relOffs = (ssize_t)(emitOffsetToPtr(dstOffs) - emitOffsetToPtr(srcOffs));
10786 printf("pc%s%d (%d instructions)", (relOffs >= 0) ? "+" : "", relOffs, instrCount);
10789 else if (id->idIsBound())
10791 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10795 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10800 case IF_BI_0C: // BI_0C ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
10801 if (id->idIsCallAddr())
10803 offs = (ssize_t)id->idAddr()->iiaAddr;
10809 methodName = emitComp->eeGetMethodFullName((CORINFO_METHOD_HANDLE)id->idDebugOnlyInfo()->idMemCookie);
10814 if (id->idIsDspReloc())
10816 printf("%08X", offs);
10820 printf("%s", methodName);
10824 case IF_BI_1A: // BI_1A ......iiiiiiiiii iiiiiiiiiiittttt Rt simm19:00
10825 assert(insOptsNone(id->idInsOpt()));
10826 emitDispReg(id->idReg1(), size, true);
10827 if (id->idIsBound())
10829 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10833 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10837 case IF_BI_1B: // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
10838 assert(insOptsNone(id->idInsOpt()));
10839 emitDispReg(id->idReg1(), size, true);
10840 emitDispImm(emitGetInsSC(id), true);
10841 if (id->idIsBound())
10843 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10847 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10851 case IF_BR_1A: // BR_1A ................ ......nnnnn..... Rn
10852 assert(insOptsNone(id->idInsOpt()));
10853 emitDispReg(id->idReg1(), size, false);
10856 case IF_BR_1B: // BR_1B ................ ......nnnnn..... Rn
10857 assert(insOptsNone(id->idInsOpt()));
10858 emitDispReg(id->idReg3(), size, false);
10861 case IF_LS_1A: // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB)
10862 case IF_DI_1E: // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
10865 assert(insOptsNone(id->idInsOpt()));
10866 emitDispReg(id->idReg1(), size, true);
10867 imm = emitGetInsSC(id);
10869 /* Is this actually a reference to a data section? */
10870 if (fmt == IF_LARGEADR)
10872 printf("(LARGEADR)");
10874 else if (fmt == IF_LARGELDC)
10876 printf("(LARGELDC)");
10880 if (id->idAddr()->iiaIsJitDataOffset())
10882 doffs = Compiler::eeGetJitDataOffs(id->idAddr()->iiaFieldHnd);
10883 /* Display a data section reference */
10886 printf("@CNS%02u", doffs - 1);
10888 printf("@RWD%02u", doffs);
10891 printf("%+Id", imm);
10896 if (id->idIsReloc())
10899 emitDispImm((ssize_t)id->idAddr()->iiaAddr, false);
10901 else if (id->idIsBound())
10903 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10907 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10913 case IF_LS_2A: // LS_2A .X.......X...... ......nnnnnttttt Rt Rn
10914 assert(insOptsNone(id->idInsOpt()));
10915 assert(emitGetInsSC(id) == 0);
10916 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10917 emitDispAddrRI(id->idReg2(), id->idInsOpt(), 0);
10920 case IF_LS_2B: // LS_2B .X.......Xiiiiii iiiiiinnnnnttttt Rt Rn imm(0-4095)
10921 assert(insOptsNone(id->idInsOpt()));
10922 imm = emitGetInsSC(id);
10923 scale = NaturalScale_helper(emitInsLoadStoreSize(id));
10924 imm <<= scale; // The immediate is scaled by the size of the ld/st
10925 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10926 emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
10929 case IF_LS_2C: // LS_2C .X.......X.iiiii iiiiPPnnnnnttttt Rt Rn imm(-256..+255) no/pre/post inc
10930 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
10931 imm = emitGetInsSC(id);
10932 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10933 emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
10936 case IF_LS_3A: // LS_3A .X.......X.mmmmm oooS..nnnnnttttt Rt Rn Rm ext(Rm) LSL {}
10937 assert(insOptsLSExtend(id->idInsOpt()));
10938 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10939 if (id->idIsLclVar())
10941 emitDispAddrRRExt(id->idReg2(), codeGen->rsGetRsvdReg(), id->idInsOpt(), false, size);
10945 emitDispAddrRRExt(id->idReg2(), id->idReg3(), id->idInsOpt(), id->idReg3Scaled(), size);
10949 case IF_LS_3B: // LS_3B X............... .aaaaannnnnddddd Rt Ra Rn
10950 assert(insOptsNone(id->idInsOpt()));
10951 assert(emitGetInsSC(id) == 0);
10952 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10953 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10954 emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
10957 case IF_LS_3C: // LS_3C X.........iiiiii iaaaaannnnnddddd Rt Ra Rn imm(im7,sh)
10958 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
10959 imm = emitGetInsSC(id);
10960 scale = NaturalScale_helper(emitInsLoadStoreSize(id));
10962 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10963 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10964 emitDispAddrRI(id->idReg3(), id->idInsOpt(), imm);
10967 case IF_LS_3D: // LS_3D .X.......X.mmmmm ......nnnnnttttt Wm Rt Rn
10968 assert(insOptsNone(id->idInsOpt()));
10969 emitDispReg(id->idReg1(), EA_4BYTE, true);
10970 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10971 emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
10974 case IF_DI_1A: // DI_1A X.......shiiiiii iiiiiinnnnn..... Rn imm(i12,sh)
10975 emitDispReg(id->idReg1(), size, true);
10976 emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
10979 case IF_DI_1B: // DI_1B X........hwiiiii iiiiiiiiiiiddddd Rd imm(i16,hw)
10980 emitDispReg(id->idReg1(), size, true);
10981 hwi.immHWVal = (unsigned)emitGetInsSC(id);
10982 if (ins == INS_mov)
10984 emitDispImm(emitDecodeHalfwordImm(hwi, size), false);
10986 else // movz, movn, movk
10988 emitDispImm(hwi.immVal, false);
10989 if (hwi.immHW != 0)
10991 emitDispShiftOpts(INS_OPTS_LSL);
10992 emitDispImm(hwi.immHW * 16, false);
10997 case IF_DI_1C: // DI_1C X........Nrrrrrr ssssssnnnnn..... Rn imm(N,r,s)
10998 emitDispReg(id->idReg1(), size, true);
10999 bmi.immNRS = (unsigned)emitGetInsSC(id);
11000 emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
11003 case IF_DI_1D: // DI_1D X........Nrrrrrr ssssss.....ddddd Rd imm(N,r,s)
11004 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11005 bmi.immNRS = (unsigned)emitGetInsSC(id);
11006 emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
11009 case IF_DI_2A: // DI_2A X.......shiiiiii iiiiiinnnnnddddd Rd Rn imm(i12,sh)
11010 if ((ins == INS_add) || (ins == INS_sub))
11012 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11013 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11017 emitDispReg(id->idReg1(), size, true);
11018 emitDispReg(id->idReg2(), size, true);
11020 emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
11023 case IF_DI_2B: // DI_2B X........X.nnnnn ssssssnnnnnddddd Rd Rn imm(0-63)
11024 emitDispReg(id->idReg1(), size, true);
11025 emitDispReg(id->idReg2(), size, true);
11026 emitDispImm(emitGetInsSC(id), false);
11029 case IF_DI_2C: // DI_2C X........Nrrrrrr ssssssnnnnnddddd Rd Rn imm(N,r,s)
11030 if (ins == INS_ands)
11032 emitDispReg(id->idReg1(), size, true);
11036 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11038 emitDispReg(id->idReg2(), size, true);
11039 bmi.immNRS = (unsigned)emitGetInsSC(id);
11040 emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
11043 case IF_DI_2D: // DI_2D X........Nrrrrrr ssssssnnnnnddddd Rd Rn imr, ims (N,r,s)
11044 emitDispReg(id->idReg1(), size, true);
11045 emitDispReg(id->idReg2(), size, true);
11047 imm = emitGetInsSC(id);
11048 bmi.immNRS = (unsigned)imm;
11055 emitDispImm(bmi.immR, true);
11056 emitDispImm(bmi.immS, false);
11062 emitDispImm(getBitWidth(size) - bmi.immR, true);
11063 emitDispImm(bmi.immS + 1, false);
11069 emitDispImm(bmi.immR, true);
11070 emitDispImm(bmi.immS - bmi.immR + 1, false);
11076 emitDispImm(imm, false);
11080 assert(!"Unexpected instruction in IF_DI_2D");
11085 case IF_DI_1F: // DI_1F X..........iiiii cccc..nnnnn.nzcv Rn imm5 nzcv cond
11086 emitDispReg(id->idReg1(), size, true);
11087 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11088 emitDispImm(cfi.imm5, true);
11089 emitDispFlags(cfi.flags);
11091 emitDispCond(cfi.cond);
11094 case IF_DR_1D: // DR_1D X............... cccc.......mmmmm Rd cond
11095 emitDispReg(id->idReg1(), size, true);
11096 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11097 emitDispCond(cfi.cond);
11100 case IF_DR_2A: // DR_2A X..........mmmmm ......nnnnn..... Rn Rm
11101 emitDispReg(id->idReg1(), size, true);
11102 emitDispReg(id->idReg2(), size, false);
11105 case IF_DR_2B: // DR_2B X.......sh.mmmmm ssssssnnnnn..... Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
11106 emitDispReg(id->idReg1(), size, true);
11107 emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
11110 case IF_DR_2C: // DR_2C X..........mmmmm ooosssnnnnn..... Rn Rm ext(Rm) LSL imm(0-4)
11111 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11112 imm = emitGetInsSC(id);
11113 emitDispExtendReg(id->idReg2(), id->idInsOpt(), imm);
11116 case IF_DR_2D: // DR_2D X..........nnnnn cccc..nnnnnddddd Rd Rn cond
11117 emitDispReg(id->idReg1(), size, true);
11118 emitDispReg(id->idReg2(), size, true);
11119 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11120 emitDispCond(cfi.cond);
11123 case IF_DR_2E: // DR_2E X..........mmmmm ...........ddddd Rd Rm
11124 case IF_DR_2J: // DR_2J ................ ......nnnnnddddd Sd Sn
11125 emitDispReg(id->idReg1(), size, true);
11126 emitDispReg(id->idReg2(), size, false);
11129 case IF_DR_2F: // DR_2F X.......sh.mmmmm ssssss.....ddddd Rd Rm {LSL,LSR,ASR} imm(0-63)
11130 emitDispReg(id->idReg1(), size, true);
11131 emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
11134 case IF_DR_2G: // DR_2G X............... ......nnnnnddddd Rd Rn
11135 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11136 emitDispReg(encodingZRtoSP(id->idReg2()), size, false);
11139 case IF_DR_2H: // DR_2H X........X...... ......nnnnnddddd Rd Rn
11140 emitDispReg(id->idReg1(), size, true);
11141 emitDispReg(id->idReg2(), size, false);
11144 case IF_DR_2I: // DR_2I X..........mmmmm cccc..nnnnn.nzcv Rn Rm nzcv cond
11145 emitDispReg(id->idReg1(), size, true);
11146 emitDispReg(id->idReg2(), size, true);
11147 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11148 emitDispFlags(cfi.flags);
11150 emitDispCond(cfi.cond);
11153 case IF_DR_3A: // DR_3A X..........mmmmm ......nnnnnmmmmm Rd Rn Rm
11154 if ((ins == INS_add) || (ins == INS_sub))
11156 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11157 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11159 else if ((ins == INS_smull) || (ins == INS_smulh))
11161 // Rd is always 8 bytes
11162 emitDispReg(id->idReg1(), EA_8BYTE, true);
11164 // Rn, Rm effective size depends on instruction type
11165 size = (ins == INS_smulh) ? EA_8BYTE : EA_4BYTE;
11166 emitDispReg(id->idReg2(), size, true);
11170 emitDispReg(id->idReg1(), size, true);
11171 emitDispReg(id->idReg2(), size, true);
11173 if (id->idIsLclVar())
11175 emitDispReg(codeGen->rsGetRsvdReg(), size, false);
11179 emitDispReg(id->idReg3(), size, false);
11184 case IF_DR_3B: // DR_3B X.......sh.mmmmm ssssssnnnnnddddd Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
11185 emitDispReg(id->idReg1(), size, true);
11186 emitDispReg(id->idReg2(), size, true);
11187 emitDispShiftedReg(id->idReg3(), id->idInsOpt(), emitGetInsSC(id), size);
11190 case IF_DR_3C: // DR_3C X..........mmmmm ooosssnnnnnddddd Rd Rn Rm ext(Rm) LSL imm(0-4)
11191 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11192 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11193 imm = emitGetInsSC(id);
11194 emitDispExtendReg(id->idReg3(), id->idInsOpt(), imm);
11197 case IF_DR_3D: // DR_3D X..........mmmmm cccc..nnnnnmmmmm Rd Rn Rm cond
11198 emitDispReg(id->idReg1(), size, true);
11199 emitDispReg(id->idReg2(), size, true);
11200 emitDispReg(id->idReg3(), size, true);
11201 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11202 emitDispCond(cfi.cond);
11205 case IF_DR_3E: // DR_3E X........X.mmmmm ssssssnnnnnddddd Rd Rn Rm imm(0-63)
11206 emitDispReg(id->idReg1(), size, true);
11207 emitDispReg(id->idReg2(), size, true);
11208 emitDispReg(id->idReg3(), size, true);
11209 emitDispImm(emitGetInsSC(id), false);
11212 case IF_DR_4A: // DR_4A X..........mmmmm .aaaaannnnnmmmmm Rd Rn Rm Ra
11213 emitDispReg(id->idReg1(), size, true);
11214 emitDispReg(id->idReg2(), size, true);
11215 emitDispReg(id->idReg3(), size, true);
11216 emitDispReg(id->idReg4(), size, false);
11219 case IF_DV_1A: // DV_1A .........X.iiiii iii........ddddd Vd imm8 (fmov - immediate scalar)
11220 elemsize = id->idOpSize();
11221 emitDispReg(id->idReg1(), elemsize, true);
11222 emitDispFloatImm(emitGetInsSC(id));
11225 case IF_DV_1B: // DV_1B .QX..........iii cmod..iiiiiddddd Vd imm8 (immediate vector)
11226 imm = emitGetInsSC(id) & 0x0ff;
11227 immShift = (emitGetInsSC(id) & 0x700) >> 8;
11228 hasShift = (immShift != 0);
11229 elemsize = optGetElemsize(id->idInsOpt());
11230 if (id->idInsOpt() == INS_OPTS_1D)
11232 assert(elemsize == size);
11233 emitDispReg(id->idReg1(), size, true);
11237 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11239 if (ins == INS_fmov)
11241 emitDispFloatImm(imm);
11242 assert(hasShift == false);
11246 if (elemsize == EA_8BYTE)
11248 assert(ins == INS_movi);
11250 const ssize_t mask8 = 0xFF;
11251 for (unsigned b = 0; b < 8; b++)
11253 if (imm & (1 << b))
11255 imm64 |= (mask8 << (b * 8));
11258 emitDispImm(imm64, hasShift, true);
11262 emitDispImm(imm, hasShift, true);
11266 insOpts opt = (immShift & 0x4) ? INS_OPTS_MSL : INS_OPTS_LSL;
11267 unsigned shift = (immShift & 0x3) * 8;
11268 emitDispShiftOpts(opt);
11269 emitDispImm(shift, false);
11274 case IF_DV_1C: // DV_1C .........X...... ......nnnnn..... Vn #0.0 (fcmp - with zero)
11275 elemsize = id->idOpSize();
11276 emitDispReg(id->idReg1(), elemsize, true);
11277 emitDispFloatZero();
11280 case IF_DV_2A: // DV_2A .Q.......X...... ......nnnnnddddd Vd Vn (fabs, fcvt - vector)
11281 case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
11282 case IF_DV_2P: // DV_2P ................ ......nnnnnddddd Vd Vn (aes*, sha1su1)
11283 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11284 emitDispVectorReg(id->idReg2(), id->idInsOpt(), false);
11287 case IF_DV_2N: // DV_2N .........iiiiiii ......nnnnnddddd Vd Vn imm (shift - scalar)
11288 elemsize = id->idOpSize();
11289 emitDispReg(id->idReg1(), elemsize, true);
11290 emitDispReg(id->idReg2(), elemsize, true);
11291 emitDispImm(emitGetInsSC(id), false);
11294 case IF_DV_2O: // DV_2O .Q.......iiiiiii ......nnnnnddddd Vd Vn imm (shift - vector)
11295 imm = emitGetInsSC(id);
11296 // Do we have a sxtl or uxtl instruction?
11297 isExtendAlias = ((ins == INS_sxtl) || (ins == INS_sxtl2) || (ins == INS_uxtl) || (ins == INS_uxtl2));
11298 code = emitInsCode(ins, fmt);
11299 if (code & 0x00008000) // widen/narrow opcodes
11301 if (code & 0x00002000) // SHL opcodes
11303 emitDispVectorReg(id->idReg1(), optWidenElemsize(id->idInsOpt()), true);
11304 emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11306 else // SHR opcodes
11308 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11309 emitDispVectorReg(id->idReg2(), optWidenElemsize(id->idInsOpt()), !isExtendAlias);
11314 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11315 emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11317 // Print the immediate unless we have a sxtl or uxtl instruction
11318 if (!isExtendAlias)
11320 emitDispImm(imm, false);
11324 case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov/smov - to general)
11325 srcsize = id->idOpSize();
11326 index = emitGetInsSC(id);
11327 if (ins == INS_smov)
11329 dstsize = EA_8BYTE;
11331 else // INS_umov or INS_mov
11333 dstsize = (srcsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE;
11335 emitDispReg(id->idReg1(), dstsize, true);
11336 emitDispVectorRegIndex(id->idReg2(), srcsize, index, false);
11339 case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
11340 if (ins == INS_dup)
11342 datasize = id->idOpSize();
11343 assert(isValidVectorDatasize(datasize));
11344 assert(isValidArrangement(datasize, id->idInsOpt()));
11345 elemsize = optGetElemsize(id->idInsOpt());
11346 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11350 elemsize = id->idOpSize();
11351 index = emitGetInsSC(id);
11352 assert(isValidVectorElemsize(elemsize));
11353 emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11355 emitDispReg(id->idReg2(), (elemsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE, false);
11358 case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
11359 datasize = id->idOpSize();
11360 assert(isValidVectorDatasize(datasize));
11361 assert(isValidArrangement(datasize, id->idInsOpt()));
11362 elemsize = optGetElemsize(id->idInsOpt());
11363 index = emitGetInsSC(id);
11364 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11365 emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11368 case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
11369 elemsize = id->idOpSize();
11370 index = emitGetInsSC(id);
11371 emitDispReg(id->idReg1(), elemsize, true);
11372 emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11375 case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
11376 imm = emitGetInsSC(id);
11377 index = (imm >> 4) & 0xf;
11378 index2 = imm & 0xf;
11379 elemsize = id->idOpSize();
11380 emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11381 emitDispVectorRegIndex(id->idReg2(), elemsize, index2, false);
11384 case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov, fcvtXX - register)
11385 case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
11386 case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
11387 elemsize = id->idOpSize();
11388 emitDispReg(id->idReg1(), elemsize, true);
11389 emitDispReg(id->idReg2(), elemsize, false);
11392 case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov, fcvtXX - to general)
11393 case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov, Xcvtf - from general)
11394 case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
11395 dstsize = optGetDstsize(id->idInsOpt());
11396 srcsize = optGetSrcsize(id->idInsOpt());
11398 emitDispReg(id->idReg1(), dstsize, true);
11399 emitDispReg(id->idReg2(), srcsize, false);
11402 case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11403 case IF_DV_3B: // DV_3B .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11404 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11405 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11406 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11409 case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11410 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11411 if (ins != INS_mov)
11413 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11415 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11418 case IF_DV_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
11419 case IF_DV_3BI: // DV_3BI .Q........Lmmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
11420 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11421 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11422 elemsize = optGetElemsize(id->idInsOpt());
11423 emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11426 case IF_DV_3D: // DV_3D .........X.mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
11427 case IF_DV_3E: // DV_3E ...........mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
11428 emitDispReg(id->idReg1(), size, true);
11429 emitDispReg(id->idReg2(), size, true);
11430 emitDispReg(id->idReg3(), size, false);
11433 case IF_DV_3F: // DV_3F ..........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11434 if ((ins == INS_sha1c) || (ins == INS_sha1m) || (ins == INS_sha1p))
11436 // Qd, Sn, Vm (vector)
11437 emitDispReg(id->idReg1(), size, true);
11438 emitDispReg(id->idReg2(), EA_4BYTE, true);
11439 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11443 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11444 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11445 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11449 case IF_DV_3DI: // DV_3DI .........XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (scalar by elem)
11450 emitDispReg(id->idReg1(), size, true);
11451 emitDispReg(id->idReg2(), size, true);
11453 emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11456 case IF_DV_4A: // DV_4A .........X.mmmmm .aaaaannnnnddddd Vd Va Vn Vm (scalar)
11457 emitDispReg(id->idReg1(), size, true);
11458 emitDispReg(id->idReg2(), size, true);
11459 emitDispReg(id->idReg3(), size, true);
11460 emitDispReg(id->idReg4(), size, false);
11463 case IF_SN_0A: // SN_0A ................ ................
11466 case IF_SI_0A: // SI_0A ...........iiiii iiiiiiiiiii..... imm16
11467 emitDispImm(emitGetInsSC(id), false);
11470 case IF_SI_0B: // SI_0B ................ ....bbbb........ imm4 - barrier
11471 emitDispBarrier((insBarrier)emitGetInsSC(id));
11475 printf("unexpected format %s", emitIfName(id->idInsFmt()));
11476 assert(!"unexpectedFormat");
11480 if (id->idDebugOnlyInfo()->idVarRefOffs)
11483 emitDispFrameRef(id->idAddr()->iiaLclVar.lvaVarNum(), id->idAddr()->iiaLclVar.lvaOffset(),
11484 id->idDebugOnlyInfo()->idVarRefOffs, asmfm);
11490 /*****************************************************************************
11492 * Display a stack frame reference.
11495 void emitter::emitDispFrameRef(int varx, int disp, int offs, bool asmfm)
11500 printf("TEMP_%02u", -varx);
11502 emitComp->gtDispLclVar(+varx, false);
11505 printf("-0x%02x", -disp);
11507 printf("+0x%02x", +disp);
11511 if (varx >= 0 && emitComp->opts.varNames)
11514 const char* varName;
11516 assert((unsigned)varx < emitComp->lvaCount);
11517 varDsc = emitComp->lvaTable + varx;
11518 varName = emitComp->compLocalVarName(varx, offs);
11522 printf("'%s", varName);
11525 printf("-%d", -disp);
11527 printf("+%d", +disp);
11536 // Generate code for a load or store operation with a potentially complex addressing mode
11537 // This method handles the case of a GT_IND with contained GT_LEA op1 of the x86 form [base + index*sccale + offset]
11538 // Since Arm64 does not directly support this complex of an addressing mode
11539 // we may generates up to three instructions for this for Arm64
11541 void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataReg, GenTreeIndir* indir)
11543 emitAttr ldstAttr = isVectorRegister(dataReg) ? attr : emitInsAdjustLoadStoreAttr(ins, attr);
11545 GenTree* addr = indir->Addr();
11547 if (addr->isContained())
11549 assert(addr->OperGet() == GT_LCL_VAR_ADDR || addr->OperGet() == GT_LEA);
11554 if (addr->OperGet() == GT_LEA)
11556 offset = addr->AsAddrMode()->Offset();
11557 if (addr->AsAddrMode()->gtScale > 0)
11559 assert(isPow2(addr->AsAddrMode()->gtScale));
11560 BitScanForward(&lsl, addr->AsAddrMode()->gtScale);
11564 GenTree* memBase = indir->Base();
11566 if (indir->HasIndex())
11568 GenTree* index = indir->Index();
11572 regNumber tmpReg = indir->GetSingleTempReg();
11574 emitAttr addType = varTypeIsGC(memBase) ? EA_BYREF : EA_PTRSIZE;
11576 if (emitIns_valid_imm_for_add(offset, EA_8BYTE))
11580 // Generate code to set tmpReg = base + index*scale
11581 emitIns_R_R_R_I(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum, lsl,
11586 // Generate code to set tmpReg = base + index
11587 emitIns_R_R_R(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum);
11590 noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11592 // Then load/store dataReg from/to [tmpReg + offset]
11593 emitIns_R_R_I(ins, ldstAttr, dataReg, tmpReg, offset);
11595 else // large offset
11597 // First load/store tmpReg with the large offset constant
11598 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11599 // Then add the base register
11601 emitIns_R_R_R(INS_add, addType, tmpReg, tmpReg, memBase->gtRegNum);
11603 noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11604 noway_assert(tmpReg != index->gtRegNum);
11606 // Then load/store dataReg from/to [tmpReg + index*scale]
11607 emitIns_R_R_R_I(ins, ldstAttr, dataReg, tmpReg, index->gtRegNum, lsl, INS_OPTS_LSL);
11610 else // (offset == 0)
11614 // Then load/store dataReg from/to [memBase + index*scale]
11615 emitIns_R_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum, lsl, INS_OPTS_LSL);
11619 // Then load/store dataReg from/to [memBase + index]
11620 emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum);
11624 else // no Index register
11626 if (emitIns_valid_imm_for_ldst_offset(offset, EA_SIZE(attr)))
11628 // Then load/store dataReg from/to [memBase + offset]
11629 emitIns_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, offset);
11633 // We require a tmpReg to hold the offset
11634 regNumber tmpReg = indir->GetSingleTempReg();
11636 // First load/store tmpReg with the large offset constant
11637 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11639 // Then load/store dataReg from/to [memBase + tmpReg]
11640 emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, tmpReg);
11644 else // addr is not contained, so we evaluate it into a register
11646 // Then load/store dataReg from/to [addrReg]
11647 emitIns_R_R(ins, ldstAttr, dataReg, addr->gtRegNum);
11651 // The callee must call genConsumeReg() for any non-contained srcs
11652 // and genProduceReg() for any non-contained dsts.
11654 regNumber emitter::emitInsBinary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src)
11656 regNumber result = REG_NA;
11658 // dst can only be a reg
11659 assert(!dst->isContained());
11661 // src can be immed or reg
11662 assert(!src->isContained() || src->isContainedIntOrIImmed());
11664 // find immed (if any) - it cannot be a dst
11665 GenTreeIntConCommon* intConst = nullptr;
11666 if (src->isContainedIntOrIImmed())
11668 intConst = src->AsIntConCommon();
11673 emitIns_R_I(ins, attr, dst->gtRegNum, intConst->IconValue());
11674 return dst->gtRegNum;
11678 emitIns_R_R(ins, attr, dst->gtRegNum, src->gtRegNum);
11679 return dst->gtRegNum;
11683 // The callee must call genConsumeReg() for any non-contained srcs
11684 // and genProduceReg() for any non-contained dsts.
11686 regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src1, GenTree* src2)
11688 regNumber result = REG_NA;
11690 // dst can only be a reg
11691 assert(!dst->isContained());
11693 // find immed (if any) - it cannot be a dst
11694 // Only one src can be an int.
11695 GenTreeIntConCommon* intConst = nullptr;
11696 GenTree* nonIntReg = nullptr;
11698 if (varTypeIsFloating(dst))
11700 // src1 can only be a reg
11701 assert(!src1->isContained());
11702 // src2 can only be a reg
11703 assert(!src2->isContained());
11705 else // not floating point
11707 // src2 can be immed or reg
11708 assert(!src2->isContained() || src2->isContainedIntOrIImmed());
11710 // Check src2 first as we can always allow it to be a contained immediate
11711 if (src2->isContainedIntOrIImmed())
11713 intConst = src2->AsIntConCommon();
11716 // Only for commutative operations do we check src1 and allow it to be a contained immediate
11717 else if (dst->OperIsCommutative())
11719 // src1 can be immed or reg
11720 assert(!src1->isContained() || src1->isContainedIntOrIImmed());
11722 // Check src1 and allow it to be a contained immediate
11723 if (src1->isContainedIntOrIImmed())
11725 assert(!src2->isContainedIntOrIImmed());
11726 intConst = src1->AsIntConCommon();
11732 // src1 can only be a reg
11733 assert(!src1->isContained());
11737 bool isMulOverflow = false;
11738 if (dst->gtOverflowEx())
11740 if ((ins == INS_add) || (ins == INS_adds))
11744 else if ((ins == INS_sub) || (ins == INS_subs))
11748 else if (ins == INS_mul)
11750 isMulOverflow = true;
11751 assert(intConst == nullptr); // overflow format doesn't support an int constant operand
11755 assert(!"Invalid ins for overflow check");
11758 if (intConst != nullptr)
11760 emitIns_R_R_I(ins, attr, dst->gtRegNum, nonIntReg->gtRegNum, intConst->IconValue());
11766 regNumber extraReg = dst->GetSingleTempReg();
11767 assert(extraReg != dst->gtRegNum);
11769 if ((dst->gtFlags & GTF_UNSIGNED) != 0)
11771 if (attr == EA_4BYTE)
11773 // Compute 8 byte results from 4 byte by 4 byte multiplication.
11774 emitIns_R_R_R(INS_umull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11776 // Get the high result by shifting dst.
11777 emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11781 assert(attr == EA_8BYTE);
11782 // Compute the high result.
11783 emitIns_R_R_R(INS_umulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11785 // Now multiply without skewing the high result.
11786 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11789 // zero-sign bit comparison to detect overflow.
11790 emitIns_R_I(INS_cmp, attr, extraReg, 0);
11795 if (attr == EA_4BYTE)
11797 // Compute 8 byte results from 4 byte by 4 byte multiplication.
11798 emitIns_R_R_R(INS_smull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11800 // Get the high result by shifting dst.
11801 emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11807 assert(attr == EA_8BYTE);
11808 // Save the high result in a temporary register.
11809 emitIns_R_R_R(INS_smulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11811 // Now multiply without skewing the high result.
11812 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11817 // Sign bit comparison to detect overflow.
11818 emitIns_R_R_I(INS_cmp, attr, extraReg, dst->gtRegNum, bitShift, INS_OPTS_ASR);
11823 // We can just multiply.
11824 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11828 if (dst->gtOverflowEx())
11830 assert(!varTypeIsFloating(dst));
11831 codeGen->genCheckOverflow(dst);
11834 return dst->gtRegNum;
11837 #endif // defined(_TARGET_ARM64_)