1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
5 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
6 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
10 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
11 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
19 #if defined(_TARGET_ARM64_)
21 /*****************************************************************************/
22 /*****************************************************************************/
28 /* static */ bool emitter::strictArmAsm = true;
30 /*****************************************************************************/
32 const instruction emitJumpKindInstructions[] = {
35 #define JMP_SMALL(en, rev, ins) INS_##ins,
39 const emitJumpKind emitReverseJumpKinds[] = {
42 #define JMP_SMALL(en, rev, ins) EJ_##rev,
46 /*****************************************************************************
47 * Look up the instruction for a jump kind
50 /*static*/ instruction emitter::emitJumpKindToIns(emitJumpKind jumpKind)
52 assert((unsigned)jumpKind < ArrLen(emitJumpKindInstructions));
53 return emitJumpKindInstructions[jumpKind];
56 /*****************************************************************************
57 * Look up the jump kind for an instruction. It better be a conditional
58 * branch instruction with a jump kind!
61 /*static*/ emitJumpKind emitter::emitInsToJumpKind(instruction ins)
63 for (unsigned i = 0; i < ArrLen(emitJumpKindInstructions); i++)
65 if (ins == emitJumpKindInstructions[i])
67 emitJumpKind ret = (emitJumpKind)i;
68 assert(EJ_NONE < ret && ret < EJ_COUNT);
75 /*****************************************************************************
76 * Reverse the conditional jump
79 /*static*/ emitJumpKind emitter::emitReverseJumpKind(emitJumpKind jumpKind)
81 assert(jumpKind < EJ_COUNT);
82 return emitReverseJumpKinds[jumpKind];
85 /*****************************************************************************
87 * Return the allocated size (in bytes) of the given instruction descriptor.
90 size_t emitter::emitSizeOfInsDsc(instrDesc* id)
92 assert(!emitIsTinyInsDsc(id));
94 if (emitIsScnsInsDsc(id))
95 return SMALL_IDSC_SIZE;
97 assert((unsigned)id->idInsFmt() < emitFmtCount);
99 ID_OPS idOp = (ID_OPS)emitFmtToOps[id->idInsFmt()];
100 bool isCallIns = (id->idIns() == INS_bl) || (id->idIns() == INS_blr) || (id->idIns() == INS_b_tail) ||
101 (id->idIns() == INS_br_tail);
102 bool maybeCallIns = (id->idIns() == INS_b) || (id->idIns() == INS_br);
110 return sizeof(instrDescJmp);
113 assert(isCallIns || maybeCallIns);
114 if (id->idIsLargeCall())
116 /* Must be a "fat" call descriptor */
117 return sizeof(instrDescCGCA);
121 assert(!id->idIsLargeDsp());
122 assert(!id->idIsLargeCns());
123 return sizeof(instrDesc);
128 NO_WAY("unexpected instruction descriptor format");
132 if (id->idIsLargeCns())
134 if (id->idIsLargeDsp())
135 return sizeof(instrDescCnsDsp);
137 return sizeof(instrDescCns);
141 if (id->idIsLargeDsp())
142 return sizeof(instrDescDsp);
144 return sizeof(instrDesc);
149 /*****************************************************************************
151 * The following called for each recorded instruction -- use for debugging.
153 void emitter::emitInsSanityCheck(instrDesc* id)
155 /* What instruction format have we got? */
157 switch (id->idInsFmt())
169 case IF_BI_0A: // BI_0A ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
172 case IF_BI_0B: // BI_0B ......iiiiiiiiii iiiiiiiiiiii.... simm19:00
180 case IF_BI_0C: // BI_0C ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
183 case IF_BI_1A: // BI_1A ......iiiiiiiiii iiiiiiiiiiittttt Rt simm19:00
184 assert(isValidGeneralDatasize(id->idOpSize()));
185 assert(isGeneralRegister(id->idReg1()));
188 case IF_BI_1B: // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
189 assert(isValidGeneralDatasize(id->idOpSize()));
190 assert(isGeneralRegister(id->idReg1()));
191 assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
194 case IF_BR_1A: // BR_1A ................ ......nnnnn..... Rn
195 assert(isGeneralRegister(id->idReg1()));
198 case IF_BR_1B: // BR_1B ................ ......nnnnn..... Rn
199 assert(isGeneralRegister(id->idReg3()));
202 case IF_LS_1A: // LS_1A .X......iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB)
203 assert(isGeneralRegister(id->idReg1()) || isVectorRegister(id->idReg1()));
204 assert(insOptsNone(id->idInsOpt()));
207 case IF_LS_2A: // LS_2A .X.......X...... ......nnnnnttttt Rt Rn
208 assert(isIntegerRegister(id->idReg1()) || // ZR
209 isVectorRegister(id->idReg1()));
210 assert(isIntegerRegister(id->idReg2())); // SP
211 assert(emitGetInsSC(id) == 0);
212 assert(insOptsNone(id->idInsOpt()));
215 case IF_LS_2B: // LS_2B .X.......Xiiiiii iiiiiinnnnnttttt Rt Rn imm(0-4095)
216 assert(isIntegerRegister(id->idReg1()) || // ZR
217 isVectorRegister(id->idReg1()));
218 assert(isIntegerRegister(id->idReg2())); // SP
219 assert(isValidUimm12(emitGetInsSC(id)));
220 assert(insOptsNone(id->idInsOpt()));
223 case IF_LS_2C: // LS_2C .X.......X.iiiii iiiiPPnnnnnttttt Rt Rn imm(-256..+255) no/pre/post inc
224 assert(isIntegerRegister(id->idReg1()) || // ZR
225 isVectorRegister(id->idReg1()));
226 assert(isIntegerRegister(id->idReg2())); // SP
227 assert(emitGetInsSC(id) >= -0x100);
228 assert(emitGetInsSC(id) < 0x100);
229 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
232 case IF_LS_3A: // LS_3A .X.......X.mmmmm oooS..nnnnnttttt Rt Rn Rm ext(Rm) LSL {}
233 assert(isIntegerRegister(id->idReg1()) || // ZR
234 isVectorRegister(id->idReg1()));
235 assert(isIntegerRegister(id->idReg2())); // SP
236 if (id->idIsLclVar())
238 assert(isGeneralRegister(codeGen->rsGetRsvdReg()));
242 assert(isGeneralRegister(id->idReg3()));
244 assert(insOptsLSExtend(id->idInsOpt()));
247 case IF_LS_3B: // LS_3B X............... .aaaaannnnnttttt Rt Ra Rn
248 assert((isValidGeneralDatasize(id->idOpSize()) && isIntegerRegister(id->idReg1())) ||
249 (isValidVectorLSPDatasize(id->idOpSize()) && isVectorRegister(id->idReg1())));
250 assert(isIntegerRegister(id->idReg1()) || // ZR
251 isVectorRegister(id->idReg1()));
252 assert(isIntegerRegister(id->idReg2()) || // ZR
253 isVectorRegister(id->idReg2()));
254 assert(isIntegerRegister(id->idReg3())); // SP
255 assert(emitGetInsSC(id) == 0);
256 assert(insOptsNone(id->idInsOpt()));
259 case IF_LS_3C: // LS_3C X.........iiiiii iaaaaannnnnttttt Rt Ra Rn imm(im7,sh)
260 assert((isValidGeneralDatasize(id->idOpSize()) && isIntegerRegister(id->idReg1())) ||
261 (isValidVectorLSPDatasize(id->idOpSize()) && isVectorRegister(id->idReg1())));
262 assert(isIntegerRegister(id->idReg1()) || // ZR
263 isVectorRegister(id->idReg1()));
264 assert(isIntegerRegister(id->idReg2()) || // ZR
265 isVectorRegister(id->idReg2()));
266 assert(isIntegerRegister(id->idReg3())); // SP
267 assert(emitGetInsSC(id) >= -0x40);
268 assert(emitGetInsSC(id) < 0x40);
269 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
272 case IF_LS_3D: // LS_3D .X.......X.mmmmm ......nnnnnttttt Wm Rt Rn
273 assert(isIntegerRegister(id->idReg1()));
274 assert(isIntegerRegister(id->idReg2()));
275 assert(isIntegerRegister(id->idReg3()));
276 assert(emitGetInsSC(id) == 0);
277 assert(!id->idIsLclVar());
278 assert(insOptsNone(id->idInsOpt()));
281 case IF_DI_1A: // DI_1A X.......shiiiiii iiiiiinnnnn..... Rn imm(i12,sh)
282 assert(isValidGeneralDatasize(id->idOpSize()));
283 assert(isGeneralRegister(id->idReg1()));
284 assert(isValidUimm12(emitGetInsSC(id)));
285 assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
288 case IF_DI_1B: // DI_1B X........hwiiiii iiiiiiiiiiiddddd Rd imm(i16,hw)
289 assert(isValidGeneralDatasize(id->idOpSize()));
290 assert(isGeneralRegister(id->idReg1()));
291 assert(isValidImmHWVal(emitGetInsSC(id), id->idOpSize()));
294 case IF_DI_1C: // DI_1C X........Nrrrrrr ssssssnnnnn..... Rn imm(N,r,s)
295 assert(isValidGeneralDatasize(id->idOpSize()));
296 assert(isGeneralRegister(id->idReg1()));
297 assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
300 case IF_DI_1D: // DI_1D X........Nrrrrrr ssssss.....ddddd Rd imm(N,r,s)
301 assert(isValidGeneralDatasize(id->idOpSize()));
302 assert(isIntegerRegister(id->idReg1())); // SP
303 assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
306 case IF_DI_1E: // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
307 assert(isGeneralRegister(id->idReg1()));
310 case IF_DI_1F: // DI_1F X..........iiiii cccc..nnnnn.nzcv Rn imm5 nzcv cond
311 assert(isValidGeneralDatasize(id->idOpSize()));
312 assert(isGeneralRegister(id->idReg1()));
313 assert(isValidImmCondFlagsImm5(emitGetInsSC(id)));
316 case IF_DI_2A: // DI_2A X.......shiiiiii iiiiiinnnnnddddd Rd Rn imm(i12,sh)
317 assert(isValidGeneralDatasize(id->idOpSize()));
318 assert(isIntegerRegister(id->idReg1())); // SP
319 assert(isIntegerRegister(id->idReg2())); // SP
320 assert(isValidUimm12(emitGetInsSC(id)));
321 assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
324 case IF_DI_2B: // DI_2B X.........Xnnnnn ssssssnnnnnddddd Rd Rn imm(0-63)
325 assert(isValidGeneralDatasize(id->idOpSize()));
326 assert(isGeneralRegister(id->idReg1()));
327 assert(isGeneralRegister(id->idReg2()));
328 assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
331 case IF_DI_2C: // DI_2C X........Nrrrrrr ssssssnnnnnddddd Rd Rn imm(N,r,s)
332 assert(isValidGeneralDatasize(id->idOpSize()));
333 assert(isIntegerRegister(id->idReg1())); // SP
334 assert(isGeneralRegister(id->idReg2()));
335 assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
338 case IF_DI_2D: // DI_2D X........Nrrrrrr ssssssnnnnnddddd Rd Rn imr, imms (N,r,s)
339 assert(isValidGeneralDatasize(id->idOpSize()));
340 assert(isGeneralRegister(id->idReg1()));
341 assert(isGeneralRegister(id->idReg2()));
342 assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
345 case IF_DR_1D: // DR_1D X............... cccc.......ddddd Rd cond
346 assert(isValidGeneralDatasize(id->idOpSize()));
347 assert(isGeneralRegister(id->idReg1()));
348 assert(isValidImmCond(emitGetInsSC(id)));
351 case IF_DR_2A: // DR_2A X..........mmmmm ......nnnnn..... Rn Rm
352 assert(isValidGeneralDatasize(id->idOpSize()));
353 assert(isGeneralRegister(id->idReg1()));
354 assert(isGeneralRegister(id->idReg2()));
357 case IF_DR_2B: // DR_2B X.......sh.mmmmm ssssssnnnnn..... Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
358 assert(isValidGeneralDatasize(id->idOpSize()));
359 assert(isIntegerRegister(id->idReg1())); // ZR
360 assert(isGeneralRegister(id->idReg2()));
361 assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
362 if (!insOptsNone(id->idInsOpt()))
364 if (id->idIns() == INS_tst) // tst allows ROR, cmp/cmn don't
366 assert(insOptsAnyShift(id->idInsOpt()));
370 assert(insOptsAluShift(id->idInsOpt()));
373 assert(insOptsNone(id->idInsOpt()) || (emitGetInsSC(id) > 0));
376 case IF_DR_2C: // DR_2C X..........mmmmm ooosssnnnnn..... Rn Rm ext(Rm) LSL imm(0-4)
377 assert(isValidGeneralDatasize(id->idOpSize()));
378 assert(isIntegerRegister(id->idReg1())); // SP
379 assert(isGeneralRegister(id->idReg2()));
380 assert(insOptsNone(id->idInsOpt()) || insOptsLSL(id->idInsOpt()) || insOptsAnyExtend(id->idInsOpt()));
381 assert(emitGetInsSC(id) >= 0);
382 assert(emitGetInsSC(id) <= 4);
383 if (insOptsLSL(id->idInsOpt()))
385 assert(emitGetInsSC(id) > 0);
389 case IF_DR_2D: // DR_2D X..........nnnnn cccc..nnnnnmmmmm Rd Rn cond
390 assert(isValidGeneralDatasize(id->idOpSize()));
391 assert(isGeneralRegister(id->idReg1()));
392 assert(isGeneralRegister(id->idReg2()));
393 assert(isValidImmCond(emitGetInsSC(id)));
396 case IF_DR_2E: // DR_2E X..........mmmmm ...........ddddd Rd Rm
397 assert(isValidGeneralDatasize(id->idOpSize()));
398 assert(isGeneralRegister(id->idReg1()));
399 assert(isIntegerRegister(id->idReg2())); // ZR
402 case IF_DR_2F: // DR_2F X.......sh.mmmmm ssssss.....ddddd Rd Rm {LSL,LSR,ASR} imm(0-63)
403 assert(isValidGeneralDatasize(id->idOpSize()));
404 assert(isGeneralRegister(id->idReg1()));
405 assert(isGeneralRegister(id->idReg2()));
406 assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
407 assert(insOptsNone(id->idInsOpt()) || insOptsAluShift(id->idInsOpt()));
408 assert(insOptsNone(id->idInsOpt()) || (emitGetInsSC(id) > 0));
411 case IF_DR_2G: // DR_2G X............... ......nnnnnddddd Rd Rm
412 assert(isValidGeneralDatasize(id->idOpSize()));
413 assert(isIntegerRegister(id->idReg1())); // SP
414 assert(isIntegerRegister(id->idReg2())); // SP
417 case IF_DR_2H: // DR_2H X........X...... ......nnnnnddddd Rd Rn
418 assert(isValidGeneralDatasize(id->idOpSize()));
419 assert(isGeneralRegister(id->idReg1()));
420 assert(isGeneralRegister(id->idReg2()));
423 case IF_DR_2I: // DR_2I X..........mmmmm cccc..nnnnn.nzcv Rn Rm nzcv cond
424 assert(isValidGeneralDatasize(id->idOpSize()));
425 assert(isGeneralRegister(id->idReg1()));
426 assert(isGeneralRegister(id->idReg2()));
427 assert(isValidImmCondFlags(emitGetInsSC(id)));
430 case IF_DR_2J: // DR_2J ................ ......nnnnnddddd Sd Sn (sha1h)
431 assert(isValidGeneralDatasize(id->idOpSize()));
432 assert(isVectorRegister(id->idReg1()));
433 assert(isVectorRegister(id->idReg2()));
436 case IF_DR_3A: // DR_3A X..........mmmmm ......nnnnnmmmmm Rd Rn Rm
437 assert(isValidGeneralDatasize(id->idOpSize()));
438 assert(isIntegerRegister(id->idReg1())); // SP
439 assert(isIntegerRegister(id->idReg2())); // SP
440 if (id->idIsLclVar())
442 assert(isGeneralRegister(codeGen->rsGetRsvdReg()));
446 assert(isGeneralRegister(id->idReg3()));
448 assert(insOptsNone(id->idInsOpt()));
451 case IF_DR_3B: // DR_3B X.......sh.mmmmm ssssssnnnnnddddd Rd Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
452 assert(isValidGeneralDatasize(id->idOpSize()));
453 assert(isGeneralRegister(id->idReg1()));
454 assert(isGeneralRegister(id->idReg2()));
455 assert(isGeneralRegister(id->idReg3()));
456 assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
457 assert(insOptsNone(id->idInsOpt()) || insOptsAnyShift(id->idInsOpt()));
458 assert(insOptsNone(id->idInsOpt()) || (emitGetInsSC(id) > 0));
461 case IF_DR_3C: // DR_3C X..........mmmmm ooosssnnnnnddddd Rd Rn Rm ext(Rm) LSL imm(0-4)
462 assert(isValidGeneralDatasize(id->idOpSize()));
463 assert(isIntegerRegister(id->idReg1())); // SP
464 assert(isIntegerRegister(id->idReg2())); // SP
465 assert(isGeneralRegister(id->idReg3()));
466 assert(insOptsNone(id->idInsOpt()) || insOptsLSL(id->idInsOpt()) || insOptsAnyExtend(id->idInsOpt()));
467 assert(emitGetInsSC(id) >= 0);
468 assert(emitGetInsSC(id) <= 4);
469 if (insOptsLSL(id->idInsOpt()))
471 assert((emitGetInsSC(id) > 0) ||
472 (id->idReg2() == REG_ZR)); // REG_ZR encodes SP and we allow a shift of zero
476 case IF_DR_3D: // DR_3D X..........mmmmm cccc..nnnnnmmmmm Rd Rn Rm cond
477 assert(isValidGeneralDatasize(id->idOpSize()));
478 assert(isGeneralRegister(id->idReg1()));
479 assert(isGeneralRegister(id->idReg2()));
480 assert(isGeneralRegister(id->idReg3()));
481 assert(isValidImmCond(emitGetInsSC(id)));
484 case IF_DR_3E: // DR_3E X........X.mmmmm ssssssnnnnnddddd Rd Rn Rm imm(0-63)
485 assert(isValidGeneralDatasize(id->idOpSize()));
486 assert(isGeneralRegister(id->idReg1()));
487 assert(isGeneralRegister(id->idReg2()));
488 assert(isGeneralRegister(id->idReg3()));
489 assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
490 assert(insOptsNone(id->idInsOpt()));
493 case IF_DR_4A: // DR_4A X..........mmmmm .aaaaannnnnddddd Rd Rn Rm Ra
494 assert(isValidGeneralDatasize(id->idOpSize()));
495 assert(isGeneralRegister(id->idReg1()));
496 assert(isGeneralRegister(id->idReg2()));
497 assert(isGeneralRegister(id->idReg3()));
498 assert(isGeneralRegister(id->idReg4()));
501 case IF_DV_1A: // DV_1A .........X.iiiii iii........ddddd Vd imm8 (fmov - immediate scalar)
502 assert(insOptsNone(id->idInsOpt()));
503 elemsize = id->idOpSize();
504 assert(isValidVectorElemsizeFloat(elemsize));
505 assert(isVectorRegister(id->idReg1()));
506 assert(isValidUimm8(emitGetInsSC(id)));
509 case IF_DV_1B: // DV_1B .QX..........iii cmod..iiiiiddddd Vd imm8 (immediate vector)
511 imm = emitGetInsSC(id) & 0x0ff;
512 immShift = (emitGetInsSC(id) & 0x700) >> 8;
513 assert(immShift >= 0);
514 datasize = id->idOpSize();
515 assert(isValidVectorDatasize(datasize));
516 assert(isValidArrangement(datasize, id->idInsOpt()));
517 elemsize = optGetElemsize(id->idInsOpt());
520 assert(isValidVectorElemsizeFloat(elemsize));
521 assert(id->idInsOpt() != INS_OPTS_1D); // Reserved encoding
522 assert(immShift == 0);
526 assert(isValidVectorElemsize(elemsize));
527 assert((immShift != 4) && (immShift != 7)); // always invalid values
528 if (ins != INS_movi) // INS_mvni, INS_orr, INS_bic
530 assert((elemsize != EA_1BYTE) && (elemsize != EA_8BYTE)); // only H or S
531 if (elemsize == EA_2BYTE)
533 assert(immShift < 2);
535 else // (elemsize == EA_4BYTE)
539 assert(immShift < 4);
544 assert(isVectorRegister(id->idReg1()));
545 assert(isValidUimm8(imm));
548 case IF_DV_1C: // DV_1C .........X...... ......nnnnn..... Vn #0.0 (fcmp - with zero)
549 assert(insOptsNone(id->idInsOpt()));
550 elemsize = id->idOpSize();
551 assert(isValidVectorElemsizeFloat(elemsize));
552 assert(isVectorRegister(id->idReg1()));
555 case IF_DV_2A: // DV_2A .Q.......X...... ......nnnnnddddd Vd Vn (fabs, fcvt - vector)
556 case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
557 case IF_DV_2P: // DV_2P ................ ......nnnnnddddd Vd Vn (aes*, sha1su1)
558 assert(isValidVectorDatasize(id->idOpSize()));
559 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
560 assert(isVectorRegister(id->idReg1()));
561 assert(isVectorRegister(id->idReg2()));
564 case IF_DV_2N: // DV_2N .........iiiiiii ......nnnnnddddd Vd Vn imm (shift - scalar)
565 assert(id->idOpSize() == EA_8BYTE);
566 assert(insOptsNone(id->idInsOpt()));
567 assert(isVectorRegister(id->idReg1()));
568 assert(isVectorRegister(id->idReg2()));
569 assert(isValidImmShift(emitGetInsSC(id), EA_8BYTE));
572 case IF_DV_2O: // DV_2O .Q.......iiiiiii ......nnnnnddddd Vd Vn imm (shift - vector)
573 assert(isValidVectorDatasize(id->idOpSize()));
574 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
575 assert(isVectorRegister(id->idReg1()));
576 assert(isVectorRegister(id->idReg2()));
577 elemsize = optGetElemsize(id->idInsOpt());
578 assert(isValidImmShift(emitGetInsSC(id), elemsize));
581 case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov/smov - to general)
582 elemsize = id->idOpSize();
583 index = emitGetInsSC(id);
584 assert(insOptsNone(id->idInsOpt()));
585 assert(isValidVectorIndex(EA_16BYTE, elemsize, index));
586 assert(isValidVectorElemsize(elemsize));
587 assert(isGeneralRegister(id->idReg1()));
588 assert(isVectorRegister(id->idReg2()));
591 case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
592 if (id->idIns() == INS_dup)
594 datasize = id->idOpSize();
595 assert(isValidVectorDatasize(datasize));
596 assert(isValidArrangement(datasize, id->idInsOpt()));
597 elemsize = optGetElemsize(id->idInsOpt());
601 datasize = EA_16BYTE;
602 elemsize = id->idOpSize();
603 assert(isValidVectorElemsize(elemsize));
605 assert(isVectorRegister(id->idReg1()));
606 assert(isGeneralRegisterOrZR(id->idReg2()));
609 case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
610 datasize = id->idOpSize();
611 assert(isValidVectorDatasize(datasize));
612 assert(isValidArrangement(datasize, id->idInsOpt()));
613 elemsize = optGetElemsize(id->idInsOpt());
614 index = emitGetInsSC(id);
615 assert(isValidVectorIndex(datasize, elemsize, index));
616 assert(isVectorRegister(id->idReg1()));
617 assert(isVectorRegister(id->idReg2()));
620 case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
621 elemsize = id->idOpSize();
622 index = emitGetInsSC(id);
623 assert(isValidVectorIndex(EA_16BYTE, elemsize, index));
624 assert(isValidVectorElemsize(elemsize));
625 assert(isVectorRegister(id->idReg1()));
626 assert(isVectorRegister(id->idReg2()));
629 case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
630 imm = emitGetInsSC(id);
631 index = (imm >> 4) & 0xf;
633 elemsize = id->idOpSize();
634 assert(isValidVectorElemsize(elemsize));
635 assert(isValidVectorIndex(EA_16BYTE, elemsize, index));
636 assert(isValidVectorIndex(EA_16BYTE, elemsize, index2));
637 assert(isVectorRegister(id->idReg1()));
638 assert(isVectorRegister(id->idReg2()));
641 case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
642 assert(id->idOpSize() == EA_8BYTE); // only type D is supported
645 case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov, fcvtXX - register)
646 case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
647 assert(insOptsNone(id->idInsOpt()));
648 assert(isValidVectorElemsizeFloat(id->idOpSize()));
649 assert(isVectorRegister(id->idReg1()));
650 assert(isVectorRegister(id->idReg2()));
653 case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov/fcvtXX - to general)
654 assert(insOptsConvertFloatToInt(id->idInsOpt()));
655 dstsize = optGetDstsize(id->idInsOpt());
656 srcsize = optGetSrcsize(id->idInsOpt());
657 assert(isValidGeneralDatasize(dstsize));
658 assert(isValidVectorElemsizeFloat(srcsize));
659 assert(dstsize == id->idOpSize());
660 assert(isGeneralRegister(id->idReg1()));
661 assert(isVectorRegister(id->idReg2()));
664 case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov/Xcvtf - from general)
665 assert(insOptsConvertIntToFloat(id->idInsOpt()));
666 dstsize = optGetDstsize(id->idInsOpt());
667 srcsize = optGetSrcsize(id->idInsOpt());
668 assert(isValidGeneralDatasize(srcsize));
669 assert(isValidVectorElemsizeFloat(dstsize));
670 assert(dstsize == id->idOpSize());
671 assert(isVectorRegister(id->idReg1()));
672 assert(isGeneralRegister(id->idReg2()));
675 case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
676 assert(insOptsConvertFloatToFloat(id->idInsOpt()));
677 dstsize = optGetDstsize(id->idInsOpt());
678 srcsize = optGetSrcsize(id->idInsOpt());
679 assert(isValidVectorFcvtsize(srcsize));
680 assert(isValidVectorFcvtsize(dstsize));
681 assert(dstsize == id->idOpSize());
682 assert(isVectorRegister(id->idReg1()));
683 assert(isVectorRegister(id->idReg2()));
686 case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
687 assert(isValidVectorDatasize(id->idOpSize()));
688 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
689 assert(isVectorRegister(id->idReg1()));
690 assert(isVectorRegister(id->idReg2()));
691 assert(isVectorRegister(id->idReg3()));
692 elemsize = optGetElemsize(id->idInsOpt());
696 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
698 else if (ins == INS_pmul)
700 assert(elemsize == EA_1BYTE); // only supports 8B or 16B
704 case IF_DV_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
705 assert(isValidVectorDatasize(id->idOpSize()));
706 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
707 assert(isVectorRegister(id->idReg1()));
708 assert(isVectorRegister(id->idReg2()));
709 assert(isVectorRegister(id->idReg3()));
710 elemsize = optGetElemsize(id->idInsOpt());
711 assert(isValidVectorIndex(EA_16BYTE, elemsize, emitGetInsSC(id)));
712 // Only has encodings for H or S elemsize
713 assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE));
716 case IF_DV_3B: // DV_3B .Q.......X.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
717 assert(isValidVectorDatasize(id->idOpSize()));
718 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
719 assert(isVectorRegister(id->idReg1()));
720 assert(isVectorRegister(id->idReg2()));
721 assert(isVectorRegister(id->idReg3()));
724 case IF_DV_3BI: // DV_3BI .Q.......XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
725 assert(isValidVectorDatasize(id->idOpSize()));
726 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
727 assert(isVectorRegister(id->idReg1()));
728 assert(isVectorRegister(id->idReg2()));
729 assert(isVectorRegister(id->idReg3()));
730 elemsize = optGetElemsize(id->idInsOpt());
731 assert(isValidVectorIndex(id->idOpSize(), elemsize, emitGetInsSC(id)));
734 case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
735 assert(isValidVectorDatasize(id->idOpSize()));
736 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
737 assert(isVectorRegister(id->idReg1()));
738 assert(isVectorRegister(id->idReg2()));
739 assert(isVectorRegister(id->idReg3()));
742 case IF_DV_3D: // DV_3D .........X.mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
743 assert(isValidScalarDatasize(id->idOpSize()));
744 assert(insOptsNone(id->idInsOpt()));
745 assert(isVectorRegister(id->idReg1()));
746 assert(isVectorRegister(id->idReg2()));
747 assert(isVectorRegister(id->idReg3()));
750 case IF_DV_3DI: // DV_3DI .........XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (scalar by elem)
751 assert(isValidScalarDatasize(id->idOpSize()));
752 assert(insOptsNone(id->idInsOpt()));
753 assert(isVectorRegister(id->idReg1()));
754 assert(isVectorRegister(id->idReg2()));
755 assert(isVectorRegister(id->idReg3()));
756 elemsize = id->idOpSize();
757 assert(isValidVectorIndex(EA_16BYTE, elemsize, emitGetInsSC(id)));
760 case IF_DV_3E: // DV_3E ...........mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
761 assert(insOptsNone(id->idInsOpt()));
762 assert(id->idOpSize() == EA_8BYTE);
763 assert(isVectorRegister(id->idReg1()));
764 assert(isVectorRegister(id->idReg2()));
765 assert(isVectorRegister(id->idReg3()));
768 case IF_DV_3F: // DV_3F ...........mmmmm ......nnnnnddddd Vd Vn Vm
769 assert(isValidVectorDatasize(id->idOpSize()));
770 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
771 assert(isVectorRegister(id->idReg1()));
772 assert(isVectorRegister(id->idReg2()));
773 assert(isVectorRegister(id->idReg3()));
776 case IF_DV_4A: // DR_4A .........X.mmmmm .aaaaannnnnddddd Rd Rn Rm Ra (scalar)
777 assert(isValidGeneralDatasize(id->idOpSize()));
778 assert(isVectorRegister(id->idReg1()));
779 assert(isVectorRegister(id->idReg2()));
780 assert(isVectorRegister(id->idReg3()));
781 assert(isVectorRegister(id->idReg4()));
784 case IF_SN_0A: // SN_0A ................ ................
785 case IF_SI_0A: // SI_0A ...........iiiii iiiiiiiiiii..... imm16
786 case IF_SI_0B: // SI_0B ................ ....bbbb........ imm4 - barrier
790 printf("unexpected format %s\n", emitIfName(id->idInsFmt()));
791 assert(!"Unexpected format");
797 bool emitter::emitInsMayWriteToGCReg(instrDesc* id)
799 instruction ins = id->idIns();
800 insFormat fmt = id->idInsFmt();
805 // These are the formats with "destination" registers:
807 case IF_DI_1B: // DI_1B X........hwiiiii iiiiiiiiiiiddddd Rd imm(i16,hw)
808 case IF_DI_1D: // DI_1D X........Nrrrrrr ssssss.....ddddd Rd imm(N,r,s)
809 case IF_DI_1E: // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
811 case IF_DI_2A: // DI_2A X.......shiiiiii iiiiiinnnnnddddd Rd Rn imm(i12,sh)
812 case IF_DI_2B: // DI_2B X.........Xnnnnn ssssssnnnnnddddd Rd Rn imm(0-63)
813 case IF_DI_2C: // DI_2C X........Nrrrrrr ssssssnnnnnddddd Rd Rn imm(N,r,s)
814 case IF_DI_2D: // DI_2D X........Nrrrrrr ssssssnnnnnddddd Rd Rn imr, imms (N,r,s)
816 case IF_DR_1D: // DR_1D X............... cccc.......ddddd Rd cond
818 case IF_DR_2D: // DR_2D X..........nnnnn cccc..nnnnnddddd Rd Rn cond
819 case IF_DR_2E: // DR_2E X..........mmmmm ...........ddddd Rd Rm
820 case IF_DR_2F: // DR_2F X.......sh.mmmmm ssssss.....ddddd Rd Rm {LSL,LSR,ASR} imm(0-63)
821 case IF_DR_2G: // DR_2G X............... ......nnnnnddddd Rd Rn
822 case IF_DR_2H: // DR_2H X........X...... ......nnnnnddddd Rd Rn
824 case IF_DR_3A: // DR_3A X..........mmmmm ......nnnnnddddd Rd Rn Rm
825 case IF_DR_3B: // DR_3B X.......sh.mmmmm ssssssnnnnnddddd Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
826 case IF_DR_3C: // DR_3C X..........mmmmm xxxsssnnnnnddddd Rd Rn Rm ext(Rm) LSL imm(0-4)
827 case IF_DR_3D: // DR_3D X..........mmmmm cccc..nnnnnddddd Rd Rn Rm cond
828 case IF_DR_3E: // DR_3E X........X.mmmmm ssssssnnnnnddddd Rd Rn Rm imm(0-63)
829 case IF_DV_3F: // DV_3F ...........mmmmm ......nnnnnddddd Vd Vn Vm (vector) - Vd both source and dest
831 case IF_DR_4A: // DR_4A X..........mmmmm .aaaaannnnnddddd Rd Rn Rm Ra
833 case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov - to general)
834 case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov - to general)
838 case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
839 case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
840 case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
841 case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
842 case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov, fcvtXX - register)
843 case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov - from general)
844 case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
845 case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
846 case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
847 case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
848 case IF_DV_2P: // DV_2P ................ ......nnnnnddddd Vd Vn (aes*, sha1su1) - Vd both source and
851 case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
852 case IF_DV_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector)
853 case IF_DV_3B: // DV_3B .Q.......X.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
854 case IF_DV_3BI: // DV_3BI .Q.......XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
855 case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
856 case IF_DV_3D: // DV_3D .........X.mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
857 case IF_DV_3DI: // DV_3DI .........XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (scalar by elem)
858 case IF_DV_3E: // DV_3E ...........mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
859 case IF_DV_4A: // DV_4A .........X.mmmmm .aaaaannnnnddddd Vd Va Vn Vm (scalar)
860 // Tracked GC pointers cannot be placed into the SIMD registers.
863 // These are the load/store formats with "target" registers:
865 case IF_LS_1A: // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB)
866 case IF_LS_2A: // LS_2A .X.......X...... ......nnnnnttttt Rt Rn
867 case IF_LS_2B: // LS_2B .X.......Xiiiiii iiiiiinnnnnttttt Rt Rn imm(0-4095)
868 case IF_LS_2C: // LS_2C .X.......X.iiiii iiiiP.nnnnnttttt Rt Rn imm(-256..+255) pre/post inc
869 case IF_LS_3A: // LS_3A .X.......X.mmmmm xxxS..nnnnnttttt Rt Rn Rm ext(Rm) LSL {}
870 case IF_LS_3B: // LS_3B X............... .aaaaannnnnttttt Rt Ra Rn
871 case IF_LS_3C: // LS_3C X.........iiiiii iaaaaannnnnttttt Rt Ra Rn imm(im7,sh)
872 case IF_LS_3D: // LS_3D .X.......X.mmmmm ......nnnnnttttt Wm Rt Rn
874 // For the Store instructions the "target" register is actually a "source" value
876 if (emitInsIsStore(ins))
882 assert(emitInsIsLoad(ins));
891 bool emitter::emitInsWritesToLclVarStackLoc(instrDesc* id)
893 if (!id->idIsLclVar())
896 instruction ins = id->idIns();
898 // This list is related to the list of instructions used to store local vars in emitIns_S_R().
899 // We don't accept writing to float local vars.
915 bool emitter::emitInsWritesToLclVarStackLocPair(instrDesc* id)
917 if (!id->idIsLclVar())
920 instruction ins = id->idIns();
922 // This list is related to the list of instructions used to store local vars in emitIns_S_S_R_R().
923 // We don't accept writing to float local vars.
935 bool emitter::emitInsMayWriteMultipleRegs(instrDesc* id)
937 instruction ins = id->idIns();
950 // For the small loads/store instruction we adjust the size 'attr'
951 // depending upon whether we have a load or a store
953 emitAttr emitter::emitInsAdjustLoadStoreAttr(instruction ins, emitAttr attr)
955 if (EA_SIZE(attr) <= EA_4BYTE)
957 if (emitInsIsLoad(ins))
959 // The value of 'ins' encodes the size to load
960 // we use EA_8BYTE here because it is the size we will write (into dataReg)
961 // it is also required when ins is INS_ldrsw
967 assert(emitInsIsStore(ins));
969 // The value of 'ins' encodes the size to store
970 // we use EA_4BYTE here because it is the size of the register
971 // that we want to display when storing small values
979 // Takes an instrDesc 'id' and uses the instruction 'ins' to determine the
980 // size of the target register that is written or read by the instruction.
981 // Note that even if EA_4BYTE is returned a load instruction will still
982 // always zero the upper 4 bytes of the target register.
983 // This method is required so that we can distinguish between loads that are
984 // sign-extending as they can have two different sizes for their target register.
985 // Additionally for instructions like 'ldr' and 'str' these can load/store
986 // either 4 byte or 8 bytes to/from the target register.
987 // By convention the small unsigned load instructions are considered to write
988 // a 4 byte sized target register, though since these also zero the upper 4 bytes
989 // they could equally be considered to write the unsigned value to full 8 byte register.
991 emitAttr emitter::emitInsTargetRegSize(instrDesc* id)
993 instruction ins = id->idIns();
994 emitAttr result = EA_UNKNOWN;
996 // This is used to determine the size of the target registers for a load/store instruction
1030 if (id->idOpSize() == EA_8BYTE)
1046 result = id->idOpSize();
1059 result = id->idOpSize();
1063 NO_WAY("unexpected instruction");
1069 // Takes an instrDesc and uses the instruction to determine the 'size' of the
1070 // data that is loaded from memory.
1072 emitAttr emitter::emitInsLoadStoreSize(instrDesc* id)
1074 instruction ins = id->idIns();
1075 emitAttr result = EA_UNKNOWN;
1077 // The 'result' returned is the 'size' of the data that is loaded from memory.
1113 result = id->idOpSize();
1122 result = id->idOpSize();
1126 NO_WAY("unexpected instruction");
1132 /*****************************************************************************/
1136 static const char * const xRegNames[] =
1138 #define REGDEF(name, rnum, mask, xname, wname) xname,
1139 #include "register.h"
1142 static const char * const wRegNames[] =
1144 #define REGDEF(name, rnum, mask, xname, wname) wname,
1145 #include "register.h"
1148 static const char * const vRegNames[] =
1150 "v0", "v1", "v2", "v3", "v4",
1151 "v5", "v6", "v7", "v8", "v9",
1152 "v10", "v11", "v12", "v13", "v14",
1153 "v15", "v16", "v17", "v18", "v19",
1154 "v20", "v21", "v22", "v23", "v24",
1155 "v25", "v26", "v27", "v28", "v29",
1159 static const char * const qRegNames[] =
1161 "q0", "q1", "q2", "q3", "q4",
1162 "q5", "q6", "q7", "q8", "q9",
1163 "q10", "q11", "q12", "q13", "q14",
1164 "q15", "q16", "q17", "q18", "q19",
1165 "q20", "q21", "q22", "q23", "q24",
1166 "q25", "q26", "q27", "q28", "q29",
1170 static const char * const hRegNames[] =
1172 "h0", "h1", "h2", "h3", "h4",
1173 "h5", "h6", "h7", "h8", "h9",
1174 "h10", "h11", "h12", "h13", "h14",
1175 "h15", "h16", "h17", "h18", "h19",
1176 "h20", "h21", "h22", "h23", "h24",
1177 "h25", "h26", "h27", "h28", "h29",
1180 static const char * const bRegNames[] =
1182 "b0", "b1", "b2", "b3", "b4",
1183 "b5", "b6", "b7", "b8", "b9",
1184 "b10", "b11", "b12", "b13", "b14",
1185 "b15", "b16", "b17", "b18", "b19",
1186 "b20", "b21", "b22", "b23", "b24",
1187 "b25", "b26", "b27", "b28", "b29",
1192 /*****************************************************************************
1194 * Return a string that represents the given register.
1197 const char* emitter::emitRegName(regNumber reg, emitAttr size, bool varName)
1199 assert(reg < REG_COUNT);
1201 const char* rn = nullptr;
1203 if (size == EA_8BYTE)
1205 rn = xRegNames[reg];
1207 else if (size == EA_4BYTE)
1209 rn = wRegNames[reg];
1211 else if (isVectorRegister(reg))
1213 if (size == EA_16BYTE)
1215 rn = qRegNames[reg - REG_V0];
1217 else if (size == EA_2BYTE)
1219 rn = hRegNames[reg - REG_V0];
1221 else if (size == EA_1BYTE)
1223 rn = bRegNames[reg - REG_V0];
1227 assert(rn != nullptr);
1232 /*****************************************************************************
1234 * Return a string that represents the given register.
1237 const char* emitter::emitVectorRegName(regNumber reg)
1239 assert((reg >= REG_V0) && (reg <= REG_V31));
1241 int index = (int)reg - (int)REG_V0;
1243 return vRegNames[index];
1247 /*****************************************************************************
1249 * Returns the base encoding of the given CPU instruction.
1252 emitter::insFormat emitter::emitInsFormat(instruction ins)
1255 const static insFormat insFormats[] =
1257 #define INST1(id, nm, fp, ldst, fmt, e1 ) fmt,
1258 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) fmt,
1259 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) fmt,
1260 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) fmt,
1261 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) fmt,
1262 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) fmt,
1263 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) fmt,
1268 assert(ins < ArrLen(insFormats));
1269 assert((insFormats[ins] != IF_NONE));
1271 return insFormats[ins];
1280 /*static*/ const BYTE CodeGenInterface::instInfo[] =
1282 #define INST1(id, nm, fp, ldst, fmt, e1 ) ldst | INST_FP*fp,
1283 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) ldst | INST_FP*fp,
1284 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) ldst | INST_FP*fp,
1285 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) ldst | INST_FP*fp,
1286 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) ldst | INST_FP*fp,
1287 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) ldst | INST_FP*fp,
1288 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) ldst | INST_FP*fp,
1293 /*****************************************************************************
1295 * Returns true if the instruction is some kind of compare or test instruction
1298 bool emitter::emitInsIsCompare(instruction ins)
1300 // We have pseudo ins like lea which are not included in emitInsLdStTab.
1301 if (ins < ArrLen(CodeGenInterface::instInfo))
1302 return (CodeGenInterface::instInfo[ins] & CMP) ? true : false;
1307 /*****************************************************************************
1309 * Returns true if the instruction is some kind of load instruction
1312 bool emitter::emitInsIsLoad(instruction ins)
1314 // We have pseudo ins like lea which are not included in emitInsLdStTab.
1315 if (ins < ArrLen(CodeGenInterface::instInfo))
1316 return (CodeGenInterface::instInfo[ins] & LD) ? true : false;
1320 /*****************************************************************************
1322 * Returns true if the instruction is some kind of store instruction
1325 bool emitter::emitInsIsStore(instruction ins)
1327 // We have pseudo ins like lea which are not included in emitInsLdStTab.
1328 if (ins < ArrLen(CodeGenInterface::instInfo))
1329 return (CodeGenInterface::instInfo[ins] & ST) ? true : false;
1334 /*****************************************************************************
1336 * Returns true if the instruction is some kind of load/store instruction
1339 bool emitter::emitInsIsLoadOrStore(instruction ins)
1341 // We have pseudo ins like lea which are not included in emitInsLdStTab.
1342 if (ins < ArrLen(CodeGenInterface::instInfo))
1343 return (CodeGenInterface::instInfo[ins] & (LD | ST)) ? true : false;
1352 /*****************************************************************************
1354 * Returns the specific encoding of the given CPU instruction and format
1357 emitter::code_t emitter::emitInsCode(instruction ins, insFormat fmt)
1360 const static code_t insCodes1[] =
1362 #define INST1(id, nm, fp, ldst, fmt, e1 ) e1,
1363 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) e1,
1364 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) e1,
1365 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e1,
1366 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e1,
1367 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e1,
1368 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e1,
1371 const static code_t insCodes2[] =
1373 #define INST1(id, nm, fp, ldst, fmt, e1 )
1374 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) e2,
1375 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) e2,
1376 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e2,
1377 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e2,
1378 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e2,
1379 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e2,
1382 const static code_t insCodes3[] =
1384 #define INST1(id, nm, fp, ldst, fmt, e1 )
1385 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1386 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) e3,
1387 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e3,
1388 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e3,
1389 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e3,
1390 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e3,
1393 const static code_t insCodes4[] =
1395 #define INST1(id, nm, fp, ldst, fmt, e1 )
1396 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1397 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
1398 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e4,
1399 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e4,
1400 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e4,
1401 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e4,
1404 const static code_t insCodes5[] =
1406 #define INST1(id, nm, fp, ldst, fmt, e1 )
1407 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1408 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
1409 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
1410 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e5,
1411 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e5,
1412 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e5,
1415 const static code_t insCodes6[] =
1417 #define INST1(id, nm, fp, ldst, fmt, e1 )
1418 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1419 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
1420 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
1421 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
1422 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e6,
1423 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e6,
1426 const static code_t insCodes7[] =
1428 #define INST1(id, nm, fp, ldst, fmt, e1 )
1429 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1430 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
1431 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
1432 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
1433 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 )
1434 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e7,
1437 const static code_t insCodes8[] =
1439 #define INST1(id, nm, fp, ldst, fmt, e1 )
1440 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1441 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
1442 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
1443 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
1444 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 )
1445 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e8,
1448 const static code_t insCodes9[] =
1450 #define INST1(id, nm, fp, ldst, fmt, e1 )
1451 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1452 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
1453 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
1454 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
1455 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 )
1456 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e9,
1461 const static insFormat formatEncode9[9] = {IF_DR_2E, IF_DR_2G, IF_DI_1B, IF_DI_1D, IF_DV_3C,
1462 IF_DV_2B, IF_DV_2C, IF_DV_2E, IF_DV_2F};
1463 const static insFormat formatEncode6A[6] = {IF_DR_3A, IF_DR_3B, IF_DR_3C, IF_DI_2A, IF_DV_3A, IF_DV_3E};
1464 const static insFormat formatEncode5A[5] = {IF_LS_2A, IF_LS_2B, IF_LS_2C, IF_LS_3A, IF_LS_1A};
1465 const static insFormat formatEncode5B[5] = {IF_DV_2G, IF_DV_2H, IF_DV_2I, IF_DV_1A, IF_DV_1B};
1466 const static insFormat formatEncode5C[5] = {IF_DR_3A, IF_DR_3B, IF_DI_2C, IF_DV_3C, IF_DV_1B};
1467 const static insFormat formatEncode4A[4] = {IF_LS_2A, IF_LS_2B, IF_LS_2C, IF_LS_3A};
1468 const static insFormat formatEncode4B[4] = {IF_DR_3A, IF_DR_3B, IF_DR_3C, IF_DI_2A};
1469 const static insFormat formatEncode4C[4] = {IF_DR_2A, IF_DR_2B, IF_DR_2C, IF_DI_1A};
1470 const static insFormat formatEncode4D[4] = {IF_DV_3B, IF_DV_3D, IF_DV_3BI, IF_DV_3DI};
1471 const static insFormat formatEncode4E[4] = {IF_DR_3A, IF_DR_3B, IF_DI_2C, IF_DV_3C};
1472 const static insFormat formatEncode4F[4] = {IF_DR_3A, IF_DR_3B, IF_DV_3C, IF_DV_1B};
1473 const static insFormat formatEncode4G[4] = {IF_DR_2E, IF_DR_2F, IF_DV_2M, IF_DV_2L};
1474 const static insFormat formatEncode4H[4] = {IF_DV_3E, IF_DV_3A, IF_DV_2L, IF_DV_2M};
1475 const static insFormat formatEncode4I[4] = {IF_DV_3D, IF_DV_3B, IF_DV_2G, IF_DV_2A};
1476 const static insFormat formatEncode3A[3] = {IF_DR_3A, IF_DR_3B, IF_DI_2C};
1477 const static insFormat formatEncode3B[3] = {IF_DR_2A, IF_DR_2B, IF_DI_1C};
1478 const static insFormat formatEncode3C[3] = {IF_DR_3A, IF_DR_3B, IF_DV_3C};
1479 const static insFormat formatEncode3D[3] = {IF_DV_2C, IF_DV_2D, IF_DV_2E};
1480 const static insFormat formatEncode3E[3] = {IF_DV_3B, IF_DV_3BI, IF_DV_3DI};
1481 const static insFormat formatEncode3F[3] = {IF_DV_2A, IF_DV_2G, IF_DV_2H};
1482 const static insFormat formatEncode3G[3] = {IF_DV_2A, IF_DV_2G, IF_DV_2I};
1483 const static insFormat formatEncode3H[3] = {IF_DR_3A, IF_DV_3A, IF_DV_3AI};
1484 const static insFormat formatEncode3I[3] = {IF_DR_2E, IF_DR_2F, IF_DV_2M};
1485 const static insFormat formatEncode2A[2] = {IF_DR_2E, IF_DR_2F};
1486 const static insFormat formatEncode2B[2] = {IF_DR_3A, IF_DR_3B};
1487 const static insFormat formatEncode2C[2] = {IF_DR_3A, IF_DI_2D};
1488 const static insFormat formatEncode2D[2] = {IF_DR_3A, IF_DI_2B};
1489 const static insFormat formatEncode2E[2] = {IF_LS_3B, IF_LS_3C};
1490 const static insFormat formatEncode2F[2] = {IF_DR_2I, IF_DI_1F};
1491 const static insFormat formatEncode2G[2] = {IF_DV_3B, IF_DV_3D};
1492 const static insFormat formatEncode2H[2] = {IF_DV_2C, IF_DV_2F};
1493 const static insFormat formatEncode2I[2] = {IF_DV_2K, IF_DV_1C};
1494 const static insFormat formatEncode2J[2] = {IF_DV_2A, IF_DV_2G};
1495 const static insFormat formatEncode2K[2] = {IF_DV_2M, IF_DV_2L};
1496 const static insFormat formatEncode2L[2] = {IF_DV_2G, IF_DV_2M};
1497 const static insFormat formatEncode2M[2] = {IF_DV_3A, IF_DV_3AI};
1498 const static insFormat formatEncode2N[2] = {IF_DV_2N, IF_DV_2O};
1499 const static insFormat formatEncode2O[2] = {IF_DV_3E, IF_DV_3A};
1500 const static insFormat formatEncode2P[2] = {IF_DV_2G, IF_DV_3B};
1502 code_t code = BAD_CODE;
1503 insFormat insFmt = emitInsFormat(ins);
1504 bool encoding_found = false;
1510 for (index = 0; index < 9; index++)
1512 if (fmt == formatEncode9[index])
1514 encoding_found = true;
1521 for (index = 0; index < 6; index++)
1523 if (fmt == formatEncode6A[index])
1525 encoding_found = true;
1532 for (index = 0; index < 5; index++)
1534 if (fmt == formatEncode5A[index])
1536 encoding_found = true;
1543 for (index = 0; index < 5; index++)
1545 if (fmt == formatEncode5B[index])
1547 encoding_found = true;
1554 for (index = 0; index < 5; index++)
1556 if (fmt == formatEncode5C[index])
1558 encoding_found = true;
1565 for (index = 0; index < 4; index++)
1567 if (fmt == formatEncode4A[index])
1569 encoding_found = true;
1576 for (index = 0; index < 4; index++)
1578 if (fmt == formatEncode4B[index])
1580 encoding_found = true;
1587 for (index = 0; index < 4; index++)
1589 if (fmt == formatEncode4C[index])
1591 encoding_found = true;
1598 for (index = 0; index < 4; index++)
1600 if (fmt == formatEncode4D[index])
1602 encoding_found = true;
1609 for (index = 0; index < 4; index++)
1611 if (fmt == formatEncode4E[index])
1613 encoding_found = true;
1620 for (index = 0; index < 4; index++)
1622 if (fmt == formatEncode4F[index])
1624 encoding_found = true;
1631 for (index = 0; index < 4; index++)
1633 if (fmt == formatEncode4G[index])
1635 encoding_found = true;
1642 for (index = 0; index < 4; index++)
1644 if (fmt == formatEncode4H[index])
1646 encoding_found = true;
1653 for (index = 0; index < 4; index++)
1655 if (fmt == formatEncode4I[index])
1657 encoding_found = true;
1664 for (index = 0; index < 3; index++)
1666 if (fmt == formatEncode3A[index])
1668 encoding_found = true;
1675 for (index = 0; index < 3; index++)
1677 if (fmt == formatEncode3B[index])
1679 encoding_found = true;
1686 for (index = 0; index < 3; index++)
1688 if (fmt == formatEncode3C[index])
1690 encoding_found = true;
1697 for (index = 0; index < 3; index++)
1699 if (fmt == formatEncode3D[index])
1701 encoding_found = true;
1708 for (index = 0; index < 3; index++)
1710 if (fmt == formatEncode3E[index])
1712 encoding_found = true;
1719 for (index = 0; index < 3; index++)
1721 if (fmt == formatEncode3F[index])
1723 encoding_found = true;
1730 for (index = 0; index < 3; index++)
1732 if (fmt == formatEncode3G[index])
1734 encoding_found = true;
1741 for (index = 0; index < 3; index++)
1743 if (fmt == formatEncode3H[index])
1745 encoding_found = true;
1752 for (index = 0; index < 3; index++)
1754 if (fmt == formatEncode3I[index])
1756 encoding_found = true;
1763 for (index = 0; index < 2; index++)
1765 if (fmt == formatEncode2A[index])
1767 encoding_found = true;
1774 for (index = 0; index < 2; index++)
1776 if (fmt == formatEncode2B[index])
1778 encoding_found = true;
1785 for (index = 0; index < 2; index++)
1787 if (fmt == formatEncode2C[index])
1789 encoding_found = true;
1796 for (index = 0; index < 2; index++)
1798 if (fmt == formatEncode2D[index])
1800 encoding_found = true;
1807 for (index = 0; index < 2; index++)
1809 if (fmt == formatEncode2E[index])
1811 encoding_found = true;
1818 for (index = 0; index < 2; index++)
1820 if (fmt == formatEncode2F[index])
1822 encoding_found = true;
1829 for (index = 0; index < 2; index++)
1831 if (fmt == formatEncode2G[index])
1833 encoding_found = true;
1840 for (index = 0; index < 2; index++)
1842 if (fmt == formatEncode2H[index])
1844 encoding_found = true;
1851 for (index = 0; index < 2; index++)
1853 if (fmt == formatEncode2I[index])
1855 encoding_found = true;
1862 for (index = 0; index < 2; index++)
1864 if (fmt == formatEncode2J[index])
1866 encoding_found = true;
1873 for (index = 0; index < 2; index++)
1875 if (fmt == formatEncode2K[index])
1877 encoding_found = true;
1884 for (index = 0; index < 2; index++)
1886 if (fmt == formatEncode2L[index])
1888 encoding_found = true;
1895 for (index = 0; index < 2; index++)
1897 if (fmt == formatEncode2M[index])
1899 encoding_found = true;
1906 for (index = 0; index < 2; index++)
1908 if (fmt == formatEncode2N[index])
1910 encoding_found = true;
1917 for (index = 0; index < 2; index++)
1919 if (fmt == formatEncode2O[index])
1921 encoding_found = true;
1928 for (index = 0; index < 2; index++)
1930 if (fmt == formatEncode2P[index])
1932 encoding_found = true;
2014 encoding_found = true;
2019 encoding_found = false;
2023 assert(encoding_found);
2028 assert(ins < ArrLen(insCodes1));
2029 code = insCodes1[ins];
2032 assert(ins < ArrLen(insCodes2));
2033 code = insCodes2[ins];
2036 assert(ins < ArrLen(insCodes3));
2037 code = insCodes3[ins];
2040 assert(ins < ArrLen(insCodes4));
2041 code = insCodes4[ins];
2044 assert(ins < ArrLen(insCodes5));
2045 code = insCodes5[ins];
2048 assert(ins < ArrLen(insCodes6));
2049 code = insCodes6[ins];
2052 assert(ins < ArrLen(insCodes7));
2053 code = insCodes7[ins];
2056 assert(ins < ArrLen(insCodes8));
2057 code = insCodes8[ins];
2060 assert(ins < ArrLen(insCodes9));
2061 code = insCodes9[ins];
2065 assert((code != BAD_CODE));
2070 // true if this 'imm' can be encoded as a input operand to a mov instruction
2071 /*static*/ bool emitter::emitIns_valid_imm_for_mov(INT64 imm, emitAttr size)
2073 // Check for "MOV (wide immediate)".
2074 if (canEncodeHalfwordImm(imm, size))
2077 // Next try the ones-complement form of 'halfword immediate' imm(i16,hw),
2078 // namely "MOV (inverted wide immediate)".
2079 ssize_t notOfImm = NOT_helper(imm, getBitWidth(size));
2080 if (canEncodeHalfwordImm(notOfImm, size))
2083 // Finally try "MOV (bitmask immediate)" imm(N,r,s)
2084 if (canEncodeBitMaskImm(imm, size))
2090 // true if this 'imm' can be encoded as a input operand to a vector movi instruction
2091 /*static*/ bool emitter::emitIns_valid_imm_for_movi(INT64 imm, emitAttr elemsize)
2093 if (elemsize == EA_8BYTE)
2098 INT64 loByte = uimm & 0xFF;
2099 if ((loByte == 0) || (loByte == 0xFF))
2113 // First try the standard 'byteShifted immediate' imm(i8,bySh)
2114 if (canEncodeByteShiftedImm(imm, elemsize, true))
2117 // Next try the ones-complement form of the 'immediate' imm(i8,bySh)
2118 ssize_t notOfImm = NOT_helper(imm, getBitWidth(elemsize));
2119 if (canEncodeByteShiftedImm(notOfImm, elemsize, true))
2125 // true if this 'imm' can be encoded as a input operand to a fmov instruction
2126 /*static*/ bool emitter::emitIns_valid_imm_for_fmov(double immDbl)
2128 if (canEncodeFloatImm8(immDbl))
2134 // true if this 'imm' can be encoded as a input operand to an add instruction
2135 /*static*/ bool emitter::emitIns_valid_imm_for_add(INT64 imm, emitAttr size)
2137 if (unsigned_abs(imm) <= 0x0fff)
2139 else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
2145 // true if this 'imm' can be encoded as a input operand to an non-add/sub alu instruction
2146 /*static*/ bool emitter::emitIns_valid_imm_for_cmp(INT64 imm, emitAttr size)
2148 return emitIns_valid_imm_for_add(imm, size);
2151 // true if this 'imm' can be encoded as a input operand to an non-add/sub alu instruction
2152 /*static*/ bool emitter::emitIns_valid_imm_for_alu(INT64 imm, emitAttr size)
2154 if (canEncodeBitMaskImm(imm, size))
2160 // true if this 'imm' can be encoded as the offset in a ldr/str instruction
2161 /*static*/ bool emitter::emitIns_valid_imm_for_ldst_offset(INT64 imm, emitAttr attr)
2164 return true; // Encodable using IF_LS_2A
2166 if ((imm >= -256) && (imm <= 255))
2167 return true; // Encodable using IF_LS_2C (or possibly IF_LS_2B)
2170 return false; // not encodable
2172 emitAttr size = EA_SIZE(attr);
2173 unsigned scale = NaturalScale_helper(size);
2174 ssize_t mask = size - 1; // the mask of low bits that must be zero to encode the immediate
2176 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
2177 return true; // Encodable using IF_LS_2B
2179 return false; // not encodable
2182 /************************************************************************
2184 * A helper method to return the natural scale for an EA 'size'
2187 /*static*/ unsigned emitter::NaturalScale_helper(emitAttr size)
2189 assert(size == EA_1BYTE || size == EA_2BYTE || size == EA_4BYTE || size == EA_8BYTE || size == EA_16BYTE);
2191 unsigned result = 0;
2192 unsigned utemp = (unsigned)size;
2194 // Compute log base 2 of utemp (aka 'size')
2204 /************************************************************************
2206 * A helper method to perform a Rotate-Right shift operation
2207 * the source is 'value' and it is rotated right by 'sh' bits
2208 * 'value' is considered to be a fixed size 'width' set of bits.
2211 * value is '00001111', sh is 2 and width is 8
2212 * result is '11000011'
2215 /*static*/ UINT64 emitter::ROR_helper(UINT64 value, unsigned sh, unsigned width)
2217 assert(width <= 64);
2218 // Check that 'value' fits in 'width' bits
2219 assert((width == 64) || (value < (1ULL << width)));
2220 // We don't support shifts >= width
2226 unsigned lsh = width - rsh;
2228 result = (value >> rsh);
2229 result |= (value << lsh);
2233 // mask off any extra bits that we got from the left shift
2234 result &= ((1ULL << width) - 1);
2238 /************************************************************************
2240 * A helper method to perform a 'NOT' bitwise complement operation.
2241 * 'value' is considered to be a fixed size 'width' set of bits.
2244 * value is '01001011', and width is 8
2245 * result is '10110100'
2248 /*static*/ UINT64 emitter::NOT_helper(UINT64 value, unsigned width)
2250 assert(width <= 64);
2252 UINT64 result = ~value;
2256 // Check that 'value' fits in 'width' bits. Don't consider "sign" bits above width.
2257 UINT64 maxVal = 1ULL << width;
2258 UINT64 lowBitsMask = maxVal - 1;
2259 UINT64 signBitsMask = ~lowBitsMask | (1ULL << (width - 1)); // The high bits must be set, and the top bit
2260 // (sign bit) must be set.
2261 assert((value < maxVal) || ((value & signBitsMask) == signBitsMask));
2263 // mask off any extra bits that we got from the complement operation
2264 result &= lowBitsMask;
2270 /************************************************************************
2272 * A helper method to perform a bit Replicate operation
2273 * the source is 'value' with a fixed size 'width' set of bits.
2274 * value is replicated to fill out 32 or 64 bits as determined by 'size'.
2277 * value is '11000011' (0xE3), width is 8 and size is EA_8BYTE
2278 * result is '11000011 11000011 11000011 11000011 11000011 11000011 11000011 11000011'
2279 * 0xE3E3E3E3E3E3E3E3
2282 /*static*/ UINT64 emitter::Replicate_helper(UINT64 value, unsigned width, emitAttr size)
2284 assert(emitter::isValidGeneralDatasize(size));
2286 unsigned immWidth = (size == EA_8BYTE) ? 64 : 32;
2287 assert(width <= immWidth);
2289 UINT64 result = value;
2290 unsigned filledBits = width;
2292 while (filledBits < immWidth)
2296 filledBits += width;
2301 /************************************************************************
2303 * Convert an imm(N,r,s) into a 64-bit immediate
2304 * inputs 'bmImm' a bitMaskImm struct
2305 * 'size' specifies the size of the result (64 or 32 bits)
2308 /*static*/ INT64 emitter::emitDecodeBitMaskImm(const emitter::bitMaskImm bmImm, emitAttr size)
2310 assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2312 unsigned N = bmImm.immN; // read the N,R and S values from the 'bitMaskImm' encoding
2313 unsigned R = bmImm.immR;
2314 unsigned S = bmImm.immS;
2316 unsigned elemWidth = 64; // used when immN == 1
2318 if (bmImm.immN == 0) // find the smaller elemWidth when immN == 0
2320 // Scan S for the highest bit not set
2322 for (unsigned bitNum = 5; bitNum > 0; bitNum--)
2324 unsigned oneBit = elemWidth;
2325 if ((S & oneBit) == 0)
2332 assert(size == EA_8BYTE);
2335 unsigned maskSR = elemWidth - 1;
2340 // encoding for S is one less than the number of consecutive one bits
2341 S++; // Number of consecutive ones to generate in 'welem'
2345 // 'elemWidth' is the number of bits that we will use for the ROR and Replicate operations
2346 // 'S' is the number of consecutive 1 bits for the immediate
2347 // 'R' is the number of bits that we will Rotate Right the immediate
2348 // 'size' selects the final size of the immedate that we return (64 or 32 bits)
2350 assert(S < elemWidth); // 'elemWidth' consecutive one's is a reserved encoding
2355 welem = (1ULL << S) - 1;
2357 wmask = ROR_helper(welem, R, elemWidth);
2358 wmask = Replicate_helper(wmask, elemWidth, size);
2363 /*****************************************************************************
2365 * Check if an immediate can use the left shifted by 12 bits encoding
2368 /*static*/ bool emitter::canEncodeWithShiftImmBy12(INT64 imm)
2372 imm = -imm; // convert to unsigned
2377 return false; // Must be MIN_INT64
2380 if ((imm & 0xfff) != 0) // Now the low 12 bits all have to be zero
2385 imm >>= 12; // shift right by 12 bits
2387 return (imm <= 0x0fff); // Does it fit in 12 bits
2390 /*****************************************************************************
2392 * Normalize the 'imm' so that the upper bits, as defined by 'size' are zero
2395 /*static*/ INT64 emitter::normalizeImm64(INT64 imm, emitAttr size)
2397 unsigned immWidth = getBitWidth(size);
2402 // Check that 'imm' fits in 'immWidth' bits. Don't consider "sign" bits above width.
2403 INT64 maxVal = 1LL << immWidth;
2404 INT64 lowBitsMask = maxVal - 1;
2405 INT64 hiBitsMask = ~lowBitsMask;
2406 INT64 signBitsMask =
2407 hiBitsMask | (1LL << (immWidth - 1)); // The high bits must be set, and the top bit (sign bit) must be set.
2408 assert((imm < maxVal) || ((imm & signBitsMask) == signBitsMask));
2410 // mask off the hiBits
2411 result &= lowBitsMask;
2416 /*****************************************************************************
2418 * Normalize the 'imm' so that the upper bits, as defined by 'size' are zero
2421 /*static*/ INT32 emitter::normalizeImm32(INT32 imm, emitAttr size)
2423 unsigned immWidth = getBitWidth(size);
2428 // Check that 'imm' fits in 'immWidth' bits. Don't consider "sign" bits above width.
2429 INT32 maxVal = 1 << immWidth;
2430 INT32 lowBitsMask = maxVal - 1;
2431 INT32 hiBitsMask = ~lowBitsMask;
2432 INT32 signBitsMask = hiBitsMask | (1 << (immWidth - 1)); // The high bits must be set, and the top bit
2433 // (sign bit) must be set.
2434 assert((imm < maxVal) || ((imm & signBitsMask) == signBitsMask));
2436 // mask off the hiBits
2437 result &= lowBitsMask;
2442 /************************************************************************
2444 * returns true if 'imm' of 'size bits (32/64) can be encoded
2445 * using the ARM64 'bitmask immediate' form.
2446 * When a non-null value is passed for 'wbBMI' then this method
2447 * writes back the 'N','S' and 'R' values use to encode this immediate
2451 /*static*/ bool emitter::canEncodeBitMaskImm(INT64 imm, emitAttr size, emitter::bitMaskImm* wbBMI)
2453 assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2455 unsigned immWidth = (size == EA_8BYTE) ? 64 : 32;
2456 unsigned maxLen = (size == EA_8BYTE) ? 6 : 5;
2458 imm = normalizeImm64(imm, size);
2460 // Starting with len=1, elemWidth is 2 bits
2461 // len=2, elemWidth is 4 bits
2462 // len=3, elemWidth is 8 bits
2463 // len=4, elemWidth is 16 bits
2464 // len=5, elemWidth is 32 bits
2465 // (optionally) len=6, elemWidth is 64 bits
2467 for (unsigned len = 1; (len <= maxLen); len++)
2469 unsigned elemWidth = 1 << len;
2470 UINT64 elemMask = ((UINT64)-1) >> (64 - elemWidth);
2471 UINT64 tempImm = (UINT64)imm; // A working copy of 'imm' that we can mutate
2472 UINT64 elemVal = tempImm & elemMask; // The low 'elemWidth' bits of 'imm'
2474 // Check for all 1's or 0's as these can't be encoded
2475 if ((elemVal == 0) || (elemVal == elemMask))
2478 // 'checkedBits' is the count of bits that are known to match 'elemVal' when replicated
2479 unsigned checkedBits = elemWidth; // by definition the first 'elemWidth' bits match
2481 // Now check to see if each of the next bits match...
2483 while (checkedBits < immWidth)
2485 tempImm >>= elemWidth;
2487 UINT64 nextElem = tempImm & elemMask;
2488 if (nextElem != elemVal)
2490 // Not matching, exit this loop and checkedBits will not be equal to immWidth
2494 // The 'nextElem' is matching, so increment 'checkedBits'
2495 checkedBits += elemWidth;
2498 // Did the full immediate contain bits that can be formed by repeating 'elemVal'?
2499 if (checkedBits == immWidth)
2501 // We are not quite done, since the only values that we can encode as a
2502 // 'bitmask immediate' are those that can be formed by starting with a
2503 // bit string of 0*1* that is rotated by some number of bits.
2505 // We check to see if 'elemVal' can be formed using these restrictions.
2508 // Rotating by one bit any value that passes these restrictions
2509 // can be xor-ed with the original value and will result it a string
2510 // of bits that have exactly two 1 bits: 'elemRorXor'
2511 // Further the distance between the two one bits tells us the value
2512 // of S and the location of the 1 bits tells us the value of R
2514 // Some examples: (immWidth is 8)
2516 // S=4,R=0 S=5,R=3 S=3,R=6
2517 // elemVal: 00001111 11100011 00011100
2518 // elemRor: 10000111 11110001 00001110
2519 // elemRorXor: 10001000 00010010 00010010
2520 // compute S 45678--- ---5678- ---3210-
2521 // compute R 01234567 ---34567 ------67
2523 UINT64 elemRor = ROR_helper(elemVal, 1, elemWidth); // Rotate 'elemVal' Right by one bit
2524 UINT64 elemRorXor = elemVal ^ elemRor; // Xor elemVal and elemRor
2526 // If we only have a two-bit change in elemROR then we can form a mask for this value
2527 unsigned bitCount = 0;
2528 UINT64 oneBit = 0x1;
2529 unsigned R = elemWidth; // R is shift count for ROR (rotate right shift)
2530 unsigned S = 0; // S is number of consecutive one bits
2533 // Loop over the 'elemWidth' bits in 'elemRorXor'
2535 for (unsigned bitNum = 0; bitNum < elemWidth; bitNum++)
2539 R--; // We decrement R by one whenever incr is -1
2543 S += incr; // We incr/decr S, after we find the first one bit in 'elemRorXor'
2546 // Is this bit position a 1 bit in 'elemRorXor'?
2548 if (oneBit & elemRorXor)
2551 // Is this the first 1 bit that we found in 'elemRorXor'?
2554 // Does this 1 bit represent a transition to zero bits?
2555 bool toZeros = ((oneBit & elemVal) != 0);
2558 // S :: Count down from elemWidth
2562 else // this 1 bit represent a transition to one bits.
2564 // S :: Count up from zero
2569 else // bitCount > 1
2571 // We found the second (or third...) 1 bit in 'elemRorXor'
2572 incr = 0; // stop decrementing 'R'
2576 // More than 2 transitions from 0/1 in 'elemVal'
2577 // This means that 'elemVal' can't be encoded
2578 // using a 'bitmask immediate'.
2580 // Furthermore, it will continue to fail
2581 // with any larger 'len' that we try.
2582 // so just return false.
2589 // shift oneBit left by one bit to test the next position
2593 // We expect that bitCount will always be two at this point
2594 // but just in case return false for any bad cases.
2596 assert(bitCount == 2);
2600 // Perform some sanity checks on the values of 'S' and 'R'
2602 assert(S < elemWidth);
2603 assert(R < elemWidth);
2605 // Does the caller want us to return the N,R,S encoding values?
2607 if (wbBMI != nullptr)
2610 // The encoding used for S is one less than the
2611 // number of consecutive one bits
2621 // The encoding used for 'S' here is a bit peculiar.
2623 // The upper bits need to be complemented, followed by a zero bit
2624 // then the value of 'S-1'
2626 unsigned upperBitsOfS = 64 - (1 << (len + 1));
2632 // Verify that what we are returning is correct.
2633 assert(imm == emitDecodeBitMaskImm(*wbBMI, size));
2635 // Tell the caller that we can successfully encode this immediate
2636 // using a 'bitmask immediate'.
2644 /************************************************************************
2646 * Convert a 64-bit immediate into its 'bitmask immediate' representation imm(N,r,s)
2649 /*static*/ emitter::bitMaskImm emitter::emitEncodeBitMaskImm(INT64 imm, emitAttr size)
2651 emitter::bitMaskImm result;
2654 bool canEncode = canEncodeBitMaskImm(imm, size, &result);
2660 /************************************************************************
2662 * Convert an imm(i16,hw) into a 32/64-bit immediate
2663 * inputs 'hwImm' a halfwordImm struct
2664 * 'size' specifies the size of the result (64 or 32 bits)
2667 /*static*/ INT64 emitter::emitDecodeHalfwordImm(const emitter::halfwordImm hwImm, emitAttr size)
2669 assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2671 unsigned hw = hwImm.immHW;
2672 INT64 val = (INT64)hwImm.immVal;
2674 assert((hw <= 1) || (size == EA_8BYTE));
2676 INT64 result = val << (16 * hw);
2680 /************************************************************************
2682 * returns true if 'imm' of 'size' bits (32/64) can be encoded
2683 * using the ARM64 'halfword immediate' form.
2684 * When a non-null value is passed for 'wbHWI' then this method
2685 * writes back the 'immHW' and 'immVal' values use to encode this immediate
2689 /*static*/ bool emitter::canEncodeHalfwordImm(INT64 imm, emitAttr size, emitter::halfwordImm* wbHWI)
2691 assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2693 unsigned immWidth = (size == EA_8BYTE) ? 64 : 32;
2694 unsigned maxHW = (size == EA_8BYTE) ? 4 : 2;
2696 // setup immMask to a (EA_4BYTE) 0x00000000_FFFFFFFF or (EA_8BYTE) 0xFFFFFFFF_FFFFFFFF
2697 const UINT64 immMask = ((UINT64)-1) >> (64 - immWidth);
2698 const INT64 mask16 = (INT64)0xFFFF;
2700 imm = normalizeImm64(imm, size);
2702 // Try each of the valid hw shift sizes
2703 for (unsigned hw = 0; (hw < maxHW); hw++)
2705 INT64 curMask = mask16 << (hw * 16); // Represents the mask of the bits in the current halfword
2706 INT64 checkBits = immMask & ~curMask;
2708 // Excluding the current halfword (using ~curMask)
2709 // does the immediate have zero bits in every other bit that we care about?
2710 // note we care about all 64-bits for EA_8BYTE
2711 // and we care about the lowest 32 bits for EA_4BYTE
2713 if ((imm & checkBits) == 0)
2715 // Does the caller want us to return the imm(i16,hw) encoding values?
2717 if (wbHWI != nullptr)
2719 INT64 val = ((imm & curMask) >> (hw * 16)) & mask16;
2721 wbHWI->immVal = val;
2723 // Verify that what we are returning is correct.
2724 assert(imm == emitDecodeHalfwordImm(*wbHWI, size));
2726 // Tell the caller that we can successfully encode this immediate
2727 // using a 'halfword immediate'.
2735 /************************************************************************
2737 * Convert a 64-bit immediate into its 'halfword immediate' representation imm(i16,hw)
2740 /*static*/ emitter::halfwordImm emitter::emitEncodeHalfwordImm(INT64 imm, emitAttr size)
2742 emitter::halfwordImm result;
2743 result.immHWVal = 0;
2745 bool canEncode = canEncodeHalfwordImm(imm, size, &result);
2751 /************************************************************************
2753 * Convert an imm(i8,sh) into a 16/32-bit immediate
2754 * inputs 'bsImm' a byteShiftedImm struct
2755 * 'size' specifies the size of the result (16 or 32 bits)
2758 /*static*/ INT32 emitter::emitDecodeByteShiftedImm(const emitter::byteShiftedImm bsImm, emitAttr size)
2760 bool onesShift = (bsImm.immOnes == 1);
2761 unsigned bySh = bsImm.immBY; // Num Bytes to shift 0,1,2,3
2762 INT32 val = (INT32)bsImm.immVal; // 8-bit immediate
2767 assert((size == EA_2BYTE) || (size == EA_4BYTE)); // Only EA_2BYTE or EA_4BYTE forms
2768 if (size == EA_2BYTE)
2777 result <<= (8 * bySh);
2781 result |= ((1 << (8 * bySh)) - 1);
2787 /************************************************************************
2789 * returns true if 'imm' of 'size' bits (16/32) can be encoded
2790 * using the ARM64 'byteShifted immediate' form.
2791 * When a non-null value is passed for 'wbBSI' then this method
2792 * writes back the 'immBY' and 'immVal' values use to encode this immediate
2796 /*static*/ bool emitter::canEncodeByteShiftedImm(INT64 imm,
2799 emitter::byteShiftedImm* wbBSI)
2801 bool canEncode = false;
2802 bool onesShift = false; // true if we use the shifting ones variant
2803 unsigned bySh = 0; // number of bytes to shift: 0, 1, 2, 3
2804 unsigned imm8 = 0; // immediate to use in the encoding
2806 imm = normalizeImm64(imm, size);
2808 if (size == EA_1BYTE)
2810 imm8 = (unsigned)imm;
2811 assert(imm8 < 0x100);
2814 else if (size == EA_8BYTE)
2816 imm8 = (unsigned)imm;
2817 assert(imm8 < 0x100);
2822 assert((size == EA_2BYTE) || (size == EA_4BYTE)); // Only EA_2BYTE or EA_4BYTE forms
2824 unsigned immWidth = (size == EA_4BYTE) ? 32 : 16;
2825 unsigned maxBY = (size == EA_4BYTE) ? 4 : 2;
2827 // setup immMask to a (EA_2BYTE) 0x0000FFFF or (EA_4BYTE) 0xFFFFFFFF
2828 const UINT32 immMask = ((UINT32)-1) >> (32 - immWidth);
2829 const INT32 mask8 = (INT32)0xFF;
2831 // Try each of the valid by shift sizes
2832 for (bySh = 0; (bySh < maxBY); bySh++)
2834 INT32 curMask = mask8 << (bySh * 8); // Represents the mask of the bits in the current byteShifted
2835 INT32 checkBits = immMask & ~curMask;
2836 INT32 immCheck = (imm & checkBits);
2838 // Excluding the current byte (using ~curMask)
2839 // does the immediate have zero bits in every other bit that we care about?
2840 // or can be use the shifted one variant?
2841 // note we care about all 32-bits for EA_4BYTE
2842 // and we care about the lowest 16 bits for EA_2BYTE
2850 if ((bySh == 1) && (immCheck == 0xFF))
2855 else if ((bySh == 2) && (immCheck == 0xFFFF))
2863 imm8 = (unsigned)(((imm & curMask) >> (bySh * 8)) & mask8);
2871 // Does the caller want us to return the imm(i8,bySh) encoding values?
2873 if (wbBSI != nullptr)
2875 wbBSI->immOnes = onesShift;
2876 wbBSI->immBY = bySh;
2877 wbBSI->immVal = imm8;
2879 // Verify that what we are returning is correct.
2880 assert(imm == emitDecodeByteShiftedImm(*wbBSI, size));
2882 // Tell the caller that we can successfully encode this immediate
2883 // using a 'byteShifted immediate'.
2890 /************************************************************************
2892 * Convert a 32-bit immediate into its 'byteShifted immediate' representation imm(i8,by)
2895 /*static*/ emitter::byteShiftedImm emitter::emitEncodeByteShiftedImm(INT64 imm, emitAttr size, bool allow_MSL)
2897 emitter::byteShiftedImm result;
2898 result.immBSVal = 0;
2900 bool canEncode = canEncodeByteShiftedImm(imm, size, allow_MSL, &result);
2906 /************************************************************************
2908 * Convert a 'float 8-bit immediate' into a double.
2909 * inputs 'fpImm' a floatImm8 struct
2912 /*static*/ double emitter::emitDecodeFloatImm8(const emitter::floatImm8 fpImm)
2914 unsigned sign = fpImm.immSign;
2915 unsigned exp = fpImm.immExp ^ 0x4;
2916 unsigned mant = fpImm.immMant + 16;
2917 unsigned scale = 16 * 8;
2925 double result = ((double)mant) / ((double)scale);
2934 /************************************************************************
2936 * returns true if the 'immDbl' can be encoded using the 'float 8-bit immediate' form.
2937 * also returns the encoding if wbFPI is non-null
2941 /*static*/ bool emitter::canEncodeFloatImm8(double immDbl, emitter::floatImm8* wbFPI)
2943 bool canEncode = false;
2944 double val = immDbl;
2954 while ((val < 1.0) && (exp >= -4))
2959 while ((val >= 2.0) && (exp <= 5))
2966 int ival = (int)val;
2968 if ((exp >= 0) && (exp <= 7))
2970 if (val == (double)ival)
2974 if (wbFPI != nullptr)
2977 assert((ival >= 0) && (ival <= 15));
2979 wbFPI->immSign = sign;
2980 wbFPI->immExp = exp ^ 0x4;
2981 wbFPI->immMant = ival;
2982 unsigned imm8 = wbFPI->immFPIVal;
2983 assert((imm8 >= 0) && (imm8 <= 0xff));
2991 /************************************************************************
2993 * Convert a double into its 'float 8-bit immediate' representation
2996 /*static*/ emitter::floatImm8 emitter::emitEncodeFloatImm8(double immDbl)
2998 emitter::floatImm8 result;
2999 result.immFPIVal = 0;
3001 bool canEncode = canEncodeFloatImm8(immDbl, &result);
3007 /*****************************************************************************
3009 * For the given 'ins' returns the reverse instruction
3010 * if one exists, otherwise returns INS_INVALID
3013 /*static*/ instruction emitter::insReverse(instruction ins)
3042 /*****************************************************************************
3044 * For the given 'datasize' and 'elemsize', make the proper arrangement option
3045 * returns the insOpts that specifies the vector register arrangement
3046 * if one does not exist returns INS_OPTS_NONE
3049 /*static*/ insOpts emitter::optMakeArrangement(emitAttr datasize, emitAttr elemsize)
3051 insOpts result = INS_OPTS_NONE;
3053 if (datasize == EA_8BYTE)
3058 result = INS_OPTS_8B;
3061 result = INS_OPTS_4H;
3064 result = INS_OPTS_2S;
3067 result = INS_OPTS_1D;
3074 else if (datasize == EA_16BYTE)
3079 result = INS_OPTS_16B;
3082 result = INS_OPTS_8H;
3085 result = INS_OPTS_4S;
3088 result = INS_OPTS_2D;
3098 /*****************************************************************************
3100 * For the given 'datasize' and arrangement 'opts'
3101 * returns true is the pair spcifies a valid arrangement
3103 /*static*/ bool emitter::isValidArrangement(emitAttr datasize, insOpts opt)
3105 if (datasize == EA_8BYTE)
3107 if ((opt == INS_OPTS_8B) || (opt == INS_OPTS_4H) || (opt == INS_OPTS_2S) || (opt == INS_OPTS_1D))
3112 else if (datasize == EA_16BYTE)
3114 if ((opt == INS_OPTS_16B) || (opt == INS_OPTS_8H) || (opt == INS_OPTS_4S) || (opt == INS_OPTS_2D))
3122 // For the given 'arrangement' returns the 'datasize' specified by the vector register arrangement
3123 // asserts and returns EA_UNKNOWN if an invalid 'arrangement' value is passed
3125 /*static*/ emitAttr emitter::optGetDatasize(insOpts arrangement)
3127 if ((arrangement == INS_OPTS_8B) || (arrangement == INS_OPTS_4H) || (arrangement == INS_OPTS_2S) ||
3128 (arrangement == INS_OPTS_1D))
3132 else if ((arrangement == INS_OPTS_16B) || (arrangement == INS_OPTS_8H) || (arrangement == INS_OPTS_4S) ||
3133 (arrangement == INS_OPTS_2D))
3139 assert(!" invalid 'arrangement' value");
3144 // For the given 'arrangement' returns the 'elemsize' specified by the vector register arrangement
3145 // asserts and returns EA_UNKNOWN if an invalid 'arrangement' value is passed
3147 /*static*/ emitAttr emitter::optGetElemsize(insOpts arrangement)
3149 if ((arrangement == INS_OPTS_8B) || (arrangement == INS_OPTS_16B))
3153 else if ((arrangement == INS_OPTS_4H) || (arrangement == INS_OPTS_8H))
3157 else if ((arrangement == INS_OPTS_2S) || (arrangement == INS_OPTS_4S))
3161 else if ((arrangement == INS_OPTS_1D) || (arrangement == INS_OPTS_2D))
3167 assert(!" invalid 'arrangement' value");
3172 // For the given 'arrangement' returns the 'widen-arrangement' specified by the vector register arrangement
3173 // asserts and returns INS_OPTS_NONE if an invalid 'arrangement' value is passed
3175 /*static*/ insOpts emitter::optWidenElemsize(insOpts arrangement)
3177 if ((arrangement == INS_OPTS_8B) || (arrangement == INS_OPTS_16B))
3181 else if ((arrangement == INS_OPTS_4H) || (arrangement == INS_OPTS_8H))
3185 else if ((arrangement == INS_OPTS_2S) || (arrangement == INS_OPTS_4S))
3191 assert(!" invalid 'arrangement' value");
3192 return INS_OPTS_NONE;
3196 // For the given 'conversion' returns the 'dstsize' specified by the conversion option
3197 /*static*/ emitAttr emitter::optGetDstsize(insOpts conversion)
3201 case INS_OPTS_S_TO_8BYTE:
3202 case INS_OPTS_D_TO_8BYTE:
3203 case INS_OPTS_4BYTE_TO_D:
3204 case INS_OPTS_8BYTE_TO_D:
3205 case INS_OPTS_S_TO_D:
3206 case INS_OPTS_H_TO_D:
3210 case INS_OPTS_S_TO_4BYTE:
3211 case INS_OPTS_D_TO_4BYTE:
3212 case INS_OPTS_4BYTE_TO_S:
3213 case INS_OPTS_8BYTE_TO_S:
3214 case INS_OPTS_D_TO_S:
3215 case INS_OPTS_H_TO_S:
3219 case INS_OPTS_S_TO_H:
3220 case INS_OPTS_D_TO_H:
3225 assert(!" invalid 'conversion' value");
3230 // For the given 'conversion' returns the 'srcsize' specified by the conversion option
3231 /*static*/ emitAttr emitter::optGetSrcsize(insOpts conversion)
3235 case INS_OPTS_D_TO_8BYTE:
3236 case INS_OPTS_D_TO_4BYTE:
3237 case INS_OPTS_8BYTE_TO_D:
3238 case INS_OPTS_8BYTE_TO_S:
3239 case INS_OPTS_D_TO_S:
3240 case INS_OPTS_D_TO_H:
3244 case INS_OPTS_S_TO_8BYTE:
3245 case INS_OPTS_S_TO_4BYTE:
3246 case INS_OPTS_4BYTE_TO_S:
3247 case INS_OPTS_4BYTE_TO_D:
3248 case INS_OPTS_S_TO_D:
3249 case INS_OPTS_S_TO_H:
3253 case INS_OPTS_H_TO_S:
3254 case INS_OPTS_H_TO_D:
3259 assert(!" invalid 'conversion' value");
3264 // For the given 'size' and 'index' returns true if it specifies a valid index for a vector register of 'size'
3265 /*static*/ bool emitter::isValidVectorIndex(emitAttr datasize, emitAttr elemsize, ssize_t index)
3267 assert(isValidVectorDatasize(datasize));
3268 assert(isValidVectorElemsize(elemsize));
3270 bool result = false;
3273 if (datasize == EA_8BYTE)
3278 result = (index < 8);
3281 result = (index < 4);
3284 result = (index < 2);
3287 result = (index < 1);
3294 else if (datasize == EA_16BYTE)
3299 result = (index < 16);
3302 result = (index < 8);
3305 result = (index < 4);
3308 result = (index < 2);
3319 /*****************************************************************************
3321 * Add an instruction with no operands.
3324 void emitter::emitIns(instruction ins)
3326 instrDesc* id = emitNewInstrSmall(EA_8BYTE);
3327 insFormat fmt = emitInsFormat(ins);
3329 assert(fmt == IF_SN_0A);
3338 /*****************************************************************************
3340 * Add an instruction with a single immediate value.
3343 void emitter::emitIns_I(instruction ins, emitAttr attr, ssize_t imm)
3345 insFormat fmt = IF_NONE;
3347 /* Figure out the encoding format of the instruction */
3351 if ((imm & 0x0000ffff) == imm)
3357 assert(!"Instruction cannot be encoded: IF_SI_0A");
3364 assert(fmt != IF_NONE);
3366 instrDesc* id = emitNewInstrSC(attr, imm);
3375 /*****************************************************************************
3377 * Add an instruction referencing a single register.
3380 void emitter::emitIns_R(instruction ins, emitAttr attr, regNumber reg)
3382 emitAttr size = EA_SIZE(attr);
3383 insFormat fmt = IF_NONE;
3384 instrDesc* id = nullptr;
3386 /* Figure out the encoding format of the instruction */
3391 assert(isGeneralRegister(reg));
3392 id = emitNewInstrSmall(attr);
3401 assert(fmt != IF_NONE);
3410 /*****************************************************************************
3412 * Add an instruction referencing a register and a constant.
3415 void emitter::emitIns_R_I(instruction ins, emitAttr attr, regNumber reg, ssize_t imm, insOpts opt /* = INS_OPTS_NONE */)
3417 emitAttr size = EA_SIZE(attr);
3418 emitAttr elemsize = EA_UNKNOWN;
3419 insFormat fmt = IF_NONE;
3420 bool canEncode = false;
3422 /* Figure out the encoding format of the instruction */
3431 assert(insOptsNone(opt));
3432 assert(isGeneralRegister(reg));
3434 canEncode = canEncodeBitMaskImm(imm, size, &bmi);
3438 assert(isValidImmNRS(imm, size));
3446 assert(isValidGeneralDatasize(size));
3447 assert(insOptsNone(opt)); // No LSL here (you must use emitIns_R_I_I if a shift is needed)
3448 assert(isGeneralRegister(reg));
3449 assert(isValidUimm16(imm));
3453 assert(imm == emitDecodeHalfwordImm(hwi, size));
3461 assert(isValidGeneralDatasize(size));
3462 assert(insOptsNone(opt)); // No explicit LSL here
3463 // We will automatically determine the shift based upon the imm
3465 // First try the standard 'halfword immediate' imm(i16,hw)
3467 canEncode = canEncodeHalfwordImm(imm, size, &hwi);
3470 // uses a movz encoding
3471 assert(isGeneralRegister(reg));
3473 assert(isValidImmHWVal(imm, size));
3478 // Next try the ones-complement form of 'halfword immediate' imm(i16,hw)
3479 notOfImm = NOT_helper(imm, getBitWidth(size));
3480 canEncode = canEncodeHalfwordImm(notOfImm, size, &hwi);
3483 assert(isGeneralRegister(reg));
3485 ins = INS_movn; // uses a movn encoding
3486 assert(isValidImmHWVal(imm, size));
3491 // Finally try the 'bitmask immediate' imm(N,r,s)
3493 canEncode = canEncodeBitMaskImm(imm, size, &bmi);
3496 assert(isGeneralRegisterOrSP(reg));
3497 reg = encodingSPtoZR(reg);
3499 assert(isValidImmNRS(imm, size));
3505 assert(!"Instruction cannot be encoded: mov imm");
3511 assert(isValidVectorDatasize(size));
3512 assert(isVectorRegister(reg));
3513 if (insOptsNone(opt) && (size == EA_8BYTE))
3517 assert(isValidArrangement(size, opt));
3518 elemsize = optGetElemsize(opt);
3520 if (elemsize == EA_8BYTE)
3526 bool failed = false;
3529 INT64 loByte = uimm & 0xFF;
3530 if (((loByte == 0) || (loByte == 0xFF)) && (pos < 8))
3546 assert(isValidUimm8(imm));
3554 // No explicit LSL/MSL is used for the immediate
3555 // We will automatically determine the shift based upon the value of imm
3557 // First try the standard 'byteShifted immediate' imm(i8,bySh)
3559 canEncode = canEncodeByteShiftedImm(imm, elemsize, true, &bsi);
3563 assert(isValidImmBSVal(imm, size));
3568 // Next try the ones-complement form of the 'immediate' imm(i8,bySh)
3569 if ((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE)) // Only EA_2BYTE or EA_4BYTE forms
3571 notOfImm = NOT_helper(imm, getBitWidth(elemsize));
3572 canEncode = canEncodeByteShiftedImm(notOfImm, elemsize, true, &bsi);
3576 ins = INS_mvni; // uses a mvni encoding
3577 assert(isValidImmBSVal(imm, size));
3588 assert(isValidVectorDatasize(size));
3589 assert(isVectorRegister(reg));
3590 assert(isValidArrangement(size, opt));
3591 elemsize = optGetElemsize(opt);
3592 assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE)); // Only EA_2BYTE or EA_4BYTE forms
3596 // No explicit LSL/MSL is used for the immediate
3597 // We will automatically determine the shift based upon the value of imm
3599 // First try the standard 'byteShifted immediate' imm(i8,bySh)
3601 canEncode = canEncodeByteShiftedImm(imm, elemsize,
3602 (ins == INS_mvni), // mvni supports the ones shifting variant (aka MSL)
3607 assert(isValidImmBSVal(imm, size));
3615 assert(insOptsNone(opt));
3616 assert(isGeneralRegister(reg));
3618 if (unsigned_abs(imm) <= 0x0fff)
3622 ins = insReverse(ins);
3625 assert(isValidUimm12(imm));
3629 else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
3631 // Encoding will use a 12-bit left shift of the immediate
3632 opt = INS_OPTS_LSL12;
3635 ins = insReverse(ins);
3638 assert((imm & 0xfff) == 0);
3640 assert(isValidUimm12(imm));
3646 assert(!"Instruction cannot be encoded: IF_DI_1A");
3654 } // end switch (ins)
3657 assert(fmt != IF_NONE);
3659 instrDesc* id = emitNewInstrSC(attr, imm);
3671 /*****************************************************************************
3673 * Add an instruction referencing a register and a floating point constant.
3676 void emitter::emitIns_R_F(
3677 instruction ins, emitAttr attr, regNumber reg, double immDbl, insOpts opt /* = INS_OPTS_NONE */)
3680 emitAttr size = EA_SIZE(attr);
3681 emitAttr elemsize = EA_UNKNOWN;
3682 insFormat fmt = IF_NONE;
3684 bool canEncode = false;
3686 /* Figure out the encoding format of the instruction */
3693 assert(insOptsNone(opt));
3694 assert(isValidVectorElemsizeFloat(size));
3695 assert(isVectorRegister(reg));
3704 assert(isVectorRegister(reg));
3706 canEncode = canEncodeFloatImm8(immDbl, &fpi);
3708 if (insOptsAnyArrangement(opt))
3711 assert(isValidVectorDatasize(size));
3712 assert(isValidArrangement(size, opt));
3713 elemsize = optGetElemsize(opt);
3714 assert(isValidVectorElemsizeFloat(elemsize));
3715 assert(opt != INS_OPTS_1D); // Reserved encoding
3719 imm = fpi.immFPIVal;
3720 assert((imm >= 0) && (imm <= 0xff));
3727 assert(insOptsNone(opt));
3728 assert(isValidVectorElemsizeFloat(size));
3732 imm = fpi.immFPIVal;
3733 assert((imm >= 0) && (imm <= 0xff));
3743 } // end switch (ins)
3746 assert(fmt != IF_NONE);
3748 instrDesc* id = emitNewInstrSC(attr, imm);
3760 /*****************************************************************************
3762 * Add an instruction referencing two registers
3765 void emitter::emitIns_R_R(
3766 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insOpts opt /* = INS_OPTS_NONE */)
3768 emitAttr size = EA_SIZE(attr);
3769 emitAttr elemsize = EA_UNKNOWN;
3770 insFormat fmt = IF_NONE;
3772 /* Figure out the encoding format of the instruction */
3776 assert(insOptsNone(opt));
3777 // Is the mov even necessary?
3780 // A mov with a EA_4BYTE has the side-effect of clearing the upper bits
3781 // So only eliminate mov instructions that are not clearing the upper bits
3783 if (isGeneralRegisterOrSP(reg1) && (size == EA_8BYTE))
3787 else if (isVectorRegister(reg1) && (size == EA_16BYTE))
3793 // Check for the 'mov' aliases for the vector registers
3794 if (isVectorRegister(reg1))
3796 if (isVectorRegister(reg2) && isValidVectorDatasize(size))
3798 return emitIns_R_R_R(INS_mov, size, reg1, reg2, reg2);
3802 return emitIns_R_R_I(INS_mov, size, reg1, reg2, 0);
3807 if (isVectorRegister(reg2))
3809 assert(isGeneralRegister(reg1));
3810 return emitIns_R_R_I(INS_mov, size, reg1, reg2, 0);
3814 // Is this a MOV to/from SP instruction?
3815 if ((reg1 == REG_SP) || (reg2 == REG_SP))
3817 assert(isGeneralRegisterOrSP(reg1));
3818 assert(isGeneralRegisterOrSP(reg2));
3819 reg1 = encodingSPtoZR(reg1);
3820 reg2 = encodingSPtoZR(reg2);
3825 assert(insOptsNone(opt));
3826 assert(isGeneralRegister(reg1));
3827 assert(isGeneralRegisterOrZR(reg2));
3834 assert(insOptsAnyArrangement(opt));
3835 assert(isVectorRegister(reg1));
3836 assert(isGeneralRegisterOrZR(reg2));
3837 assert(isValidVectorDatasize(size));
3838 assert(isValidArrangement(size, opt));
3844 assert(isVectorRegister(reg1));
3845 assert(isVectorRegister(reg2));
3848 assert(isValidVectorDatasize(size));
3849 // Bitwise behavior is independent of element size, but is always encoded as 1 Byte
3850 opt = optMakeArrangement(size, EA_1BYTE);
3852 if (insOptsNone(opt))
3855 assert(size == EA_8BYTE); // Only type D is supported
3861 assert(insOptsAnyArrangement(opt));
3862 assert(isValidVectorDatasize(size));
3863 assert(isValidArrangement(size, opt));
3864 elemsize = optGetElemsize(opt);
3871 if (isVectorRegister(reg1))
3873 assert(isVectorRegister(reg2));
3876 assert(isValidVectorDatasize(size));
3877 // Bitwise behavior is independent of element size, but is always encoded as 1 Byte
3878 opt = optMakeArrangement(size, EA_1BYTE);
3880 if (insOptsNone(opt))
3883 assert(size == EA_8BYTE); // Only type D is supported
3889 assert(isValidVectorDatasize(size));
3890 assert(isValidArrangement(size, opt));
3891 elemsize = optGetElemsize(opt);
3899 assert(insOptsNone(opt));
3900 assert(isGeneralRegister(reg1));
3901 assert(isGeneralRegisterOrZR(reg2));
3906 assert(size == EA_8BYTE);
3913 assert(insOptsNone(opt));
3914 assert(isValidGeneralDatasize(size));
3915 assert(isGeneralRegister(reg1));
3916 assert(isGeneralRegister(reg2));
3924 return emitIns_R_R_I(ins, size, reg1, reg2, 0, opt);
3932 if (isVectorRegister(reg1))
3934 assert(isVectorRegister(reg2));
3935 assert(isValidVectorDatasize(size));
3936 assert(isValidArrangement(size, opt));
3937 elemsize = optGetElemsize(opt);
3938 if ((ins == INS_cls) || (ins == INS_clz))
3940 assert(elemsize != EA_8BYTE); // No encoding for type D
3942 else if (ins == INS_rev32)
3944 assert((elemsize == EA_2BYTE) || (elemsize == EA_1BYTE));
3948 assert(elemsize == EA_1BYTE); // Only supports 8B or 16B
3955 // Doesn't have general register version(s)
3962 assert(insOptsNone(opt));
3963 assert(isGeneralRegister(reg1));
3964 assert(isGeneralRegister(reg2));
3965 if (ins == INS_rev32)
3967 assert(size == EA_8BYTE);
3971 assert(isValidGeneralDatasize(size));
3984 assert(isVectorRegister(reg1));
3985 assert(isVectorRegister(reg2));
3986 assert(isValidVectorDatasize(size));
3987 assert(isValidArrangement(size, opt));
3988 elemsize = optGetElemsize(opt);
3989 assert(elemsize != EA_8BYTE); // No encoding for type D
3995 assert(isVectorRegister(reg1));
3996 assert(isVectorRegister(reg2));
3997 assert(isValidVectorDatasize(size));
3998 assert(isValidArrangement(size, opt));
3999 elemsize = optGetElemsize(opt);
4000 // size is determined by instruction
4003 assert(size == EA_8BYTE);
4005 else // ins == INS_xtn2
4007 assert(size == EA_16BYTE);
4009 assert(elemsize != EA_8BYTE); // Narrowing must not end with 8 byte data
4017 assert(isValidGeneralDatasize(size));
4029 assert(isValidGeneralLSDatasize(size));
4030 assert(isGeneralRegisterOrZR(reg1));
4031 assert(isGeneralRegisterOrSP(reg2));
4032 assert(insOptsNone(opt));
4034 reg2 = encodingSPtoZR(reg2);
4052 assert(insOptsNone(opt));
4053 emitIns_R_R_I(ins, attr, reg1, reg2, 0, INS_OPTS_NONE);
4057 assert(isValidVectorElemsizeFloat(size));
4059 // Is the mov even necessary?
4065 if (isVectorRegister(reg1))
4067 if (isVectorRegister(reg2))
4069 assert(insOptsNone(opt));
4074 assert(isGeneralRegister(reg2));
4076 // if the optional conversion specifier is not present we calculate it
4077 if (opt == INS_OPTS_NONE)
4079 opt = (size == EA_4BYTE) ? INS_OPTS_4BYTE_TO_S : INS_OPTS_8BYTE_TO_D;
4081 assert(insOptsConvertIntToFloat(opt));
4088 assert(isGeneralRegister(reg1));
4089 assert(isVectorRegister(reg2));
4091 // if the optional conversion specifier is not present we calculate it
4092 if (opt == INS_OPTS_NONE)
4094 opt = (size == EA_4BYTE) ? INS_OPTS_S_TO_4BYTE : INS_OPTS_D_TO_8BYTE;
4096 assert(insOptsConvertFloatToInt(opt));
4104 assert(insOptsNone(opt));
4105 assert(isValidVectorElemsizeFloat(size));
4106 assert(isVectorRegister(reg1));
4107 assert(isVectorRegister(reg2));
4121 if (insOptsAnyArrangement(opt))
4124 assert(isVectorRegister(reg1));
4125 assert(isVectorRegister(reg2));
4126 assert(isValidVectorDatasize(size));
4127 assert(isValidArrangement(size, opt));
4128 elemsize = optGetElemsize(opt);
4129 assert(isValidVectorElemsizeFloat(elemsize));
4130 assert(opt != INS_OPTS_1D); // Reserved encoding
4136 assert(isVectorRegister(reg2));
4137 if (isVectorRegister(reg1))
4139 assert(insOptsNone(opt));
4140 assert(isValidVectorElemsizeFloat(size));
4145 assert(isGeneralRegister(reg1));
4146 assert(insOptsConvertFloatToInt(opt));
4147 assert(isValidVectorElemsizeFloat(size));
4157 assert(isVectorRegister(reg1));
4158 assert(isVectorRegister(reg2));
4159 assert(isValidVectorDatasize(size));
4160 assert(insOptsNone(opt));
4161 assert(size == EA_8BYTE); // Narrowing from Double or Widening to Double (Half not supported)
4167 if (insOptsAnyArrangement(opt))
4170 assert(isVectorRegister(reg1));
4171 assert(isVectorRegister(reg2));
4172 assert(isValidVectorDatasize(size));
4173 assert(isValidArrangement(size, opt));
4174 elemsize = optGetElemsize(opt);
4175 assert(isValidVectorElemsizeFloat(elemsize));
4176 assert(opt != INS_OPTS_1D); // Reserved encoding
4182 assert(isVectorRegister(reg1));
4183 if (isVectorRegister(reg2))
4185 assert(insOptsNone(opt));
4186 assert(isValidVectorElemsizeFloat(size));
4191 assert(isGeneralRegister(reg2));
4192 assert(insOptsConvertIntToFloat(opt));
4193 assert(isValidVectorElemsizeFloat(size));
4209 if (insOptsAnyArrangement(opt))
4212 assert(isVectorRegister(reg1));
4213 assert(isVectorRegister(reg2));
4214 assert(isValidVectorDatasize(size));
4215 assert(isValidArrangement(size, opt));
4216 elemsize = optGetElemsize(opt);
4217 assert(isValidVectorElemsizeFloat(elemsize));
4218 assert(opt != INS_OPTS_1D); // Reserved encoding
4224 assert(insOptsNone(opt));
4225 assert(isValidVectorElemsizeFloat(size));
4226 assert(isVectorRegister(reg1));
4227 assert(isVectorRegister(reg2));
4234 assert(insOptsNone(opt));
4235 assert(isValidVectorElemsizeFloat(size));
4236 assert(isVectorRegister(reg1));
4237 assert(isVectorRegister(reg2));
4242 assert(insOptsConvertFloatToFloat(opt));
4243 assert(isValidVectorFcvtsize(size));
4244 assert(isVectorRegister(reg1));
4245 assert(isVectorRegister(reg2));
4254 assert(isVectorRegister(reg1));
4255 assert(isVectorRegister(reg2));
4257 if (isValidVectorDatasize(size))
4260 assert(insOptsAnyArrangement(opt));
4261 assert(isValidArrangement(size, opt));
4262 elemsize = optGetElemsize(opt);
4269 assert(size == EA_8BYTE); // Only Double supported
4279 assert(isVectorRegister(reg1));
4280 assert(isVectorRegister(reg2));
4282 if (isValidVectorDatasize(size))
4285 assert(insOptsAnyArrangement(opt));
4286 assert(isValidArrangement(size, opt));
4287 elemsize = optGetElemsize(opt);
4288 assert((elemsize == EA_8BYTE) || (elemsize == EA_4BYTE)); // Only Double/Float supported
4289 assert(opt != INS_OPTS_1D); // Reserved encoding
4296 assert((size == EA_8BYTE) || (size == EA_4BYTE)); // Only Double/Float supported
4304 assert(isVectorRegister(reg1));
4305 assert(isVectorRegister(reg2));
4306 assert(isValidVectorDatasize(size));
4307 elemsize = optGetElemsize(opt);
4308 assert(elemsize == EA_1BYTE);
4313 assert(insOptsNone(opt));
4314 assert(isVectorRegister(reg1));
4315 assert(isVectorRegister(reg2));
4321 assert(isVectorRegister(reg1));
4322 assert(isVectorRegister(reg2));
4323 assert(isValidVectorDatasize(size));
4324 elemsize = optGetElemsize(opt);
4325 assert(elemsize == EA_4BYTE);
4333 } // end switch (ins)
4335 assert(fmt != IF_NONE);
4337 instrDesc* id = emitNewInstrSmall(attr);
4350 /*****************************************************************************
4352 * Add an instruction referencing a register and two constants.
4355 void emitter::emitIns_R_I_I(
4356 instruction ins, emitAttr attr, regNumber reg, ssize_t imm1, ssize_t imm2, insOpts opt /* = INS_OPTS_NONE */)
4358 emitAttr size = EA_SIZE(attr);
4359 insFormat fmt = IF_NONE;
4360 size_t immOut = 0; // composed from imm1 and imm2 and stored in the instrDesc
4362 /* Figure out the encoding format of the instruction */
4369 ins = INS_movz; // INS_mov with LSL is an alias for INS_movz LSL
4375 assert(isValidGeneralDatasize(size));
4376 assert(isGeneralRegister(reg));
4377 assert(isValidUimm16(imm1));
4378 assert(insOptsLSL(opt)); // Must be INS_OPTS_LSL
4380 if (size == EA_8BYTE)
4382 assert((imm2 == 0) || (imm2 == 16) || // shift amount: 0, 16, 32 or 48
4383 (imm2 == 32) || (imm2 == 48));
4387 assert((imm2 == 0) || (imm2 == 16)); // shift amount: 0 or 16
4422 immOut = hwi.immHWVal;
4423 assert(isValidImmHWVal(immOut, size));
4432 } // end switch (ins)
4434 assert(fmt != IF_NONE);
4436 instrDesc* id = emitNewInstrSC(attr, immOut);
4447 /*****************************************************************************
4449 * Add an instruction referencing two registers and a constant.
4452 void emitter::emitIns_R_R_I(
4453 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm, insOpts opt /* = INS_OPTS_NONE */)
4455 emitAttr size = EA_SIZE(attr);
4456 emitAttr elemsize = EA_UNKNOWN;
4457 insFormat fmt = IF_NONE;
4458 bool isLdSt = false;
4459 bool isSIMD = false;
4460 bool isAddSub = false;
4461 bool setFlags = false;
4463 bool unscaledOp = false;
4465 /* Figure out the encoding format of the instruction */
4472 // Check for the 'mov' aliases for the vector registers
4473 assert(insOptsNone(opt));
4474 assert(isValidVectorElemsize(size));
4476 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4478 if (isVectorRegister(reg1))
4480 if (isGeneralRegisterOrZR(reg2))
4482 fmt = IF_DV_2C; // Alias for 'ins'
4485 else if (isVectorRegister(reg2))
4487 fmt = IF_DV_2E; // Alias for 'dup'
4491 else // isGeneralRegister(reg1)
4493 assert(isGeneralRegister(reg1));
4494 if (isVectorRegister(reg2))
4496 fmt = IF_DV_2B; // Alias for 'umov'
4500 assert(!" invalid INS_mov operands");
4506 assert(insOptsNone(opt));
4507 assert(isValidGeneralDatasize(size));
4508 assert(isGeneralRegister(reg1));
4509 assert(isGeneralRegister(reg2));
4510 assert(isValidImmShift(imm, size));
4515 assert(insOptsNone(opt));
4516 assert(isValidGeneralDatasize(size));
4517 assert(isGeneralRegister(reg1));
4518 assert(isGeneralRegister(reg2));
4519 assert(isValidImmShift(imm, size));
4534 assert(isVectorRegister(reg1));
4535 assert(isVectorRegister(reg2));
4536 if (insOptsAnyArrangement(opt))
4539 assert(isValidVectorDatasize(size));
4540 assert(isValidArrangement(size, opt));
4541 elemsize = optGetElemsize(opt);
4542 assert(isValidVectorElemsize(elemsize));
4543 assert(isValidImmShift(imm, elemsize));
4544 assert(opt != INS_OPTS_1D); // Reserved encoding
4551 assert(insOptsNone(opt));
4552 assert(size == EA_8BYTE); // only supported size
4553 assert(isValidImmShift(imm, size));
4567 assert(isVectorRegister(reg1));
4568 assert(isVectorRegister(reg2));
4570 assert(size == EA_8BYTE);
4571 assert(isValidArrangement(size, opt));
4572 elemsize = optGetElemsize(opt);
4573 assert(elemsize != EA_8BYTE); // Reserved encodings
4574 assert(isValidVectorElemsize(elemsize));
4575 assert(isValidImmShift(imm, elemsize));
4588 assert(isVectorRegister(reg1));
4589 assert(isVectorRegister(reg2));
4591 assert(size == EA_16BYTE);
4592 assert(isValidArrangement(size, opt));
4593 elemsize = optGetElemsize(opt);
4594 assert(elemsize != EA_8BYTE); // Reserved encodings
4595 assert(isValidVectorElemsize(elemsize));
4596 assert(isValidImmShift(imm, elemsize));
4603 assert(isValidGeneralDatasize(size));
4604 assert(isGeneralRegister(reg1));
4605 assert(isGeneralRegisterOrZR(reg2));
4609 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4617 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
4621 assert(insOptsAluShift(opt)); // a non-zero imm, must select shift kind, can't use ROR
4623 assert(isValidImmShift(imm, size));
4629 assert(isValidGeneralDatasize(size));
4630 assert(isGeneralRegisterOrZR(reg1));
4631 assert(isGeneralRegister(reg2));
4633 if (insOptsAnyShift(opt))
4635 assert(isValidImmShift(imm, size) && (imm != 0));
4640 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4648 assert(isValidGeneralDatasize(size));
4649 assert(isGeneralRegisterOrSP(reg1));
4650 assert(isGeneralRegister(reg2));
4652 reg1 = encodingSPtoZR(reg1);
4653 if (insOptsAnyExtend(opt))
4655 assert((imm >= 0) && (imm <= 4));
4661 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4667 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
4668 assert(isValidImmShift(imm, size));
4677 assert(insOptsNone(opt));
4678 assert(isGeneralRegister(reg2));
4679 if (ins == INS_ands)
4681 assert(isGeneralRegister(reg1));
4685 assert(isGeneralRegisterOrSP(reg1));
4686 reg1 = encodingSPtoZR(reg1);
4690 canEncode = canEncodeBitMaskImm(imm, size, &bmi);
4694 assert(isValidImmNRS(imm, size));
4699 case INS_dup: // by element, imm selects the element of reg2
4700 assert(isVectorRegister(reg1));
4701 if (isVectorRegister(reg2))
4703 if (insOptsAnyArrangement(opt))
4706 assert(isValidVectorDatasize(size));
4707 assert(isValidArrangement(size, opt));
4708 elemsize = optGetElemsize(opt);
4709 assert(isValidVectorElemsize(elemsize));
4710 assert(isValidVectorIndex(size, elemsize, imm));
4711 assert(opt != INS_OPTS_1D); // Reserved encoding
4718 assert(insOptsNone(opt));
4720 assert(isValidVectorElemsize(elemsize));
4721 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4728 case INS_ins: // (MOV from general)
4729 assert(insOptsNone(opt));
4730 assert(isValidVectorElemsize(size));
4731 assert(isVectorRegister(reg1));
4732 assert(isGeneralRegisterOrZR(reg2));
4734 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4738 case INS_umov: // (MOV to general)
4739 assert(insOptsNone(opt));
4740 assert(isValidVectorElemsize(size));
4741 assert(isGeneralRegister(reg1));
4742 assert(isVectorRegister(reg2));
4744 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4749 assert(insOptsNone(opt));
4750 assert(isValidVectorElemsize(size));
4751 assert(size != EA_8BYTE); // no encoding, use INS_umov
4752 assert(isGeneralRegister(reg1));
4753 assert(isVectorRegister(reg2));
4755 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4773 // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4774 assert(isValidGeneralDatasize(size));
4775 unscaledOp = (ins == INS_ldursb);
4782 // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4783 assert(isValidGeneralDatasize(size));
4784 unscaledOp = (ins == INS_ldursh);
4791 // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4792 assert(size == EA_8BYTE);
4793 unscaledOp = (ins == INS_ldursw);
4832 // Is the target a vector register?
4833 if (isVectorRegister(reg1))
4835 assert(isValidVectorLSDatasize(size));
4836 assert(isGeneralRegisterOrSP(reg2));
4841 assert(isValidGeneralDatasize(size));
4844 scale = NaturalScale_helper(size);
4850 // Is the target a vector register?
4851 if (isVectorRegister(reg1))
4853 assert(isValidVectorLSDatasize(size));
4854 assert(isGeneralRegisterOrSP(reg2));
4859 assert(isValidGeneralDatasize(size));
4870 } // end switch (ins)
4878 assert(isValidVectorLSDatasize(size));
4879 assert(isVectorRegister(reg1));
4880 assert((scale >= 0) && (scale <= 4));
4884 assert(isValidGeneralLSDatasize(size));
4885 assert(isGeneralRegisterOrZR(reg1));
4886 assert((scale >= 0) && (scale <= 3));
4889 assert(isGeneralRegisterOrSP(reg2));
4891 // Load/Store reserved encodings:
4892 if (insOptsIndexed(opt))
4894 assert(reg1 != reg2);
4897 reg2 = encodingSPtoZR(reg2);
4899 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
4902 assert(insOptsNone(opt)); // PRE/POST Index doesn't make sense with an immediate of zero
4906 else if (insOptsIndexed(opt) || unscaledOp || (imm < 0) || ((imm & mask) != 0))
4908 if ((imm >= -256) && (imm <= 255))
4914 assert(!"Instruction cannot be encoded: IF_LS_2C");
4919 assert(insOptsNone(opt));
4920 assert(!unscaledOp);
4922 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
4924 imm >>= scale; // The immediate is scaled by the size of the ld/st
4930 assert(!"Instruction cannot be encoded: IF_LS_2B");
4937 assert(insOptsNone(opt));
4939 if (setFlags) // Can't encode SP with setFlags
4941 assert(isGeneralRegister(reg1));
4942 assert(isGeneralRegister(reg2));
4946 assert(isGeneralRegisterOrSP(reg1));
4947 assert(isGeneralRegisterOrSP(reg2));
4949 // Is it just a mov?
4952 // Is the mov even necessary?
4955 emitIns_R_R(INS_mov, attr, reg1, reg2);
4960 reg1 = encodingSPtoZR(reg1);
4961 reg2 = encodingSPtoZR(reg2);
4964 if (unsigned_abs(imm) <= 0x0fff)
4968 ins = insReverse(ins);
4971 assert(isValidUimm12(imm));
4974 else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
4976 // Encoding will use a 12-bit left shift of the immediate
4977 opt = INS_OPTS_LSL12;
4980 ins = insReverse(ins);
4983 assert((imm & 0xfff) == 0);
4985 assert(isValidUimm12(imm));
4990 assert(!"Instruction cannot be encoded: IF_DI_2A");
4994 assert(fmt != IF_NONE);
4996 instrDesc* id = emitNewInstrSC(attr, imm);
5009 /*****************************************************************************
5011 * Add an instruction referencing two registers and a constant.
5012 * Also checks for a large immediate that needs a second instruction
5013 * and will load it in reg1
5015 * - Supports instructions: add, adds, sub, subs, and, ands, eor and orr
5016 * - Requires that reg1 is a general register and not SP or ZR
5017 * - Requires that reg1 != reg2
5019 void emitter::emitIns_R_R_Imm(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm)
5021 assert(isGeneralRegister(reg1));
5022 assert(reg1 != reg2);
5024 bool immFits = true;
5032 immFits = emitter::emitIns_valid_imm_for_add(imm, attr);
5039 immFits = emitter::emitIns_valid_imm_for_alu(imm, attr);
5043 assert(!"Unsupported instruction in emitIns_R_R_Imm");
5048 emitIns_R_R_I(ins, attr, reg1, reg2, imm);
5052 // Load 'imm' into the reg1 register
5053 // then issue: 'ins' reg1, reg2, reg1
5055 codeGen->instGen_Set_Reg_To_Imm(attr, reg1, imm);
5056 emitIns_R_R_R(ins, attr, reg1, reg2, reg1);
5060 /*****************************************************************************
5062 * Add an instruction referencing three registers.
5065 void emitter::emitIns_R_R_R(
5066 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insOpts opt) /* = INS_OPTS_NONE */
5068 emitAttr size = EA_SIZE(attr);
5069 emitAttr elemsize = EA_UNKNOWN;
5070 insFormat fmt = IF_NONE;
5072 /* Figure out the encoding format of the instruction */
5096 assert(insOptsNone(opt));
5097 assert(isValidGeneralDatasize(size));
5098 assert(isGeneralRegister(reg1));
5099 assert(isGeneralRegister(reg2));
5100 assert(isGeneralRegister(reg3));
5105 if (insOptsNone(opt))
5108 assert(isValidGeneralDatasize(size));
5109 assert(isGeneralRegister(reg1));
5110 assert(isGeneralRegister(reg2));
5111 assert(isGeneralRegister(reg3));
5120 assert(insOptsAnyArrangement(opt));
5121 assert(isVectorRegister(reg1));
5122 assert(isVectorRegister(reg2));
5123 assert(isVectorRegister(reg3));
5124 assert(isValidVectorDatasize(size));
5125 assert(isValidArrangement(size, opt));
5126 elemsize = optGetElemsize(opt);
5127 if (ins == INS_pmul)
5129 assert(elemsize == EA_1BYTE); // only supports 8B or 16B
5131 else // INS_mul, INS_mla, INS_mls
5133 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
5140 if (isVectorRegister(reg1))
5142 assert(isVectorRegister(reg2));
5143 assert(isVectorRegister(reg3));
5145 if (insOptsAnyArrangement(opt))
5148 assert(opt != INS_OPTS_1D); // Reserved encoding
5149 assert(isValidVectorDatasize(size));
5150 assert(isValidArrangement(size, opt));
5156 assert(insOptsNone(opt));
5157 assert(size == EA_8BYTE);
5166 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, INS_OPTS_NONE);
5175 assert(isVectorRegister(reg1));
5176 assert(isVectorRegister(reg2));
5177 assert(isVectorRegister(reg3));
5179 if (isValidVectorDatasize(size))
5182 assert(insOptsAnyArrangement(opt));
5183 assert(isValidArrangement(size, opt));
5184 elemsize = optGetElemsize(opt);
5191 assert(size == EA_8BYTE); // Only Double supported
5199 assert(isVectorRegister(reg1));
5200 assert(isVectorRegister(reg2));
5201 assert(isVectorRegister(reg3));
5203 if (isValidVectorDatasize(size))
5206 assert(insOptsAnyArrangement(opt));
5207 assert(isValidArrangement(size, opt));
5208 elemsize = optGetElemsize(opt);
5209 assert((elemsize == EA_8BYTE) || (elemsize == EA_4BYTE)); // Only Double/Float supported
5210 assert(opt != INS_OPTS_1D); // Reserved encoding
5217 assert((size == EA_8BYTE) || (size == EA_4BYTE)); // Only Double/Float supported
5230 assert(isVectorRegister(reg1));
5231 assert(isVectorRegister(reg2));
5232 assert(isVectorRegister(reg3));
5233 assert(insOptsAnyArrangement(opt));
5236 assert(isValidVectorDatasize(size));
5237 assert(isValidArrangement(size, opt));
5238 elemsize = optGetElemsize(opt);
5239 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
5245 assert(isVectorRegister(reg1));
5246 assert(isVectorRegister(reg2));
5247 assert(reg2 == reg3);
5248 assert(isValidVectorDatasize(size));
5249 // INS_mov is an alias for INS_orr (vector register)
5250 if (opt == INS_OPTS_NONE)
5252 elemsize = EA_1BYTE;
5253 opt = optMakeArrangement(size, elemsize);
5255 assert(isValidArrangement(size, opt));
5264 if (isVectorRegister(reg1))
5266 assert(isValidVectorDatasize(size));
5267 assert(isVectorRegister(reg2));
5268 assert(isVectorRegister(reg3));
5269 if (opt == INS_OPTS_NONE)
5271 elemsize = EA_1BYTE;
5272 opt = optMakeArrangement(size, elemsize);
5274 assert(isValidArrangement(size, opt));
5283 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, INS_OPTS_NONE);
5289 assert(isValidVectorDatasize(size));
5290 assert(isVectorRegister(reg1));
5291 assert(isVectorRegister(reg2));
5292 assert(isVectorRegister(reg3));
5293 if (opt == INS_OPTS_NONE)
5295 elemsize = EA_1BYTE;
5296 opt = optMakeArrangement(size, elemsize);
5298 assert(isValidArrangement(size, opt));
5310 assert(isVectorRegister(reg1));
5311 assert(isVectorRegister(reg2));
5312 assert(isVectorRegister(reg3));
5313 if (insOptsAnyArrangement(opt))
5316 assert(isValidVectorDatasize(size));
5317 assert(isValidArrangement(size, opt));
5318 elemsize = optGetElemsize(opt);
5319 assert(isValidVectorElemsizeFloat(elemsize));
5320 assert(opt != INS_OPTS_1D); // Reserved encoding
5326 assert(insOptsNone(opt));
5327 assert(isValidScalarDatasize(size));
5334 assert(insOptsNone(opt));
5335 assert(isVectorRegister(reg1));
5336 assert(isVectorRegister(reg2));
5337 assert(isVectorRegister(reg3));
5338 assert(isValidScalarDatasize(size));
5345 assert(isVectorRegister(reg1));
5346 assert(isVectorRegister(reg2));
5347 assert(isVectorRegister(reg3));
5348 assert(insOptsAnyArrangement(opt)); // no scalar encoding, use 4-operand 'fmadd' or 'fmsub'
5351 assert(isValidVectorDatasize(size));
5352 assert(isValidArrangement(size, opt));
5353 elemsize = optGetElemsize(opt);
5354 assert(isValidVectorElemsizeFloat(elemsize));
5355 assert(opt != INS_OPTS_1D); // Reserved encoding
5368 emitIns_R_R_R_Ext(ins, attr, reg1, reg2, reg3, opt);
5376 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0);
5385 assert(isGeneralRegisterOrZR(reg1));
5386 assert(isGeneralRegisterOrZR(reg2));
5387 assert(isGeneralRegisterOrSP(reg3));
5398 assert(isValidVectorDatasize(size));
5399 assert(isVectorRegister(reg1));
5400 assert(isVectorRegister(reg2));
5401 assert(isVectorRegister(reg3));
5402 if (opt == INS_OPTS_NONE)
5404 elemsize = EA_4BYTE;
5405 opt = optMakeArrangement(size, elemsize);
5407 assert(isValidArrangement(size, opt));
5415 } // end switch (ins)
5417 assert(fmt != IF_NONE);
5419 instrDesc* id = emitNewInstr(attr);
5433 /*****************************************************************************
5435 * Add an instruction referencing three registers and a constant.
5438 void emitter::emitIns_R_R_R_I(instruction ins,
5444 insOpts opt /* = INS_OPTS_NONE */,
5445 emitAttr attrReg2 /* = EA_UNKNOWN */)
5447 emitAttr size = EA_SIZE(attr);
5448 emitAttr elemsize = EA_UNKNOWN;
5449 insFormat fmt = IF_NONE;
5450 bool isLdSt = false;
5451 bool isSIMD = false;
5452 bool isAddSub = false;
5453 bool setFlags = false;
5456 /* Figure out the encoding format of the instruction */
5460 assert(insOptsNone(opt));
5461 assert(isValidGeneralDatasize(size));
5462 assert(isGeneralRegister(reg1));
5463 assert(isGeneralRegister(reg2));
5464 assert(isGeneralRegister(reg3));
5465 assert(isValidImmShift(imm, size));
5477 assert(isValidGeneralDatasize(size));
5478 assert(isGeneralRegister(reg1));
5479 assert(isGeneralRegister(reg2));
5480 assert(isGeneralRegister(reg3));
5481 assert(isValidImmShift(imm, size));
5484 assert(insOptsNone(opt)); // a zero imm, means no shift kind
5489 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
5494 case INS_fmul: // by element, imm[0..3] selects the element of reg3
5498 assert(isVectorRegister(reg1));
5499 assert(isVectorRegister(reg2));
5500 assert(isVectorRegister(reg3));
5501 if (insOptsAnyArrangement(opt))
5504 assert(isValidVectorDatasize(size));
5505 assert(isValidArrangement(size, opt));
5506 elemsize = optGetElemsize(opt);
5507 assert(isValidVectorElemsizeFloat(elemsize));
5508 assert(isValidVectorIndex(size, elemsize, imm));
5509 assert(opt != INS_OPTS_1D); // Reserved encoding
5515 assert(insOptsNone(opt));
5516 assert(isValidScalarDatasize(size));
5518 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
5523 case INS_mul: // by element, imm[0..7] selects the element of reg3
5526 assert(isVectorRegister(reg1));
5527 assert(isVectorRegister(reg2));
5528 assert(isVectorRegister(reg3));
5530 assert(insOptsAnyArrangement(opt));
5531 assert(isValidVectorDatasize(size));
5532 assert(isValidArrangement(size, opt));
5533 elemsize = optGetElemsize(opt);
5534 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
5535 // Only has encodings for H or S elemsize
5536 assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE));
5537 // Only has encodings for V0..V15
5538 if ((elemsize == EA_2BYTE) && (reg3 >= REG_V16))
5540 noway_assert(!"Invalid reg3");
5564 assert(insOptsNone(opt)); // Can't use Pre/Post index on these two instructions
5569 // Is the target a vector register?
5570 if (isVectorRegister(reg1))
5572 scale = NaturalScale_helper(size);
5577 scale = (size == EA_8BYTE) ? 3 : 2;
5586 } // end switch (ins)
5591 assert(isGeneralRegisterOrSP(reg3));
5592 assert(insOptsNone(opt) || insOptsIndexed(opt));
5596 assert(isValidVectorLSPDatasize(size));
5597 assert(isVectorRegister(reg1));
5598 assert(isVectorRegister(reg2));
5599 assert((scale >= 2) && (scale <= 4));
5603 assert(isValidGeneralDatasize(size));
5604 assert(isGeneralRegisterOrZR(reg1));
5605 assert(isGeneralRegisterOrZR(reg2));
5606 assert((scale == 2) || (scale == 3));
5609 // Load/Store Pair reserved encodings:
5610 if (emitInsIsLoad(ins))
5612 assert(reg1 != reg2);
5614 if (insOptsIndexed(opt))
5616 assert(reg1 != reg3);
5617 assert(reg2 != reg3);
5620 reg3 = encodingSPtoZR(reg3);
5622 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
5625 assert(insOptsNone(opt)); // PRE/POST Index doesn't make sense with an immediate of zero
5631 if ((imm & mask) == 0)
5633 imm >>= scale; // The immediate is scaled by the size of the ld/st
5635 if ((imm >= -64) && (imm <= 63))
5641 if (fmt != IF_LS_3C)
5643 assert(!"Instruction cannot be encoded: IF_LS_3C");
5650 bool reg2IsSP = (reg2 == REG_SP);
5652 assert(isValidGeneralDatasize(size));
5653 assert(isGeneralRegister(reg3));
5655 if (setFlags || insOptsAluShift(opt)) // Can't encode SP in reg1 with setFlags or AluShift option
5657 assert(isGeneralRegisterOrZR(reg1));
5661 assert(isGeneralRegisterOrSP(reg1));
5662 reg1 = encodingSPtoZR(reg1);
5665 if (insOptsAluShift(opt)) // Can't encode SP in reg2 with AluShift option
5667 assert(isGeneralRegister(reg2));
5671 assert(isGeneralRegisterOrSP(reg2));
5672 reg2 = encodingSPtoZR(reg2);
5675 if (insOptsAnyExtend(opt))
5677 assert((imm >= 0) && (imm <= 4));
5681 else if (insOptsAluShift(opt))
5683 // imm should be non-zero and in [1..63]
5684 assert(isValidImmShift(imm, size) && (imm != 0));
5689 assert(insOptsNone(opt));
5693 // To encode the SP register as reg2 we must use the IF_DR_3C encoding
5694 // and also specify a LSL of zero (imm == 0)
5705 assert(!"Instruction cannot be encoded: Add/Sub IF_DR_3A");
5708 assert(fmt != IF_NONE);
5710 instrDesc* id = emitNewInstrCns(attr, imm);
5720 // Record the attribute for the second register in the pair
5721 id->idGCrefReg2(GCT_NONE);
5722 if (attrReg2 != EA_UNKNOWN)
5724 // Record the attribute for the second register in the pair
5725 assert((fmt == IF_LS_3B) || (fmt == IF_LS_3C));
5726 if (EA_IS_GCREF(attrReg2))
5728 id->idGCrefReg2(GCT_GCREF);
5730 else if (EA_IS_BYREF(attrReg2))
5732 id->idGCrefReg2(GCT_BYREF);
5740 /*****************************************************************************
5742 * Add an instruction referencing three registers, with an extend option
5745 void emitter::emitIns_R_R_R_Ext(instruction ins,
5750 insOpts opt, /* = INS_OPTS_NONE */
5751 int shiftAmount) /* = -1 -- unset */
5753 emitAttr size = EA_SIZE(attr);
5754 insFormat fmt = IF_NONE;
5755 bool isSIMD = false;
5758 /* Figure out the encoding format of the instruction */
5779 // Is the target a vector register?
5780 if (isVectorRegister(reg1))
5782 assert(isValidVectorLSDatasize(size));
5783 scale = NaturalScale_helper(size);
5788 assert(isValidGeneralDatasize(size));
5789 scale = (size == EA_8BYTE) ? 3 : 2;
5798 } // end switch (ins)
5800 assert(scale != -1);
5801 assert(insOptsLSExtend(opt));
5805 assert(isValidVectorLSDatasize(size));
5806 assert(isVectorRegister(reg1));
5810 assert(isValidGeneralLSDatasize(size));
5811 assert(isGeneralRegisterOrZR(reg1));
5814 assert(isGeneralRegisterOrSP(reg2));
5815 assert(isGeneralRegister(reg3));
5817 // Load/Store reserved encodings:
5818 if (insOptsIndexed(opt))
5820 assert(reg1 != reg2);
5823 if (shiftAmount == -1)
5825 shiftAmount = insOptsLSL(opt) ? scale : 0;
5827 assert((shiftAmount == scale) || (shiftAmount == 0));
5829 reg2 = encodingSPtoZR(reg2);
5832 instrDesc* id = emitNewInstr(attr);
5841 id->idReg3Scaled(shiftAmount == scale);
5847 /*****************************************************************************
5849 * Add an instruction referencing two registers and two constants.
5852 void emitter::emitIns_R_R_I_I(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, int imm1, int imm2)
5854 emitAttr size = EA_SIZE(attr);
5855 emitAttr elemsize = EA_UNKNOWN;
5856 insFormat fmt = IF_NONE;
5857 size_t immOut = 0; // composed from imm1 and imm2 and stored in the instrDesc
5859 /* Figure out the encoding format of the instruction */
5869 assert(isGeneralRegister(reg1));
5870 assert(isGeneralRegister(reg2));
5871 assert(isValidImmShift(imm1, size));
5872 assert(isValidImmShift(imm2, size));
5874 bmi.immN = (size == EA_8BYTE);
5877 immOut = bmi.immNRS;
5884 assert(isGeneralRegister(reg1));
5885 assert(isGeneralRegister(reg2));
5886 lsb = getBitWidth(size) - imm1;
5888 assert(isValidImmShift(lsb, size));
5889 assert(isValidImmShift(width, size));
5891 bmi.immN = (size == EA_8BYTE);
5894 immOut = bmi.immNRS;
5901 assert(isGeneralRegister(reg1));
5902 assert(isGeneralRegister(reg2));
5904 width = imm2 + imm1 - 1;
5905 assert(isValidImmShift(lsb, size));
5906 assert(isValidImmShift(width, size));
5908 bmi.immN = (size == EA_8BYTE);
5910 bmi.immS = imm2 + imm1 - 1;
5911 immOut = bmi.immNRS;
5917 assert(isVectorRegister(reg1));
5918 assert(isVectorRegister(reg2));
5920 assert(isValidVectorElemsize(elemsize));
5921 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm1));
5922 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm2));
5923 immOut = (imm1 << 4) + imm2;
5931 assert(fmt != IF_NONE);
5933 instrDesc* id = emitNewInstrSC(attr, immOut);
5945 /*****************************************************************************
5947 * Add an instruction referencing four registers.
5950 void emitter::emitIns_R_R_R_R(
5951 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, regNumber reg4)
5953 emitAttr size = EA_SIZE(attr);
5954 insFormat fmt = IF_NONE;
5956 /* Figure out the encoding format of the instruction */
5965 assert(isValidGeneralDatasize(size));
5966 assert(isGeneralRegister(reg1));
5967 assert(isGeneralRegister(reg2));
5968 assert(isGeneralRegister(reg3));
5969 assert(isGeneralRegister(reg4));
5978 assert(isValidScalarDatasize(size));
5979 assert(isVectorRegister(reg1));
5980 assert(isVectorRegister(reg2));
5981 assert(isVectorRegister(reg3));
5982 assert(isVectorRegister(reg4));
5994 assert(fmt != IF_NONE);
5996 instrDesc* id = emitNewInstr(attr);
6010 /*****************************************************************************
6012 * Add an instruction referencing a register and a condition code
6015 void emitter::emitIns_R_COND(instruction ins, emitAttr attr, regNumber reg, insCond cond)
6017 emitAttr size = EA_SIZE(attr);
6018 insFormat fmt = IF_NONE;
6022 /* Figure out the encoding format of the instruction */
6027 assert(isGeneralRegister(reg));
6036 } // end switch (ins)
6038 assert(fmt != IF_NONE);
6039 assert(isValidImmCond(cfi.immCFVal));
6041 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6045 id->idInsOpt(INS_OPTS_NONE);
6053 /*****************************************************************************
6055 * Add an instruction referencing two registers and a condition code
6058 void emitter::emitIns_R_R_COND(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insCond cond)
6060 emitAttr size = EA_SIZE(attr);
6061 insFormat fmt = IF_NONE;
6065 /* Figure out the encoding format of the instruction */
6071 assert(isGeneralRegister(reg1));
6072 assert(isGeneralRegister(reg2));
6080 } // end switch (ins)
6082 assert(fmt != IF_NONE);
6083 assert(isValidImmCond(cfi.immCFVal));
6085 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6089 id->idInsOpt(INS_OPTS_NONE);
6098 /*****************************************************************************
6100 * Add an instruction referencing two registers and a condition code
6103 void emitter::emitIns_R_R_R_COND(
6104 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insCond cond)
6106 emitAttr size = EA_SIZE(attr);
6107 insFormat fmt = IF_NONE;
6111 /* Figure out the encoding format of the instruction */
6118 assert(isGeneralRegister(reg1));
6119 assert(isGeneralRegister(reg2));
6120 assert(isGeneralRegister(reg3));
6129 } // end switch (ins)
6131 assert(fmt != IF_NONE);
6132 assert(isValidImmCond(cfi.immCFVal));
6134 instrDesc* id = emitNewInstr(attr);
6138 id->idInsOpt(INS_OPTS_NONE);
6143 id->idSmallCns(cfi.immCFVal);
6149 /*****************************************************************************
6151 * Add an instruction referencing two registers the flags and a condition code
6154 void emitter::emitIns_R_R_FLAGS_COND(
6155 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insCflags flags, insCond cond)
6157 emitAttr size = EA_SIZE(attr);
6158 insFormat fmt = IF_NONE;
6162 /* Figure out the encoding format of the instruction */
6167 assert(isGeneralRegister(reg1));
6168 assert(isGeneralRegister(reg2));
6176 } // end switch (ins)
6178 assert(fmt != IF_NONE);
6179 assert(isValidImmCondFlags(cfi.immCFVal));
6181 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6185 id->idInsOpt(INS_OPTS_NONE);
6194 /*****************************************************************************
6196 * Add an instruction referencing a register, an immediate, the flags and a condition code
6199 void emitter::emitIns_R_I_FLAGS_COND(
6200 instruction ins, emitAttr attr, regNumber reg, int imm, insCflags flags, insCond cond)
6202 emitAttr size = EA_SIZE(attr);
6203 insFormat fmt = IF_NONE;
6207 /* Figure out the encoding format of the instruction */
6212 assert(isGeneralRegister(reg));
6215 ins = insReverse(ins);
6218 if ((imm >= 0) && (imm <= 31))
6227 assert(!"Instruction cannot be encoded: ccmp/ccmn imm5");
6233 } // end switch (ins)
6235 assert(fmt != IF_NONE);
6236 assert(isValidImmCondFlagsImm5(cfi.immCFVal));
6238 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6242 id->idInsOpt(INS_OPTS_NONE);
6250 /*****************************************************************************
6252 * Add a memory barrier instruction with a 'barrier' immediate
6255 void emitter::emitIns_BARR(instruction ins, insBarrier barrier)
6257 insFormat fmt = IF_NONE;
6260 /* Figure out the encoding format of the instruction */
6268 imm = (ssize_t)barrier;
6273 } // end switch (ins)
6275 assert(fmt != IF_NONE);
6277 instrDesc* id = emitNewInstrSC(EA_8BYTE, imm);
6281 id->idInsOpt(INS_OPTS_NONE);
6287 /*****************************************************************************
6289 * Add an instruction with a static data member operand. If 'size' is 0, the
6290 * instruction operates on the address of the static member instead of its
6291 * value (e.g. "push offset clsvar", rather than "push dword ptr [clsvar]").
6294 void emitter::emitIns_C(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, int offs)
6299 /*****************************************************************************
6301 * Add an instruction referencing stack-based local variable.
6304 void emitter::emitIns_S(instruction ins, emitAttr attr, int varx, int offs)
6309 /*****************************************************************************
6311 * Add an instruction referencing a register and a stack-based local variable.
6313 void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
6315 emitAttr size = EA_SIZE(attr);
6316 insFormat fmt = IF_NONE;
6322 // TODO-ARM64-CQ: use unscaled loads?
6323 /* Figure out the encoding format of the instruction */
6344 assert(isValidGeneralDatasize(size) || isValidVectorDatasize(size));
6345 scale = genLog2(EA_SIZE_IN_BYTES(size));
6349 assert(size == EA_8BYTE);
6354 NYI("emitIns_R_S"); // FP locals?
6357 } // end switch (ins)
6359 /* Figure out the variable's frame position */
6364 base = emitComp->lvaFrameAddress(varx, &FPbased);
6366 assert((scale >= 0) && (scale <= 4));
6368 regNumber reg2 = FPbased ? REG_FPBASE : REG_SPBASE;
6369 reg2 = encodingSPtoZR(reg2);
6386 fmt = IF_DI_2A; // add reg1,reg2,#disp
6390 regNumber rsvdReg = codeGen->rsGetRsvdReg();
6391 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6392 fmt = IF_DR_3A; // add reg1,reg2,rsvdReg
6397 bool useRegForImm = false;
6398 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6405 else if ((imm < 0) || ((imm & mask) != 0))
6407 if ((imm >= -256) && (imm <= 255))
6413 useRegForImm = true;
6418 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
6420 imm >>= scale; // The immediate is scaled by the size of the ld/st
6426 useRegForImm = true;
6432 regNumber rsvdReg = codeGen->rsGetRsvdReg();
6433 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6438 assert(fmt != IF_NONE);
6440 instrDesc* id = emitNewInstrCns(attr, imm);
6444 id->idInsOpt(INS_OPTS_NONE);
6448 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6449 id->idSetIsLclVar();
6452 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6459 /*****************************************************************************
6461 * Add an instruction referencing two register and consectutive stack-based local variable slots.
6463 void emitter::emitIns_R_R_S_S(
6464 instruction ins, emitAttr attr1, emitAttr attr2, regNumber reg1, regNumber reg2, int varx, int offs)
6466 assert((ins == INS_ldp) || (ins == INS_ldnp));
6467 assert(EA_8BYTE == EA_SIZE(attr1));
6468 assert(EA_8BYTE == EA_SIZE(attr2));
6469 assert(isGeneralRegisterOrZR(reg1));
6470 assert(isGeneralRegisterOrZR(reg2));
6473 insFormat fmt = IF_LS_3B;
6475 const unsigned scale = 3;
6477 /* Figure out the variable's frame position */
6481 base = emitComp->lvaFrameAddress(varx, &FPbased);
6484 // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6485 regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE;
6486 reg3 = encodingSPtoZR(reg3);
6488 bool useRegForAdr = true;
6490 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6493 useRegForAdr = false;
6497 if ((imm & mask) == 0)
6499 ssize_t immShift = imm >> scale; // The immediate is scaled by the size of the ld/st
6501 if ((immShift >= -64) && (immShift <= 63))
6504 useRegForAdr = false;
6512 regNumber rsvd = codeGen->rsGetRsvdReg();
6513 emitIns_R_R_Imm(INS_add, EA_PTRSIZE, rsvd, reg3, imm);
6518 assert(fmt != IF_NONE);
6520 instrDesc* id = emitNewInstrCns(attr1, imm);
6524 id->idInsOpt(INS_OPTS_NONE);
6526 // Record the attribute for the second register in the pair
6527 if (EA_IS_GCREF(attr2))
6529 id->idGCrefReg2(GCT_GCREF);
6531 else if (EA_IS_BYREF(attr2))
6533 id->idGCrefReg2(GCT_BYREF);
6537 id->idGCrefReg2(GCT_NONE);
6543 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6544 id->idSetIsLclVar();
6547 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6554 /*****************************************************************************
6556 * Add an instruction referencing a stack-based local variable and a register
6558 void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
6561 emitAttr size = EA_SIZE(attr);
6562 insFormat fmt = IF_NONE;
6565 bool isVectorStore = false;
6567 // TODO-ARM64-CQ: use unscaled loads?
6568 /* Figure out the encoding format of the instruction */
6573 assert(isGeneralRegisterOrZR(reg1));
6578 assert(isGeneralRegisterOrZR(reg1));
6582 if (isGeneralRegisterOrZR(reg1))
6584 assert(isValidGeneralDatasize(size));
6585 scale = (size == EA_8BYTE) ? 3 : 2;
6589 assert(isVectorRegister(reg1));
6590 assert(isValidVectorLSDatasize(size));
6591 scale = NaturalScale_helper(size);
6592 isVectorStore = true;
6597 NYI("emitIns_S_R"); // FP locals?
6600 } // end switch (ins)
6602 /* Figure out the variable's frame position */
6606 base = emitComp->lvaFrameAddress(varx, &FPbased);
6618 // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6619 regNumber reg2 = FPbased ? REG_FPBASE : REG_SPBASE;
6620 reg2 = encodingSPtoZR(reg2);
6622 bool useRegForImm = false;
6624 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6629 else if ((imm < 0) || ((imm & mask) != 0))
6631 if ((imm >= -256) && (imm <= 255))
6637 useRegForImm = true;
6642 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
6644 imm >>= scale; // The immediate is scaled by the size of the ld/st
6650 useRegForImm = true;
6656 // The reserved register is not stored in idReg3() since that field overlaps with iiaLclVar.
6657 // It is instead implicit when idSetIsLclVar() is set, with this encoding format.
6658 regNumber rsvdReg = codeGen->rsGetRsvdReg();
6659 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6663 assert(fmt != IF_NONE);
6665 instrDesc* id = emitNewInstrCns(attr, imm);
6669 id->idInsOpt(INS_OPTS_NONE);
6673 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6674 id->idSetIsLclVar();
6677 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6684 /*****************************************************************************
6686 * Add an instruction referencing consecutive stack-based local variable slots and two registers
6688 void emitter::emitIns_S_S_R_R(
6689 instruction ins, emitAttr attr1, emitAttr attr2, regNumber reg1, regNumber reg2, int varx, int offs)
6691 assert((ins == INS_stp) || (ins == INS_stnp));
6692 assert(EA_8BYTE == EA_SIZE(attr1));
6693 assert(EA_8BYTE == EA_SIZE(attr2));
6694 assert(isGeneralRegisterOrZR(reg1));
6695 assert(isGeneralRegisterOrZR(reg2));
6698 insFormat fmt = IF_LS_3B;
6700 const unsigned scale = 3;
6702 /* Figure out the variable's frame position */
6706 base = emitComp->lvaFrameAddress(varx, &FPbased);
6709 // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6710 regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE;
6711 reg3 = encodingSPtoZR(reg3);
6713 bool useRegForAdr = true;
6715 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6718 useRegForAdr = false;
6722 if ((imm & mask) == 0)
6724 ssize_t immShift = imm >> scale; // The immediate is scaled by the size of the ld/st
6726 if ((immShift >= -64) && (immShift <= 63))
6729 useRegForAdr = false;
6737 regNumber rsvd = codeGen->rsGetRsvdReg();
6738 emitIns_R_R_Imm(INS_add, EA_PTRSIZE, rsvd, reg3, imm);
6743 assert(fmt != IF_NONE);
6745 instrDesc* id = emitNewInstrCns(attr1, imm);
6749 id->idInsOpt(INS_OPTS_NONE);
6751 // Record the attribute for the second register in the pair
6752 if (EA_IS_GCREF(attr2))
6754 id->idGCrefReg2(GCT_GCREF);
6756 else if (EA_IS_BYREF(attr2))
6758 id->idGCrefReg2(GCT_BYREF);
6762 id->idGCrefReg2(GCT_NONE);
6768 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6769 id->idSetIsLclVar();
6772 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6779 /*****************************************************************************
6781 * Add an instruction referencing stack-based local variable and an immediate
6783 void emitter::emitIns_S_I(instruction ins, emitAttr attr, int varx, int offs, int val)
6788 /*****************************************************************************
6790 * Add an instruction with a register + static member operands.
6791 * Constant is stored into JIT data which is adjacent to code.
6792 * No relocation is needed. PC-relative offset will be encoded directly into instruction.
6795 void emitter::emitIns_R_C(
6796 instruction ins, emitAttr attr, regNumber reg, regNumber addrReg, CORINFO_FIELD_HANDLE fldHnd, int offs)
6799 assert(instrDesc::fitsInSmallCns(offs));
6801 emitAttr size = EA_SIZE(attr);
6802 insFormat fmt = IF_NONE;
6804 instrDescJmp* id = emitNewInstrJmp();
6809 // This is case to get address to the constant data.
6811 assert(isGeneralRegister(reg));
6812 assert(isValidGeneralDatasize(size));
6817 if (isVectorRegister(reg))
6819 assert(isValidScalarDatasize(size));
6820 // For vector (float/double) register, we should have an integer address reg to
6821 // compute long address which consists of page address and page offset.
6822 // For integer constant, this is not needed since the dest reg can be used to
6823 // compute address as well as contain the final contents.
6824 assert(isGeneralRegister(reg) || (addrReg != REG_NA));
6828 assert(isGeneralRegister(reg));
6829 assert(isValidGeneralDatasize(size));
6836 assert(fmt != IF_NONE);
6840 id->idInsOpt(INS_OPTS_NONE);
6841 id->idSmallCns(offs);
6843 id->idAddr()->iiaFieldHnd = fldHnd;
6844 id->idSetIsBound(); // We won't patch address since we will know the exact distance once JIT code and data are
6845 // allocated together.
6847 id->idReg1(reg); // destination register that will get the constant value.
6848 if (addrReg != REG_NA)
6850 id->idReg2(addrReg); // integer register to compute long address (used for vector dest when we end up with long
6853 id->idjShort = false; // Assume loading constant from long address
6855 // Keep it long if it's in cold code.
6856 id->idjKeepLong = emitComp->fgIsBlockCold(emitComp->compCurBB);
6859 if (emitComp->opts.compLongAddress)
6860 id->idjKeepLong = 1;
6863 // If it's possible to be shortened, then put it in jump list
6864 // to be revisited by emitJumpDistBind.
6865 if (!id->idjKeepLong)
6867 /* Record the jump's IG and offset within it */
6868 id->idjIG = emitCurIG;
6869 id->idjOffs = emitCurIGsize;
6871 /* Append this jump to this IG's jump list */
6872 id->idjNext = emitCurIGjmpList;
6873 emitCurIGjmpList = id;
6884 /*****************************************************************************
6886 * Add an instruction with a static member + constant.
6889 void emitter::emitIns_C_I(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, ssize_t offs, ssize_t val)
6894 /*****************************************************************************
6896 * Add an instruction with a static member + register operands.
6899 void emitter::emitIns_C_R(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, regNumber reg, int offs)
6901 assert(!"emitIns_C_R not supported for RyuJIT backend");
6904 void emitter::emitIns_R_AR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
6906 NYI("emitIns_R_AR");
6909 // This computes address from the immediate which is relocatable.
6910 void emitter::emitIns_R_AI(instruction ins, emitAttr attr, regNumber ireg, ssize_t addr)
6912 assert(EA_IS_RELOC(attr));
6913 emitAttr size = EA_SIZE(attr);
6914 insFormat fmt = IF_DI_1E;
6915 bool needAdd = false;
6916 instrDescJmp* id = emitNewInstrJmp();
6921 // This computes page address.
6922 // page offset is needed using add.
6933 id->idInsOpt(INS_OPTS_NONE);
6935 id->idAddr()->iiaAddr = (BYTE*)addr;
6937 id->idSetIsDspReloc();
6944 // add reg, reg, imm
6947 instrDesc* id = emitAllocInstr(attr);
6948 assert(id->idIsReloc());
6952 id->idInsOpt(INS_OPTS_NONE);
6954 id->idAddr()->iiaAddr = (BYTE*)addr;
6963 void emitter::emitIns_AR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
6965 NYI("emitIns_AR_R");
6968 void emitter::emitIns_R_ARR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
6970 NYI("emitIns_R_ARR");
6973 void emitter::emitIns_ARR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
6975 NYI("emitIns_R_ARR");
6978 void emitter::emitIns_R_ARX(
6979 instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, unsigned mul, int disp)
6981 NYI("emitIns_R_ARR");
6984 /*****************************************************************************
6986 * Record that a jump instruction uses the short encoding
6989 void emitter::emitSetShortJump(instrDescJmp* id)
6991 if (id->idjKeepLong)
6994 insFormat fmt = IF_NONE;
6995 if (emitIsCondJump(id))
6997 switch (id->idIns())
7012 else if (emitIsLoadLabel(id))
7016 else if (emitIsLoadConstant(id))
7026 id->idjShort = true;
7029 /*****************************************************************************
7031 * Add a label instruction.
7034 void emitter::emitIns_R_L(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
7036 assert(dst->bbFlags & BBF_JMP_TARGET);
7038 insFormat fmt = IF_NONE;
7049 instrDescJmp* id = emitNewInstrJmp();
7053 id->idjShort = false;
7054 id->idAddr()->iiaBBlabel = dst;
7056 id->idOpSize(EA_PTRSIZE);
7059 // Mark the catch return
7060 if (emitComp->compCurBB->bbJumpKind == BBJ_EHCATCHRET)
7062 id->idDebugOnlyInfo()->idCatchRet = true;
7066 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7069 if (emitComp->opts.compLongAddress)
7070 id->idjKeepLong = 1;
7073 /* Record the jump's IG and offset within it */
7075 id->idjIG = emitCurIG;
7076 id->idjOffs = emitCurIGsize;
7078 /* Append this jump to this IG's jump list */
7080 id->idjNext = emitCurIGjmpList;
7081 emitCurIGjmpList = id;
7091 /*****************************************************************************
7093 * Add a data label instruction.
7096 void emitter::emitIns_R_D(instruction ins, emitAttr attr, unsigned offs, regNumber reg)
7101 void emitter::emitIns_J_R(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
7103 assert((ins == INS_cbz) || (ins == INS_cbnz));
7105 assert(dst != nullptr);
7106 assert((dst->bbFlags & BBF_JMP_TARGET) != 0);
7108 insFormat fmt = IF_LARGEJMP;
7110 instrDescJmp* id = emitNewInstrJmp();
7115 id->idjShort = false;
7116 id->idOpSize(EA_SIZE(attr));
7118 id->idAddr()->iiaBBlabel = dst;
7119 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7121 /* Record the jump's IG and offset within it */
7123 id->idjIG = emitCurIG;
7124 id->idjOffs = emitCurIGsize;
7126 /* Append this jump to this IG's jump list */
7128 id->idjNext = emitCurIGjmpList;
7129 emitCurIGjmpList = id;
7139 void emitter::emitIns_J_R_I(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg, int imm)
7141 assert((ins == INS_tbz) || (ins == INS_tbnz));
7143 assert(dst != nullptr);
7144 assert((dst->bbFlags & BBF_JMP_TARGET) != 0);
7145 assert((EA_SIZE(attr) == EA_4BYTE) || (EA_SIZE(attr) == EA_8BYTE));
7146 assert(imm < ((EA_SIZE(attr) == EA_4BYTE) ? 32 : 64));
7148 insFormat fmt = IF_LARGEJMP;
7150 instrDescJmp* id = emitNewInstrJmp();
7155 id->idjShort = false;
7156 id->idSmallCns(imm);
7157 id->idOpSize(EA_SIZE(attr));
7159 id->idAddr()->iiaBBlabel = dst;
7160 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7162 /* Record the jump's IG and offset within it */
7164 id->idjIG = emitCurIG;
7165 id->idjOffs = emitCurIGsize;
7167 /* Append this jump to this IG's jump list */
7169 id->idjNext = emitCurIGjmpList;
7170 emitCurIGjmpList = id;
7180 void emitter::emitIns_J(instruction ins, BasicBlock* dst, int instrCount)
7182 insFormat fmt = IF_NONE;
7186 assert(dst->bbFlags & BBF_JMP_TARGET);
7190 assert(instrCount != 0);
7193 /* Figure out the encoding format of the instruction */
7195 bool idjShort = false;
7200 // Unconditional jump is a single form.
7219 // Assume conditional jump is long.
7228 instrDescJmp* id = emitNewInstrJmp();
7232 id->idjShort = idjShort;
7235 // Mark the finally call
7236 if (ins == INS_bl_local && emitComp->compCurBB->bbJumpKind == BBJ_CALLFINALLY)
7238 id->idDebugOnlyInfo()->idFinallyCall = true;
7244 id->idAddr()->iiaBBlabel = dst;
7246 // Skip unconditional jump that has a single form.
7247 // TODO-ARM64-NYI: enable hot/cold splittingNYI.
7248 // The target needs to be relocated.
7251 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7254 if (emitComp->opts.compLongAddress) // Force long branches
7255 id->idjKeepLong = 1;
7261 id->idAddr()->iiaSetInstrCount(instrCount);
7262 id->idjKeepLong = false;
7263 /* This jump must be short */
7264 emitSetShortJump(id);
7268 /* Record the jump's IG and offset within it */
7270 id->idjIG = emitCurIG;
7271 id->idjOffs = emitCurIGsize;
7273 /* Append this jump to this IG's jump list */
7275 id->idjNext = emitCurIGjmpList;
7276 emitCurIGjmpList = id;
7286 /*****************************************************************************
7288 * Add a call instruction (direct or indirect).
7289 * argSize<0 means that the caller will pop the arguments
7291 * The other arguments are interpreted depending on callType as shown:
7292 * Unless otherwise specified, ireg,xreg,xmul,disp should have default values.
7294 * EC_FUNC_TOKEN : addr is the method address
7295 * EC_FUNC_ADDR : addr is the absolute address of the function
7297 * If callType is one of these emitCallTypes, addr has to be NULL.
7298 * EC_INDIR_R : "call ireg".
7300 * For ARM xreg, xmul and disp are never used and should always be 0/REG_NA.
7302 * Please consult the "debugger team notification" comment in genFnProlog().
7305 void emitter::emitIns_Call(EmitCallType callType,
7306 CORINFO_METHOD_HANDLE methHnd,
7307 INDEBUG_LDISASM_COMMA(CORINFO_SIG_INFO* sigInfo) // used to report call sites to the EE
7311 emitAttr secondRetSize,
7312 VARSET_VALARG_TP ptrVars,
7313 regMaskTP gcrefRegs,
7314 regMaskTP byrefRegs,
7315 IL_OFFSETX ilOffset /* = BAD_IL_OFFSET */,
7316 regNumber ireg /* = REG_NA */,
7317 regNumber xreg /* = REG_NA */,
7318 unsigned xmul /* = 0 */,
7319 ssize_t disp /* = 0 */,
7320 bool isJump /* = false */,
7321 bool isNoGC /* = false */,
7322 bool isProfLeaveCB /* = false */)
7324 /* Sanity check the arguments depending on callType */
7326 assert(callType < EC_COUNT);
7327 assert((callType != EC_FUNC_TOKEN && callType != EC_FUNC_ADDR) ||
7328 (ireg == REG_NA && xreg == REG_NA && xmul == 0 && disp == 0));
7329 assert(callType < EC_INDIR_R || addr == NULL);
7330 assert(callType != EC_INDIR_R || (ireg < REG_COUNT && xreg == REG_NA && xmul == 0 && disp == 0));
7332 // ARM never uses these
7333 assert(xreg == REG_NA && xmul == 0 && disp == 0);
7335 // Our stack level should be always greater than the bytes of arguments we push. Just
7337 assert((unsigned)abs(argSize) <= codeGen->genStackLevel);
7342 /* This is the saved set of registers after a normal call */
7343 regMaskTP savedSet = RBM_CALLEE_SAVED;
7345 /* some special helper calls have a different saved set registers */
7349 assert(emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
7351 // Get the set of registers that this call kills and remove it from the saved set.
7352 savedSet = RBM_ALLINT & ~emitComp->compNoGCHelperCallKillSet(Compiler::eeGetHelperNum(methHnd));
7354 // In case of Leave profiler callback, we need to preserve liveness of REG_PROFILER_RET_SCRATCH
7357 savedSet |= RBM_PROFILER_RET_SCRATCH;
7361 if (emitComp->verbose)
7363 printf("NOGC Call: savedSet=");
7364 printRegMaskInt(savedSet);
7365 emitDispRegSet(savedSet);
7372 assert(!emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
7375 /* Trim out any callee-trashed registers from the live set */
7377 gcrefRegs &= savedSet;
7378 byrefRegs &= savedSet;
7381 if (EMIT_GC_VERBOSE)
7383 printf("Call: GCvars=%s ", VarSetOps::ToString(emitComp, ptrVars));
7384 dumpConvertedVarSet(emitComp, ptrVars);
7385 printf(", gcrefRegs=");
7386 printRegMaskInt(gcrefRegs);
7387 emitDispRegSet(gcrefRegs);
7388 printf(", byrefRegs=");
7389 printRegMaskInt(byrefRegs);
7390 emitDispRegSet(byrefRegs);
7395 assert(argSize % REGSIZE_BYTES == 0);
7396 argCnt = (int)(argSize / (int)REGSIZE_BYTES);
7398 /* Managed RetVal: emit sequence point for the call */
7399 if (emitComp->opts.compDbgInfo && ilOffset != BAD_IL_OFFSET)
7401 codeGen->genIPmappingAdd(ilOffset, false);
7405 We need to allocate the appropriate instruction descriptor based
7406 on whether this is a direct/indirect call, and whether we need to
7407 record an updated set of live GC variables.
7410 if (callType >= EC_INDIR_R)
7412 /* Indirect call, virtual calls */
7414 assert(callType == EC_INDIR_R);
7416 id = emitNewInstrCallInd(argCnt, disp, ptrVars, gcrefRegs, byrefRegs, retSize, secondRetSize);
7420 /* Helper/static/nonvirtual/function calls (direct or through handle),
7421 and calls to an absolute addr. */
7423 assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
7425 id = emitNewInstrCallDir(argCnt, ptrVars, gcrefRegs, byrefRegs, retSize, secondRetSize);
7428 /* Update the emitter's live GC ref sets */
7430 VarSetOps::Assign(emitComp, emitThisGCrefVars, ptrVars);
7431 emitThisGCrefRegs = gcrefRegs;
7432 emitThisByrefRegs = byrefRegs;
7434 /* Set the instruction - special case jumping a function */
7436 insFormat fmt = IF_NONE;
7438 id->idSetIsNoGC(isNoGC);
7440 /* Record the address: method, indirection, or funcptr */
7442 if (callType > EC_FUNC_ADDR)
7444 /* This is an indirect call (either a virtual call or func ptr call) */
7448 case EC_INDIR_R: // the address is in a register
7450 id->idSetIsCallRegPtr();
7454 ins = INS_br_tail; // INS_br_tail Reg
7458 ins = INS_blr; // INS_blr Reg
7466 assert(xreg == REG_NA);
7470 NO_WAY("unexpected instruction");
7476 /* This is a simple direct call: "call helper/method/addr" */
7478 assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
7480 assert(addr != NULL);
7484 ins = INS_b_tail; // INS_b_tail imm28
7488 ins = INS_bl; // INS_bl imm28
7495 id->idAddr()->iiaAddr = (BYTE*)addr;
7497 if (callType == EC_FUNC_ADDR)
7499 id->idSetIsCallAddr();
7502 if (emitComp->opts.compReloc)
7504 id->idSetIsDspReloc();
7509 if (EMIT_GC_VERBOSE)
7511 if (id->idIsLargeCall())
7513 printf("[%02u] Rec call GC vars = %s\n", id->idDebugOnlyInfo()->idNum,
7514 VarSetOps::ToString(emitComp, ((instrDescCGCA*)id)->idcGCvars));
7518 id->idDebugOnlyInfo()->idMemCookie = (size_t)methHnd; // method token
7519 id->idDebugOnlyInfo()->idCallSig = sigInfo;
7523 if (addr != nullptr)
7525 codeGen->getDisAssembler().disSetMethod((size_t)addr, methHnd);
7527 #endif // LATE_DISASM
7533 /*****************************************************************************
7535 * Returns true if 'imm' is valid Cond encoding
7538 /*static*/ bool emitter::isValidImmCond(ssize_t imm)
7540 // range check the ssize_t value, to make sure it is a small unsigned value
7541 // and that only the bits in the cfi.cond are set
7542 if ((imm < 0) || (imm > 0xF))
7546 cfi.immCFVal = (unsigned)imm;
7548 return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7551 /*****************************************************************************
7553 * Returns true if 'imm' is valid Cond/Flags encoding
7556 /*static*/ bool emitter::isValidImmCondFlags(ssize_t imm)
7558 // range check the ssize_t value, to make sure it is a small unsigned value
7559 // and that only the bits in the cfi.cond or cfi.flags are set
7560 if ((imm < 0) || (imm > 0xFF))
7564 cfi.immCFVal = (unsigned)imm;
7566 return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7569 /*****************************************************************************
7571 * Returns true if 'imm' is valid Cond/Flags/Imm5 encoding
7574 /*static*/ bool emitter::isValidImmCondFlagsImm5(ssize_t imm)
7576 // range check the ssize_t value, to make sure it is a small unsigned value
7577 // and that only the bits in the cfi.cond, cfi.flags or cfi.imm5 are set
7578 if ((imm < 0) || (imm > 0x1FFF))
7582 cfi.immCFVal = (unsigned)imm;
7584 return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7587 /*****************************************************************************
7589 * Returns an encoding for the specified register used in the 'Rd' position
7592 /*static*/ emitter::code_t emitter::insEncodeReg_Rd(regNumber reg)
7594 assert(isIntegerRegister(reg));
7595 emitter::code_t ureg = (emitter::code_t)reg;
7596 assert((ureg >= 0) && (ureg <= 31));
7600 /*****************************************************************************
7602 * Returns an encoding for the specified register used in the 'Rt' position
7605 /*static*/ emitter::code_t emitter::insEncodeReg_Rt(regNumber reg)
7607 assert(isIntegerRegister(reg));
7608 emitter::code_t ureg = (emitter::code_t)reg;
7609 assert((ureg >= 0) && (ureg <= 31));
7613 /*****************************************************************************
7615 * Returns an encoding for the specified register used in the 'Rn' position
7618 /*static*/ emitter::code_t emitter::insEncodeReg_Rn(regNumber reg)
7620 assert(isIntegerRegister(reg));
7621 emitter::code_t ureg = (emitter::code_t)reg;
7622 assert((ureg >= 0) && (ureg <= 31));
7626 /*****************************************************************************
7628 * Returns an encoding for the specified register used in the 'Rm' position
7631 /*static*/ emitter::code_t emitter::insEncodeReg_Rm(regNumber reg)
7633 assert(isIntegerRegister(reg));
7634 emitter::code_t ureg = (emitter::code_t)reg;
7635 assert((ureg >= 0) && (ureg <= 31));
7639 /*****************************************************************************
7641 * Returns an encoding for the specified register used in the 'Ra' position
7644 /*static*/ emitter::code_t emitter::insEncodeReg_Ra(regNumber reg)
7646 assert(isIntegerRegister(reg));
7647 emitter::code_t ureg = (emitter::code_t)reg;
7648 assert((ureg >= 0) && (ureg <= 31));
7652 /*****************************************************************************
7654 * Returns an encoding for the specified register used in the 'Vd' position
7657 /*static*/ emitter::code_t emitter::insEncodeReg_Vd(regNumber reg)
7659 assert(emitter::isVectorRegister(reg));
7660 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7661 assert((ureg >= 0) && (ureg <= 31));
7665 /*****************************************************************************
7667 * Returns an encoding for the specified register used in the 'Vt' position
7670 /*static*/ emitter::code_t emitter::insEncodeReg_Vt(regNumber reg)
7672 assert(emitter::isVectorRegister(reg));
7673 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7674 assert((ureg >= 0) && (ureg <= 31));
7678 /*****************************************************************************
7680 * Returns an encoding for the specified register used in the 'Vn' position
7683 /*static*/ emitter::code_t emitter::insEncodeReg_Vn(regNumber reg)
7685 assert(emitter::isVectorRegister(reg));
7686 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7687 assert((ureg >= 0) && (ureg <= 31));
7691 /*****************************************************************************
7693 * Returns an encoding for the specified register used in the 'Vm' position
7696 /*static*/ emitter::code_t emitter::insEncodeReg_Vm(regNumber reg)
7698 assert(emitter::isVectorRegister(reg));
7699 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7700 assert((ureg >= 0) && (ureg <= 31));
7704 /*****************************************************************************
7706 * Returns an encoding for the specified register used in the 'Va' position
7709 /*static*/ emitter::code_t emitter::insEncodeReg_Va(regNumber reg)
7711 assert(emitter::isVectorRegister(reg));
7712 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7713 assert((ureg >= 0) && (ureg <= 31));
7717 /*****************************************************************************
7719 * Returns an encoding for the specified condition code.
7722 /*static*/ emitter::code_t emitter::insEncodeCond(insCond cond)
7724 emitter::code_t uimm = (emitter::code_t)cond;
7728 /*****************************************************************************
7730 * Returns an encoding for the condition code with the lowest bit inverted (marked by invert(<cond>) in the
7731 * architecture manual).
7734 /*static*/ emitter::code_t emitter::insEncodeInvertedCond(insCond cond)
7736 emitter::code_t uimm = (emitter::code_t)cond;
7737 uimm ^= 1; // invert the lowest bit
7741 /*****************************************************************************
7743 * Returns an encoding for the specified flags.
7746 /*static*/ emitter::code_t emitter::insEncodeFlags(insCflags flags)
7748 emitter::code_t uimm = (emitter::code_t)flags;
7752 /*****************************************************************************
7754 * Returns the encoding for the Shift Count bits to be used for Arm64 encodings
7757 /*static*/ emitter::code_t emitter::insEncodeShiftCount(ssize_t imm, emitAttr size)
7759 assert((imm & 0x003F) == imm);
7760 assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
7762 return (emitter::code_t)imm << 10;
7765 /*****************************************************************************
7767 * Returns the encoding to select a 64-bit datasize for an Arm64 instruction
7770 /*static*/ emitter::code_t emitter::insEncodeDatasize(emitAttr size)
7772 if (size == EA_8BYTE)
7774 return 0x80000000; // set the bit at location 31
7778 assert(size == EA_4BYTE);
7783 /*****************************************************************************
7785 * Returns the encoding to select the datasize for the general load/store Arm64 instructions
7789 /*static*/ emitter::code_t emitter::insEncodeDatasizeLS(emitter::code_t code, emitAttr size)
7791 bool exclusive = ((code & 0x35000000) == 0);
7793 if ((code & 0x00800000) && !exclusive) // Is this a sign-extending opcode? (i.e. ldrsw, ldrsh, ldrsb)
7795 if ((code & 0x80000000) == 0) // Is it a ldrsh or ldrsb and not ldrsw ?
7797 if (EA_SIZE(size) != EA_8BYTE) // Do we need to encode the 32-bit Rt size bit?
7799 return 0x00400000; // set the bit at location 22
7803 else if (code & 0x80000000) // Is this a ldr/str/ldur/stur opcode?
7805 if (EA_SIZE(size) == EA_8BYTE) // Do we need to encode the 64-bit size bit?
7807 return 0x40000000; // set the bit at location 30
7813 /*****************************************************************************
7815 * Returns the encoding to select the datasize for the vector load/store Arm64 instructions
7819 /*static*/ emitter::code_t emitter::insEncodeDatasizeVLS(emitter::code_t code, emitAttr size)
7824 if ((code & 0x20000000) == 0)
7828 if (size == EA_16BYTE)
7830 // set the operation size in bit 31
7831 result = 0x80000000;
7833 else if (size == EA_8BYTE)
7835 // set the operation size in bit 30
7836 result = 0x40000000;
7840 assert(size == EA_4BYTE);
7842 result = 0x00000000;
7849 if (size == EA_16BYTE)
7851 // The operation size in bits 31 and 30 are zero
7852 // Bit 23 specifies a 128-bit Load/Store
7853 result = 0x00800000;
7855 else if (size == EA_8BYTE)
7857 // set the operation size in bits 31 and 30
7858 result = 0xC0000000;
7860 else if (size == EA_4BYTE)
7862 // set the operation size in bit 31
7863 result = 0x80000000;
7865 else if (size == EA_2BYTE)
7867 // set the operation size in bit 30
7868 result = 0x40000000;
7872 assert(size == EA_1BYTE);
7873 // The operation size in bits 31 and 30 are zero
7874 result = 0x00000000;
7878 // Or in bit 26 to indicate a Vector register is used as 'target'
7879 result |= 0x04000000;
7884 /*****************************************************************************
7886 * Returns the encoding to select the datasize for the vector load/store Arm64 instructions
7890 /*static*/ emitter::code_t emitter::insEncodeDatasizeVPLS(emitter::code_t code, emitAttr size)
7894 if (size == EA_16BYTE)
7896 // The operation size in bits 31 and 30 are zero
7897 // Bit 23 specifies a 128-bit Load/Store
7898 result = 0x80000000;
7900 else if (size == EA_8BYTE)
7902 // set the operation size in bits 31 and 30
7903 result = 0x40000000;
7905 else if (size == EA_4BYTE)
7907 // set the operation size in bit 31
7908 result = 0x00000000;
7911 // Or in bit 26 to indicate a Vector register is used as 'target'
7912 result |= 0x04000000;
7917 /*****************************************************************************
7919 * Returns the encoding to set the size bit and the N bits for a 'bitfield' instruction
7923 /*static*/ emitter::code_t emitter::insEncodeDatasizeBF(emitter::code_t code, emitAttr size)
7925 // is bit 30 equal to 0?
7926 if ((code & 0x40000000) == 0) // is the opcode one of extr, sxtb, sxth or sxtw
7928 if (size == EA_8BYTE) // Do we need to set the sf and N bits?
7930 return 0x80400000; // set the sf-bit at location 31 and the N-bit at location 22
7933 return 0; // don't set any bits
7936 /*****************************************************************************
7938 * Returns the encoding to select the 64/128-bit datasize for an Arm64 vector instruction
7941 /*static*/ emitter::code_t emitter::insEncodeVectorsize(emitAttr size)
7943 if (size == EA_16BYTE)
7945 return 0x40000000; // set the bit at location 30
7949 assert(size == EA_8BYTE);
7954 /*****************************************************************************
7956 * Returns the encoding to select 'index' for an Arm64 vector elem instruction
7958 /*static*/ emitter::code_t emitter::insEncodeVectorIndex(emitAttr elemsize, ssize_t index)
7960 code_t bits = (code_t)index;
7961 if (elemsize == EA_1BYTE)
7966 else if (elemsize == EA_2BYTE)
7971 else if (elemsize == EA_4BYTE)
7978 assert(elemsize == EA_8BYTE);
7982 assert((bits >= 1) && (bits <= 0x1f));
7984 return (bits << 16); // bits at locations [20,19,18,17,16]
7987 /*****************************************************************************
7989 * Returns the encoding to select 'index2' for an Arm64 'ins' elem instruction
7991 /*static*/ emitter::code_t emitter::insEncodeVectorIndex2(emitAttr elemsize, ssize_t index2)
7993 code_t bits = (code_t)index2;
7994 if (elemsize == EA_1BYTE)
7998 else if (elemsize == EA_2BYTE)
8002 else if (elemsize == EA_4BYTE)
8008 assert(elemsize == EA_8BYTE);
8011 assert((bits >= 0) && (bits <= 0xf));
8013 return (bits << 11); // bits at locations [14,13,12,11]
8016 /*****************************************************************************
8018 * Returns the encoding to select the 'index' for an Arm64 'mul' by elem instruction
8020 /*static*/ emitter::code_t emitter::insEncodeVectorIndexLMH(emitAttr elemsize, ssize_t index)
8024 if (elemsize == EA_2BYTE)
8026 assert((index >= 0) && (index <= 7));
8029 bits |= (1 << 11); // set bit 11 'H'
8033 bits |= (1 << 21); // set bit 21 'L'
8037 bits |= (1 << 20); // set bit 20 'M'
8040 else if (elemsize == EA_4BYTE)
8042 assert((index >= 0) && (index <= 3));
8045 bits |= (1 << 11); // set bit 11 'H'
8049 bits |= (1 << 21); // set bit 21 'L'
8054 assert(!"Invalid 'elemsize' value");
8060 /*****************************************************************************
8062 * Returns the encoding to shift by 'shift' for an Arm64 vector or scalar instruction
8065 /*static*/ emitter::code_t emitter::insEncodeVectorShift(emitAttr size, ssize_t shift)
8067 assert(shift < getBitWidth(size));
8069 code_t imm = (code_t)(getBitWidth(size) + shift);
8074 /*****************************************************************************
8076 * Returns the encoding to select the 1/2/4/8 byte elemsize for an Arm64 vector instruction
8079 /*static*/ emitter::code_t emitter::insEncodeElemsize(emitAttr size)
8081 if (size == EA_8BYTE)
8083 return 0x00C00000; // set the bit at location 23 and 22
8085 else if (size == EA_4BYTE)
8087 return 0x00800000; // set the bit at location 23
8089 else if (size == EA_2BYTE)
8091 return 0x00400000; // set the bit at location 22
8093 assert(size == EA_1BYTE);
8097 /*****************************************************************************
8099 * Returns the encoding to select the 4/8 byte elemsize for an Arm64 float vector instruction
8102 /*static*/ emitter::code_t emitter::insEncodeFloatElemsize(emitAttr size)
8104 if (size == EA_8BYTE)
8106 return 0x00400000; // set the bit at location 22
8108 assert(size == EA_4BYTE);
8112 // Returns the encoding to select the index for an Arm64 float vector by elem instruction
8113 /*static*/ emitter::code_t emitter::insEncodeFloatIndex(emitAttr elemsize, ssize_t index)
8115 code_t result = 0x00000000;
8116 if (elemsize == EA_8BYTE)
8118 assert((index >= 0) && (index <= 1));
8121 result |= 0x00000800; // 'H' - set the bit at location 11
8126 assert(elemsize == EA_4BYTE);
8127 assert((index >= 0) && (index <= 3));
8130 result |= 0x00000800; // 'H' - set the bit at location 11
8134 result |= 0x00200000; // 'L' - set the bit at location 21
8140 /*****************************************************************************
8142 * Returns the encoding to select the fcvt operation for Arm64 instructions
8144 /*static*/ emitter::code_t emitter::insEncodeConvertOpt(insFormat fmt, insOpts conversion)
8149 case INS_OPTS_S_TO_D: // Single to Double
8150 assert(fmt == IF_DV_2J);
8151 result = 0x00008000; // type=00, opc=01
8154 case INS_OPTS_D_TO_S: // Double to Single
8155 assert(fmt == IF_DV_2J);
8156 result = 0x00400000; // type=01, opc=00
8159 case INS_OPTS_H_TO_S: // Half to Single
8160 assert(fmt == IF_DV_2J);
8161 result = 0x00C00000; // type=11, opc=00
8164 case INS_OPTS_H_TO_D: // Half to Double
8165 assert(fmt == IF_DV_2J);
8166 result = 0x00C08000; // type=11, opc=01
8169 case INS_OPTS_S_TO_H: // Single to Half
8170 assert(fmt == IF_DV_2J);
8171 result = 0x00018000; // type=00, opc=11
8174 case INS_OPTS_D_TO_H: // Double to Half
8175 assert(fmt == IF_DV_2J);
8176 result = 0x00418000; // type=01, opc=11
8179 case INS_OPTS_S_TO_4BYTE: // Single to INT32
8180 assert(fmt == IF_DV_2H);
8181 result = 0x00000000; // sf=0, type=00
8184 case INS_OPTS_D_TO_4BYTE: // Double to INT32
8185 assert(fmt == IF_DV_2H);
8186 result = 0x00400000; // sf=0, type=01
8189 case INS_OPTS_S_TO_8BYTE: // Single to INT64
8190 assert(fmt == IF_DV_2H);
8191 result = 0x80000000; // sf=1, type=00
8194 case INS_OPTS_D_TO_8BYTE: // Double to INT64
8195 assert(fmt == IF_DV_2H);
8196 result = 0x80400000; // sf=1, type=01
8199 case INS_OPTS_4BYTE_TO_S: // INT32 to Single
8200 assert(fmt == IF_DV_2I);
8201 result = 0x00000000; // sf=0, type=00
8204 case INS_OPTS_4BYTE_TO_D: // INT32 to Double
8205 assert(fmt == IF_DV_2I);
8206 result = 0x00400000; // sf=0, type=01
8209 case INS_OPTS_8BYTE_TO_S: // INT64 to Single
8210 assert(fmt == IF_DV_2I);
8211 result = 0x80000000; // sf=1, type=00
8214 case INS_OPTS_8BYTE_TO_D: // INT64 to Double
8215 assert(fmt == IF_DV_2I);
8216 result = 0x80400000; // sf=1, type=01
8220 assert(!"Invalid 'conversion' value");
8226 /*****************************************************************************
8228 * Returns the encoding to have the Rn register be updated Pre/Post indexed
8232 /*static*/ emitter::code_t emitter::insEncodeIndexedOpt(insOpts opt)
8234 assert(emitter::insOptsNone(opt) || emitter::insOptsIndexed(opt));
8236 if (emitter::insOptsIndexed(opt))
8238 if (emitter::insOptsPostIndex(opt))
8240 return 0x00000400; // set the bit at location 10
8244 assert(emitter::insOptsPreIndex(opt));
8245 return 0x00000C00; // set the bit at location 10 and 11
8250 assert(emitter::insOptsNone(opt));
8251 return 0; // bits 10 and 11 are zero
8255 /*****************************************************************************
8257 * Returns the encoding for a ldp/stp instruction to have the Rn register
8258 * be updated Pre/Post indexed or not updated
8261 /*static*/ emitter::code_t emitter::insEncodePairIndexedOpt(instruction ins, insOpts opt)
8263 assert(emitter::insOptsNone(opt) || emitter::insOptsIndexed(opt));
8265 if ((ins == INS_ldnp) || (ins == INS_stnp))
8267 assert(emitter::insOptsNone(opt));
8268 return 0; // bits 23 and 24 are zero
8272 if (emitter::insOptsIndexed(opt))
8274 if (emitter::insOptsPostIndex(opt))
8276 return 0x00800000; // set the bit at location 23
8280 assert(emitter::insOptsPreIndex(opt));
8281 return 0x01800000; // set the bit at location 24 and 23
8286 assert(emitter::insOptsNone(opt));
8287 return 0x01000000; // set the bit at location 24
8292 /*****************************************************************************
8294 * Returns the encoding to apply a Shift Type on the Rm register
8297 /*static*/ emitter::code_t emitter::insEncodeShiftType(insOpts opt)
8299 if (emitter::insOptsNone(opt))
8301 // None implies the we encode LSL (with a zero immediate)
8304 assert(emitter::insOptsAnyShift(opt));
8306 emitter::code_t option = (emitter::code_t)opt - (emitter::code_t)INS_OPTS_LSL;
8307 assert(option <= 3);
8309 return option << 22; // bits 23, 22
8312 /*****************************************************************************
8314 * Returns the encoding to apply a 12 bit left shift to the immediate
8317 /*static*/ emitter::code_t emitter::insEncodeShiftImm12(insOpts opt)
8319 if (emitter::insOptsLSL12(opt))
8321 return 0x00400000; // set the bit at location 22
8326 /*****************************************************************************
8328 * Returns the encoding to have the Rm register use an extend operation
8331 /*static*/ emitter::code_t emitter::insEncodeExtend(insOpts opt)
8333 if (emitter::insOptsNone(opt) || (opt == INS_OPTS_LSL))
8335 // None or LSL implies the we encode UXTX
8336 opt = INS_OPTS_UXTX;
8338 assert(emitter::insOptsAnyExtend(opt));
8340 emitter::code_t option = (emitter::code_t)opt - (emitter::code_t)INS_OPTS_UXTB;
8341 assert(option <= 7);
8343 return option << 13; // bits 15,14,13
8346 /*****************************************************************************
8348 * Returns the encoding to scale the Rm register by {0,1,2,3,4}
8349 * when using an extend operation
8352 /*static*/ emitter::code_t emitter::insEncodeExtendScale(ssize_t imm)
8354 assert((imm >= 0) && (imm <= 4));
8356 return (emitter::code_t)imm << 10; // bits 12,11,10
8359 /*****************************************************************************
8361 * Returns the encoding to have the Rm register be auto scaled by the ld/st size
8364 /*static*/ emitter::code_t emitter::insEncodeReg3Scale(bool isScaled)
8368 return 0x00001000; // set the bit at location 12
8376 BYTE* emitter::emitOutputLoadLabel(BYTE* dst, BYTE* srcAddr, BYTE* dstAddr, instrDescJmp* id)
8378 instruction ins = id->idIns();
8379 insFormat fmt = id->idInsFmt();
8380 regNumber dstReg = id->idReg1();
8383 // adr x, [rel addr] -- compute address: current addr(ip) + rel addr.
8384 assert(ins == INS_adr);
8385 assert(fmt == IF_DI_1E);
8386 ssize_t distVal = (ssize_t)(dstAddr - srcAddr);
8387 dst = emitOutputShortAddress(dst, ins, fmt, distVal, dstReg);
8391 // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8392 assert(fmt == IF_LARGEADR);
8393 ssize_t relPageAddr =
8394 (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8395 dst = emitOutputShortAddress(dst, INS_adrp, IF_DI_1E, relPageAddr, dstReg);
8397 // add x, x, page offs -- compute address = page addr + page offs
8398 ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8399 assert(isValidUimm12(imm12));
8401 emitInsCode(INS_add, IF_DI_2A); // DI_2A X0010001shiiiiii iiiiiinnnnnddddd 1100 0000 imm(i12, sh)
8402 code |= insEncodeDatasize(EA_8BYTE); // X
8403 code |= ((code_t)imm12 << 10); // iiiiiiiiiiii
8404 code |= insEncodeReg_Rd(dstReg); // ddddd
8405 code |= insEncodeReg_Rn(dstReg); // nnnnn
8406 dst += emitOutput_Instr(dst, code);
8411 /*****************************************************************************
8413 * Output a local jump or other instruction with a pc-relative immediate.
8414 * Note that this may be invoked to overwrite an existing jump instruction at 'dst'
8415 * to handle forward branch patching.
8418 BYTE* emitter::emitOutputLJ(insGroup* ig, BYTE* dst, instrDesc* i)
8420 instrDescJmp* id = (instrDescJmp*)i;
8429 // Set default ins/fmt from id.
8430 instruction ins = id->idIns();
8431 insFormat fmt = id->idInsFmt();
8433 bool loadLabel = false;
8434 bool isJump = false;
8435 bool loadConstant = false;
8452 loadConstant = true;
8461 /* Figure out the distance to the target */
8463 srcOffs = emitCurCodeOffs(dst);
8464 srcAddr = emitOffsetToPtr(srcOffs);
8466 if (id->idAddr()->iiaIsJitDataOffset())
8468 assert(loadConstant || loadLabel);
8469 int doff = id->idAddr()->iiaGetJitDataOffset();
8471 ssize_t imm = emitGetInsSC(id);
8472 assert((imm >= 0) && (imm < 0x1000)); // 0x1000 is arbitrary, currently 'imm' is always 0
8474 unsigned dataOffs = (unsigned)(doff + imm);
8475 assert(dataOffs < emitDataSize());
8476 dstAddr = emitDataOffsetToPtr(dataOffs);
8478 regNumber dstReg = id->idReg1();
8479 regNumber addrReg = dstReg; // an integer register to compute long address.
8480 emitAttr opSize = id->idOpSize();
8486 // ldr x/v, [rel addr] -- load constant from current addr(ip) + rel addr.
8487 assert(ins == INS_ldr);
8488 assert(fmt == IF_LS_1A);
8489 distVal = (ssize_t)(dstAddr - srcAddr);
8490 dst = emitOutputShortConstant(dst, ins, fmt, distVal, dstReg, opSize);
8494 // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8495 assert(fmt == IF_LARGELDC);
8496 ssize_t relPageAddr =
8497 (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8498 if (isVectorRegister(dstReg))
8500 // Update addrReg with the reserved integer register
8501 // since we cannot use dstReg (vector) to load constant directly from memory.
8502 addrReg = id->idReg2();
8503 assert(isGeneralRegister(addrReg));
8507 dst = emitOutputShortAddress(dst, ins, fmt, relPageAddr, addrReg);
8509 // ldr x, [x, page offs] -- load constant from page address + page offset into integer register.
8510 ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8511 assert(isValidUimm12(imm12));
8514 dst = emitOutputShortConstant(dst, ins, fmt, imm12, addrReg, opSize);
8516 // fmov v, d -- copy constant in integer register to vector register.
8517 // This is needed only for vector constant.
8518 if (addrReg != dstReg)
8520 // fmov Vd,Rn DV_2I X00111100X100111 000000nnnnnddddd 1E27 0000 Vd,Rn
8521 // (scalar, from general)
8522 assert(isVectorRegister(dstReg) && isGeneralRegister(addrReg));
8525 code_t code = emitInsCode(ins, fmt);
8527 code |= insEncodeReg_Vd(dstReg); // ddddd
8528 code |= insEncodeReg_Rn(addrReg); // nnnnn
8529 if (id->idOpSize() == EA_8BYTE)
8531 code |= 0x80400000; // X ... X
8533 dst += emitOutput_Instr(dst, code);
8540 dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8546 assert(loadLabel || isJump);
8548 if (id->idAddr()->iiaHasInstrCount())
8551 int instrCount = id->idAddr()->iiaGetInstrCount();
8552 unsigned insNum = emitFindInsNum(ig, id);
8555 // Backward branches using instruction count must be within the same instruction group.
8556 assert(insNum + 1 >= (unsigned)(-instrCount));
8558 dstOffs = ig->igOffs + emitFindOffset(ig, (insNum + 1 + instrCount));
8559 dstAddr = emitOffsetToPtr(dstOffs);
8563 dstOffs = id->idAddr()->iiaIGlabel->igOffs;
8564 dstAddr = emitOffsetToPtr(dstOffs);
8567 distVal = (ssize_t)(dstAddr - srcAddr);
8569 if (dstOffs <= srcOffs)
8572 /* This is a backward jump - distance is known at this point */
8574 if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8576 size_t blkOffs = id->idjIG->igOffs;
8578 if (INTERESTING_JUMP_NUM == 0)
8579 printf("[3] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8580 printf("[3] Jump block is at %08X - %02X = %08X\n", blkOffs, emitOffsAdj, blkOffs - emitOffsAdj);
8581 printf("[3] Jump is at %08X - %02X = %08X\n", srcOffs, emitOffsAdj, srcOffs - emitOffsAdj);
8582 printf("[3] Label block is at %08X - %02X = %08X\n", dstOffs, emitOffsAdj, dstOffs - emitOffsAdj);
8588 /* This is a forward jump - distance will be an upper limit */
8590 emitFwdJumps = true;
8592 /* The target offset will be closer by at least 'emitOffsAdj', but only if this
8593 jump doesn't cross the hot-cold boundary. */
8595 if (!emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8597 dstOffs -= emitOffsAdj;
8598 distVal -= emitOffsAdj;
8601 /* Record the location of the jump for later patching */
8603 id->idjOffs = dstOffs;
8605 /* Are we overflowing the id->idjOffs bitfield? */
8606 if (id->idjOffs != dstOffs)
8607 IMPL_LIMITATION("Method is too large");
8610 if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8612 size_t blkOffs = id->idjIG->igOffs;
8614 if (INTERESTING_JUMP_NUM == 0)
8615 printf("[4] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8616 printf("[4] Jump block is at %08X\n", blkOffs);
8617 printf("[4] Jump is at %08X\n", srcOffs);
8618 printf("[4] Label block is at %08X - %02X = %08X\n", dstOffs + emitOffsAdj, emitOffsAdj, dstOffs);
8624 if (0 && emitComp->verbose)
8627 int distValSize = id->idjShort ? 4 : 8;
8628 printf("; %s jump [%08X/%03u] from %0*X to %0*X: dist = %08XH\n", (dstOffs <= srcOffs) ? "Fwd" : "Bwd",
8629 dspPtr(id), id->idDebugOnlyInfo()->idNum, distValSize, srcOffs + sz, distValSize, dstOffs, distVal);
8633 /* For forward jumps, record the address of the distance value */
8634 id->idjTemp.idjAddr = (distVal > 0) ? dst : NULL;
8636 if (emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8638 assert(!id->idjShort);
8639 NYI_ARM64("Relocation Support for long address");
8642 assert(insOptsNone(id->idInsOpt()));
8648 // Short conditional/unconditional jump
8649 assert(!id->idjKeepLong);
8650 assert(emitJumpCrossHotColdBoundary(srcOffs, dstOffs) == false);
8651 assert((fmt == IF_BI_0A) || (fmt == IF_BI_0B) || (fmt == IF_BI_1A) || (fmt == IF_BI_1B));
8655 // Long conditional jump
8656 assert(fmt == IF_LARGEJMP);
8657 // This is a pseudo-instruction format representing a large conditional branch, to allow
8658 // us to get a greater branch target range than we can get by using a straightforward conditional
8659 // branch. It is encoded as a short conditional branch that branches around a long unconditional
8662 // Conceptually, we have:
8666 // The code we emit is:
8668 // b<!cond> L_not // 4 bytes. Note that we reverse the condition.
8669 // b L_target // 4 bytes
8672 // Note that we don't actually insert any blocks: we simply encode "b <!cond> L_not" as a branch with
8673 // the correct offset. Note also that this works for both integer and floating-point conditions, because
8674 // the condition inversion takes ordered/unordered into account, preserving NaN behavior. For example,
8675 // "GT" (greater than) is inverted to "LE" (less than, equal, or unordered).
8677 instruction reverseIns;
8678 insFormat reverseFmt;
8683 reverseIns = INS_cbnz;
8684 reverseFmt = IF_BI_1A;
8687 reverseIns = INS_cbz;
8688 reverseFmt = IF_BI_1A;
8691 reverseIns = INS_tbnz;
8692 reverseFmt = IF_BI_1B;
8695 reverseIns = INS_tbz;
8696 reverseFmt = IF_BI_1B;
8699 reverseIns = emitJumpKindToIns(emitReverseJumpKind(emitInsToJumpKind(ins)));
8700 reverseFmt = IF_BI_0B;
8704 emitOutputShortBranch(dst,
8705 reverseIns, // reverse the conditional instruction
8707 8, /* 8 bytes from start of this large conditional pseudo-instruction to L_not. */
8710 // Now, pretend we've got a normal unconditional branch, and fall through to the code to emit that.
8714 // The distVal was computed based on the beginning of the pseudo-instruction,
8715 // So subtract the size of the conditional branch so that it is relative to the
8716 // unconditional branch.
8720 dst = emitOutputShortBranch(dst, ins, fmt, distVal, id);
8724 dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8730 /*****************************************************************************
8732 * Output a short branch instruction.
8734 BYTE* emitter::emitOutputShortBranch(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, instrDescJmp* id)
8736 code_t code = emitInsCode(ins, fmt);
8738 ssize_t loBits = (distVal & 3);
8739 noway_assert(loBits == 0);
8740 distVal >>= 2; // branch offset encodings are scaled by 4.
8742 if (fmt == IF_BI_0A)
8744 // INS_b or INS_bl_local
8745 noway_assert(isValidSimm26(distVal));
8746 distVal &= 0x3FFFFFFLL;
8749 else if (fmt == IF_BI_0B) // BI_0B 01010100iiiiiiii iiiiiiiiiiiXXXXX simm19:00
8751 // INS_beq, INS_bne, etc...
8752 noway_assert(isValidSimm19(distVal));
8753 distVal &= 0x7FFFFLL;
8754 code |= distVal << 5;
8756 else if (fmt == IF_BI_1A) // BI_1A X.......iiiiiiii iiiiiiiiiiittttt Rt simm19:00
8758 // INS_cbz or INS_cbnz
8759 assert(id != nullptr);
8760 code |= insEncodeDatasize(id->idOpSize()); // X
8761 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
8763 noway_assert(isValidSimm19(distVal));
8764 distVal &= 0x7FFFFLL; // 19 bits
8765 code |= distVal << 5;
8767 else if (fmt == IF_BI_1B) // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
8769 // INS_tbz or INS_tbnz
8770 assert(id != nullptr);
8771 ssize_t imm = emitGetInsSC(id);
8772 assert(isValidImmShift(imm, id->idOpSize()));
8774 if (imm & 0x20) // test bit 32-63 ?
8776 code |= 0x80000000; // B
8778 code |= ((imm & 0x1F) << 19); // bbbbb
8779 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
8781 noway_assert(isValidSimm14(distVal));
8782 distVal &= 0x3FFFLL; // 14 bits
8783 code |= distVal << 5;
8787 assert(!"Unknown fmt for emitOutputShortBranch");
8790 dst += emitOutput_Instr(dst, code);
8795 /*****************************************************************************
8797 * Output a short address instruction.
8799 BYTE* emitter::emitOutputShortAddress(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, regNumber reg)
8801 ssize_t loBits = (distVal & 3);
8804 code_t code = emitInsCode(ins, fmt);
8805 if (fmt == IF_DI_1E) // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
8807 // INS_adr or INS_adrp
8808 code |= insEncodeReg_Rd(reg); // ddddd
8810 noway_assert(isValidSimm19(distVal));
8811 distVal &= 0x7FFFFLL; // 19 bits
8812 code |= distVal << 5;
8813 code |= loBits << 29; // 2 bits
8817 assert(!"Unknown fmt for emitOutputShortAddress");
8820 dst += emitOutput_Instr(dst, code);
8825 /*****************************************************************************
8827 * Output a short constant instruction.
8829 BYTE* emitter::emitOutputShortConstant(
8830 BYTE* dst, instruction ins, insFormat fmt, ssize_t imm, regNumber reg, emitAttr opSize)
8832 code_t code = emitInsCode(ins, fmt);
8834 if (fmt == IF_LS_1A)
8836 // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt simm21
8837 // INS_ldr or INS_ldrsw (PC-Relative)
8839 ssize_t loBits = (imm & 3);
8840 noway_assert(loBits == 0);
8841 ssize_t distVal = imm >>= 2; // load offset encodings are scaled by 4.
8843 noway_assert(isValidSimm19(distVal));
8845 // Is the target a vector register?
8846 if (isVectorRegister(reg))
8848 code |= insEncodeDatasizeVLS(code, opSize); // XX V
8849 code |= insEncodeReg_Vt(reg); // ttttt
8853 assert(isGeneralRegister(reg));
8854 // insEncodeDatasizeLS is not quite right for this case.
8855 // So just specialize it.
8856 if ((ins == INS_ldr) && (opSize == EA_8BYTE))
8858 // set the operation size in bit 30
8862 code |= insEncodeReg_Rt(reg); // ttttt
8865 distVal &= 0x7FFFFLL; // 19 bits
8866 code |= distVal << 5;
8868 else if (fmt == IF_LS_2B)
8870 // ldr Rt,[Xn+pimm12] LS_2B 1X11100101iiiiii iiiiiinnnnnttttt B940 0000 imm(0-4095<<{2,3})
8871 // INS_ldr or INS_ldrsw (PC-Relative)
8872 noway_assert(isValidUimm12(imm));
8873 assert(isGeneralRegister(reg));
8875 if (opSize == EA_8BYTE)
8877 // insEncodeDatasizeLS is not quite right for this case.
8878 // So just specialize it.
8881 // set the operation size in bit 30
8884 // Low 3 bits should be 0 -- 8 byte JIT data should be aligned on 8 byte.
8885 assert((imm & 7) == 0);
8890 assert(opSize == EA_4BYTE);
8891 // Low 2 bits should be 0 -- 4 byte aligned data.
8892 assert((imm & 3) == 0);
8896 code |= insEncodeReg_Rt(reg); // ttttt
8897 code |= insEncodeReg_Rn(reg); // nnnnn
8902 assert(!"Unknown fmt for emitOutputShortConstant");
8905 dst += emitOutput_Instr(dst, code);
8909 /*****************************************************************************
8911 * Output a call instruction.
8914 unsigned emitter::emitOutputCall(insGroup* ig, BYTE* dst, instrDesc* id, code_t code)
8916 const unsigned char callInstrSize = sizeof(code_t); // 4 bytes
8917 regMaskTP gcrefRegs;
8918 regMaskTP byrefRegs;
8920 VARSET_TP GCvars(VarSetOps::UninitVal());
8922 // Is this a "fat" call descriptor?
8923 if (id->idIsLargeCall())
8925 instrDescCGCA* idCall = (instrDescCGCA*)id;
8926 gcrefRegs = idCall->idcGcrefRegs;
8927 byrefRegs = idCall->idcByrefRegs;
8928 VarSetOps::Assign(emitComp, GCvars, idCall->idcGCvars);
8932 assert(!id->idIsLargeDsp());
8933 assert(!id->idIsLargeCns());
8935 gcrefRegs = emitDecodeCallGCregs(id);
8937 VarSetOps::AssignNoCopy(emitComp, GCvars, VarSetOps::MakeEmpty(emitComp));
8940 /* We update the GC info before the call as the variables cannot be
8941 used by the call. Killing variables before the call helps with
8942 boundary conditions if the call is CORINFO_HELP_THROW - see bug 50029.
8943 If we ever track aliased variables (which could be used by the
8944 call), we would have to keep them alive past the call. */
8946 emitUpdateLiveGCvars(GCvars, dst);
8948 // Now output the call instruction and update the 'dst' pointer
8950 unsigned outputInstrSize = emitOutput_Instr(dst, code);
8951 dst += outputInstrSize;
8953 // All call instructions are 4-byte in size on ARM64
8955 assert(outputInstrSize == callInstrSize);
8957 // If the method returns a GC ref, mark INTRET (R0) appropriately.
8958 if (id->idGCref() == GCT_GCREF)
8960 gcrefRegs |= RBM_INTRET;
8962 else if (id->idGCref() == GCT_BYREF)
8964 byrefRegs |= RBM_INTRET;
8967 // If is a multi-register return method is called, mark INTRET_1 (X1) appropriately
8968 if (id->idIsLargeCall())
8970 instrDescCGCA* idCall = (instrDescCGCA*)id;
8971 if (idCall->idSecondGCref() == GCT_GCREF)
8973 gcrefRegs |= RBM_INTRET_1;
8975 else if (idCall->idSecondGCref() == GCT_BYREF)
8977 byrefRegs |= RBM_INTRET_1;
8981 // If the GC register set has changed, report the new set.
8982 if (gcrefRegs != emitThisGCrefRegs)
8984 emitUpdateLiveGCregs(GCT_GCREF, gcrefRegs, dst);
8986 // If the Byref register set has changed, report the new set.
8987 if (byrefRegs != emitThisByrefRegs)
8989 emitUpdateLiveGCregs(GCT_BYREF, byrefRegs, dst);
8992 // Some helper calls may be marked as not requiring GC info to be recorded.
8993 if ((!id->idIsNoGC()))
8995 // On ARM64, as on AMD64, we don't change the stack pointer to push/pop args.
8996 // So we're not really doing a "stack pop" here (note that "args" is 0), but we use this mechanism
8997 // to record the call for GC info purposes. (It might be best to use an alternate call,
8998 // and protect "emitStackPop" under the EMIT_TRACK_STACK_DEPTH preprocessor variable.)
8999 emitStackPop(dst, /*isCall*/ true, callInstrSize, /*args*/ 0);
9001 // Do we need to record a call location for GC purposes?
9003 if (!emitFullGCinfo)
9005 emitRecordGCcall(dst, callInstrSize);
9008 return callInstrSize;
9011 /*****************************************************************************
9013 * Emit a 32-bit Arm64 instruction
9016 /*static*/ unsigned emitter::emitOutput_Instr(BYTE* dst, code_t code)
9018 assert(sizeof(code_t) == 4);
9019 *((code_t*)dst) = code;
9021 return sizeof(code_t);
9024 /*****************************************************************************
9026 * Append the machine code corresponding to the given instruction descriptor
9027 * to the code block at '*dp'; the base of the code block is 'bp', and 'ig'
9028 * is the instruction group that contains the instruction. Updates '*dp' to
9029 * point past the generated code, and returns the size of the instruction
9030 * descriptor in bytes.
9033 size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
9038 size_t sz = emitGetInstrDescSize(id); // TODO-ARM64-Cleanup: on ARM, this is set in each case. why?
9039 instruction ins = id->idIns();
9040 insFormat fmt = id->idInsFmt();
9041 emitAttr size = id->idOpSize();
9042 unsigned char callInstrSize = 0;
9047 bool dspOffs = emitComp->opts.dspGCtbls;
9049 bool dspOffs = !emitComp->opts.disDiffable;
9053 assert(REG_NA == (int)REG_NA);
9055 VARSET_TP GCvars(VarSetOps::UninitVal());
9057 /* What instruction format have we got? */
9072 case IF_BI_0A: // BI_0A ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
9073 case IF_BI_0B: // BI_0B ......iiiiiiiiii iiiiiiiiiii..... simm19:00
9075 assert(id->idGCref() == GCT_NONE);
9076 assert(id->idIsBound());
9077 dst = emitOutputLJ(ig, dst, id);
9078 sz = sizeof(instrDescJmp);
9081 case IF_BI_0C: // BI_0C ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
9082 code = emitInsCode(ins, fmt);
9083 sz = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
9084 dst += emitOutputCall(ig, dst, id, code);
9085 // Always call RecordRelocation so that we wire in a JumpStub when we don't reach
9086 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_BRANCH26);
9089 case IF_BI_1A: // BI_1A ......iiiiiiiiii iiiiiiiiiiittttt Rt simm19:00
9090 assert(insOptsNone(id->idInsOpt()));
9091 assert(id->idIsBound());
9093 dst = emitOutputLJ(ig, dst, id);
9094 sz = sizeof(instrDescJmp);
9097 case IF_BI_1B: // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
9098 assert(insOptsNone(id->idInsOpt()));
9099 assert(id->idIsBound());
9101 dst = emitOutputLJ(ig, dst, id);
9102 sz = sizeof(instrDescJmp);
9105 case IF_BR_1A: // BR_1A ................ ......nnnnn..... Rn
9106 assert(insOptsNone(id->idInsOpt()));
9107 assert((ins == INS_ret) || (ins == INS_br));
9108 code = emitInsCode(ins, fmt);
9109 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9111 dst += emitOutput_Instr(dst, code);
9114 case IF_BR_1B: // BR_1B ................ ......nnnnn..... Rn
9115 assert(insOptsNone(id->idInsOpt()));
9116 assert((ins == INS_br_tail) || (ins == INS_blr));
9117 code = emitInsCode(ins, fmt);
9118 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9120 sz = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
9121 dst += emitOutputCall(ig, dst, id, code);
9124 case IF_LS_1A: // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB)
9126 assert(insOptsNone(id->idInsOpt()));
9127 assert(id->idIsBound());
9129 dst = emitOutputLJ(ig, dst, id);
9130 sz = sizeof(instrDescJmp);
9133 case IF_LS_2A: // LS_2A .X.......X...... ......nnnnnttttt Rt Rn
9134 assert(insOptsNone(id->idInsOpt()));
9135 code = emitInsCode(ins, fmt);
9136 // Is the target a vector register?
9137 if (isVectorRegister(id->idReg1()))
9139 code &= 0x3FFFFFFF; // clear the size bits
9140 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9141 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9145 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9146 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9148 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9149 dst += emitOutput_Instr(dst, code);
9152 case IF_LS_2B: // LS_2B .X.......Xiiiiii iiiiiinnnnnttttt Rt Rn imm(0-4095)
9153 assert(insOptsNone(id->idInsOpt()));
9154 imm = emitGetInsSC(id);
9155 assert(isValidUimm12(imm));
9156 code = emitInsCode(ins, fmt);
9157 // Is the target a vector register?
9158 if (isVectorRegister(id->idReg1()))
9160 code &= 0x3FFFFFFF; // clear the size bits
9161 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9162 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9166 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9167 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9169 code |= ((code_t)imm << 10); // iiiiiiiiiiii
9170 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9171 dst += emitOutput_Instr(dst, code);
9174 case IF_LS_2C: // LS_2C .X.......X.iiiii iiiiPPnnnnnttttt Rt Rn imm(-256..+255) no/pre/post inc
9175 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9176 imm = emitGetInsSC(id);
9177 assert((imm >= -256) && (imm <= 255)); // signed 9 bits
9178 imm &= 0x1ff; // force into unsigned 9 bit representation
9179 code = emitInsCode(ins, fmt);
9180 // Is the target a vector register?
9181 if (isVectorRegister(id->idReg1()))
9183 code &= 0x3FFFFFFF; // clear the size bits
9184 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9185 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9189 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9190 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9192 code |= insEncodeIndexedOpt(id->idInsOpt()); // PP
9193 code |= ((code_t)imm << 12); // iiiiiiiii
9194 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9195 dst += emitOutput_Instr(dst, code);
9198 case IF_LS_3A: // LS_3A .X.......X.mmmmm oooS..nnnnnttttt Rt Rn Rm ext(Rm) LSL {}
9199 assert(insOptsLSExtend(id->idInsOpt()));
9200 code = emitInsCode(ins, fmt);
9201 // Is the target a vector register?
9202 if (isVectorRegister(id->idReg1()))
9204 code &= 0x3FFFFFFF; // clear the size bits
9205 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9206 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9210 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9211 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9213 code |= insEncodeExtend(id->idInsOpt()); // ooo
9214 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9215 if (id->idIsLclVar())
9217 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9221 code |= insEncodeReg3Scale(id->idReg3Scaled()); // S
9222 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9224 dst += emitOutput_Instr(dst, code);
9227 case IF_LS_3B: // LS_3B X............... .aaaaannnnnddddd Rd Ra Rn
9228 assert(insOptsNone(id->idInsOpt()));
9229 code = emitInsCode(ins, fmt);
9230 // Is the target a vector register?
9231 if (isVectorRegister(id->idReg1()))
9233 code &= 0x3FFFFFFF; // clear the size bits
9234 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9235 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9236 code |= insEncodeReg_Va(id->idReg2()); // aaaaa
9240 code |= insEncodeDatasize(id->idOpSize()); // X
9241 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9242 code |= insEncodeReg_Ra(id->idReg2()); // aaaaa
9244 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9245 dst += emitOutput_Instr(dst, code);
9248 case IF_LS_3C: // LS_3C X......PP.iiiiii iaaaaannnnnddddd Rd Ra Rn imm(im7,sh)
9249 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9250 imm = emitGetInsSC(id);
9251 assert((imm >= -64) && (imm <= 63)); // signed 7 bits
9252 imm &= 0x7f; // force into unsigned 7 bit representation
9253 code = emitInsCode(ins, fmt);
9254 // Is the target a vector register?
9255 if (isVectorRegister(id->idReg1()))
9257 code &= 0x3FFFFFFF; // clear the size bits
9258 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9259 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9260 code |= insEncodeReg_Va(id->idReg2()); // aaaaa
9264 code |= insEncodeDatasize(id->idOpSize()); // X
9265 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9266 code |= insEncodeReg_Ra(id->idReg2()); // aaaaa
9268 code |= insEncodePairIndexedOpt(ins, id->idInsOpt()); // PP
9269 code |= ((code_t)imm << 15); // iiiiiiiii
9270 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9271 dst += emitOutput_Instr(dst, code);
9274 case IF_LS_3D: // LS_3D .X.......X.mmmmm ......nnnnnttttt Wm Rt Rn
9275 code = emitInsCode(ins, fmt);
9276 // Arm64 store exclusive unpredictable cases
9277 assert(id->idReg1() != id->idReg2());
9278 assert(id->idReg1() != id->idReg3());
9279 code |= insEncodeDatasizeLS(code, id->idOpSize()); // X
9280 code |= insEncodeReg_Rm(id->idReg1()); // mmmmm
9281 code |= insEncodeReg_Rt(id->idReg2()); // ttttt
9282 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9283 dst += emitOutput_Instr(dst, code);
9286 case IF_DI_1A: // DI_1A X.......shiiiiii iiiiiinnnnn..... Rn imm(i12,sh)
9287 assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9288 imm = emitGetInsSC(id);
9289 assert(isValidUimm12(imm));
9290 code = emitInsCode(ins, fmt);
9291 code |= insEncodeDatasize(id->idOpSize()); // X
9292 code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9293 code |= ((code_t)imm << 10); // iiiiiiiiiiii
9294 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9295 dst += emitOutput_Instr(dst, code);
9298 case IF_DI_1B: // DI_1B X........hwiiiii iiiiiiiiiiiddddd Rd imm(i16,hw)
9299 imm = emitGetInsSC(id);
9300 assert(isValidImmHWVal(imm, id->idOpSize()));
9301 code = emitInsCode(ins, fmt);
9302 code |= insEncodeDatasize(id->idOpSize()); // X
9303 code |= ((code_t)imm << 5); // hwiiiii iiiiiiiiiii
9304 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9305 dst += emitOutput_Instr(dst, code);
9308 case IF_DI_1C: // DI_1C X........Nrrrrrr ssssssnnnnn..... Rn imm(N,r,s)
9309 imm = emitGetInsSC(id);
9310 assert(isValidImmNRS(imm, id->idOpSize()));
9311 code = emitInsCode(ins, fmt);
9312 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9313 code |= insEncodeDatasize(id->idOpSize()); // X
9314 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9315 dst += emitOutput_Instr(dst, code);
9318 case IF_DI_1D: // DI_1D X........Nrrrrrr ssssss.....ddddd Rd imm(N,r,s)
9319 imm = emitGetInsSC(id);
9320 assert(isValidImmNRS(imm, id->idOpSize()));
9321 code = emitInsCode(ins, fmt);
9322 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9323 code |= insEncodeDatasize(id->idOpSize()); // X
9324 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9325 dst += emitOutput_Instr(dst, code);
9328 case IF_DI_1E: // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
9330 assert(insOptsNone(id->idInsOpt()));
9331 if (id->idIsReloc())
9333 code = emitInsCode(ins, fmt);
9334 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9335 dst += emitOutput_Instr(dst, code);
9336 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEBASE_REL21);
9340 // Local jmp/load case which does not need a relocation.
9341 assert(id->idIsBound());
9342 dst = emitOutputLJ(ig, dst, id);
9344 sz = sizeof(instrDescJmp);
9347 case IF_DI_1F: // DI_1F X..........iiiii cccc..nnnnn.nzcv Rn imm5 nzcv cond
9348 imm = emitGetInsSC(id);
9349 assert(isValidImmCondFlagsImm5(imm));
9352 cfi.immCFVal = (unsigned)imm;
9353 code = emitInsCode(ins, fmt);
9354 code |= insEncodeDatasize(id->idOpSize()); // X
9355 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9356 code |= ((code_t)cfi.imm5 << 16); // iiiii
9357 code |= insEncodeFlags(cfi.flags); // nzcv
9358 code |= insEncodeCond(cfi.cond); // cccc
9359 dst += emitOutput_Instr(dst, code);
9363 case IF_DI_2A: // DI_2A X.......shiiiiii iiiiiinnnnnddddd Rd Rn imm(i12,sh)
9364 assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9365 imm = emitGetInsSC(id);
9366 assert(isValidUimm12(imm));
9367 code = emitInsCode(ins, fmt);
9368 code |= insEncodeDatasize(id->idOpSize()); // X
9369 code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9370 code |= ((code_t)imm << 10); // iiiiiiiiiiii
9371 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9372 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9373 dst += emitOutput_Instr(dst, code);
9375 if (id->idIsReloc())
9377 assert(sz == sizeof(instrDesc));
9378 assert(id->idAddr()->iiaAddr != nullptr);
9379 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEOFFSET_12A);
9383 case IF_DI_2B: // DI_2B X.........Xnnnnn ssssssnnnnnddddd Rd Rn imm(0-63)
9384 code = emitInsCode(ins, fmt);
9385 imm = emitGetInsSC(id);
9386 assert(isValidImmShift(imm, id->idOpSize()));
9387 code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9388 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9389 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9390 code |= insEncodeReg_Rm(id->idReg2()); // Reg2 also in mmmmm
9391 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9392 dst += emitOutput_Instr(dst, code);
9395 case IF_DI_2C: // DI_2C X........Nrrrrrr ssssssnnnnnddddd Rd Rn imm(N,r,s)
9396 imm = emitGetInsSC(id);
9397 assert(isValidImmNRS(imm, id->idOpSize()));
9398 code = emitInsCode(ins, fmt);
9399 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9400 code |= insEncodeDatasize(id->idOpSize()); // X
9401 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9402 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9403 dst += emitOutput_Instr(dst, code);
9406 case IF_DI_2D: // DI_2D X........Nrrrrrr ssssssnnnnnddddd Rd Rn imr, imms (N,r,s)
9407 if (ins == INS_asr || ins == INS_lsl || ins == INS_lsr)
9409 imm = emitGetInsSC(id);
9410 assert(isValidImmShift(imm, id->idOpSize()));
9412 // Shift immediates are aliases of the SBFM/UBFM instructions
9413 // that actually take 2 registers and 2 constants,
9414 // Since we stored the shift immediate value
9415 // we need to calculate the N,R and S values here.
9420 bmi.immN = (size == EA_8BYTE) ? 1 : 0;
9422 bmi.immS = (size == EA_8BYTE) ? 0x3f : 0x1f;
9424 // immR and immS are now set correctly for INS_asr and INS_lsr
9425 // but for INS_lsl we have to adjust the values for immR and immS
9429 bmi.immR = -imm & bmi.immS;
9430 bmi.immS = bmi.immS - imm;
9433 // setup imm with the proper 13 bit value N:R:S
9439 // The other instructions have already have encoded N,R and S values
9440 imm = emitGetInsSC(id);
9442 assert(isValidImmNRS(imm, id->idOpSize()));
9444 code = emitInsCode(ins, fmt);
9445 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9446 code |= insEncodeDatasize(id->idOpSize()); // X
9447 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9448 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9449 dst += emitOutput_Instr(dst, code);
9452 case IF_DR_1D: // DR_1D X............... cccc.......ddddd Rd cond
9453 imm = emitGetInsSC(id);
9454 assert(isValidImmCond(imm));
9457 cfi.immCFVal = (unsigned)imm;
9458 code = emitInsCode(ins, fmt);
9459 code |= insEncodeDatasize(id->idOpSize()); // X
9460 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9461 code |= insEncodeInvertedCond(cfi.cond); // cccc
9462 dst += emitOutput_Instr(dst, code);
9466 case IF_DR_2A: // DR_2A X..........mmmmm ......nnnnn..... Rn Rm
9467 assert(insOptsNone(id->idInsOpt()));
9468 code = emitInsCode(ins, fmt);
9469 code |= insEncodeDatasize(id->idOpSize()); // X
9470 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9471 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9472 dst += emitOutput_Instr(dst, code);
9475 case IF_DR_2B: // DR_2B X.......sh.mmmmm ssssssnnnnn..... Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
9476 code = emitInsCode(ins, fmt);
9477 imm = emitGetInsSC(id);
9478 assert(isValidImmShift(imm, id->idOpSize()));
9479 code |= insEncodeDatasize(id->idOpSize()); // X
9480 code |= insEncodeShiftType(id->idInsOpt()); // sh
9481 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9482 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9483 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9484 dst += emitOutput_Instr(dst, code);
9487 case IF_DR_2C: // DR_2C X..........mmmmm ooosssnnnnn..... Rn Rm ext(Rm) LSL imm(0-4)
9488 code = emitInsCode(ins, fmt);
9489 imm = emitGetInsSC(id);
9490 assert((imm >= 0) && (imm <= 4)); // imm [0..4]
9491 code |= insEncodeDatasize(id->idOpSize()); // X
9492 code |= insEncodeExtend(id->idInsOpt()); // ooo
9493 code |= insEncodeExtendScale(imm); // sss
9494 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9495 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9496 dst += emitOutput_Instr(dst, code);
9499 case IF_DR_2D: // DR_2D X..........nnnnn cccc..nnnnnddddd Rd Rn cond
9500 imm = emitGetInsSC(id);
9501 assert(isValidImmCond(imm));
9504 cfi.immCFVal = (unsigned)imm;
9505 code = emitInsCode(ins, fmt);
9506 code |= insEncodeDatasize(id->idOpSize()); // X
9507 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9508 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9509 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9510 code |= insEncodeInvertedCond(cfi.cond); // cccc
9511 dst += emitOutput_Instr(dst, code);
9515 case IF_DR_2E: // DR_2E X..........mmmmm ...........ddddd Rd Rm
9516 code = emitInsCode(ins, fmt);
9517 code |= insEncodeDatasize(id->idOpSize()); // X
9518 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9519 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9520 dst += emitOutput_Instr(dst, code);
9523 case IF_DR_2F: // DR_2F X.......sh.mmmmm ssssss.....ddddd Rd Rm {LSL,LSR,ASR} imm(0-63)
9524 code = emitInsCode(ins, fmt);
9525 imm = emitGetInsSC(id);
9526 assert(isValidImmShift(imm, id->idOpSize()));
9527 code |= insEncodeDatasize(id->idOpSize()); // X
9528 code |= insEncodeShiftType(id->idInsOpt()); // sh
9529 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9530 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9531 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9532 dst += emitOutput_Instr(dst, code);
9535 case IF_DR_2G: // DR_2G X............... .....xnnnnnddddd Rd Rn
9536 code = emitInsCode(ins, fmt);
9537 code |= insEncodeDatasize(id->idOpSize()); // X
9540 if (size == EA_8BYTE)
9542 code |= 0x00000400; // x - bit at location 10
9545 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9546 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9547 dst += emitOutput_Instr(dst, code);
9550 case IF_DR_2H: // DR_2H X........X...... ......nnnnnddddd Rd Rn
9551 code = emitInsCode(ins, fmt);
9552 code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9553 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9554 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9555 dst += emitOutput_Instr(dst, code);
9558 case IF_DR_2I: // DR_2I X..........mmmmm cccc..nnnnn.nzcv Rn Rm nzcv cond
9559 imm = emitGetInsSC(id);
9560 assert(isValidImmCondFlags(imm));
9563 cfi.immCFVal = (unsigned)imm;
9564 code = emitInsCode(ins, fmt);
9565 code |= insEncodeDatasize(id->idOpSize()); // X
9566 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9567 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9568 code |= insEncodeFlags(cfi.flags); // nzcv
9569 code |= insEncodeCond(cfi.cond); // cccc
9570 dst += emitOutput_Instr(dst, code);
9574 case IF_DR_2J: // DR_2J ................ ......nnnnnddddd Sd Sn (sha1h)
9575 code = emitInsCode(ins, fmt);
9576 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9577 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9578 dst += emitOutput_Instr(dst, code);
9581 case IF_DR_3A: // DR_3A X..........mmmmm ......nnnnnmmmmm Rd Rn Rm
9582 code = emitInsCode(ins, fmt);
9583 code |= insEncodeDatasize(id->idOpSize()); // X
9584 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9585 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9586 if (id->idIsLclVar())
9588 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9592 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9594 dst += emitOutput_Instr(dst, code);
9597 case IF_DR_3B: // DR_3B X.......sh.mmmmm ssssssnnnnnddddd Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
9598 code = emitInsCode(ins, fmt);
9599 imm = emitGetInsSC(id);
9600 assert(isValidImmShift(imm, id->idOpSize()));
9601 code |= insEncodeDatasize(id->idOpSize()); // X
9602 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9603 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9604 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9605 code |= insEncodeShiftType(id->idInsOpt()); // sh
9606 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9607 dst += emitOutput_Instr(dst, code);
9610 case IF_DR_3C: // DR_3C X..........mmmmm ooosssnnnnnddddd Rd Rn Rm ext(Rm) LSL imm(0-4)
9611 code = emitInsCode(ins, fmt);
9612 imm = emitGetInsSC(id);
9613 assert((imm >= 0) && (imm <= 4)); // imm [0..4]
9614 code |= insEncodeDatasize(id->idOpSize()); // X
9615 code |= insEncodeExtend(id->idInsOpt()); // ooo
9616 code |= insEncodeExtendScale(imm); // sss
9617 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9618 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9619 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9620 dst += emitOutput_Instr(dst, code);
9623 case IF_DR_3D: // DR_3D X..........mmmmm cccc..nnnnnddddd Rd Rn Rm cond
9624 imm = emitGetInsSC(id);
9625 assert(isValidImmCond(imm));
9628 cfi.immCFVal = (unsigned)imm;
9629 code = emitInsCode(ins, fmt);
9630 code |= insEncodeDatasize(id->idOpSize()); // X
9631 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9632 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9633 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9634 code |= insEncodeCond(cfi.cond); // cccc
9635 dst += emitOutput_Instr(dst, code);
9639 case IF_DR_3E: // DR_3E X........X.mmmmm ssssssnnnnnddddd Rd Rn Rm imm(0-63)
9640 code = emitInsCode(ins, fmt);
9641 imm = emitGetInsSC(id);
9642 assert(isValidImmShift(imm, id->idOpSize()));
9643 code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9644 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9645 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9646 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9647 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9648 dst += emitOutput_Instr(dst, code);
9651 case IF_DR_4A: // DR_4A X..........mmmmm .aaaaannnnnmmmmm Rd Rn Rm Ra
9652 code = emitInsCode(ins, fmt);
9653 code |= insEncodeDatasize(id->idOpSize()); // X
9654 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9655 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9656 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9657 code |= insEncodeReg_Ra(id->idReg4()); // aaaaa
9658 dst += emitOutput_Instr(dst, code);
9661 case IF_DV_1A: // DV_1A .........X.iiiii iii........ddddd Vd imm8 (fmov - immediate scalar)
9662 imm = emitGetInsSC(id);
9663 elemsize = id->idOpSize();
9664 code = emitInsCode(ins, fmt);
9665 code |= insEncodeFloatElemsize(elemsize); // X
9666 code |= ((code_t)imm << 13); // iiiii iii
9667 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9668 dst += emitOutput_Instr(dst, code);
9671 case IF_DV_1B: // DV_1B .QX..........iii cmod..iiiiiddddd Vd imm8 (immediate vector)
9672 imm = emitGetInsSC(id) & 0x0ff;
9673 immShift = (emitGetInsSC(id) & 0x700) >> 8;
9674 elemsize = optGetElemsize(id->idInsOpt());
9679 cmode = 0xE; // 1110
9683 cmode |= (immShift << 1); // 10x0
9689 cmode |= (immShift << 1); // 0xx0
9699 cmode = 0xE; // 1110
9706 code = emitInsCode(ins, fmt);
9707 code |= insEncodeVectorsize(id->idOpSize()); // Q
9708 if ((ins == INS_fmov) || (ins == INS_movi))
9710 if (elemsize == EA_8BYTE)
9712 code |= 0x20000000; // X
9715 if (ins != INS_fmov)
9717 assert((cmode >= 0) && (cmode <= 0xF));
9718 code |= (cmode << 12); // cmod
9720 code |= (((code_t)imm >> 5) << 16); // iii
9721 code |= (((code_t)imm & 0x1f) << 5); // iiiii
9722 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9723 dst += emitOutput_Instr(dst, code);
9726 case IF_DV_1C: // DV_1C .........X...... ......nnnnn..... Vn #0.0 (fcmp - with zero)
9727 elemsize = id->idOpSize();
9728 code = emitInsCode(ins, fmt);
9729 code |= insEncodeFloatElemsize(elemsize); // X
9730 code |= insEncodeReg_Vn(id->idReg1()); // nnnnn
9731 dst += emitOutput_Instr(dst, code);
9734 case IF_DV_2A: // DV_2A .Q.......X...... ......nnnnnddddd Vd Vn (fabs, fcvt - vector)
9735 elemsize = optGetElemsize(id->idInsOpt());
9736 code = emitInsCode(ins, fmt);
9737 code |= insEncodeVectorsize(id->idOpSize()); // Q
9738 code |= insEncodeFloatElemsize(elemsize); // X
9739 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9740 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9741 dst += emitOutput_Instr(dst, code);
9744 case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov/smov - to general)
9745 elemsize = id->idOpSize();
9746 index = emitGetInsSC(id);
9747 datasize = (elemsize == EA_8BYTE) ? EA_16BYTE : EA_8BYTE;
9748 if (ins == INS_smov)
9750 datasize = EA_16BYTE;
9752 code = emitInsCode(ins, fmt);
9753 code |= insEncodeVectorsize(datasize); // Q
9754 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9755 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9756 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9757 dst += emitOutput_Instr(dst, code);
9760 case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
9763 datasize = id->idOpSize();
9764 elemsize = optGetElemsize(id->idInsOpt());
9769 datasize = EA_16BYTE;
9770 elemsize = id->idOpSize();
9771 index = emitGetInsSC(id);
9773 code = emitInsCode(ins, fmt);
9774 code |= insEncodeVectorsize(datasize); // Q
9775 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9776 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9777 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9778 dst += emitOutput_Instr(dst, code);
9781 case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
9782 index = emitGetInsSC(id);
9783 elemsize = optGetElemsize(id->idInsOpt());
9784 code = emitInsCode(ins, fmt);
9785 code |= insEncodeVectorsize(id->idOpSize()); // Q
9786 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9787 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9788 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9789 dst += emitOutput_Instr(dst, code);
9792 case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
9793 index = emitGetInsSC(id);
9794 elemsize = id->idOpSize();
9795 code = emitInsCode(ins, fmt);
9796 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9797 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9798 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9799 dst += emitOutput_Instr(dst, code);
9802 case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
9803 elemsize = id->idOpSize();
9804 imm = emitGetInsSC(id);
9805 index = (imm >> 4) & 0xf;
9807 code = emitInsCode(ins, fmt);
9808 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9809 code |= insEncodeVectorIndex2(elemsize, index2); // jjjj
9810 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9811 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9812 dst += emitOutput_Instr(dst, code);
9815 case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov,fcvtXX - register)
9816 elemsize = id->idOpSize();
9817 code = emitInsCode(ins, fmt);
9818 code |= insEncodeFloatElemsize(elemsize); // X
9819 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9820 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9821 dst += emitOutput_Instr(dst, code);
9824 case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov - to general)
9825 elemsize = id->idOpSize();
9826 code = emitInsCode(ins, fmt);
9827 code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X X
9828 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9829 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9830 dst += emitOutput_Instr(dst, code);
9833 case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov - from general)
9834 elemsize = id->idOpSize();
9835 code = emitInsCode(ins, fmt);
9836 code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X X
9837 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9838 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9839 dst += emitOutput_Instr(dst, code);
9842 case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
9843 code = emitInsCode(ins, fmt);
9844 code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // SS DD
9845 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9846 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9847 dst += emitOutput_Instr(dst, code);
9850 case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
9851 elemsize = id->idOpSize();
9852 code = emitInsCode(ins, fmt);
9853 code |= insEncodeFloatElemsize(elemsize); // X
9854 code |= insEncodeReg_Vn(id->idReg1()); // nnnnn
9855 code |= insEncodeReg_Vm(id->idReg2()); // mmmmm
9856 dst += emitOutput_Instr(dst, code);
9859 case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
9860 elemsize = id->idOpSize();
9861 code = emitInsCode(ins, fmt);
9862 code |= insEncodeElemsize(elemsize); // XX
9863 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9864 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9865 dst += emitOutput_Instr(dst, code);
9868 case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
9869 elemsize = optGetElemsize(id->idInsOpt());
9870 code = emitInsCode(ins, fmt);
9871 code |= insEncodeVectorsize(id->idOpSize()); // Q
9872 code |= insEncodeElemsize(elemsize); // XX
9873 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9874 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9875 dst += emitOutput_Instr(dst, code);
9878 case IF_DV_2N: // DV_2N .........iiiiiii ......nnnnnddddd Vd Vn imm (shift - scalar)
9879 imm = emitGetInsSC(id);
9880 code = emitInsCode(ins, fmt);
9881 code |= insEncodeVectorShift(EA_8BYTE, imm); // iiiiiii
9882 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9883 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9884 dst += emitOutput_Instr(dst, code);
9887 case IF_DV_2O: // DV_2O .Q.......iiiiiii ......nnnnnddddd Vd Vn imm (shift - vector)
9888 imm = emitGetInsSC(id);
9889 elemsize = optGetElemsize(id->idInsOpt());
9890 code = emitInsCode(ins, fmt);
9891 code |= insEncodeVectorsize(id->idOpSize()); // Q
9892 code |= insEncodeVectorShift(elemsize, imm); // iiiiiii
9893 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9894 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9895 dst += emitOutput_Instr(dst, code);
9898 case IF_DV_2P: // DV_2P ............... ......nnnnnddddd Vd Vn (aes*, sha1su1)
9899 elemsize = optGetElemsize(id->idInsOpt());
9900 code = emitInsCode(ins, fmt);
9901 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9902 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9903 dst += emitOutput_Instr(dst, code);
9906 case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
9907 code = emitInsCode(ins, fmt);
9908 elemsize = optGetElemsize(id->idInsOpt());
9909 code |= insEncodeVectorsize(id->idOpSize()); // Q
9910 code |= insEncodeElemsize(elemsize); // XX
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_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector)
9918 code = emitInsCode(ins, fmt);
9919 imm = emitGetInsSC(id);
9920 elemsize = optGetElemsize(id->idInsOpt());
9921 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
9922 code |= insEncodeVectorsize(id->idOpSize()); // Q
9923 code |= insEncodeElemsize(elemsize); // XX
9924 code |= insEncodeVectorIndexLMH(elemsize, imm); // LM H
9925 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9926 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9927 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9928 dst += emitOutput_Instr(dst, code);
9931 case IF_DV_3B: // DV_3B .Q.......X.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
9932 code = emitInsCode(ins, fmt);
9933 elemsize = optGetElemsize(id->idInsOpt());
9934 code |= insEncodeVectorsize(id->idOpSize()); // Q
9935 code |= insEncodeFloatElemsize(elemsize); // X
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_3BI: // DV_3BI .Q.......XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
9943 code = emitInsCode(ins, fmt);
9944 imm = emitGetInsSC(id);
9945 elemsize = optGetElemsize(id->idInsOpt());
9946 assert(isValidVectorIndex(id->idOpSize(), elemsize, imm));
9947 code |= insEncodeVectorsize(id->idOpSize()); // Q
9948 code |= insEncodeFloatElemsize(elemsize); // X
9949 code |= insEncodeFloatIndex(elemsize, imm); // L H
9950 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9951 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9952 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9953 dst += emitOutput_Instr(dst, code);
9956 case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
9957 code = emitInsCode(ins, fmt);
9958 code |= insEncodeVectorsize(id->idOpSize()); // Q
9959 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9960 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9961 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9962 dst += emitOutput_Instr(dst, code);
9965 case IF_DV_3D: // DV_3D .........X.mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
9966 code = emitInsCode(ins, fmt);
9967 code |= insEncodeFloatElemsize(id->idOpSize()); // X
9968 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9969 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9970 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9971 dst += emitOutput_Instr(dst, code);
9974 case IF_DV_3DI: // DV_3DI .........XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (scalar by elem)
9975 code = emitInsCode(ins, fmt);
9976 imm = emitGetInsSC(id);
9977 elemsize = id->idOpSize();
9978 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
9979 code |= insEncodeFloatElemsize(elemsize); // X
9980 code |= insEncodeFloatIndex(elemsize, imm); // L H
9981 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9982 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9983 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9984 dst += emitOutput_Instr(dst, code);
9987 case IF_DV_3E: // DV_3E ...........mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
9988 case IF_DV_3F: // DV_3F ...........mmmmm ......nnnnnddddd Vd Vn Vm (vector) - source dest regs overlap
9989 code = emitInsCode(ins, fmt);
9990 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9991 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9992 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9993 dst += emitOutput_Instr(dst, code);
9996 case IF_DV_4A: // DV_4A .........X.mmmmm .aaaaannnnnddddd Vd Va Vn Vm (scalar)
9997 code = emitInsCode(ins, fmt);
9998 elemsize = id->idOpSize();
9999 code |= insEncodeFloatElemsize(elemsize); // X
10000 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
10001 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
10002 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
10003 code |= insEncodeReg_Va(id->idReg4()); // aaaaa
10004 dst += emitOutput_Instr(dst, code);
10007 case IF_SN_0A: // SN_0A ................ ................
10008 code = emitInsCode(ins, fmt);
10009 dst += emitOutput_Instr(dst, code);
10012 case IF_SI_0A: // SI_0A ...........iiiii iiiiiiiiiii..... imm16
10013 imm = emitGetInsSC(id);
10014 assert(isValidUimm16(imm));
10015 code = emitInsCode(ins, fmt);
10016 code |= ((code_t)imm << 5); // iiiii iiiiiiiiiii
10017 dst += emitOutput_Instr(dst, code);
10020 case IF_SI_0B: // SI_0B ................ ....bbbb........ imm4 - barrier
10021 imm = emitGetInsSC(id);
10022 assert((imm >= 0) && (imm <= 15));
10023 code = emitInsCode(ins, fmt);
10024 code |= ((code_t)imm << 8); // bbbb
10025 dst += emitOutput_Instr(dst, code);
10029 assert(!"Unexpected format");
10033 // Determine if any registers now hold GC refs, or whether a register that was overwritten held a GC ref.
10034 // We assume here that "id->idGCref()" is not GC_NONE only if the instruction described by "id" writes a
10035 // GC ref to register "id->idReg1()". (It may, apparently, also not be GC_NONE in other cases, such as
10036 // for stores, but we ignore those cases here.)
10037 if (emitInsMayWriteToGCReg(id)) // True if "id->idIns()" writes to a register than can hold GC ref.
10039 // We assume that "idReg1" is the primary destination register for all instructions
10040 if (id->idGCref() != GCT_NONE)
10042 emitGCregLiveUpd(id->idGCref(), id->idReg1(), dst);
10046 emitGCregDeadUpd(id->idReg1(), dst);
10049 if (emitInsMayWriteMultipleRegs(id))
10052 // "idReg2" is the secondary destination register
10053 if (id->idGCrefReg2() != GCT_NONE)
10055 emitGCregLiveUpd(id->idGCrefReg2(), id->idReg2(), dst);
10059 emitGCregDeadUpd(id->idReg2(), dst);
10064 // Now we determine if the instruction has written to a (local variable) stack location, and either written a GC
10065 // ref or overwritten one.
10066 if (emitInsWritesToLclVarStackLoc(id) || emitInsWritesToLclVarStackLocPair(id))
10068 int varNum = id->idAddr()->iiaLclVar.lvaVarNum();
10069 unsigned ofs = AlignDown(id->idAddr()->iiaLclVar.lvaOffset(), TARGET_POINTER_SIZE);
10071 int adr = emitComp->lvaFrameAddress(varNum, &FPbased);
10072 if (id->idGCref() != GCT_NONE)
10074 emitGCvarLiveUpd(adr + ofs, varNum, id->idGCref(), dst);
10078 // If the type of the local is a gc ref type, update the liveness.
10082 // "Regular" (non-spill-temp) local.
10083 vt = var_types(emitComp->lvaTable[varNum].lvType);
10087 TempDsc* tmpDsc = emitComp->tmpFindNum(varNum);
10088 vt = tmpDsc->tdTempType();
10090 if (vt == TYP_REF || vt == TYP_BYREF)
10091 emitGCvarDeadUpd(adr + ofs, dst);
10093 if (emitInsWritesToLclVarStackLocPair(id))
10095 unsigned ofs2 = ofs + TARGET_POINTER_SIZE;
10096 if (id->idGCrefReg2() != GCT_NONE)
10098 emitGCvarLiveUpd(adr + ofs2, varNum, id->idGCrefReg2(), dst);
10102 // If the type of the local is a gc ref type, update the liveness.
10106 // "Regular" (non-spill-temp) local.
10107 vt = var_types(emitComp->lvaTable[varNum].lvType);
10111 TempDsc* tmpDsc = emitComp->tmpFindNum(varNum);
10112 vt = tmpDsc->tdTempType();
10114 if (vt == TYP_REF || vt == TYP_BYREF)
10115 emitGCvarDeadUpd(adr + ofs2, dst);
10121 /* Make sure we set the instruction descriptor size correctly */
10123 size_t expected = emitSizeOfInsDsc(id);
10124 assert(sz == expected);
10126 if (emitComp->opts.disAsm || emitComp->opts.dspEmit || emitComp->verbose)
10128 emitDispIns(id, false, dspOffs, true, emitCurCodeOffs(odst), *dp, (dst - *dp), ig);
10131 if (emitComp->compDebugBreak)
10133 // For example, set JitBreakEmitOutputInstr=a6 will break when this method is called for
10134 // emitting instruction a6, (i.e. IN00a6 in jitdump).
10135 if ((unsigned)JitConfig.JitBreakEmitOutputInstr() == id->idDebugOnlyInfo()->idNum)
10137 assert(!"JitBreakEmitOutputInstr reached");
10142 /* All instructions are expected to generate code */
10144 assert(*dp != dst);
10151 /*****************************************************************************/
10152 /*****************************************************************************/
10156 /*****************************************************************************
10158 * Display the instruction name
10160 void emitter::emitDispInst(instruction ins)
10162 const char* insstr = codeGen->genInsName(ins);
10163 size_t len = strlen(insstr);
10165 /* Display the instruction name */
10167 printf("%s", insstr);
10170 // Add at least one space after the instruction name
10171 // and add spaces until we have reach the normal size of 8
10179 /*****************************************************************************
10181 * Display an reloc value
10182 * If we are formatting for an assembly listing don't print the hex value
10183 * since it will prevent us from doing assembly diffs
10185 void emitter::emitDispReloc(int value, bool addComma)
10187 if (emitComp->opts.disAsm)
10193 printf("(reloc 0x%x)", dspPtr(value));
10200 /*****************************************************************************
10202 * Display an immediate value
10204 void emitter::emitDispImm(ssize_t imm, bool addComma, bool alwaysHex /* =false */)
10211 // Munge any pointers if we want diff-able disassembly.
10212 // Since some may be emitted as partial words, print as diffable anything that has
10213 // significant bits beyond the lowest 8-bits.
10214 if (emitComp->opts.disDiffable)
10216 ssize_t top56bits = (imm >> 8);
10217 if ((top56bits != 0) && (top56bits != -1))
10221 if (!alwaysHex && (imm > -1000) && (imm < 1000))
10227 if ((imm < 0) && ((imm & 0xFFFFFFFF00000000LL) == 0xFFFFFFFF00000000LL))
10233 if ((imm & 0xFFFFFFFF00000000LL) != 0)
10235 printf("0x%llx", imm);
10239 printf("0x%02x", imm);
10247 /*****************************************************************************
10249 * Display a float zero constant
10251 void emitter::emitDispFloatZero()
10260 /*****************************************************************************
10262 * Display an encoded float constant value
10264 void emitter::emitDispFloatImm(ssize_t imm8)
10266 assert((0 <= imm8) && (imm8 <= 0x0ff));
10273 fpImm.immFPIVal = (unsigned)imm8;
10274 double result = emitDecodeFloatImm8(fpImm);
10276 printf("%.4f", result);
10279 /*****************************************************************************
10281 * Display an immediate that is optionally LSL12.
10283 void emitter::emitDispImmOptsLSL12(ssize_t imm, insOpts opt)
10285 if (!strictArmAsm && insOptsLSL12(opt))
10289 emitDispImm(imm, false);
10290 if (strictArmAsm && insOptsLSL12(opt))
10292 printf(", LSL #12");
10296 /*****************************************************************************
10298 * Display an ARM64 condition code for the conditional instructions
10300 void emitter::emitDispCond(insCond cond)
10302 const static char* armCond[16] = {"eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc",
10303 "hi", "ls", "ge", "lt", "gt", "le", "AL", "NV"}; // The last two are invalid
10304 unsigned imm = (unsigned)cond;
10305 assert((0 <= imm) && (imm < ArrLen(armCond)));
10306 printf(armCond[imm]);
10309 /*****************************************************************************
10311 * Display an ARM64 flags for the conditional instructions
10313 void emitter::emitDispFlags(insCflags flags)
10315 const static char* armFlags[16] = {"0", "v", "c", "cv", "z", "zv", "zc", "zcv",
10316 "n", "nv", "nc", "ncv", "nz", "nzv", "nzc", "nzcv"};
10317 unsigned imm = (unsigned)flags;
10318 assert((0 <= imm) && (imm < ArrLen(armFlags)));
10319 printf(armFlags[imm]);
10322 /*****************************************************************************
10324 * Display an ARM64 'barrier' for the memory barrier instructions
10326 void emitter::emitDispBarrier(insBarrier barrier)
10328 const static char* armBarriers[16] = {"#0", "oshld", "oshst", "osh", "#4", "nshld", "nshst", "nsh",
10329 "#8", "ishld", "ishst", "ish", "#12", "ld", "st", "sy"};
10330 unsigned imm = (unsigned)barrier;
10331 assert((0 <= imm) && (imm < ArrLen(armBarriers)));
10332 printf(armBarriers[imm]);
10335 /*****************************************************************************
10337 * Prints the encoding for the Shift Type encoding
10340 void emitter::emitDispShiftOpts(insOpts opt)
10342 if (opt == INS_OPTS_LSL)
10344 else if (opt == INS_OPTS_LSR)
10346 else if (opt == INS_OPTS_ASR)
10348 else if (opt == INS_OPTS_ROR)
10350 else if (opt == INS_OPTS_MSL)
10353 assert(!"Bad value");
10356 /*****************************************************************************
10358 * Prints the encoding for the Extend Type encoding
10361 void emitter::emitDispExtendOpts(insOpts opt)
10363 if (opt == INS_OPTS_UXTB)
10365 else if (opt == INS_OPTS_UXTH)
10367 else if (opt == INS_OPTS_UXTW)
10369 else if (opt == INS_OPTS_UXTX)
10371 else if (opt == INS_OPTS_SXTB)
10373 else if (opt == INS_OPTS_SXTH)
10375 else if (opt == INS_OPTS_SXTW)
10377 else if (opt == INS_OPTS_SXTX)
10380 assert(!"Bad value");
10383 /*****************************************************************************
10385 * Prints the encoding for the Extend Type encoding in loads/stores
10388 void emitter::emitDispLSExtendOpts(insOpts opt)
10390 if (opt == INS_OPTS_LSL)
10392 else if (opt == INS_OPTS_UXTW)
10394 else if (opt == INS_OPTS_UXTX)
10396 else if (opt == INS_OPTS_SXTW)
10398 else if (opt == INS_OPTS_SXTX)
10401 assert(!"Bad value");
10404 /*****************************************************************************
10406 * Display a register
10408 void emitter::emitDispReg(regNumber reg, emitAttr attr, bool addComma)
10410 emitAttr size = EA_SIZE(attr);
10411 printf(emitRegName(reg, size));
10417 /*****************************************************************************
10419 * Display a vector register with an arrangement suffix
10421 void emitter::emitDispVectorReg(regNumber reg, insOpts opt, bool addComma)
10423 assert(isVectorRegister(reg));
10424 printf(emitVectorRegName(reg));
10425 emitDispArrangement(opt);
10431 /*****************************************************************************
10433 * Display an vector register index suffix
10435 void emitter::emitDispVectorRegIndex(regNumber reg, emitAttr elemsize, ssize_t index, bool addComma)
10437 assert(isVectorRegister(reg));
10438 printf(emitVectorRegName(reg));
10455 assert(!"invalid elemsize");
10459 printf("[%d]", index);
10465 /*****************************************************************************
10467 * Display an arrangement suffix
10469 void emitter::emitDispArrangement(insOpts opt)
10471 const char* str = "???";
10501 assert(!"Invalid insOpt for vector register");
10507 /*****************************************************************************
10509 * Display a register with an optional shift operation
10511 void emitter::emitDispShiftedReg(regNumber reg, insOpts opt, ssize_t imm, emitAttr attr)
10513 emitAttr size = EA_SIZE(attr);
10514 assert((imm & 0x003F) == imm);
10515 assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
10517 printf(emitRegName(reg, size));
10525 emitDispShiftOpts(opt);
10526 emitDispImm(imm, false);
10530 /*****************************************************************************
10532 * Display a register with an optional extend and scale operations
10534 void emitter::emitDispExtendReg(regNumber reg, insOpts opt, ssize_t imm)
10536 assert((imm >= 0) && (imm <= 4));
10537 assert(insOptsNone(opt) || insOptsAnyExtend(opt) || (opt == INS_OPTS_LSL));
10539 // size is based on the extend option, not the instr size.
10540 emitAttr size = insOpts32BitExtend(opt) ? EA_4BYTE : EA_8BYTE;
10544 if (insOptsNone(opt))
10546 emitDispReg(reg, size, false);
10550 emitDispReg(reg, size, true);
10551 if (opt == INS_OPTS_LSL)
10554 emitDispExtendOpts(opt);
10555 if ((imm > 0) || (opt == INS_OPTS_LSL))
10558 emitDispImm(imm, false);
10562 else // !strictArmAsm
10564 if (insOptsNone(opt))
10566 emitDispReg(reg, size, false);
10570 if (opt != INS_OPTS_LSL)
10572 emitDispExtendOpts(opt);
10574 emitDispReg(reg, size, false);
10581 emitDispImm(1 << imm, false);
10586 /*****************************************************************************
10588 * Display an addressing operand [reg + imm]
10590 void emitter::emitDispAddrRI(regNumber reg, insOpts opt, ssize_t imm)
10592 reg = encodingZRtoSP(reg); // ZR (R31) encodes the SP register
10598 emitDispReg(reg, EA_8BYTE, false);
10600 if (!insOptsPostIndex(opt) && (imm != 0))
10603 emitDispImm(imm, false);
10607 if (insOptsPreIndex(opt))
10611 else if (insOptsPostIndex(opt))
10614 emitDispImm(imm, false);
10617 else // !strictArmAsm
10621 const char* operStr = "++";
10628 if (insOptsPreIndex(opt))
10633 emitDispReg(reg, EA_8BYTE, false);
10635 if (insOptsPostIndex(opt))
10640 if (insOptsIndexed(opt))
10646 printf("%c", operStr[1]);
10648 emitDispImm(imm, false);
10653 /*****************************************************************************
10655 * Display an addressing operand [reg + extended reg]
10657 void emitter::emitDispAddrRRExt(regNumber reg1, regNumber reg2, insOpts opt, bool isScaled, emitAttr size)
10659 reg1 = encodingZRtoSP(reg1); // ZR (R31) encodes the SP register
10661 unsigned scale = 0;
10664 scale = NaturalScale_helper(size);
10671 emitDispReg(reg1, EA_8BYTE, true);
10672 emitDispExtendReg(reg2, opt, scale);
10674 else // !strictArmAsm
10676 emitDispReg(reg1, EA_8BYTE, false);
10678 emitDispExtendReg(reg2, opt, scale);
10684 /*****************************************************************************
10686 * Display (optionally) the instruction encoding in hex
10689 void emitter::emitDispInsHex(BYTE* code, size_t sz)
10691 // We do not display the instruction hex if we want diff-able disassembly
10692 if (!emitComp->opts.disDiffable)
10696 printf(" %08X ", (*((code_t*)code)));
10705 /****************************************************************************
10707 * Display the given instruction.
10710 void emitter::emitDispIns(
10711 instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* pCode, size_t sz, insGroup* ig)
10716 id->idDebugOnlyInfo()->idNum; // Do not remove this! It is needed for VisualStudio conditional breakpoints
10718 printf("IN%04x: ", idNum);
10724 if (!emitComp->opts.dspEmit && !isNew && !asmfm && sz)
10727 /* Display the instruction offset */
10729 emitDispInsOffs(offset, doffs);
10731 /* Display the instruction hex code */
10733 emitDispInsHex(pCode, sz);
10737 /* Get the instruction and format */
10739 instruction ins = id->idIns();
10740 insFormat fmt = id->idInsFmt();
10744 /* If this instruction has just been added, check its size */
10746 assert(isNew == false || (int)emitSizeOfInsDsc(id) == emitCurIGfreeNext - (BYTE*)id);
10748 /* Figure out the operand size */
10749 emitAttr size = id->idOpSize();
10750 emitAttr attr = size;
10751 if (id->idGCref() == GCT_GCREF)
10753 else if (id->idGCref() == GCT_BYREF)
10761 bool isExtendAlias;
10770 const char* methodName;
10778 case IF_BI_0A: // BI_0A ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
10779 case IF_BI_0B: // BI_0B ......iiiiiiiiii iiiiiiiiiii..... simm19:00
10782 if (fmt == IF_LARGEJMP)
10784 printf("(LARGEJMP)");
10786 if (id->idAddr()->iiaHasInstrCount())
10788 int instrCount = id->idAddr()->iiaGetInstrCount();
10792 printf("pc%s%d instructions", (instrCount >= 0) ? "+" : "", instrCount);
10796 unsigned insNum = emitFindInsNum(ig, id);
10797 UNATIVE_OFFSET srcOffs = ig->igOffs + emitFindOffset(ig, insNum + 1);
10798 UNATIVE_OFFSET dstOffs = ig->igOffs + emitFindOffset(ig, insNum + 1 + instrCount);
10799 ssize_t relOffs = (ssize_t)(emitOffsetToPtr(dstOffs) - emitOffsetToPtr(srcOffs));
10800 printf("pc%s%d (%d instructions)", (relOffs >= 0) ? "+" : "", relOffs, instrCount);
10803 else if (id->idIsBound())
10805 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10809 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10814 case IF_BI_0C: // BI_0C ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
10815 if (id->idIsCallAddr())
10817 offs = (ssize_t)id->idAddr()->iiaAddr;
10823 methodName = emitComp->eeGetMethodFullName((CORINFO_METHOD_HANDLE)id->idDebugOnlyInfo()->idMemCookie);
10828 if (id->idIsDspReloc())
10830 printf("%08X", offs);
10834 printf("%s", methodName);
10838 case IF_BI_1A: // BI_1A ......iiiiiiiiii iiiiiiiiiiittttt Rt simm19:00
10839 assert(insOptsNone(id->idInsOpt()));
10840 emitDispReg(id->idReg1(), size, 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_BI_1B: // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
10852 assert(insOptsNone(id->idInsOpt()));
10853 emitDispReg(id->idReg1(), size, true);
10854 emitDispImm(emitGetInsSC(id), true);
10855 if (id->idIsBound())
10857 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10861 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10865 case IF_BR_1A: // BR_1A ................ ......nnnnn..... Rn
10866 assert(insOptsNone(id->idInsOpt()));
10867 emitDispReg(id->idReg1(), size, false);
10870 case IF_BR_1B: // BR_1B ................ ......nnnnn..... Rn
10871 assert(insOptsNone(id->idInsOpt()));
10872 emitDispReg(id->idReg3(), size, false);
10875 case IF_LS_1A: // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB)
10876 case IF_DI_1E: // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
10879 assert(insOptsNone(id->idInsOpt()));
10880 emitDispReg(id->idReg1(), size, true);
10881 imm = emitGetInsSC(id);
10883 /* Is this actually a reference to a data section? */
10884 if (fmt == IF_LARGEADR)
10886 printf("(LARGEADR)");
10888 else if (fmt == IF_LARGELDC)
10890 printf("(LARGELDC)");
10894 if (id->idAddr()->iiaIsJitDataOffset())
10896 doffs = Compiler::eeGetJitDataOffs(id->idAddr()->iiaFieldHnd);
10897 /* Display a data section reference */
10900 printf("@CNS%02u", doffs - 1);
10902 printf("@RWD%02u", doffs);
10905 printf("%+Id", imm);
10910 if (id->idIsReloc())
10913 emitDispImm((ssize_t)id->idAddr()->iiaAddr, false);
10915 else if (id->idIsBound())
10917 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10921 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10927 case IF_LS_2A: // LS_2A .X.......X...... ......nnnnnttttt Rt Rn
10928 assert(insOptsNone(id->idInsOpt()));
10929 assert(emitGetInsSC(id) == 0);
10930 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10931 emitDispAddrRI(id->idReg2(), id->idInsOpt(), 0);
10934 case IF_LS_2B: // LS_2B .X.......Xiiiiii iiiiiinnnnnttttt Rt Rn imm(0-4095)
10935 assert(insOptsNone(id->idInsOpt()));
10936 imm = emitGetInsSC(id);
10937 scale = NaturalScale_helper(emitInsLoadStoreSize(id));
10938 imm <<= scale; // The immediate is scaled by the size of the ld/st
10939 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10940 emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
10943 case IF_LS_2C: // LS_2C .X.......X.iiiii iiiiPPnnnnnttttt Rt Rn imm(-256..+255) no/pre/post inc
10944 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
10945 imm = emitGetInsSC(id);
10946 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10947 emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
10950 case IF_LS_3A: // LS_3A .X.......X.mmmmm oooS..nnnnnttttt Rt Rn Rm ext(Rm) LSL {}
10951 assert(insOptsLSExtend(id->idInsOpt()));
10952 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10953 if (id->idIsLclVar())
10955 emitDispAddrRRExt(id->idReg2(), codeGen->rsGetRsvdReg(), id->idInsOpt(), false, size);
10959 emitDispAddrRRExt(id->idReg2(), id->idReg3(), id->idInsOpt(), id->idReg3Scaled(), size);
10963 case IF_LS_3B: // LS_3B X............... .aaaaannnnnddddd Rt Ra Rn
10964 assert(insOptsNone(id->idInsOpt()));
10965 assert(emitGetInsSC(id) == 0);
10966 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10967 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10968 emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
10971 case IF_LS_3C: // LS_3C X.........iiiiii iaaaaannnnnddddd Rt Ra Rn imm(im7,sh)
10972 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
10973 imm = emitGetInsSC(id);
10974 scale = NaturalScale_helper(emitInsLoadStoreSize(id));
10976 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10977 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10978 emitDispAddrRI(id->idReg3(), id->idInsOpt(), imm);
10981 case IF_LS_3D: // LS_3D .X.......X.mmmmm ......nnnnnttttt Wm Rt Rn
10982 assert(insOptsNone(id->idInsOpt()));
10983 emitDispReg(id->idReg1(), EA_4BYTE, true);
10984 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10985 emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
10988 case IF_DI_1A: // DI_1A X.......shiiiiii iiiiiinnnnn..... Rn imm(i12,sh)
10989 emitDispReg(id->idReg1(), size, true);
10990 emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
10993 case IF_DI_1B: // DI_1B X........hwiiiii iiiiiiiiiiiddddd Rd imm(i16,hw)
10994 emitDispReg(id->idReg1(), size, true);
10995 hwi.immHWVal = (unsigned)emitGetInsSC(id);
10996 if (ins == INS_mov)
10998 emitDispImm(emitDecodeHalfwordImm(hwi, size), false);
11000 else // movz, movn, movk
11002 emitDispImm(hwi.immVal, false);
11003 if (hwi.immHW != 0)
11005 emitDispShiftOpts(INS_OPTS_LSL);
11006 emitDispImm(hwi.immHW * 16, false);
11011 case IF_DI_1C: // DI_1C X........Nrrrrrr ssssssnnnnn..... Rn imm(N,r,s)
11012 emitDispReg(id->idReg1(), size, true);
11013 bmi.immNRS = (unsigned)emitGetInsSC(id);
11014 emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
11017 case IF_DI_1D: // DI_1D X........Nrrrrrr ssssss.....ddddd Rd imm(N,r,s)
11018 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11019 bmi.immNRS = (unsigned)emitGetInsSC(id);
11020 emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
11023 case IF_DI_2A: // DI_2A X.......shiiiiii iiiiiinnnnnddddd Rd Rn imm(i12,sh)
11024 if ((ins == INS_add) || (ins == INS_sub))
11026 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11027 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11031 emitDispReg(id->idReg1(), size, true);
11032 emitDispReg(id->idReg2(), size, true);
11034 emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
11037 case IF_DI_2B: // DI_2B X........X.nnnnn ssssssnnnnnddddd Rd Rn imm(0-63)
11038 emitDispReg(id->idReg1(), size, true);
11039 emitDispReg(id->idReg2(), size, true);
11040 emitDispImm(emitGetInsSC(id), false);
11043 case IF_DI_2C: // DI_2C X........Nrrrrrr ssssssnnnnnddddd Rd Rn imm(N,r,s)
11044 if (ins == INS_ands)
11046 emitDispReg(id->idReg1(), size, true);
11050 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11052 emitDispReg(id->idReg2(), size, true);
11053 bmi.immNRS = (unsigned)emitGetInsSC(id);
11054 emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
11057 case IF_DI_2D: // DI_2D X........Nrrrrrr ssssssnnnnnddddd Rd Rn imr, ims (N,r,s)
11058 emitDispReg(id->idReg1(), size, true);
11059 emitDispReg(id->idReg2(), size, true);
11061 imm = emitGetInsSC(id);
11062 bmi.immNRS = (unsigned)imm;
11069 emitDispImm(bmi.immR, true);
11070 emitDispImm(bmi.immS, false);
11076 emitDispImm(getBitWidth(size) - bmi.immR, true);
11077 emitDispImm(bmi.immS + 1, false);
11083 emitDispImm(bmi.immR, true);
11084 emitDispImm(bmi.immS - bmi.immR + 1, false);
11090 emitDispImm(imm, false);
11094 assert(!"Unexpected instruction in IF_DI_2D");
11099 case IF_DI_1F: // DI_1F X..........iiiii cccc..nnnnn.nzcv Rn imm5 nzcv cond
11100 emitDispReg(id->idReg1(), size, true);
11101 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11102 emitDispImm(cfi.imm5, true);
11103 emitDispFlags(cfi.flags);
11105 emitDispCond(cfi.cond);
11108 case IF_DR_1D: // DR_1D X............... cccc.......mmmmm Rd cond
11109 emitDispReg(id->idReg1(), size, true);
11110 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11111 emitDispCond(cfi.cond);
11114 case IF_DR_2A: // DR_2A X..........mmmmm ......nnnnn..... Rn Rm
11115 emitDispReg(id->idReg1(), size, true);
11116 emitDispReg(id->idReg2(), size, false);
11119 case IF_DR_2B: // DR_2B X.......sh.mmmmm ssssssnnnnn..... Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
11120 emitDispReg(id->idReg1(), size, true);
11121 emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
11124 case IF_DR_2C: // DR_2C X..........mmmmm ooosssnnnnn..... Rn Rm ext(Rm) LSL imm(0-4)
11125 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11126 imm = emitGetInsSC(id);
11127 emitDispExtendReg(id->idReg2(), id->idInsOpt(), imm);
11130 case IF_DR_2D: // DR_2D X..........nnnnn cccc..nnnnnddddd Rd Rn cond
11131 emitDispReg(id->idReg1(), size, true);
11132 emitDispReg(id->idReg2(), size, true);
11133 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11134 emitDispCond(cfi.cond);
11137 case IF_DR_2E: // DR_2E X..........mmmmm ...........ddddd Rd Rm
11138 case IF_DR_2J: // DR_2J ................ ......nnnnnddddd Sd Sn
11139 emitDispReg(id->idReg1(), size, true);
11140 emitDispReg(id->idReg2(), size, false);
11143 case IF_DR_2F: // DR_2F X.......sh.mmmmm ssssss.....ddddd Rd Rm {LSL,LSR,ASR} imm(0-63)
11144 emitDispReg(id->idReg1(), size, true);
11145 emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
11148 case IF_DR_2G: // DR_2G X............... ......nnnnnddddd Rd Rn
11149 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11150 emitDispReg(encodingZRtoSP(id->idReg2()), size, false);
11153 case IF_DR_2H: // DR_2H X........X...... ......nnnnnddddd Rd Rn
11154 emitDispReg(id->idReg1(), size, true);
11155 emitDispReg(id->idReg2(), size, false);
11158 case IF_DR_2I: // DR_2I X..........mmmmm cccc..nnnnn.nzcv Rn Rm nzcv cond
11159 emitDispReg(id->idReg1(), size, true);
11160 emitDispReg(id->idReg2(), size, true);
11161 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11162 emitDispFlags(cfi.flags);
11164 emitDispCond(cfi.cond);
11167 case IF_DR_3A: // DR_3A X..........mmmmm ......nnnnnmmmmm Rd Rn Rm
11168 if ((ins == INS_add) || (ins == INS_sub))
11170 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11171 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11173 else if ((ins == INS_smull) || (ins == INS_smulh))
11175 // Rd is always 8 bytes
11176 emitDispReg(id->idReg1(), EA_8BYTE, true);
11178 // Rn, Rm effective size depends on instruction type
11179 size = (ins == INS_smulh) ? EA_8BYTE : EA_4BYTE;
11180 emitDispReg(id->idReg2(), size, true);
11184 emitDispReg(id->idReg1(), size, true);
11185 emitDispReg(id->idReg2(), size, true);
11187 if (id->idIsLclVar())
11189 emitDispReg(codeGen->rsGetRsvdReg(), size, false);
11193 emitDispReg(id->idReg3(), size, false);
11198 case IF_DR_3B: // DR_3B X.......sh.mmmmm ssssssnnnnnddddd Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
11199 emitDispReg(id->idReg1(), size, true);
11200 emitDispReg(id->idReg2(), size, true);
11201 emitDispShiftedReg(id->idReg3(), id->idInsOpt(), emitGetInsSC(id), size);
11204 case IF_DR_3C: // DR_3C X..........mmmmm ooosssnnnnnddddd Rd Rn Rm ext(Rm) LSL imm(0-4)
11205 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11206 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11207 imm = emitGetInsSC(id);
11208 emitDispExtendReg(id->idReg3(), id->idInsOpt(), imm);
11211 case IF_DR_3D: // DR_3D X..........mmmmm cccc..nnnnnmmmmm Rd Rn Rm cond
11212 emitDispReg(id->idReg1(), size, true);
11213 emitDispReg(id->idReg2(), size, true);
11214 emitDispReg(id->idReg3(), size, true);
11215 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11216 emitDispCond(cfi.cond);
11219 case IF_DR_3E: // DR_3E X........X.mmmmm ssssssnnnnnddddd Rd Rn Rm imm(0-63)
11220 emitDispReg(id->idReg1(), size, true);
11221 emitDispReg(id->idReg2(), size, true);
11222 emitDispReg(id->idReg3(), size, true);
11223 emitDispImm(emitGetInsSC(id), false);
11226 case IF_DR_4A: // DR_4A X..........mmmmm .aaaaannnnnmmmmm Rd Rn Rm Ra
11227 emitDispReg(id->idReg1(), size, true);
11228 emitDispReg(id->idReg2(), size, true);
11229 emitDispReg(id->idReg3(), size, true);
11230 emitDispReg(id->idReg4(), size, false);
11233 case IF_DV_1A: // DV_1A .........X.iiiii iii........ddddd Vd imm8 (fmov - immediate scalar)
11234 elemsize = id->idOpSize();
11235 emitDispReg(id->idReg1(), elemsize, true);
11236 emitDispFloatImm(emitGetInsSC(id));
11239 case IF_DV_1B: // DV_1B .QX..........iii cmod..iiiiiddddd Vd imm8 (immediate vector)
11240 imm = emitGetInsSC(id) & 0x0ff;
11241 immShift = (emitGetInsSC(id) & 0x700) >> 8;
11242 hasShift = (immShift != 0);
11243 elemsize = optGetElemsize(id->idInsOpt());
11244 if (id->idInsOpt() == INS_OPTS_1D)
11246 assert(elemsize == size);
11247 emitDispReg(id->idReg1(), size, true);
11251 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11253 if (ins == INS_fmov)
11255 emitDispFloatImm(imm);
11256 assert(hasShift == false);
11260 if (elemsize == EA_8BYTE)
11262 assert(ins == INS_movi);
11264 const ssize_t mask8 = 0xFF;
11265 for (unsigned b = 0; b < 8; b++)
11267 if (imm & (1 << b))
11269 imm64 |= (mask8 << (b * 8));
11272 emitDispImm(imm64, hasShift, true);
11276 emitDispImm(imm, hasShift, true);
11280 insOpts opt = (immShift & 0x4) ? INS_OPTS_MSL : INS_OPTS_LSL;
11281 unsigned shift = (immShift & 0x3) * 8;
11282 emitDispShiftOpts(opt);
11283 emitDispImm(shift, false);
11288 case IF_DV_1C: // DV_1C .........X...... ......nnnnn..... Vn #0.0 (fcmp - with zero)
11289 elemsize = id->idOpSize();
11290 emitDispReg(id->idReg1(), elemsize, true);
11291 emitDispFloatZero();
11294 case IF_DV_2A: // DV_2A .Q.......X...... ......nnnnnddddd Vd Vn (fabs, fcvt - vector)
11295 case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
11296 case IF_DV_2P: // DV_2P ................ ......nnnnnddddd Vd Vn (aes*, sha1su1)
11297 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11298 emitDispVectorReg(id->idReg2(), id->idInsOpt(), false);
11301 case IF_DV_2N: // DV_2N .........iiiiiii ......nnnnnddddd Vd Vn imm (shift - scalar)
11302 elemsize = id->idOpSize();
11303 emitDispReg(id->idReg1(), elemsize, true);
11304 emitDispReg(id->idReg2(), elemsize, true);
11305 emitDispImm(emitGetInsSC(id), false);
11308 case IF_DV_2O: // DV_2O .Q.......iiiiiii ......nnnnnddddd Vd Vn imm (shift - vector)
11309 imm = emitGetInsSC(id);
11310 // Do we have a sxtl or uxtl instruction?
11311 isExtendAlias = ((ins == INS_sxtl) || (ins == INS_sxtl2) || (ins == INS_uxtl) || (ins == INS_uxtl2));
11312 code = emitInsCode(ins, fmt);
11313 if (code & 0x00008000) // widen/narrow opcodes
11315 if (code & 0x00002000) // SHL opcodes
11317 emitDispVectorReg(id->idReg1(), optWidenElemsize(id->idInsOpt()), true);
11318 emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11320 else // SHR opcodes
11322 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11323 emitDispVectorReg(id->idReg2(), optWidenElemsize(id->idInsOpt()), !isExtendAlias);
11328 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11329 emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11331 // Print the immediate unless we have a sxtl or uxtl instruction
11332 if (!isExtendAlias)
11334 emitDispImm(imm, false);
11338 case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov/smov - to general)
11339 srcsize = id->idOpSize();
11340 index = emitGetInsSC(id);
11341 if (ins == INS_smov)
11343 dstsize = EA_8BYTE;
11345 else // INS_umov or INS_mov
11347 dstsize = (srcsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE;
11349 emitDispReg(id->idReg1(), dstsize, true);
11350 emitDispVectorRegIndex(id->idReg2(), srcsize, index, false);
11353 case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
11354 if (ins == INS_dup)
11356 datasize = id->idOpSize();
11357 assert(isValidVectorDatasize(datasize));
11358 assert(isValidArrangement(datasize, id->idInsOpt()));
11359 elemsize = optGetElemsize(id->idInsOpt());
11360 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11364 elemsize = id->idOpSize();
11365 index = emitGetInsSC(id);
11366 assert(isValidVectorElemsize(elemsize));
11367 emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11369 emitDispReg(id->idReg2(), (elemsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE, false);
11372 case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
11373 datasize = id->idOpSize();
11374 assert(isValidVectorDatasize(datasize));
11375 assert(isValidArrangement(datasize, id->idInsOpt()));
11376 elemsize = optGetElemsize(id->idInsOpt());
11377 index = emitGetInsSC(id);
11378 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11379 emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11382 case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
11383 elemsize = id->idOpSize();
11384 index = emitGetInsSC(id);
11385 emitDispReg(id->idReg1(), elemsize, true);
11386 emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11389 case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
11390 imm = emitGetInsSC(id);
11391 index = (imm >> 4) & 0xf;
11392 index2 = imm & 0xf;
11393 elemsize = id->idOpSize();
11394 emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11395 emitDispVectorRegIndex(id->idReg2(), elemsize, index2, false);
11398 case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov, fcvtXX - register)
11399 case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
11400 case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
11401 elemsize = id->idOpSize();
11402 emitDispReg(id->idReg1(), elemsize, true);
11403 emitDispReg(id->idReg2(), elemsize, false);
11406 case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov, fcvtXX - to general)
11407 case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov, Xcvtf - from general)
11408 case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
11409 dstsize = optGetDstsize(id->idInsOpt());
11410 srcsize = optGetSrcsize(id->idInsOpt());
11412 emitDispReg(id->idReg1(), dstsize, true);
11413 emitDispReg(id->idReg2(), srcsize, false);
11416 case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11417 case IF_DV_3B: // DV_3B .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11418 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11419 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11420 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11423 case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11424 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11425 if (ins != INS_mov)
11427 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11429 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11432 case IF_DV_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
11433 case IF_DV_3BI: // DV_3BI .Q........Lmmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
11434 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11435 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11436 elemsize = optGetElemsize(id->idInsOpt());
11437 emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11440 case IF_DV_3D: // DV_3D .........X.mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
11441 case IF_DV_3E: // DV_3E ...........mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
11442 emitDispReg(id->idReg1(), size, true);
11443 emitDispReg(id->idReg2(), size, true);
11444 emitDispReg(id->idReg3(), size, false);
11447 case IF_DV_3F: // DV_3F ..........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11448 if ((ins == INS_sha1c) || (ins == INS_sha1m) || (ins == INS_sha1p))
11450 // Qd, Sn, Vm (vector)
11451 emitDispReg(id->idReg1(), size, true);
11452 emitDispReg(id->idReg2(), EA_4BYTE, true);
11453 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11455 else if ((ins == INS_sha256h) || (ins == INS_sha256h2))
11457 // Qd Qn Vm (vector)
11458 emitDispReg(id->idReg1(), size, true);
11459 emitDispReg(id->idReg2(), size, true);
11460 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11462 else // INS_sha1su0, INS_sha256su1
11464 // Vd, Vn, Vm (vector)
11465 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11466 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11467 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11471 case IF_DV_3DI: // DV_3DI .........XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (scalar by elem)
11472 emitDispReg(id->idReg1(), size, true);
11473 emitDispReg(id->idReg2(), size, true);
11475 emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11478 case IF_DV_4A: // DV_4A .........X.mmmmm .aaaaannnnnddddd Vd Va Vn Vm (scalar)
11479 emitDispReg(id->idReg1(), size, true);
11480 emitDispReg(id->idReg2(), size, true);
11481 emitDispReg(id->idReg3(), size, true);
11482 emitDispReg(id->idReg4(), size, false);
11485 case IF_SN_0A: // SN_0A ................ ................
11488 case IF_SI_0A: // SI_0A ...........iiiii iiiiiiiiiii..... imm16
11489 emitDispImm(emitGetInsSC(id), false);
11492 case IF_SI_0B: // SI_0B ................ ....bbbb........ imm4 - barrier
11493 emitDispBarrier((insBarrier)emitGetInsSC(id));
11497 printf("unexpected format %s", emitIfName(id->idInsFmt()));
11498 assert(!"unexpectedFormat");
11502 if (id->idDebugOnlyInfo()->idVarRefOffs)
11505 emitDispFrameRef(id->idAddr()->iiaLclVar.lvaVarNum(), id->idAddr()->iiaLclVar.lvaOffset(),
11506 id->idDebugOnlyInfo()->idVarRefOffs, asmfm);
11512 /*****************************************************************************
11514 * Display a stack frame reference.
11517 void emitter::emitDispFrameRef(int varx, int disp, int offs, bool asmfm)
11522 printf("TEMP_%02u", -varx);
11524 emitComp->gtDispLclVar(+varx, false);
11527 printf("-0x%02x", -disp);
11529 printf("+0x%02x", +disp);
11533 if (varx >= 0 && emitComp->opts.varNames)
11536 const char* varName;
11538 assert((unsigned)varx < emitComp->lvaCount);
11539 varDsc = emitComp->lvaTable + varx;
11540 varName = emitComp->compLocalVarName(varx, offs);
11544 printf("'%s", varName);
11547 printf("-%d", -disp);
11549 printf("+%d", +disp);
11558 // Generate code for a load or store operation with a potentially complex addressing mode
11559 // This method handles the case of a GT_IND with contained GT_LEA op1 of the x86 form [base + index*sccale + offset]
11560 // Since Arm64 does not directly support this complex of an addressing mode
11561 // we may generates up to three instructions for this for Arm64
11563 void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataReg, GenTreeIndir* indir)
11565 emitAttr ldstAttr = isVectorRegister(dataReg) ? attr : emitInsAdjustLoadStoreAttr(ins, attr);
11567 GenTree* addr = indir->Addr();
11569 if (addr->isContained())
11571 assert(addr->OperGet() == GT_LCL_VAR_ADDR || addr->OperGet() == GT_LEA);
11576 if (addr->OperGet() == GT_LEA)
11578 offset = addr->AsAddrMode()->Offset();
11579 if (addr->AsAddrMode()->gtScale > 0)
11581 assert(isPow2(addr->AsAddrMode()->gtScale));
11582 BitScanForward(&lsl, addr->AsAddrMode()->gtScale);
11586 GenTree* memBase = indir->Base();
11588 if (indir->HasIndex())
11590 GenTree* index = indir->Index();
11594 regNumber tmpReg = indir->GetSingleTempReg();
11596 emitAttr addType = varTypeIsGC(memBase) ? EA_BYREF : EA_PTRSIZE;
11598 if (emitIns_valid_imm_for_add(offset, EA_8BYTE))
11602 // Generate code to set tmpReg = base + index*scale
11603 emitIns_R_R_R_I(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum, lsl,
11608 // Generate code to set tmpReg = base + index
11609 emitIns_R_R_R(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum);
11612 noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11614 // Then load/store dataReg from/to [tmpReg + offset]
11615 emitIns_R_R_I(ins, ldstAttr, dataReg, tmpReg, offset);
11617 else // large offset
11619 // First load/store tmpReg with the large offset constant
11620 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11621 // Then add the base register
11623 emitIns_R_R_R(INS_add, addType, tmpReg, tmpReg, memBase->gtRegNum);
11625 noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11626 noway_assert(tmpReg != index->gtRegNum);
11628 // Then load/store dataReg from/to [tmpReg + index*scale]
11629 emitIns_R_R_R_I(ins, ldstAttr, dataReg, tmpReg, index->gtRegNum, lsl, INS_OPTS_LSL);
11632 else // (offset == 0)
11636 // Then load/store dataReg from/to [memBase + index*scale]
11637 emitIns_R_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum, lsl, INS_OPTS_LSL);
11641 // Then load/store dataReg from/to [memBase + index]
11642 emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum);
11646 else // no Index register
11648 if (emitIns_valid_imm_for_ldst_offset(offset, EA_SIZE(attr)))
11650 // Then load/store dataReg from/to [memBase + offset]
11651 emitIns_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, offset);
11655 // We require a tmpReg to hold the offset
11656 regNumber tmpReg = indir->GetSingleTempReg();
11658 // First load/store tmpReg with the large offset constant
11659 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11661 // Then load/store dataReg from/to [memBase + tmpReg]
11662 emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, tmpReg);
11666 else // addr is not contained, so we evaluate it into a register
11668 // Then load/store dataReg from/to [addrReg]
11669 emitIns_R_R(ins, ldstAttr, dataReg, addr->gtRegNum);
11673 // The callee must call genConsumeReg() for any non-contained srcs
11674 // and genProduceReg() for any non-contained dsts.
11676 regNumber emitter::emitInsBinary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src)
11678 regNumber result = REG_NA;
11680 // dst can only be a reg
11681 assert(!dst->isContained());
11683 // src can be immed or reg
11684 assert(!src->isContained() || src->isContainedIntOrIImmed());
11686 // find immed (if any) - it cannot be a dst
11687 GenTreeIntConCommon* intConst = nullptr;
11688 if (src->isContainedIntOrIImmed())
11690 intConst = src->AsIntConCommon();
11695 emitIns_R_I(ins, attr, dst->gtRegNum, intConst->IconValue());
11696 return dst->gtRegNum;
11700 emitIns_R_R(ins, attr, dst->gtRegNum, src->gtRegNum);
11701 return dst->gtRegNum;
11705 // The callee must call genConsumeReg() for any non-contained srcs
11706 // and genProduceReg() for any non-contained dsts.
11708 regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src1, GenTree* src2)
11710 regNumber result = REG_NA;
11712 // dst can only be a reg
11713 assert(!dst->isContained());
11715 // find immed (if any) - it cannot be a dst
11716 // Only one src can be an int.
11717 GenTreeIntConCommon* intConst = nullptr;
11718 GenTree* nonIntReg = nullptr;
11720 if (varTypeIsFloating(dst))
11722 // src1 can only be a reg
11723 assert(!src1->isContained());
11724 // src2 can only be a reg
11725 assert(!src2->isContained());
11727 else // not floating point
11729 // src2 can be immed or reg
11730 assert(!src2->isContained() || src2->isContainedIntOrIImmed());
11732 // Check src2 first as we can always allow it to be a contained immediate
11733 if (src2->isContainedIntOrIImmed())
11735 intConst = src2->AsIntConCommon();
11738 // Only for commutative operations do we check src1 and allow it to be a contained immediate
11739 else if (dst->OperIsCommutative())
11741 // src1 can be immed or reg
11742 assert(!src1->isContained() || src1->isContainedIntOrIImmed());
11744 // Check src1 and allow it to be a contained immediate
11745 if (src1->isContainedIntOrIImmed())
11747 assert(!src2->isContainedIntOrIImmed());
11748 intConst = src1->AsIntConCommon();
11754 // src1 can only be a reg
11755 assert(!src1->isContained());
11759 bool isMulOverflow = false;
11760 if (dst->gtOverflowEx())
11762 if ((ins == INS_add) || (ins == INS_adds))
11766 else if ((ins == INS_sub) || (ins == INS_subs))
11770 else if (ins == INS_mul)
11772 isMulOverflow = true;
11773 assert(intConst == nullptr); // overflow format doesn't support an int constant operand
11777 assert(!"Invalid ins for overflow check");
11780 if (intConst != nullptr)
11782 emitIns_R_R_I(ins, attr, dst->gtRegNum, nonIntReg->gtRegNum, intConst->IconValue());
11788 regNumber extraReg = dst->GetSingleTempReg();
11789 assert(extraReg != dst->gtRegNum);
11791 if ((dst->gtFlags & GTF_UNSIGNED) != 0)
11793 if (attr == EA_4BYTE)
11795 // Compute 8 byte results from 4 byte by 4 byte multiplication.
11796 emitIns_R_R_R(INS_umull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11798 // Get the high result by shifting dst.
11799 emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11803 assert(attr == EA_8BYTE);
11804 // Compute the high result.
11805 emitIns_R_R_R(INS_umulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11807 // Now multiply without skewing the high result.
11808 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11811 // zero-sign bit comparison to detect overflow.
11812 emitIns_R_I(INS_cmp, attr, extraReg, 0);
11817 if (attr == EA_4BYTE)
11819 // Compute 8 byte results from 4 byte by 4 byte multiplication.
11820 emitIns_R_R_R(INS_smull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11822 // Get the high result by shifting dst.
11823 emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11829 assert(attr == EA_8BYTE);
11830 // Save the high result in a temporary register.
11831 emitIns_R_R_R(INS_smulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11833 // Now multiply without skewing the high result.
11834 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11839 // Sign bit comparison to detect overflow.
11840 emitIns_R_R_I(INS_cmp, attr, extraReg, dst->gtRegNum, bitShift, INS_OPTS_ASR);
11845 // We can just multiply.
11846 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11850 if (dst->gtOverflowEx())
11852 assert(!varTypeIsFloating(dst));
11853 codeGen->genCheckOverflow(dst);
11856 return dst->gtRegNum;
11859 #endif // defined(_TARGET_ARM64_)