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 if (emitIsScnsInsDsc(id))
93 return SMALL_IDSC_SIZE;
95 assert((unsigned)id->idInsFmt() < emitFmtCount);
97 ID_OPS idOp = (ID_OPS)emitFmtToOps[id->idInsFmt()];
98 bool isCallIns = (id->idIns() == INS_bl) || (id->idIns() == INS_blr) || (id->idIns() == INS_b_tail) ||
99 (id->idIns() == INS_br_tail);
100 bool maybeCallIns = (id->idIns() == INS_b) || (id->idIns() == INS_br);
108 return sizeof(instrDescJmp);
111 assert(isCallIns || maybeCallIns);
112 if (id->idIsLargeCall())
114 /* Must be a "fat" call descriptor */
115 return sizeof(instrDescCGCA);
119 assert(!id->idIsLargeDsp());
120 assert(!id->idIsLargeCns());
121 return sizeof(instrDesc);
126 NO_WAY("unexpected instruction descriptor format");
130 if (id->idIsLargeCns())
132 if (id->idIsLargeDsp())
133 return sizeof(instrDescCnsDsp);
135 return sizeof(instrDescCns);
139 if (id->idIsLargeDsp())
140 return sizeof(instrDescDsp);
142 return sizeof(instrDesc);
147 /*****************************************************************************
149 * The following called for each recorded instruction -- use for debugging.
151 void emitter::emitInsSanityCheck(instrDesc* id)
153 /* What instruction format have we got? */
155 switch (id->idInsFmt())
167 case IF_BI_0A: // BI_0A ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
170 case IF_BI_0B: // BI_0B ......iiiiiiiiii iiiiiiiiiiii.... simm19:00
178 case IF_BI_0C: // BI_0C ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
181 case IF_BI_1A: // BI_1A ......iiiiiiiiii iiiiiiiiiiittttt Rt simm19:00
182 assert(isValidGeneralDatasize(id->idOpSize()));
183 assert(isGeneralRegister(id->idReg1()));
186 case IF_BI_1B: // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
187 assert(isValidGeneralDatasize(id->idOpSize()));
188 assert(isGeneralRegister(id->idReg1()));
189 assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
192 case IF_BR_1A: // BR_1A ................ ......nnnnn..... Rn
193 assert(isGeneralRegister(id->idReg1()));
196 case IF_BR_1B: // BR_1B ................ ......nnnnn..... Rn
197 assert(isGeneralRegister(id->idReg3()));
200 case IF_LS_1A: // LS_1A .X......iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB)
201 assert(isGeneralRegister(id->idReg1()) || isVectorRegister(id->idReg1()));
202 assert(insOptsNone(id->idInsOpt()));
205 case IF_LS_2A: // LS_2A .X.......X...... ......nnnnnttttt Rt Rn
206 assert(isIntegerRegister(id->idReg1()) || // ZR
207 isVectorRegister(id->idReg1()));
208 assert(isIntegerRegister(id->idReg2())); // SP
209 assert(emitGetInsSC(id) == 0);
210 assert(insOptsNone(id->idInsOpt()));
213 case IF_LS_2B: // LS_2B .X.......Xiiiiii iiiiiinnnnnttttt Rt Rn imm(0-4095)
214 assert(isIntegerRegister(id->idReg1()) || // ZR
215 isVectorRegister(id->idReg1()));
216 assert(isIntegerRegister(id->idReg2())); // SP
217 assert(isValidUimm12(emitGetInsSC(id)));
218 assert(insOptsNone(id->idInsOpt()));
221 case IF_LS_2C: // LS_2C .X.......X.iiiii iiiiPPnnnnnttttt Rt Rn imm(-256..+255) no/pre/post inc
222 assert(isIntegerRegister(id->idReg1()) || // ZR
223 isVectorRegister(id->idReg1()));
224 assert(isIntegerRegister(id->idReg2())); // SP
225 assert(emitGetInsSC(id) >= -0x100);
226 assert(emitGetInsSC(id) < 0x100);
227 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
230 case IF_LS_3A: // LS_3A .X.......X.mmmmm oooS..nnnnnttttt Rt Rn Rm ext(Rm) LSL {}
231 assert(isIntegerRegister(id->idReg1()) || // ZR
232 isVectorRegister(id->idReg1()));
233 assert(isIntegerRegister(id->idReg2())); // SP
234 if (id->idIsLclVar())
236 assert(isGeneralRegister(codeGen->rsGetRsvdReg()));
240 assert(isGeneralRegister(id->idReg3()));
242 assert(insOptsLSExtend(id->idInsOpt()));
245 case IF_LS_3B: // LS_3B X............... .aaaaannnnnttttt Rt Ra Rn
246 assert((isValidGeneralDatasize(id->idOpSize()) && isIntegerRegister(id->idReg1())) ||
247 (isValidVectorLSPDatasize(id->idOpSize()) && isVectorRegister(id->idReg1())));
248 assert(isIntegerRegister(id->idReg1()) || // ZR
249 isVectorRegister(id->idReg1()));
250 assert(isIntegerRegister(id->idReg2()) || // ZR
251 isVectorRegister(id->idReg2()));
252 assert(isIntegerRegister(id->idReg3())); // SP
253 assert(emitGetInsSC(id) == 0);
254 assert(insOptsNone(id->idInsOpt()));
257 case IF_LS_3C: // LS_3C X.........iiiiii iaaaaannnnnttttt Rt Ra Rn imm(im7,sh)
258 assert((isValidGeneralDatasize(id->idOpSize()) && isIntegerRegister(id->idReg1())) ||
259 (isValidVectorLSPDatasize(id->idOpSize()) && isVectorRegister(id->idReg1())));
260 assert(isIntegerRegister(id->idReg1()) || // ZR
261 isVectorRegister(id->idReg1()));
262 assert(isIntegerRegister(id->idReg2()) || // ZR
263 isVectorRegister(id->idReg2()));
264 assert(isIntegerRegister(id->idReg3())); // SP
265 assert(emitGetInsSC(id) >= -0x40);
266 assert(emitGetInsSC(id) < 0x40);
267 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
270 case IF_LS_3D: // LS_3D .X.......X.mmmmm ......nnnnnttttt Wm Rt Rn
271 assert(isIntegerRegister(id->idReg1()));
272 assert(isIntegerRegister(id->idReg2()));
273 assert(isIntegerRegister(id->idReg3()));
274 assert(emitGetInsSC(id) == 0);
275 assert(!id->idIsLclVar());
276 assert(insOptsNone(id->idInsOpt()));
279 case IF_LS_3E: // LS_3E .X.........mmmmm ......nnnnnttttt Rm Rt Rn ARMv8.1 LSE Atomics
280 assert(isIntegerRegister(id->idReg1()));
281 assert(isIntegerRegister(id->idReg2()));
282 assert(isIntegerRegister(id->idReg3()));
283 assert(emitGetInsSC(id) == 0);
284 assert(!id->idIsLclVar());
285 assert(insOptsNone(id->idInsOpt()));
288 case IF_DI_1A: // DI_1A X.......shiiiiii iiiiiinnnnn..... Rn imm(i12,sh)
289 assert(isValidGeneralDatasize(id->idOpSize()));
290 assert(isGeneralRegister(id->idReg1()));
291 assert(isValidUimm12(emitGetInsSC(id)));
292 assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
295 case IF_DI_1B: // DI_1B X........hwiiiii iiiiiiiiiiiddddd Rd imm(i16,hw)
296 assert(isValidGeneralDatasize(id->idOpSize()));
297 assert(isGeneralRegister(id->idReg1()));
298 assert(isValidImmHWVal(emitGetInsSC(id), id->idOpSize()));
301 case IF_DI_1C: // DI_1C X........Nrrrrrr ssssssnnnnn..... Rn imm(N,r,s)
302 assert(isValidGeneralDatasize(id->idOpSize()));
303 assert(isGeneralRegister(id->idReg1()));
304 assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
307 case IF_DI_1D: // DI_1D X........Nrrrrrr ssssss.....ddddd Rd imm(N,r,s)
308 assert(isValidGeneralDatasize(id->idOpSize()));
309 assert(isIntegerRegister(id->idReg1())); // SP
310 assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
313 case IF_DI_1E: // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
314 assert(isGeneralRegister(id->idReg1()));
317 case IF_DI_1F: // DI_1F X..........iiiii cccc..nnnnn.nzcv Rn imm5 nzcv cond
318 assert(isValidGeneralDatasize(id->idOpSize()));
319 assert(isGeneralRegister(id->idReg1()));
320 assert(isValidImmCondFlagsImm5(emitGetInsSC(id)));
323 case IF_DI_2A: // DI_2A X.......shiiiiii iiiiiinnnnnddddd Rd Rn imm(i12,sh)
324 assert(isValidGeneralDatasize(id->idOpSize()));
325 assert(isIntegerRegister(id->idReg1())); // SP
326 assert(isIntegerRegister(id->idReg2())); // SP
327 assert(isValidUimm12(emitGetInsSC(id)));
328 assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
331 case IF_DI_2B: // DI_2B X.........Xnnnnn ssssssnnnnnddddd Rd Rn imm(0-63)
332 assert(isValidGeneralDatasize(id->idOpSize()));
333 assert(isGeneralRegister(id->idReg1()));
334 assert(isGeneralRegister(id->idReg2()));
335 assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
338 case IF_DI_2C: // DI_2C X........Nrrrrrr ssssssnnnnnddddd Rd Rn imm(N,r,s)
339 assert(isValidGeneralDatasize(id->idOpSize()));
340 assert(isIntegerRegister(id->idReg1())); // SP
341 assert(isGeneralRegister(id->idReg2()));
342 assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
345 case IF_DI_2D: // DI_2D X........Nrrrrrr ssssssnnnnnddddd Rd Rn imr, imms (N,r,s)
346 assert(isValidGeneralDatasize(id->idOpSize()));
347 assert(isGeneralRegister(id->idReg1()));
348 assert(isGeneralRegister(id->idReg2()));
349 assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
352 case IF_DR_1D: // DR_1D X............... cccc.......ddddd Rd cond
353 assert(isValidGeneralDatasize(id->idOpSize()));
354 assert(isGeneralRegister(id->idReg1()));
355 assert(isValidImmCond(emitGetInsSC(id)));
358 case IF_DR_2A: // DR_2A X..........mmmmm ......nnnnn..... Rn Rm
359 assert(isValidGeneralDatasize(id->idOpSize()));
360 assert(isGeneralRegister(id->idReg1()));
361 assert(isGeneralRegister(id->idReg2()));
364 case IF_DR_2B: // DR_2B X.......sh.mmmmm ssssssnnnnn..... Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
365 assert(isValidGeneralDatasize(id->idOpSize()));
366 assert(isIntegerRegister(id->idReg1())); // ZR
367 assert(isGeneralRegister(id->idReg2()));
368 assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
369 if (!insOptsNone(id->idInsOpt()))
371 if (id->idIns() == INS_tst) // tst allows ROR, cmp/cmn don't
373 assert(insOptsAnyShift(id->idInsOpt()));
377 assert(insOptsAluShift(id->idInsOpt()));
380 assert(insOptsNone(id->idInsOpt()) || (emitGetInsSC(id) > 0));
383 case IF_DR_2C: // DR_2C X..........mmmmm ooosssnnnnn..... Rn Rm ext(Rm) LSL imm(0-4)
384 assert(isValidGeneralDatasize(id->idOpSize()));
385 assert(isIntegerRegister(id->idReg1())); // SP
386 assert(isGeneralRegister(id->idReg2()));
387 assert(insOptsNone(id->idInsOpt()) || insOptsLSL(id->idInsOpt()) || insOptsAnyExtend(id->idInsOpt()));
388 assert(emitGetInsSC(id) >= 0);
389 assert(emitGetInsSC(id) <= 4);
390 if (insOptsLSL(id->idInsOpt()))
392 assert(emitGetInsSC(id) > 0);
396 case IF_DR_2D: // DR_2D X..........nnnnn cccc..nnnnnmmmmm Rd Rn cond
397 assert(isValidGeneralDatasize(id->idOpSize()));
398 assert(isGeneralRegister(id->idReg1()));
399 assert(isGeneralRegister(id->idReg2()));
400 assert(isValidImmCond(emitGetInsSC(id)));
403 case IF_DR_2E: // DR_2E X..........mmmmm ...........ddddd Rd Rm
404 assert(isValidGeneralDatasize(id->idOpSize()));
405 assert(isGeneralRegister(id->idReg1()));
406 assert(isIntegerRegister(id->idReg2())); // ZR
409 case IF_DR_2F: // DR_2F X.......sh.mmmmm ssssss.....ddddd Rd Rm {LSL,LSR,ASR} imm(0-63)
410 assert(isValidGeneralDatasize(id->idOpSize()));
411 assert(isGeneralRegister(id->idReg1()));
412 assert(isGeneralRegister(id->idReg2()));
413 assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
414 assert(insOptsNone(id->idInsOpt()) || insOptsAluShift(id->idInsOpt()));
415 assert(insOptsNone(id->idInsOpt()) || (emitGetInsSC(id) > 0));
418 case IF_DR_2G: // DR_2G X............... ......nnnnnddddd Rd Rm
419 assert(isValidGeneralDatasize(id->idOpSize()));
420 assert(isIntegerRegister(id->idReg1())); // SP
421 assert(isIntegerRegister(id->idReg2())); // SP
424 case IF_DR_2H: // DR_2H X........X...... ......nnnnnddddd Rd Rn
425 assert(isValidGeneralDatasize(id->idOpSize()));
426 assert(isGeneralRegister(id->idReg1()));
427 assert(isGeneralRegister(id->idReg2()));
430 case IF_DR_2I: // DR_2I X..........mmmmm cccc..nnnnn.nzcv Rn Rm nzcv cond
431 assert(isValidGeneralDatasize(id->idOpSize()));
432 assert(isGeneralRegister(id->idReg1()));
433 assert(isGeneralRegister(id->idReg2()));
434 assert(isValidImmCondFlags(emitGetInsSC(id)));
437 case IF_DR_2J: // DR_2J ................ ......nnnnnddddd Sd Sn (sha1h)
438 assert(isValidGeneralDatasize(id->idOpSize()));
439 assert(isVectorRegister(id->idReg1()));
440 assert(isVectorRegister(id->idReg2()));
443 case IF_DR_3A: // DR_3A X..........mmmmm ......nnnnnmmmmm Rd Rn Rm
444 assert(isValidGeneralDatasize(id->idOpSize()));
445 assert(isIntegerRegister(id->idReg1())); // SP
446 assert(isIntegerRegister(id->idReg2())); // SP
447 if (id->idIsLclVar())
449 assert(isGeneralRegister(codeGen->rsGetRsvdReg()));
453 assert(isGeneralRegister(id->idReg3()));
455 assert(insOptsNone(id->idInsOpt()));
458 case IF_DR_3B: // DR_3B X.......sh.mmmmm ssssssnnnnnddddd Rd Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
459 assert(isValidGeneralDatasize(id->idOpSize()));
460 assert(isGeneralRegister(id->idReg1()));
461 assert(isGeneralRegister(id->idReg2()));
462 assert(isGeneralRegister(id->idReg3()));
463 assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
464 assert(insOptsNone(id->idInsOpt()) || insOptsAnyShift(id->idInsOpt()));
465 assert(insOptsNone(id->idInsOpt()) || (emitGetInsSC(id) > 0));
468 case IF_DR_3C: // DR_3C X..........mmmmm ooosssnnnnnddddd Rd Rn Rm ext(Rm) LSL imm(0-4)
469 assert(isValidGeneralDatasize(id->idOpSize()));
470 assert(isIntegerRegister(id->idReg1())); // SP
471 assert(isIntegerRegister(id->idReg2())); // SP
472 assert(isGeneralRegister(id->idReg3()));
473 assert(insOptsNone(id->idInsOpt()) || insOptsLSL(id->idInsOpt()) || insOptsAnyExtend(id->idInsOpt()));
474 assert(emitGetInsSC(id) >= 0);
475 assert(emitGetInsSC(id) <= 4);
476 if (insOptsLSL(id->idInsOpt()))
478 assert((emitGetInsSC(id) > 0) ||
479 (id->idReg2() == REG_ZR)); // REG_ZR encodes SP and we allow a shift of zero
483 case IF_DR_3D: // DR_3D X..........mmmmm cccc..nnnnnmmmmm Rd Rn Rm cond
484 assert(isValidGeneralDatasize(id->idOpSize()));
485 assert(isGeneralRegister(id->idReg1()));
486 assert(isGeneralRegister(id->idReg2()));
487 assert(isGeneralRegister(id->idReg3()));
488 assert(isValidImmCond(emitGetInsSC(id)));
491 case IF_DR_3E: // DR_3E X........X.mmmmm ssssssnnnnnddddd Rd Rn Rm imm(0-63)
492 assert(isValidGeneralDatasize(id->idOpSize()));
493 assert(isGeneralRegister(id->idReg1()));
494 assert(isGeneralRegister(id->idReg2()));
495 assert(isGeneralRegister(id->idReg3()));
496 assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
497 assert(insOptsNone(id->idInsOpt()));
500 case IF_DR_4A: // DR_4A X..........mmmmm .aaaaannnnnddddd Rd Rn Rm Ra
501 assert(isValidGeneralDatasize(id->idOpSize()));
502 assert(isGeneralRegister(id->idReg1()));
503 assert(isGeneralRegister(id->idReg2()));
504 assert(isGeneralRegister(id->idReg3()));
505 assert(isGeneralRegister(id->idReg4()));
508 case IF_DV_1A: // DV_1A .........X.iiiii iii........ddddd Vd imm8 (fmov - immediate scalar)
509 assert(insOptsNone(id->idInsOpt()));
510 elemsize = id->idOpSize();
511 assert(isValidVectorElemsizeFloat(elemsize));
512 assert(isVectorRegister(id->idReg1()));
513 assert(isValidUimm8(emitGetInsSC(id)));
516 case IF_DV_1B: // DV_1B .QX..........iii cmod..iiiiiddddd Vd imm8 (immediate vector)
518 imm = emitGetInsSC(id) & 0x0ff;
519 immShift = (emitGetInsSC(id) & 0x700) >> 8;
520 assert(immShift >= 0);
521 datasize = id->idOpSize();
522 assert(isValidVectorDatasize(datasize));
523 assert(isValidArrangement(datasize, id->idInsOpt()));
524 elemsize = optGetElemsize(id->idInsOpt());
527 assert(isValidVectorElemsizeFloat(elemsize));
528 assert(id->idInsOpt() != INS_OPTS_1D); // Reserved encoding
529 assert(immShift == 0);
533 assert(isValidVectorElemsize(elemsize));
534 assert((immShift != 4) && (immShift != 7)); // always invalid values
535 if (ins != INS_movi) // INS_mvni, INS_orr, INS_bic
537 assert((elemsize != EA_1BYTE) && (elemsize != EA_8BYTE)); // only H or S
538 if (elemsize == EA_2BYTE)
540 assert(immShift < 2);
542 else // (elemsize == EA_4BYTE)
546 assert(immShift < 4);
551 assert(isVectorRegister(id->idReg1()));
552 assert(isValidUimm8(imm));
555 case IF_DV_1C: // DV_1C .........X...... ......nnnnn..... Vn #0.0 (fcmp - with zero)
556 assert(insOptsNone(id->idInsOpt()));
557 elemsize = id->idOpSize();
558 assert(isValidVectorElemsizeFloat(elemsize));
559 assert(isVectorRegister(id->idReg1()));
562 case IF_DV_2A: // DV_2A .Q.......X...... ......nnnnnddddd Vd Vn (fabs, fcvt - vector)
563 case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
564 case IF_DV_2P: // DV_2P ................ ......nnnnnddddd Vd Vn (aes*, sha1su1)
565 assert(isValidVectorDatasize(id->idOpSize()));
566 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
567 assert(isVectorRegister(id->idReg1()));
568 assert(isVectorRegister(id->idReg2()));
571 case IF_DV_2N: // DV_2N .........iiiiiii ......nnnnnddddd Vd Vn imm (shift - scalar)
572 assert(id->idOpSize() == EA_8BYTE);
573 assert(insOptsNone(id->idInsOpt()));
574 assert(isVectorRegister(id->idReg1()));
575 assert(isVectorRegister(id->idReg2()));
576 assert(isValidImmShift(emitGetInsSC(id), EA_8BYTE));
579 case IF_DV_2O: // DV_2O .Q.......iiiiiii ......nnnnnddddd Vd Vn imm (shift - vector)
580 assert(isValidVectorDatasize(id->idOpSize()));
581 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
582 assert(isVectorRegister(id->idReg1()));
583 assert(isVectorRegister(id->idReg2()));
584 elemsize = optGetElemsize(id->idInsOpt());
585 assert(isValidImmShift(emitGetInsSC(id), elemsize));
588 case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov/smov - to general)
589 elemsize = id->idOpSize();
590 index = emitGetInsSC(id);
591 assert(insOptsNone(id->idInsOpt()));
592 assert(isValidVectorIndex(EA_16BYTE, elemsize, index));
593 assert(isValidVectorElemsize(elemsize));
594 assert(isGeneralRegister(id->idReg1()));
595 assert(isVectorRegister(id->idReg2()));
598 case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
599 if (id->idIns() == INS_dup)
601 datasize = id->idOpSize();
602 assert(isValidVectorDatasize(datasize));
603 assert(isValidArrangement(datasize, id->idInsOpt()));
604 elemsize = optGetElemsize(id->idInsOpt());
608 datasize = EA_16BYTE;
609 elemsize = id->idOpSize();
610 assert(isValidVectorElemsize(elemsize));
612 assert(isVectorRegister(id->idReg1()));
613 assert(isGeneralRegisterOrZR(id->idReg2()));
616 case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
617 datasize = id->idOpSize();
618 assert(isValidVectorDatasize(datasize));
619 assert(isValidArrangement(datasize, id->idInsOpt()));
620 elemsize = optGetElemsize(id->idInsOpt());
621 index = emitGetInsSC(id);
622 assert(isValidVectorIndex(datasize, elemsize, index));
623 assert(isVectorRegister(id->idReg1()));
624 assert(isVectorRegister(id->idReg2()));
627 case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
628 elemsize = id->idOpSize();
629 index = emitGetInsSC(id);
630 assert(isValidVectorIndex(EA_16BYTE, elemsize, index));
631 assert(isValidVectorElemsize(elemsize));
632 assert(isVectorRegister(id->idReg1()));
633 assert(isVectorRegister(id->idReg2()));
636 case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
637 imm = emitGetInsSC(id);
638 index = (imm >> 4) & 0xf;
640 elemsize = id->idOpSize();
641 assert(isValidVectorElemsize(elemsize));
642 assert(isValidVectorIndex(EA_16BYTE, elemsize, index));
643 assert(isValidVectorIndex(EA_16BYTE, elemsize, index2));
644 assert(isVectorRegister(id->idReg1()));
645 assert(isVectorRegister(id->idReg2()));
648 case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
649 assert(id->idOpSize() == EA_8BYTE); // only type D is supported
652 case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov, fcvtXX - register)
653 case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
654 assert(insOptsNone(id->idInsOpt()));
655 assert(isValidVectorElemsizeFloat(id->idOpSize()));
656 assert(isVectorRegister(id->idReg1()));
657 assert(isVectorRegister(id->idReg2()));
660 case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov/fcvtXX - to general)
661 assert(insOptsConvertFloatToInt(id->idInsOpt()));
662 dstsize = optGetDstsize(id->idInsOpt());
663 srcsize = optGetSrcsize(id->idInsOpt());
664 assert(isValidGeneralDatasize(dstsize));
665 assert(isValidVectorElemsizeFloat(srcsize));
666 assert(dstsize == id->idOpSize());
667 assert(isGeneralRegister(id->idReg1()));
668 assert(isVectorRegister(id->idReg2()));
671 case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov/Xcvtf - from general)
672 assert(insOptsConvertIntToFloat(id->idInsOpt()));
673 dstsize = optGetDstsize(id->idInsOpt());
674 srcsize = optGetSrcsize(id->idInsOpt());
675 assert(isValidGeneralDatasize(srcsize));
676 assert(isValidVectorElemsizeFloat(dstsize));
677 assert(dstsize == id->idOpSize());
678 assert(isVectorRegister(id->idReg1()));
679 assert(isGeneralRegister(id->idReg2()));
682 case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
683 assert(insOptsConvertFloatToFloat(id->idInsOpt()));
684 dstsize = optGetDstsize(id->idInsOpt());
685 srcsize = optGetSrcsize(id->idInsOpt());
686 assert(isValidVectorFcvtsize(srcsize));
687 assert(isValidVectorFcvtsize(dstsize));
688 assert(dstsize == id->idOpSize());
689 assert(isVectorRegister(id->idReg1()));
690 assert(isVectorRegister(id->idReg2()));
693 case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
694 assert(isValidVectorDatasize(id->idOpSize()));
695 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
696 assert(isVectorRegister(id->idReg1()));
697 assert(isVectorRegister(id->idReg2()));
698 assert(isVectorRegister(id->idReg3()));
699 elemsize = optGetElemsize(id->idInsOpt());
703 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
705 else if (ins == INS_pmul)
707 assert(elemsize == EA_1BYTE); // only supports 8B or 16B
711 case IF_DV_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
712 assert(isValidVectorDatasize(id->idOpSize()));
713 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
714 assert(isVectorRegister(id->idReg1()));
715 assert(isVectorRegister(id->idReg2()));
716 assert(isVectorRegister(id->idReg3()));
717 elemsize = optGetElemsize(id->idInsOpt());
718 assert(isValidVectorIndex(EA_16BYTE, elemsize, emitGetInsSC(id)));
719 // Only has encodings for H or S elemsize
720 assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE));
723 case IF_DV_3B: // DV_3B .Q.......X.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
724 assert(isValidVectorDatasize(id->idOpSize()));
725 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
726 assert(isVectorRegister(id->idReg1()));
727 assert(isVectorRegister(id->idReg2()));
728 assert(isVectorRegister(id->idReg3()));
731 case IF_DV_3BI: // DV_3BI .Q.......XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
732 assert(isValidVectorDatasize(id->idOpSize()));
733 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
734 assert(isVectorRegister(id->idReg1()));
735 assert(isVectorRegister(id->idReg2()));
736 assert(isVectorRegister(id->idReg3()));
737 elemsize = optGetElemsize(id->idInsOpt());
738 assert(isValidVectorIndex(id->idOpSize(), elemsize, emitGetInsSC(id)));
741 case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
742 assert(isValidVectorDatasize(id->idOpSize()));
743 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
744 assert(isVectorRegister(id->idReg1()));
745 assert(isVectorRegister(id->idReg2()));
746 assert(isVectorRegister(id->idReg3()));
749 case IF_DV_3D: // DV_3D .........X.mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
750 assert(isValidScalarDatasize(id->idOpSize()));
751 assert(insOptsNone(id->idInsOpt()));
752 assert(isVectorRegister(id->idReg1()));
753 assert(isVectorRegister(id->idReg2()));
754 assert(isVectorRegister(id->idReg3()));
757 case IF_DV_3DI: // DV_3DI .........XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (scalar by elem)
758 assert(isValidScalarDatasize(id->idOpSize()));
759 assert(insOptsNone(id->idInsOpt()));
760 assert(isVectorRegister(id->idReg1()));
761 assert(isVectorRegister(id->idReg2()));
762 assert(isVectorRegister(id->idReg3()));
763 elemsize = id->idOpSize();
764 assert(isValidVectorIndex(EA_16BYTE, elemsize, emitGetInsSC(id)));
767 case IF_DV_3E: // DV_3E ...........mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
768 assert(insOptsNone(id->idInsOpt()));
769 assert(id->idOpSize() == EA_8BYTE);
770 assert(isVectorRegister(id->idReg1()));
771 assert(isVectorRegister(id->idReg2()));
772 assert(isVectorRegister(id->idReg3()));
775 case IF_DV_3F: // DV_3F ...........mmmmm ......nnnnnddddd Vd Vn Vm
776 assert(isValidVectorDatasize(id->idOpSize()));
777 assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
778 assert(isVectorRegister(id->idReg1()));
779 assert(isVectorRegister(id->idReg2()));
780 assert(isVectorRegister(id->idReg3()));
783 case IF_DV_4A: // DR_4A .........X.mmmmm .aaaaannnnnddddd Rd Rn Rm Ra (scalar)
784 assert(isValidGeneralDatasize(id->idOpSize()));
785 assert(isVectorRegister(id->idReg1()));
786 assert(isVectorRegister(id->idReg2()));
787 assert(isVectorRegister(id->idReg3()));
788 assert(isVectorRegister(id->idReg4()));
791 case IF_SN_0A: // SN_0A ................ ................
792 case IF_SI_0A: // SI_0A ...........iiiii iiiiiiiiiii..... imm16
793 case IF_SI_0B: // SI_0B ................ ....bbbb........ imm4 - barrier
797 printf("unexpected format %s\n", emitIfName(id->idInsFmt()));
798 assert(!"Unexpected format");
804 bool emitter::emitInsMayWriteToGCReg(instrDesc* id)
806 instruction ins = id->idIns();
807 insFormat fmt = id->idInsFmt();
812 // These are the formats with "destination" registers:
814 case IF_DI_1B: // DI_1B X........hwiiiii iiiiiiiiiiiddddd Rd imm(i16,hw)
815 case IF_DI_1D: // DI_1D X........Nrrrrrr ssssss.....ddddd Rd imm(N,r,s)
816 case IF_DI_1E: // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
818 case IF_DI_2A: // DI_2A X.......shiiiiii iiiiiinnnnnddddd Rd Rn imm(i12,sh)
819 case IF_DI_2B: // DI_2B X.........Xnnnnn ssssssnnnnnddddd Rd Rn imm(0-63)
820 case IF_DI_2C: // DI_2C X........Nrrrrrr ssssssnnnnnddddd Rd Rn imm(N,r,s)
821 case IF_DI_2D: // DI_2D X........Nrrrrrr ssssssnnnnnddddd Rd Rn imr, imms (N,r,s)
823 case IF_DR_1D: // DR_1D X............... cccc.......ddddd Rd cond
825 case IF_DR_2D: // DR_2D X..........nnnnn cccc..nnnnnddddd Rd Rn cond
826 case IF_DR_2E: // DR_2E X..........mmmmm ...........ddddd Rd Rm
827 case IF_DR_2F: // DR_2F X.......sh.mmmmm ssssss.....ddddd Rd Rm {LSL,LSR,ASR} imm(0-63)
828 case IF_DR_2G: // DR_2G X............... ......nnnnnddddd Rd Rn
829 case IF_DR_2H: // DR_2H X........X...... ......nnnnnddddd Rd Rn
831 case IF_DR_3A: // DR_3A X..........mmmmm ......nnnnnddddd Rd Rn Rm
832 case IF_DR_3B: // DR_3B X.......sh.mmmmm ssssssnnnnnddddd Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
833 case IF_DR_3C: // DR_3C X..........mmmmm xxxsssnnnnnddddd Rd Rn Rm ext(Rm) LSL imm(0-4)
834 case IF_DR_3D: // DR_3D X..........mmmmm cccc..nnnnnddddd Rd Rn Rm cond
835 case IF_DR_3E: // DR_3E X........X.mmmmm ssssssnnnnnddddd Rd Rn Rm imm(0-63)
836 case IF_DV_3F: // DV_3F ...........mmmmm ......nnnnnddddd Vd Vn Vm (vector) - Vd both source and dest
838 case IF_DR_4A: // DR_4A X..........mmmmm .aaaaannnnnddddd Rd Rn Rm Ra
840 case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov - to general)
841 case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov - to general)
845 case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
846 case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
847 case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
848 case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
849 case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov, fcvtXX - register)
850 case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov - from general)
851 case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
852 case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
853 case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
854 case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
855 case IF_DV_2P: // DV_2P ................ ......nnnnnddddd Vd Vn (aes*, sha1su1) - Vd both source and
858 case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
859 case IF_DV_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector)
860 case IF_DV_3B: // DV_3B .Q.......X.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
861 case IF_DV_3BI: // DV_3BI .Q.......XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
862 case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
863 case IF_DV_3D: // DV_3D .........X.mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
864 case IF_DV_3DI: // DV_3DI .........XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (scalar by elem)
865 case IF_DV_3E: // DV_3E ...........mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
866 case IF_DV_4A: // DV_4A .........X.mmmmm .aaaaannnnnddddd Vd Va Vn Vm (scalar)
867 // Tracked GC pointers cannot be placed into the SIMD registers.
870 // These are the load/store formats with "target" registers:
872 case IF_LS_1A: // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB)
873 case IF_LS_2A: // LS_2A .X.......X...... ......nnnnnttttt Rt Rn
874 case IF_LS_2B: // LS_2B .X.......Xiiiiii iiiiiinnnnnttttt Rt Rn imm(0-4095)
875 case IF_LS_2C: // LS_2C .X.......X.iiiii iiiiP.nnnnnttttt Rt Rn imm(-256..+255) pre/post inc
876 case IF_LS_3A: // LS_3A .X.......X.mmmmm xxxS..nnnnnttttt Rt Rn Rm ext(Rm) LSL {}
877 case IF_LS_3B: // LS_3B X............... .aaaaannnnnttttt Rt Ra Rn
878 case IF_LS_3C: // LS_3C X.........iiiiii iaaaaannnnnttttt Rt Ra Rn imm(im7,sh)
879 case IF_LS_3D: // LS_3D .X.......X.mmmmm ......nnnnnttttt Wm Rt Rn
881 // For the Store instructions the "target" register is actually a "source" value
883 if (emitInsIsStore(ins))
889 assert(emitInsIsLoad(ins));
893 case IF_LS_3E: // LS_3E .X.........mmmmm ......nnnnnttttt Rm Rt Rn ARMv8.1 LSE Atomics
895 assert(emitInsIsStore(ins));
896 assert(emitInsIsLoad(ins));
904 bool emitter::emitInsWritesToLclVarStackLoc(instrDesc* id)
906 if (!id->idIsLclVar())
909 instruction ins = id->idIns();
911 // This list is related to the list of instructions used to store local vars in emitIns_S_R().
912 // We don't accept writing to float local vars.
928 bool emitter::emitInsWritesToLclVarStackLocPair(instrDesc* id)
930 if (!id->idIsLclVar())
933 instruction ins = id->idIns();
935 // This list is related to the list of instructions used to store local vars in emitIns_S_S_R_R().
936 // We don't accept writing to float local vars.
948 bool emitter::emitInsMayWriteMultipleRegs(instrDesc* id)
950 instruction ins = id->idIns();
963 // For the small loads/store instruction we adjust the size 'attr'
964 // depending upon whether we have a load or a store
966 emitAttr emitter::emitInsAdjustLoadStoreAttr(instruction ins, emitAttr attr)
968 if (EA_SIZE(attr) <= EA_4BYTE)
970 if (emitInsIsLoad(ins))
972 // The value of 'ins' encodes the size to load
973 // we use EA_8BYTE here because it is the size we will write (into dataReg)
974 // it is also required when ins is INS_ldrsw
980 assert(emitInsIsStore(ins));
982 // The value of 'ins' encodes the size to store
983 // we use EA_4BYTE here because it is the size of the register
984 // that we want to display when storing small values
992 // Takes an instrDesc 'id' and uses the instruction 'ins' to determine the
993 // size of the target register that is written or read by the instruction.
994 // Note that even if EA_4BYTE is returned a load instruction will still
995 // always zero the upper 4 bytes of the target register.
996 // This method is required so that we can distinguish between loads that are
997 // sign-extending as they can have two different sizes for their target register.
998 // Additionally for instructions like 'ldr' and 'str' these can load/store
999 // either 4 byte or 8 bytes to/from the target register.
1000 // By convention the small unsigned load instructions are considered to write
1001 // a 4 byte sized target register, though since these also zero the upper 4 bytes
1002 // they could equally be considered to write the unsigned value to full 8 byte register.
1004 emitAttr emitter::emitInsTargetRegSize(instrDesc* id)
1006 instruction ins = id->idIns();
1007 emitAttr result = EA_UNKNOWN;
1009 // This is used to determine the size of the target registers for a load/store instruction
1043 if (id->idOpSize() == EA_8BYTE)
1059 result = id->idOpSize();
1072 result = id->idOpSize();
1076 NO_WAY("unexpected instruction");
1082 // Takes an instrDesc and uses the instruction to determine the 'size' of the
1083 // data that is loaded from memory.
1085 emitAttr emitter::emitInsLoadStoreSize(instrDesc* id)
1087 instruction ins = id->idIns();
1088 emitAttr result = EA_UNKNOWN;
1090 // The 'result' returned is the 'size' of the data that is loaded from memory.
1126 result = id->idOpSize();
1135 result = id->idOpSize();
1139 NO_WAY("unexpected instruction");
1145 /*****************************************************************************/
1149 static const char * const xRegNames[] =
1151 #define REGDEF(name, rnum, mask, xname, wname) xname,
1152 #include "register.h"
1155 static const char * const wRegNames[] =
1157 #define REGDEF(name, rnum, mask, xname, wname) wname,
1158 #include "register.h"
1161 static const char * const vRegNames[] =
1163 "v0", "v1", "v2", "v3", "v4",
1164 "v5", "v6", "v7", "v8", "v9",
1165 "v10", "v11", "v12", "v13", "v14",
1166 "v15", "v16", "v17", "v18", "v19",
1167 "v20", "v21", "v22", "v23", "v24",
1168 "v25", "v26", "v27", "v28", "v29",
1172 static const char * const qRegNames[] =
1174 "q0", "q1", "q2", "q3", "q4",
1175 "q5", "q6", "q7", "q8", "q9",
1176 "q10", "q11", "q12", "q13", "q14",
1177 "q15", "q16", "q17", "q18", "q19",
1178 "q20", "q21", "q22", "q23", "q24",
1179 "q25", "q26", "q27", "q28", "q29",
1183 static const char * const hRegNames[] =
1185 "h0", "h1", "h2", "h3", "h4",
1186 "h5", "h6", "h7", "h8", "h9",
1187 "h10", "h11", "h12", "h13", "h14",
1188 "h15", "h16", "h17", "h18", "h19",
1189 "h20", "h21", "h22", "h23", "h24",
1190 "h25", "h26", "h27", "h28", "h29",
1193 static const char * const bRegNames[] =
1195 "b0", "b1", "b2", "b3", "b4",
1196 "b5", "b6", "b7", "b8", "b9",
1197 "b10", "b11", "b12", "b13", "b14",
1198 "b15", "b16", "b17", "b18", "b19",
1199 "b20", "b21", "b22", "b23", "b24",
1200 "b25", "b26", "b27", "b28", "b29",
1205 /*****************************************************************************
1207 * Return a string that represents the given register.
1210 const char* emitter::emitRegName(regNumber reg, emitAttr size, bool varName)
1212 assert(reg < REG_COUNT);
1214 const char* rn = nullptr;
1216 if (size == EA_8BYTE)
1218 rn = xRegNames[reg];
1220 else if (size == EA_4BYTE)
1222 rn = wRegNames[reg];
1224 else if (isVectorRegister(reg))
1226 if (size == EA_16BYTE)
1228 rn = qRegNames[reg - REG_V0];
1230 else if (size == EA_2BYTE)
1232 rn = hRegNames[reg - REG_V0];
1234 else if (size == EA_1BYTE)
1236 rn = bRegNames[reg - REG_V0];
1240 assert(rn != nullptr);
1245 /*****************************************************************************
1247 * Return a string that represents the given register.
1250 const char* emitter::emitVectorRegName(regNumber reg)
1252 assert((reg >= REG_V0) && (reg <= REG_V31));
1254 int index = (int)reg - (int)REG_V0;
1256 return vRegNames[index];
1260 /*****************************************************************************
1262 * Returns the base encoding of the given CPU instruction.
1265 emitter::insFormat emitter::emitInsFormat(instruction ins)
1268 const static insFormat insFormats[] =
1270 #define INST1(id, nm, fp, ldst, fmt, e1 ) fmt,
1271 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) fmt,
1272 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) fmt,
1273 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) fmt,
1274 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) fmt,
1275 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) fmt,
1276 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) fmt,
1281 assert(ins < ArrLen(insFormats));
1282 assert((insFormats[ins] != IF_NONE));
1284 return insFormats[ins];
1293 /*static*/ const BYTE CodeGenInterface::instInfo[] =
1295 #define INST1(id, nm, fp, ldst, fmt, e1 ) ldst | INST_FP*fp,
1296 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) ldst | INST_FP*fp,
1297 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) ldst | INST_FP*fp,
1298 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) ldst | INST_FP*fp,
1299 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) ldst | INST_FP*fp,
1300 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) ldst | INST_FP*fp,
1301 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) ldst | INST_FP*fp,
1306 /*****************************************************************************
1308 * Returns true if the instruction is some kind of compare or test instruction
1311 bool emitter::emitInsIsCompare(instruction ins)
1313 // We have pseudo ins like lea which are not included in emitInsLdStTab.
1314 if (ins < ArrLen(CodeGenInterface::instInfo))
1315 return (CodeGenInterface::instInfo[ins] & CMP) ? true : false;
1320 /*****************************************************************************
1322 * Returns true if the instruction is some kind of load instruction
1325 bool emitter::emitInsIsLoad(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] & LD) ? true : false;
1333 /*****************************************************************************
1335 * Returns true if the instruction is some kind of store instruction
1338 bool emitter::emitInsIsStore(instruction ins)
1340 // We have pseudo ins like lea which are not included in emitInsLdStTab.
1341 if (ins < ArrLen(CodeGenInterface::instInfo))
1342 return (CodeGenInterface::instInfo[ins] & ST) ? true : false;
1347 /*****************************************************************************
1349 * Returns true if the instruction is some kind of load/store instruction
1352 bool emitter::emitInsIsLoadOrStore(instruction ins)
1354 // We have pseudo ins like lea which are not included in emitInsLdStTab.
1355 if (ins < ArrLen(CodeGenInterface::instInfo))
1356 return (CodeGenInterface::instInfo[ins] & (LD | ST)) ? true : false;
1365 /*****************************************************************************
1367 * Returns the specific encoding of the given CPU instruction and format
1370 emitter::code_t emitter::emitInsCode(instruction ins, insFormat fmt)
1373 const static code_t insCodes1[] =
1375 #define INST1(id, nm, fp, ldst, fmt, e1 ) e1,
1376 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) e1,
1377 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) e1,
1378 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e1,
1379 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e1,
1380 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e1,
1381 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e1,
1384 const static code_t insCodes2[] =
1386 #define INST1(id, nm, fp, ldst, fmt, e1 )
1387 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) e2,
1388 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) e2,
1389 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e2,
1390 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e2,
1391 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e2,
1392 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e2,
1395 const static code_t insCodes3[] =
1397 #define INST1(id, nm, fp, ldst, fmt, e1 )
1398 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1399 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) e3,
1400 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e3,
1401 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e3,
1402 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e3,
1403 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e3,
1406 const static code_t insCodes4[] =
1408 #define INST1(id, nm, fp, ldst, fmt, e1 )
1409 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1410 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
1411 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e4,
1412 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e4,
1413 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e4,
1414 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e4,
1417 const static code_t insCodes5[] =
1419 #define INST1(id, nm, fp, ldst, fmt, e1 )
1420 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1421 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
1422 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
1423 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e5,
1424 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e5,
1425 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e5,
1428 const static code_t insCodes6[] =
1430 #define INST1(id, nm, fp, ldst, fmt, e1 )
1431 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1432 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
1433 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
1434 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
1435 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e6,
1436 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e6,
1439 const static code_t insCodes7[] =
1441 #define INST1(id, nm, fp, ldst, fmt, e1 )
1442 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1443 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
1444 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
1445 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
1446 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 )
1447 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e7,
1450 const static code_t insCodes8[] =
1452 #define INST1(id, nm, fp, ldst, fmt, e1 )
1453 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1454 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
1455 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
1456 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
1457 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 )
1458 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e8,
1461 const static code_t insCodes9[] =
1463 #define INST1(id, nm, fp, ldst, fmt, e1 )
1464 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
1465 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
1466 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
1467 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
1468 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 )
1469 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e9,
1474 const static insFormat formatEncode9[9] = {IF_DR_2E, IF_DR_2G, IF_DI_1B, IF_DI_1D, IF_DV_3C,
1475 IF_DV_2B, IF_DV_2C, IF_DV_2E, IF_DV_2F};
1476 const static insFormat formatEncode6A[6] = {IF_DR_3A, IF_DR_3B, IF_DR_3C, IF_DI_2A, IF_DV_3A, IF_DV_3E};
1477 const static insFormat formatEncode5A[5] = {IF_LS_2A, IF_LS_2B, IF_LS_2C, IF_LS_3A, IF_LS_1A};
1478 const static insFormat formatEncode5B[5] = {IF_DV_2G, IF_DV_2H, IF_DV_2I, IF_DV_1A, IF_DV_1B};
1479 const static insFormat formatEncode5C[5] = {IF_DR_3A, IF_DR_3B, IF_DI_2C, IF_DV_3C, IF_DV_1B};
1480 const static insFormat formatEncode4A[4] = {IF_LS_2A, IF_LS_2B, IF_LS_2C, IF_LS_3A};
1481 const static insFormat formatEncode4B[4] = {IF_DR_3A, IF_DR_3B, IF_DR_3C, IF_DI_2A};
1482 const static insFormat formatEncode4C[4] = {IF_DR_2A, IF_DR_2B, IF_DR_2C, IF_DI_1A};
1483 const static insFormat formatEncode4D[4] = {IF_DV_3B, IF_DV_3D, IF_DV_3BI, IF_DV_3DI};
1484 const static insFormat formatEncode4E[4] = {IF_DR_3A, IF_DR_3B, IF_DI_2C, IF_DV_3C};
1485 const static insFormat formatEncode4F[4] = {IF_DR_3A, IF_DR_3B, IF_DV_3C, IF_DV_1B};
1486 const static insFormat formatEncode4G[4] = {IF_DR_2E, IF_DR_2F, IF_DV_2M, IF_DV_2L};
1487 const static insFormat formatEncode4H[4] = {IF_DV_3E, IF_DV_3A, IF_DV_2L, IF_DV_2M};
1488 const static insFormat formatEncode4I[4] = {IF_DV_3D, IF_DV_3B, IF_DV_2G, IF_DV_2A};
1489 const static insFormat formatEncode3A[3] = {IF_DR_3A, IF_DR_3B, IF_DI_2C};
1490 const static insFormat formatEncode3B[3] = {IF_DR_2A, IF_DR_2B, IF_DI_1C};
1491 const static insFormat formatEncode3C[3] = {IF_DR_3A, IF_DR_3B, IF_DV_3C};
1492 const static insFormat formatEncode3D[3] = {IF_DV_2C, IF_DV_2D, IF_DV_2E};
1493 const static insFormat formatEncode3E[3] = {IF_DV_3B, IF_DV_3BI, IF_DV_3DI};
1494 const static insFormat formatEncode3F[3] = {IF_DV_2A, IF_DV_2G, IF_DV_2H};
1495 const static insFormat formatEncode3G[3] = {IF_DV_2A, IF_DV_2G, IF_DV_2I};
1496 const static insFormat formatEncode3H[3] = {IF_DR_3A, IF_DV_3A, IF_DV_3AI};
1497 const static insFormat formatEncode3I[3] = {IF_DR_2E, IF_DR_2F, IF_DV_2M};
1498 const static insFormat formatEncode2A[2] = {IF_DR_2E, IF_DR_2F};
1499 const static insFormat formatEncode2B[2] = {IF_DR_3A, IF_DR_3B};
1500 const static insFormat formatEncode2C[2] = {IF_DR_3A, IF_DI_2D};
1501 const static insFormat formatEncode2D[2] = {IF_DR_3A, IF_DI_2B};
1502 const static insFormat formatEncode2E[2] = {IF_LS_3B, IF_LS_3C};
1503 const static insFormat formatEncode2F[2] = {IF_DR_2I, IF_DI_1F};
1504 const static insFormat formatEncode2G[2] = {IF_DV_3B, IF_DV_3D};
1505 const static insFormat formatEncode2H[2] = {IF_DV_2C, IF_DV_2F};
1506 const static insFormat formatEncode2I[2] = {IF_DV_2K, IF_DV_1C};
1507 const static insFormat formatEncode2J[2] = {IF_DV_2A, IF_DV_2G};
1508 const static insFormat formatEncode2K[2] = {IF_DV_2M, IF_DV_2L};
1509 const static insFormat formatEncode2L[2] = {IF_DR_2G, IF_DV_2M};
1510 const static insFormat formatEncode2M[2] = {IF_DV_3A, IF_DV_3AI};
1511 const static insFormat formatEncode2N[2] = {IF_DV_2N, IF_DV_2O};
1512 const static insFormat formatEncode2O[2] = {IF_DV_3E, IF_DV_3A};
1513 const static insFormat formatEncode2P[2] = {IF_DV_2G, IF_DV_3B};
1515 code_t code = BAD_CODE;
1516 insFormat insFmt = emitInsFormat(ins);
1517 bool encoding_found = false;
1523 for (index = 0; index < 9; index++)
1525 if (fmt == formatEncode9[index])
1527 encoding_found = true;
1534 for (index = 0; index < 6; index++)
1536 if (fmt == formatEncode6A[index])
1538 encoding_found = true;
1545 for (index = 0; index < 5; index++)
1547 if (fmt == formatEncode5A[index])
1549 encoding_found = true;
1556 for (index = 0; index < 5; index++)
1558 if (fmt == formatEncode5B[index])
1560 encoding_found = true;
1567 for (index = 0; index < 5; index++)
1569 if (fmt == formatEncode5C[index])
1571 encoding_found = true;
1578 for (index = 0; index < 4; index++)
1580 if (fmt == formatEncode4A[index])
1582 encoding_found = true;
1589 for (index = 0; index < 4; index++)
1591 if (fmt == formatEncode4B[index])
1593 encoding_found = true;
1600 for (index = 0; index < 4; index++)
1602 if (fmt == formatEncode4C[index])
1604 encoding_found = true;
1611 for (index = 0; index < 4; index++)
1613 if (fmt == formatEncode4D[index])
1615 encoding_found = true;
1622 for (index = 0; index < 4; index++)
1624 if (fmt == formatEncode4E[index])
1626 encoding_found = true;
1633 for (index = 0; index < 4; index++)
1635 if (fmt == formatEncode4F[index])
1637 encoding_found = true;
1644 for (index = 0; index < 4; index++)
1646 if (fmt == formatEncode4G[index])
1648 encoding_found = true;
1655 for (index = 0; index < 4; index++)
1657 if (fmt == formatEncode4H[index])
1659 encoding_found = true;
1666 for (index = 0; index < 4; index++)
1668 if (fmt == formatEncode4I[index])
1670 encoding_found = true;
1677 for (index = 0; index < 3; index++)
1679 if (fmt == formatEncode3A[index])
1681 encoding_found = true;
1688 for (index = 0; index < 3; index++)
1690 if (fmt == formatEncode3B[index])
1692 encoding_found = true;
1699 for (index = 0; index < 3; index++)
1701 if (fmt == formatEncode3C[index])
1703 encoding_found = true;
1710 for (index = 0; index < 3; index++)
1712 if (fmt == formatEncode3D[index])
1714 encoding_found = true;
1721 for (index = 0; index < 3; index++)
1723 if (fmt == formatEncode3E[index])
1725 encoding_found = true;
1732 for (index = 0; index < 3; index++)
1734 if (fmt == formatEncode3F[index])
1736 encoding_found = true;
1743 for (index = 0; index < 3; index++)
1745 if (fmt == formatEncode3G[index])
1747 encoding_found = true;
1754 for (index = 0; index < 3; index++)
1756 if (fmt == formatEncode3H[index])
1758 encoding_found = true;
1765 for (index = 0; index < 3; index++)
1767 if (fmt == formatEncode3I[index])
1769 encoding_found = true;
1776 for (index = 0; index < 2; index++)
1778 if (fmt == formatEncode2A[index])
1780 encoding_found = true;
1787 for (index = 0; index < 2; index++)
1789 if (fmt == formatEncode2B[index])
1791 encoding_found = true;
1798 for (index = 0; index < 2; index++)
1800 if (fmt == formatEncode2C[index])
1802 encoding_found = true;
1809 for (index = 0; index < 2; index++)
1811 if (fmt == formatEncode2D[index])
1813 encoding_found = true;
1820 for (index = 0; index < 2; index++)
1822 if (fmt == formatEncode2E[index])
1824 encoding_found = true;
1831 for (index = 0; index < 2; index++)
1833 if (fmt == formatEncode2F[index])
1835 encoding_found = true;
1842 for (index = 0; index < 2; index++)
1844 if (fmt == formatEncode2G[index])
1846 encoding_found = true;
1853 for (index = 0; index < 2; index++)
1855 if (fmt == formatEncode2H[index])
1857 encoding_found = true;
1864 for (index = 0; index < 2; index++)
1866 if (fmt == formatEncode2I[index])
1868 encoding_found = true;
1875 for (index = 0; index < 2; index++)
1877 if (fmt == formatEncode2J[index])
1879 encoding_found = true;
1886 for (index = 0; index < 2; index++)
1888 if (fmt == formatEncode2K[index])
1890 encoding_found = true;
1897 for (index = 0; index < 2; index++)
1899 if (fmt == formatEncode2L[index])
1901 encoding_found = true;
1908 for (index = 0; index < 2; index++)
1910 if (fmt == formatEncode2M[index])
1912 encoding_found = true;
1919 for (index = 0; index < 2; index++)
1921 if (fmt == formatEncode2N[index])
1923 encoding_found = true;
1930 for (index = 0; index < 2; index++)
1932 if (fmt == formatEncode2O[index])
1934 encoding_found = true;
1941 for (index = 0; index < 2; index++)
1943 if (fmt == formatEncode2P[index])
1945 encoding_found = true;
2028 encoding_found = true;
2033 encoding_found = false;
2037 assert(encoding_found);
2042 assert(ins < ArrLen(insCodes1));
2043 code = insCodes1[ins];
2046 assert(ins < ArrLen(insCodes2));
2047 code = insCodes2[ins];
2050 assert(ins < ArrLen(insCodes3));
2051 code = insCodes3[ins];
2054 assert(ins < ArrLen(insCodes4));
2055 code = insCodes4[ins];
2058 assert(ins < ArrLen(insCodes5));
2059 code = insCodes5[ins];
2062 assert(ins < ArrLen(insCodes6));
2063 code = insCodes6[ins];
2066 assert(ins < ArrLen(insCodes7));
2067 code = insCodes7[ins];
2070 assert(ins < ArrLen(insCodes8));
2071 code = insCodes8[ins];
2074 assert(ins < ArrLen(insCodes9));
2075 code = insCodes9[ins];
2079 assert((code != BAD_CODE));
2084 // true if this 'imm' can be encoded as a input operand to a mov instruction
2085 /*static*/ bool emitter::emitIns_valid_imm_for_mov(INT64 imm, emitAttr size)
2087 // Check for "MOV (wide immediate)".
2088 if (canEncodeHalfwordImm(imm, size))
2091 // Next try the ones-complement form of 'halfword immediate' imm(i16,hw),
2092 // namely "MOV (inverted wide immediate)".
2093 ssize_t notOfImm = NOT_helper(imm, getBitWidth(size));
2094 if (canEncodeHalfwordImm(notOfImm, size))
2097 // Finally try "MOV (bitmask immediate)" imm(N,r,s)
2098 if (canEncodeBitMaskImm(imm, size))
2104 // true if this 'imm' can be encoded as a input operand to a vector movi instruction
2105 /*static*/ bool emitter::emitIns_valid_imm_for_movi(INT64 imm, emitAttr elemsize)
2107 if (elemsize == EA_8BYTE)
2112 INT64 loByte = uimm & 0xFF;
2113 if ((loByte == 0) || (loByte == 0xFF))
2127 // First try the standard 'byteShifted immediate' imm(i8,bySh)
2128 if (canEncodeByteShiftedImm(imm, elemsize, true))
2131 // Next try the ones-complement form of the 'immediate' imm(i8,bySh)
2132 ssize_t notOfImm = NOT_helper(imm, getBitWidth(elemsize));
2133 if (canEncodeByteShiftedImm(notOfImm, elemsize, true))
2139 // true if this 'imm' can be encoded as a input operand to a fmov instruction
2140 /*static*/ bool emitter::emitIns_valid_imm_for_fmov(double immDbl)
2142 if (canEncodeFloatImm8(immDbl))
2148 // true if this 'imm' can be encoded as a input operand to an add instruction
2149 /*static*/ bool emitter::emitIns_valid_imm_for_add(INT64 imm, emitAttr size)
2151 if (unsigned_abs(imm) <= 0x0fff)
2153 else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
2159 // true if this 'imm' can be encoded as a input operand to an non-add/sub alu instruction
2160 /*static*/ bool emitter::emitIns_valid_imm_for_cmp(INT64 imm, emitAttr size)
2162 return emitIns_valid_imm_for_add(imm, size);
2165 // true if this 'imm' can be encoded as a input operand to an non-add/sub alu instruction
2166 /*static*/ bool emitter::emitIns_valid_imm_for_alu(INT64 imm, emitAttr size)
2168 if (canEncodeBitMaskImm(imm, size))
2174 // true if this 'imm' can be encoded as the offset in a ldr/str instruction
2175 /*static*/ bool emitter::emitIns_valid_imm_for_ldst_offset(INT64 imm, emitAttr attr)
2178 return true; // Encodable using IF_LS_2A
2180 if ((imm >= -256) && (imm <= 255))
2181 return true; // Encodable using IF_LS_2C (or possibly IF_LS_2B)
2184 return false; // not encodable
2186 emitAttr size = EA_SIZE(attr);
2187 unsigned scale = NaturalScale_helper(size);
2188 ssize_t mask = size - 1; // the mask of low bits that must be zero to encode the immediate
2190 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
2191 return true; // Encodable using IF_LS_2B
2193 return false; // not encodable
2196 /************************************************************************
2198 * A helper method to return the natural scale for an EA 'size'
2201 /*static*/ unsigned emitter::NaturalScale_helper(emitAttr size)
2203 assert(size == EA_1BYTE || size == EA_2BYTE || size == EA_4BYTE || size == EA_8BYTE || size == EA_16BYTE);
2205 unsigned result = 0;
2206 unsigned utemp = (unsigned)size;
2208 // Compute log base 2 of utemp (aka 'size')
2218 /************************************************************************
2220 * A helper method to perform a Rotate-Right shift operation
2221 * the source is 'value' and it is rotated right by 'sh' bits
2222 * 'value' is considered to be a fixed size 'width' set of bits.
2225 * value is '00001111', sh is 2 and width is 8
2226 * result is '11000011'
2229 /*static*/ UINT64 emitter::ROR_helper(UINT64 value, unsigned sh, unsigned width)
2231 assert(width <= 64);
2232 // Check that 'value' fits in 'width' bits
2233 assert((width == 64) || (value < (1ULL << width)));
2234 // We don't support shifts >= width
2240 unsigned lsh = width - rsh;
2242 result = (value >> rsh);
2243 result |= (value << lsh);
2247 // mask off any extra bits that we got from the left shift
2248 result &= ((1ULL << width) - 1);
2252 /************************************************************************
2254 * A helper method to perform a 'NOT' bitwise complement operation.
2255 * 'value' is considered to be a fixed size 'width' set of bits.
2258 * value is '01001011', and width is 8
2259 * result is '10110100'
2262 /*static*/ UINT64 emitter::NOT_helper(UINT64 value, unsigned width)
2264 assert(width <= 64);
2266 UINT64 result = ~value;
2270 // Check that 'value' fits in 'width' bits. Don't consider "sign" bits above width.
2271 UINT64 maxVal = 1ULL << width;
2272 UINT64 lowBitsMask = maxVal - 1;
2273 UINT64 signBitsMask = ~lowBitsMask | (1ULL << (width - 1)); // The high bits must be set, and the top bit
2274 // (sign bit) must be set.
2275 assert((value < maxVal) || ((value & signBitsMask) == signBitsMask));
2277 // mask off any extra bits that we got from the complement operation
2278 result &= lowBitsMask;
2284 /************************************************************************
2286 * A helper method to perform a bit Replicate operation
2287 * the source is 'value' with a fixed size 'width' set of bits.
2288 * value is replicated to fill out 32 or 64 bits as determined by 'size'.
2291 * value is '11000011' (0xE3), width is 8 and size is EA_8BYTE
2292 * result is '11000011 11000011 11000011 11000011 11000011 11000011 11000011 11000011'
2293 * 0xE3E3E3E3E3E3E3E3
2296 /*static*/ UINT64 emitter::Replicate_helper(UINT64 value, unsigned width, emitAttr size)
2298 assert(emitter::isValidGeneralDatasize(size));
2300 unsigned immWidth = (size == EA_8BYTE) ? 64 : 32;
2301 assert(width <= immWidth);
2303 UINT64 result = value;
2304 unsigned filledBits = width;
2306 while (filledBits < immWidth)
2310 filledBits += width;
2315 /************************************************************************
2317 * Convert an imm(N,r,s) into a 64-bit immediate
2318 * inputs 'bmImm' a bitMaskImm struct
2319 * 'size' specifies the size of the result (64 or 32 bits)
2322 /*static*/ INT64 emitter::emitDecodeBitMaskImm(const emitter::bitMaskImm bmImm, emitAttr size)
2324 assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2326 unsigned N = bmImm.immN; // read the N,R and S values from the 'bitMaskImm' encoding
2327 unsigned R = bmImm.immR;
2328 unsigned S = bmImm.immS;
2330 unsigned elemWidth = 64; // used when N == 1
2332 if (N == 0) // find the smaller elemWidth when N == 0
2334 // Scan S for the highest bit not set
2336 for (unsigned bitNum = 5; bitNum > 0; bitNum--)
2338 unsigned oneBit = elemWidth;
2339 if ((S & oneBit) == 0)
2346 assert(size == EA_8BYTE);
2349 unsigned maskSR = elemWidth - 1;
2354 // encoding for S is one less than the number of consecutive one bits
2355 S++; // Number of consecutive ones to generate in 'welem'
2359 // 'elemWidth' is the number of bits that we will use for the ROR and Replicate operations
2360 // 'S' is the number of consecutive 1 bits for the immediate
2361 // 'R' is the number of bits that we will Rotate Right the immediate
2362 // 'size' selects the final size of the immedate that we return (64 or 32 bits)
2364 assert(S < elemWidth); // 'elemWidth' consecutive one's is a reserved encoding
2369 welem = (1ULL << S) - 1;
2371 wmask = ROR_helper(welem, R, elemWidth);
2372 wmask = Replicate_helper(wmask, elemWidth, size);
2377 /*****************************************************************************
2379 * Check if an immediate can use the left shifted by 12 bits encoding
2382 /*static*/ bool emitter::canEncodeWithShiftImmBy12(INT64 imm)
2386 imm = -imm; // convert to unsigned
2391 return false; // Must be MIN_INT64
2394 if ((imm & 0xfff) != 0) // Now the low 12 bits all have to be zero
2399 imm >>= 12; // shift right by 12 bits
2401 return (imm <= 0x0fff); // Does it fit in 12 bits
2404 /*****************************************************************************
2406 * Normalize the 'imm' so that the upper bits, as defined by 'size' are zero
2409 /*static*/ INT64 emitter::normalizeImm64(INT64 imm, emitAttr size)
2411 unsigned immWidth = getBitWidth(size);
2416 // Check that 'imm' fits in 'immWidth' bits. Don't consider "sign" bits above width.
2417 INT64 maxVal = 1LL << immWidth;
2418 INT64 lowBitsMask = maxVal - 1;
2419 INT64 hiBitsMask = ~lowBitsMask;
2420 INT64 signBitsMask =
2421 hiBitsMask | (1LL << (immWidth - 1)); // The high bits must be set, and the top bit (sign bit) must be set.
2422 assert((imm < maxVal) || ((imm & signBitsMask) == signBitsMask));
2424 // mask off the hiBits
2425 result &= lowBitsMask;
2430 /*****************************************************************************
2432 * Normalize the 'imm' so that the upper bits, as defined by 'size' are zero
2435 /*static*/ INT32 emitter::normalizeImm32(INT32 imm, emitAttr size)
2437 unsigned immWidth = getBitWidth(size);
2442 // Check that 'imm' fits in 'immWidth' bits. Don't consider "sign" bits above width.
2443 INT32 maxVal = 1 << immWidth;
2444 INT32 lowBitsMask = maxVal - 1;
2445 INT32 hiBitsMask = ~lowBitsMask;
2446 INT32 signBitsMask = hiBitsMask | (1 << (immWidth - 1)); // The high bits must be set, and the top bit
2447 // (sign bit) must be set.
2448 assert((imm < maxVal) || ((imm & signBitsMask) == signBitsMask));
2450 // mask off the hiBits
2451 result &= lowBitsMask;
2456 /************************************************************************
2458 * returns true if 'imm' of 'size bits (32/64) can be encoded
2459 * using the ARM64 'bitmask immediate' form.
2460 * When a non-null value is passed for 'wbBMI' then this method
2461 * writes back the 'N','S' and 'R' values use to encode this immediate
2465 /*static*/ bool emitter::canEncodeBitMaskImm(INT64 imm, emitAttr size, emitter::bitMaskImm* wbBMI)
2467 assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2469 unsigned immWidth = (size == EA_8BYTE) ? 64 : 32;
2470 unsigned maxLen = (size == EA_8BYTE) ? 6 : 5;
2472 imm = normalizeImm64(imm, size);
2474 // Starting with len=1, elemWidth is 2 bits
2475 // len=2, elemWidth is 4 bits
2476 // len=3, elemWidth is 8 bits
2477 // len=4, elemWidth is 16 bits
2478 // len=5, elemWidth is 32 bits
2479 // (optionally) len=6, elemWidth is 64 bits
2481 for (unsigned len = 1; (len <= maxLen); len++)
2483 unsigned elemWidth = 1 << len;
2484 UINT64 elemMask = ((UINT64)-1) >> (64 - elemWidth);
2485 UINT64 tempImm = (UINT64)imm; // A working copy of 'imm' that we can mutate
2486 UINT64 elemVal = tempImm & elemMask; // The low 'elemWidth' bits of 'imm'
2488 // Check for all 1's or 0's as these can't be encoded
2489 if ((elemVal == 0) || (elemVal == elemMask))
2492 // 'checkedBits' is the count of bits that are known to match 'elemVal' when replicated
2493 unsigned checkedBits = elemWidth; // by definition the first 'elemWidth' bits match
2495 // Now check to see if each of the next bits match...
2497 while (checkedBits < immWidth)
2499 tempImm >>= elemWidth;
2501 UINT64 nextElem = tempImm & elemMask;
2502 if (nextElem != elemVal)
2504 // Not matching, exit this loop and checkedBits will not be equal to immWidth
2508 // The 'nextElem' is matching, so increment 'checkedBits'
2509 checkedBits += elemWidth;
2512 // Did the full immediate contain bits that can be formed by repeating 'elemVal'?
2513 if (checkedBits == immWidth)
2515 // We are not quite done, since the only values that we can encode as a
2516 // 'bitmask immediate' are those that can be formed by starting with a
2517 // bit string of 0*1* that is rotated by some number of bits.
2519 // We check to see if 'elemVal' can be formed using these restrictions.
2522 // Rotating by one bit any value that passes these restrictions
2523 // can be xor-ed with the original value and will result it a string
2524 // of bits that have exactly two 1 bits: 'elemRorXor'
2525 // Further the distance between the two one bits tells us the value
2526 // of S and the location of the 1 bits tells us the value of R
2528 // Some examples: (immWidth is 8)
2530 // S=4,R=0 S=5,R=3 S=3,R=6
2531 // elemVal: 00001111 11100011 00011100
2532 // elemRor: 10000111 11110001 00001110
2533 // elemRorXor: 10001000 00010010 00010010
2534 // compute S 45678--- ---5678- ---3210-
2535 // compute R 01234567 ---34567 ------67
2537 UINT64 elemRor = ROR_helper(elemVal, 1, elemWidth); // Rotate 'elemVal' Right by one bit
2538 UINT64 elemRorXor = elemVal ^ elemRor; // Xor elemVal and elemRor
2540 // If we only have a two-bit change in elemROR then we can form a mask for this value
2541 unsigned bitCount = 0;
2542 UINT64 oneBit = 0x1;
2543 unsigned R = elemWidth; // R is shift count for ROR (rotate right shift)
2544 unsigned S = 0; // S is number of consecutive one bits
2547 // Loop over the 'elemWidth' bits in 'elemRorXor'
2549 for (unsigned bitNum = 0; bitNum < elemWidth; bitNum++)
2553 R--; // We decrement R by one whenever incr is -1
2557 S += incr; // We incr/decr S, after we find the first one bit in 'elemRorXor'
2560 // Is this bit position a 1 bit in 'elemRorXor'?
2562 if (oneBit & elemRorXor)
2565 // Is this the first 1 bit that we found in 'elemRorXor'?
2568 // Does this 1 bit represent a transition to zero bits?
2569 bool toZeros = ((oneBit & elemVal) != 0);
2572 // S :: Count down from elemWidth
2576 else // this 1 bit represent a transition to one bits.
2578 // S :: Count up from zero
2583 else // bitCount > 1
2585 // We found the second (or third...) 1 bit in 'elemRorXor'
2586 incr = 0; // stop decrementing 'R'
2590 // More than 2 transitions from 0/1 in 'elemVal'
2591 // This means that 'elemVal' can't be encoded
2592 // using a 'bitmask immediate'.
2594 // Furthermore, it will continue to fail
2595 // with any larger 'len' that we try.
2596 // so just return false.
2603 // shift oneBit left by one bit to test the next position
2607 // We expect that bitCount will always be two at this point
2608 // but just in case return false for any bad cases.
2610 assert(bitCount == 2);
2614 // Perform some sanity checks on the values of 'S' and 'R'
2616 assert(S < elemWidth);
2617 assert(R < elemWidth);
2619 // Does the caller want us to return the N,R,S encoding values?
2621 if (wbBMI != nullptr)
2624 // The encoding used for S is one less than the
2625 // number of consecutive one bits
2635 // The encoding used for 'S' here is a bit peculiar.
2637 // The upper bits need to be complemented, followed by a zero bit
2638 // then the value of 'S-1'
2640 unsigned upperBitsOfS = 64 - (1 << (len + 1));
2646 // Verify that what we are returning is correct.
2647 assert(imm == emitDecodeBitMaskImm(*wbBMI, size));
2649 // Tell the caller that we can successfully encode this immediate
2650 // using a 'bitmask immediate'.
2658 /************************************************************************
2660 * Convert a 64-bit immediate into its 'bitmask immediate' representation imm(N,r,s)
2663 /*static*/ emitter::bitMaskImm emitter::emitEncodeBitMaskImm(INT64 imm, emitAttr size)
2665 emitter::bitMaskImm result;
2668 bool canEncode = canEncodeBitMaskImm(imm, size, &result);
2674 /************************************************************************
2676 * Convert an imm(i16,hw) into a 32/64-bit immediate
2677 * inputs 'hwImm' a halfwordImm struct
2678 * 'size' specifies the size of the result (64 or 32 bits)
2681 /*static*/ INT64 emitter::emitDecodeHalfwordImm(const emitter::halfwordImm hwImm, emitAttr size)
2683 assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2685 unsigned hw = hwImm.immHW;
2686 INT64 val = (INT64)hwImm.immVal;
2688 assert((hw <= 1) || (size == EA_8BYTE));
2690 INT64 result = val << (16 * hw);
2694 /************************************************************************
2696 * returns true if 'imm' of 'size' bits (32/64) can be encoded
2697 * using the ARM64 'halfword immediate' form.
2698 * When a non-null value is passed for 'wbHWI' then this method
2699 * writes back the 'immHW' and 'immVal' values use to encode this immediate
2703 /*static*/ bool emitter::canEncodeHalfwordImm(INT64 imm, emitAttr size, emitter::halfwordImm* wbHWI)
2705 assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2707 unsigned immWidth = (size == EA_8BYTE) ? 64 : 32;
2708 unsigned maxHW = (size == EA_8BYTE) ? 4 : 2;
2710 // setup immMask to a (EA_4BYTE) 0x00000000_FFFFFFFF or (EA_8BYTE) 0xFFFFFFFF_FFFFFFFF
2711 const UINT64 immMask = ((UINT64)-1) >> (64 - immWidth);
2712 const INT64 mask16 = (INT64)0xFFFF;
2714 imm = normalizeImm64(imm, size);
2716 // Try each of the valid hw shift sizes
2717 for (unsigned hw = 0; (hw < maxHW); hw++)
2719 INT64 curMask = mask16 << (hw * 16); // Represents the mask of the bits in the current halfword
2720 INT64 checkBits = immMask & ~curMask;
2722 // Excluding the current halfword (using ~curMask)
2723 // does the immediate have zero bits in every other bit that we care about?
2724 // note we care about all 64-bits for EA_8BYTE
2725 // and we care about the lowest 32 bits for EA_4BYTE
2727 if ((imm & checkBits) == 0)
2729 // Does the caller want us to return the imm(i16,hw) encoding values?
2731 if (wbHWI != nullptr)
2733 INT64 val = ((imm & curMask) >> (hw * 16)) & mask16;
2735 wbHWI->immVal = val;
2737 // Verify that what we are returning is correct.
2738 assert(imm == emitDecodeHalfwordImm(*wbHWI, size));
2740 // Tell the caller that we can successfully encode this immediate
2741 // using a 'halfword immediate'.
2749 /************************************************************************
2751 * Convert a 64-bit immediate into its 'halfword immediate' representation imm(i16,hw)
2754 /*static*/ emitter::halfwordImm emitter::emitEncodeHalfwordImm(INT64 imm, emitAttr size)
2756 emitter::halfwordImm result;
2757 result.immHWVal = 0;
2759 bool canEncode = canEncodeHalfwordImm(imm, size, &result);
2765 /************************************************************************
2767 * Convert an imm(i8,sh) into a 16/32-bit immediate
2768 * inputs 'bsImm' a byteShiftedImm struct
2769 * 'size' specifies the size of the result (16 or 32 bits)
2772 /*static*/ INT32 emitter::emitDecodeByteShiftedImm(const emitter::byteShiftedImm bsImm, emitAttr size)
2774 bool onesShift = (bsImm.immOnes == 1);
2775 unsigned bySh = bsImm.immBY; // Num Bytes to shift 0,1,2,3
2776 INT32 val = (INT32)bsImm.immVal; // 8-bit immediate
2781 assert((size == EA_2BYTE) || (size == EA_4BYTE)); // Only EA_2BYTE or EA_4BYTE forms
2782 if (size == EA_2BYTE)
2791 result <<= (8 * bySh);
2795 result |= ((1 << (8 * bySh)) - 1);
2801 /************************************************************************
2803 * returns true if 'imm' of 'size' bits (16/32) can be encoded
2804 * using the ARM64 'byteShifted immediate' form.
2805 * When a non-null value is passed for 'wbBSI' then this method
2806 * writes back the 'immBY' and 'immVal' values use to encode this immediate
2810 /*static*/ bool emitter::canEncodeByteShiftedImm(INT64 imm,
2813 emitter::byteShiftedImm* wbBSI)
2815 bool canEncode = false;
2816 bool onesShift = false; // true if we use the shifting ones variant
2817 unsigned bySh = 0; // number of bytes to shift: 0, 1, 2, 3
2818 unsigned imm8 = 0; // immediate to use in the encoding
2820 imm = normalizeImm64(imm, size);
2822 if (size == EA_1BYTE)
2824 imm8 = (unsigned)imm;
2825 assert(imm8 < 0x100);
2828 else if (size == EA_8BYTE)
2830 imm8 = (unsigned)imm;
2831 assert(imm8 < 0x100);
2836 assert((size == EA_2BYTE) || (size == EA_4BYTE)); // Only EA_2BYTE or EA_4BYTE forms
2838 unsigned immWidth = (size == EA_4BYTE) ? 32 : 16;
2839 unsigned maxBY = (size == EA_4BYTE) ? 4 : 2;
2841 // setup immMask to a (EA_2BYTE) 0x0000FFFF or (EA_4BYTE) 0xFFFFFFFF
2842 const UINT32 immMask = ((UINT32)-1) >> (32 - immWidth);
2843 const INT32 mask8 = (INT32)0xFF;
2845 // Try each of the valid by shift sizes
2846 for (bySh = 0; (bySh < maxBY); bySh++)
2848 INT32 curMask = mask8 << (bySh * 8); // Represents the mask of the bits in the current byteShifted
2849 INT32 checkBits = immMask & ~curMask;
2850 INT32 immCheck = (imm & checkBits);
2852 // Excluding the current byte (using ~curMask)
2853 // does the immediate have zero bits in every other bit that we care about?
2854 // or can be use the shifted one variant?
2855 // note we care about all 32-bits for EA_4BYTE
2856 // and we care about the lowest 16 bits for EA_2BYTE
2864 if ((bySh == 1) && (immCheck == 0xFF))
2869 else if ((bySh == 2) && (immCheck == 0xFFFF))
2877 imm8 = (unsigned)(((imm & curMask) >> (bySh * 8)) & mask8);
2885 // Does the caller want us to return the imm(i8,bySh) encoding values?
2887 if (wbBSI != nullptr)
2889 wbBSI->immOnes = onesShift;
2890 wbBSI->immBY = bySh;
2891 wbBSI->immVal = imm8;
2893 // Verify that what we are returning is correct.
2894 assert(imm == emitDecodeByteShiftedImm(*wbBSI, size));
2896 // Tell the caller that we can successfully encode this immediate
2897 // using a 'byteShifted immediate'.
2904 /************************************************************************
2906 * Convert a 32-bit immediate into its 'byteShifted immediate' representation imm(i8,by)
2909 /*static*/ emitter::byteShiftedImm emitter::emitEncodeByteShiftedImm(INT64 imm, emitAttr size, bool allow_MSL)
2911 emitter::byteShiftedImm result;
2912 result.immBSVal = 0;
2914 bool canEncode = canEncodeByteShiftedImm(imm, size, allow_MSL, &result);
2920 /************************************************************************
2922 * Convert a 'float 8-bit immediate' into a double.
2923 * inputs 'fpImm' a floatImm8 struct
2926 /*static*/ double emitter::emitDecodeFloatImm8(const emitter::floatImm8 fpImm)
2928 unsigned sign = fpImm.immSign;
2929 unsigned exp = fpImm.immExp ^ 0x4;
2930 unsigned mant = fpImm.immMant + 16;
2931 unsigned scale = 16 * 8;
2939 double result = ((double)mant) / ((double)scale);
2948 /************************************************************************
2950 * returns true if the 'immDbl' can be encoded using the 'float 8-bit immediate' form.
2951 * also returns the encoding if wbFPI is non-null
2955 /*static*/ bool emitter::canEncodeFloatImm8(double immDbl, emitter::floatImm8* wbFPI)
2957 bool canEncode = false;
2958 double val = immDbl;
2968 while ((val < 1.0) && (exp >= -4))
2973 while ((val >= 2.0) && (exp <= 5))
2980 int ival = (int)val;
2982 if ((exp >= 0) && (exp <= 7))
2984 if (val == (double)ival)
2988 if (wbFPI != nullptr)
2991 assert((ival >= 0) && (ival <= 15));
2993 wbFPI->immSign = sign;
2994 wbFPI->immExp = exp ^ 0x4;
2995 wbFPI->immMant = ival;
2996 unsigned imm8 = wbFPI->immFPIVal;
2997 assert((imm8 >= 0) && (imm8 <= 0xff));
3005 /************************************************************************
3007 * Convert a double into its 'float 8-bit immediate' representation
3010 /*static*/ emitter::floatImm8 emitter::emitEncodeFloatImm8(double immDbl)
3012 emitter::floatImm8 result;
3013 result.immFPIVal = 0;
3015 bool canEncode = canEncodeFloatImm8(immDbl, &result);
3021 /*****************************************************************************
3023 * For the given 'ins' returns the reverse instruction
3024 * if one exists, otherwise returns INS_INVALID
3027 /*static*/ instruction emitter::insReverse(instruction ins)
3056 /*****************************************************************************
3058 * For the given 'datasize' and 'elemsize', make the proper arrangement option
3059 * returns the insOpts that specifies the vector register arrangement
3060 * if one does not exist returns INS_OPTS_NONE
3063 /*static*/ insOpts emitter::optMakeArrangement(emitAttr datasize, emitAttr elemsize)
3065 insOpts result = INS_OPTS_NONE;
3067 if (datasize == EA_8BYTE)
3072 result = INS_OPTS_8B;
3075 result = INS_OPTS_4H;
3078 result = INS_OPTS_2S;
3081 result = INS_OPTS_1D;
3088 else if (datasize == EA_16BYTE)
3093 result = INS_OPTS_16B;
3096 result = INS_OPTS_8H;
3099 result = INS_OPTS_4S;
3102 result = INS_OPTS_2D;
3112 /*****************************************************************************
3114 * For the given 'datasize' and arrangement 'opts'
3115 * returns true is the pair spcifies a valid arrangement
3117 /*static*/ bool emitter::isValidArrangement(emitAttr datasize, insOpts opt)
3119 if (datasize == EA_8BYTE)
3121 if ((opt == INS_OPTS_8B) || (opt == INS_OPTS_4H) || (opt == INS_OPTS_2S) || (opt == INS_OPTS_1D))
3126 else if (datasize == EA_16BYTE)
3128 if ((opt == INS_OPTS_16B) || (opt == INS_OPTS_8H) || (opt == INS_OPTS_4S) || (opt == INS_OPTS_2D))
3136 // For the given 'arrangement' returns the 'datasize' specified by the vector register arrangement
3137 // asserts and returns EA_UNKNOWN if an invalid 'arrangement' value is passed
3139 /*static*/ emitAttr emitter::optGetDatasize(insOpts arrangement)
3141 if ((arrangement == INS_OPTS_8B) || (arrangement == INS_OPTS_4H) || (arrangement == INS_OPTS_2S) ||
3142 (arrangement == INS_OPTS_1D))
3146 else if ((arrangement == INS_OPTS_16B) || (arrangement == INS_OPTS_8H) || (arrangement == INS_OPTS_4S) ||
3147 (arrangement == INS_OPTS_2D))
3153 assert(!" invalid 'arrangement' value");
3158 // For the given 'arrangement' returns the 'elemsize' specified by the vector register arrangement
3159 // asserts and returns EA_UNKNOWN if an invalid 'arrangement' value is passed
3161 /*static*/ emitAttr emitter::optGetElemsize(insOpts arrangement)
3163 if ((arrangement == INS_OPTS_8B) || (arrangement == INS_OPTS_16B))
3167 else if ((arrangement == INS_OPTS_4H) || (arrangement == INS_OPTS_8H))
3171 else if ((arrangement == INS_OPTS_2S) || (arrangement == INS_OPTS_4S))
3175 else if ((arrangement == INS_OPTS_1D) || (arrangement == INS_OPTS_2D))
3181 assert(!" invalid 'arrangement' value");
3186 // For the given 'arrangement' returns the 'widen-arrangement' specified by the vector register arrangement
3187 // asserts and returns INS_OPTS_NONE if an invalid 'arrangement' value is passed
3189 /*static*/ insOpts emitter::optWidenElemsize(insOpts arrangement)
3191 if ((arrangement == INS_OPTS_8B) || (arrangement == INS_OPTS_16B))
3195 else if ((arrangement == INS_OPTS_4H) || (arrangement == INS_OPTS_8H))
3199 else if ((arrangement == INS_OPTS_2S) || (arrangement == INS_OPTS_4S))
3205 assert(!" invalid 'arrangement' value");
3206 return INS_OPTS_NONE;
3210 // For the given 'conversion' returns the 'dstsize' specified by the conversion option
3211 /*static*/ emitAttr emitter::optGetDstsize(insOpts conversion)
3215 case INS_OPTS_S_TO_8BYTE:
3216 case INS_OPTS_D_TO_8BYTE:
3217 case INS_OPTS_4BYTE_TO_D:
3218 case INS_OPTS_8BYTE_TO_D:
3219 case INS_OPTS_S_TO_D:
3220 case INS_OPTS_H_TO_D:
3224 case INS_OPTS_S_TO_4BYTE:
3225 case INS_OPTS_D_TO_4BYTE:
3226 case INS_OPTS_4BYTE_TO_S:
3227 case INS_OPTS_8BYTE_TO_S:
3228 case INS_OPTS_D_TO_S:
3229 case INS_OPTS_H_TO_S:
3233 case INS_OPTS_S_TO_H:
3234 case INS_OPTS_D_TO_H:
3239 assert(!" invalid 'conversion' value");
3244 // For the given 'conversion' returns the 'srcsize' specified by the conversion option
3245 /*static*/ emitAttr emitter::optGetSrcsize(insOpts conversion)
3249 case INS_OPTS_D_TO_8BYTE:
3250 case INS_OPTS_D_TO_4BYTE:
3251 case INS_OPTS_8BYTE_TO_D:
3252 case INS_OPTS_8BYTE_TO_S:
3253 case INS_OPTS_D_TO_S:
3254 case INS_OPTS_D_TO_H:
3258 case INS_OPTS_S_TO_8BYTE:
3259 case INS_OPTS_S_TO_4BYTE:
3260 case INS_OPTS_4BYTE_TO_S:
3261 case INS_OPTS_4BYTE_TO_D:
3262 case INS_OPTS_S_TO_D:
3263 case INS_OPTS_S_TO_H:
3267 case INS_OPTS_H_TO_S:
3268 case INS_OPTS_H_TO_D:
3273 assert(!" invalid 'conversion' value");
3278 // For the given 'size' and 'index' returns true if it specifies a valid index for a vector register of 'size'
3279 /*static*/ bool emitter::isValidVectorIndex(emitAttr datasize, emitAttr elemsize, ssize_t index)
3281 assert(isValidVectorDatasize(datasize));
3282 assert(isValidVectorElemsize(elemsize));
3284 bool result = false;
3287 if (datasize == EA_8BYTE)
3292 result = (index < 8);
3295 result = (index < 4);
3298 result = (index < 2);
3301 result = (index < 1);
3308 else if (datasize == EA_16BYTE)
3313 result = (index < 16);
3316 result = (index < 8);
3319 result = (index < 4);
3322 result = (index < 2);
3333 /*****************************************************************************
3335 * Add an instruction with no operands.
3338 void emitter::emitIns(instruction ins)
3340 instrDesc* id = emitNewInstrSmall(EA_8BYTE);
3341 insFormat fmt = emitInsFormat(ins);
3343 assert(fmt == IF_SN_0A);
3352 /*****************************************************************************
3354 * Add an instruction with a single immediate value.
3357 void emitter::emitIns_I(instruction ins, emitAttr attr, ssize_t imm)
3359 insFormat fmt = IF_NONE;
3361 /* Figure out the encoding format of the instruction */
3365 if ((imm & 0x0000ffff) == imm)
3371 assert(!"Instruction cannot be encoded: IF_SI_0A");
3378 assert(fmt != IF_NONE);
3380 instrDesc* id = emitNewInstrSC(attr, imm);
3389 /*****************************************************************************
3391 * Add an instruction referencing a single register.
3394 void emitter::emitIns_R(instruction ins, emitAttr attr, regNumber reg)
3396 insFormat fmt = IF_NONE;
3397 instrDesc* id = nullptr;
3399 /* Figure out the encoding format of the instruction */
3404 assert(isGeneralRegister(reg));
3405 id = emitNewInstrSmall(attr);
3414 assert(fmt != IF_NONE);
3423 /*****************************************************************************
3425 * Add an instruction referencing a register and a constant.
3428 void emitter::emitIns_R_I(instruction ins, emitAttr attr, regNumber reg, ssize_t imm, insOpts opt /* = INS_OPTS_NONE */)
3430 emitAttr size = EA_SIZE(attr);
3431 emitAttr elemsize = EA_UNKNOWN;
3432 insFormat fmt = IF_NONE;
3433 bool canEncode = false;
3435 /* Figure out the encoding format of the instruction */
3444 assert(insOptsNone(opt));
3445 assert(isGeneralRegister(reg));
3447 canEncode = canEncodeBitMaskImm(imm, size, &bmi);
3451 assert(isValidImmNRS(imm, size));
3459 assert(isValidGeneralDatasize(size));
3460 assert(insOptsNone(opt)); // No LSL here (you must use emitIns_R_I_I if a shift is needed)
3461 assert(isGeneralRegister(reg));
3462 assert(isValidUimm16(imm));
3466 assert(imm == emitDecodeHalfwordImm(hwi, size));
3474 assert(isValidGeneralDatasize(size));
3475 assert(insOptsNone(opt)); // No explicit LSL here
3476 // We will automatically determine the shift based upon the imm
3478 // First try the standard 'halfword immediate' imm(i16,hw)
3480 canEncode = canEncodeHalfwordImm(imm, size, &hwi);
3483 // uses a movz encoding
3484 assert(isGeneralRegister(reg));
3486 assert(isValidImmHWVal(imm, size));
3491 // Next try the ones-complement form of 'halfword immediate' imm(i16,hw)
3492 notOfImm = NOT_helper(imm, getBitWidth(size));
3493 canEncode = canEncodeHalfwordImm(notOfImm, size, &hwi);
3496 assert(isGeneralRegister(reg));
3498 ins = INS_movn; // uses a movn encoding
3499 assert(isValidImmHWVal(imm, size));
3504 // Finally try the 'bitmask immediate' imm(N,r,s)
3506 canEncode = canEncodeBitMaskImm(imm, size, &bmi);
3509 assert(isGeneralRegisterOrSP(reg));
3510 reg = encodingSPtoZR(reg);
3512 assert(isValidImmNRS(imm, size));
3518 assert(!"Instruction cannot be encoded: mov imm");
3524 assert(isValidVectorDatasize(size));
3525 assert(isVectorRegister(reg));
3526 if (insOptsNone(opt) && (size == EA_8BYTE))
3530 assert(isValidArrangement(size, opt));
3531 elemsize = optGetElemsize(opt);
3533 if (elemsize == EA_8BYTE)
3541 INT64 loByte = uimm & 0xFF;
3542 if (((loByte == 0) || (loByte == 0xFF)) && (pos < 8))
3546 imm8 |= (ssize_t{1} << pos);
3558 assert(isValidUimm8(imm));
3566 // No explicit LSL/MSL is used for the immediate
3567 // We will automatically determine the shift based upon the value of imm
3569 // First try the standard 'byteShifted immediate' imm(i8,bySh)
3571 canEncode = canEncodeByteShiftedImm(imm, elemsize, true, &bsi);
3575 assert(isValidImmBSVal(imm, size));
3580 // Next try the ones-complement form of the 'immediate' imm(i8,bySh)
3581 if ((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE)) // Only EA_2BYTE or EA_4BYTE forms
3583 notOfImm = NOT_helper(imm, getBitWidth(elemsize));
3584 canEncode = canEncodeByteShiftedImm(notOfImm, elemsize, true, &bsi);
3588 ins = INS_mvni; // uses a mvni encoding
3589 assert(isValidImmBSVal(imm, size));
3600 assert(isValidVectorDatasize(size));
3601 assert(isVectorRegister(reg));
3602 assert(isValidArrangement(size, opt));
3603 elemsize = optGetElemsize(opt);
3604 assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE)); // Only EA_2BYTE or EA_4BYTE forms
3608 // No explicit LSL/MSL is used for the immediate
3609 // We will automatically determine the shift based upon the value of imm
3611 // First try the standard 'byteShifted immediate' imm(i8,bySh)
3613 canEncode = canEncodeByteShiftedImm(imm, elemsize,
3614 (ins == INS_mvni), // mvni supports the ones shifting variant (aka MSL)
3619 assert(isValidImmBSVal(imm, size));
3627 assert(insOptsNone(opt));
3628 assert(isGeneralRegister(reg));
3630 if (unsigned_abs(imm) <= 0x0fff)
3634 ins = insReverse(ins);
3637 assert(isValidUimm12(imm));
3641 else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
3643 // Encoding will use a 12-bit left shift of the immediate
3644 opt = INS_OPTS_LSL12;
3647 ins = insReverse(ins);
3650 assert((imm & 0xfff) == 0);
3652 assert(isValidUimm12(imm));
3658 assert(!"Instruction cannot be encoded: IF_DI_1A");
3666 } // end switch (ins)
3669 assert(fmt != IF_NONE);
3671 instrDesc* id = emitNewInstrSC(attr, imm);
3683 /*****************************************************************************
3685 * Add an instruction referencing a register and a floating point constant.
3688 void emitter::emitIns_R_F(
3689 instruction ins, emitAttr attr, regNumber reg, double immDbl, insOpts opt /* = INS_OPTS_NONE */)
3692 emitAttr size = EA_SIZE(attr);
3693 emitAttr elemsize = EA_UNKNOWN;
3694 insFormat fmt = IF_NONE;
3696 bool canEncode = false;
3698 /* Figure out the encoding format of the instruction */
3705 assert(insOptsNone(opt));
3706 assert(isValidVectorElemsizeFloat(size));
3707 assert(isVectorRegister(reg));
3716 assert(isVectorRegister(reg));
3718 canEncode = canEncodeFloatImm8(immDbl, &fpi);
3720 if (insOptsAnyArrangement(opt))
3723 assert(isValidVectorDatasize(size));
3724 assert(isValidArrangement(size, opt));
3725 elemsize = optGetElemsize(opt);
3726 assert(isValidVectorElemsizeFloat(elemsize));
3727 assert(opt != INS_OPTS_1D); // Reserved encoding
3731 imm = fpi.immFPIVal;
3732 assert((imm >= 0) && (imm <= 0xff));
3739 assert(insOptsNone(opt));
3740 assert(isValidVectorElemsizeFloat(size));
3744 imm = fpi.immFPIVal;
3745 assert((imm >= 0) && (imm <= 0xff));
3755 } // end switch (ins)
3758 assert(fmt != IF_NONE);
3760 instrDesc* id = emitNewInstrSC(attr, imm);
3772 /*****************************************************************************
3774 * Add an instruction referencing two registers
3777 void emitter::emitIns_R_R(
3778 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insOpts opt /* = INS_OPTS_NONE */)
3780 emitAttr size = EA_SIZE(attr);
3781 emitAttr elemsize = EA_UNKNOWN;
3782 insFormat fmt = IF_NONE;
3784 /* Figure out the encoding format of the instruction */
3788 assert(insOptsNone(opt));
3789 // Is the mov even necessary?
3792 // A mov with a EA_4BYTE has the side-effect of clearing the upper bits
3793 // So only eliminate mov instructions that are not clearing the upper bits
3795 if (isGeneralRegisterOrSP(reg1) && (size == EA_8BYTE))
3799 else if (isVectorRegister(reg1) && (size == EA_16BYTE))
3805 // Check for the 'mov' aliases for the vector registers
3806 if (isVectorRegister(reg1))
3808 if (isVectorRegister(reg2) && isValidVectorDatasize(size))
3810 return emitIns_R_R_R(INS_mov, size, reg1, reg2, reg2);
3814 return emitIns_R_R_I(INS_mov, size, reg1, reg2, 0);
3819 if (isVectorRegister(reg2))
3821 assert(isGeneralRegister(reg1));
3822 return emitIns_R_R_I(INS_mov, size, reg1, reg2, 0);
3826 // Is this a MOV to/from SP instruction?
3827 if ((reg1 == REG_SP) || (reg2 == REG_SP))
3829 assert(isGeneralRegisterOrSP(reg1));
3830 assert(isGeneralRegisterOrSP(reg2));
3831 reg1 = encodingSPtoZR(reg1);
3832 reg2 = encodingSPtoZR(reg2);
3837 assert(insOptsNone(opt));
3838 assert(isGeneralRegister(reg1));
3839 assert(isGeneralRegisterOrZR(reg2));
3846 assert(insOptsAnyArrangement(opt));
3847 assert(isVectorRegister(reg1));
3848 assert(isGeneralRegisterOrZR(reg2));
3849 assert(isValidVectorDatasize(size));
3850 assert(isValidArrangement(size, opt));
3856 assert(isVectorRegister(reg1));
3857 assert(isVectorRegister(reg2));
3860 assert(isValidVectorDatasize(size));
3861 // Bitwise behavior is independent of element size, but is always encoded as 1 Byte
3862 opt = optMakeArrangement(size, EA_1BYTE);
3864 if (insOptsNone(opt))
3867 assert(size == EA_8BYTE); // Only type D is supported
3873 assert(insOptsAnyArrangement(opt));
3874 assert(isValidVectorDatasize(size));
3875 assert(isValidArrangement(size, opt));
3876 elemsize = optGetElemsize(opt);
3883 if (isVectorRegister(reg1))
3885 assert(isVectorRegister(reg2));
3888 assert(isValidVectorDatasize(size));
3889 // Bitwise behavior is independent of element size, but is always encoded as 1 Byte
3890 opt = optMakeArrangement(size, EA_1BYTE);
3892 if (insOptsNone(opt))
3895 assert(size == EA_8BYTE); // Only type D is supported
3901 assert(isValidVectorDatasize(size));
3902 assert(isValidArrangement(size, opt));
3903 elemsize = optGetElemsize(opt);
3911 assert(insOptsNone(opt));
3912 assert(isGeneralRegister(reg1));
3913 assert(isGeneralRegisterOrZR(reg2));
3918 assert(size == EA_8BYTE);
3925 assert(insOptsNone(opt));
3926 assert(isValidGeneralDatasize(size));
3927 assert(isGeneralRegister(reg1));
3928 assert(isGeneralRegister(reg2));
3936 return emitIns_R_R_I(ins, size, reg1, reg2, 0, opt);
3944 if (isVectorRegister(reg1))
3946 assert(isVectorRegister(reg2));
3947 assert(isValidVectorDatasize(size));
3948 assert(isValidArrangement(size, opt));
3949 elemsize = optGetElemsize(opt);
3950 if ((ins == INS_cls) || (ins == INS_clz))
3952 assert(elemsize != EA_8BYTE); // No encoding for type D
3954 else if (ins == INS_rev32)
3956 assert((elemsize == EA_2BYTE) || (elemsize == EA_1BYTE));
3960 assert(elemsize == EA_1BYTE); // Only supports 8B or 16B
3967 // Doesn't have general register version(s)
3974 assert(insOptsNone(opt));
3975 assert(isGeneralRegister(reg1));
3976 assert(isGeneralRegister(reg2));
3977 if (ins == INS_rev32)
3979 assert(size == EA_8BYTE);
3983 assert(isValidGeneralDatasize(size));
3996 assert(isVectorRegister(reg1));
3997 assert(isVectorRegister(reg2));
3998 assert(isValidVectorDatasize(size));
3999 assert(isValidArrangement(size, opt));
4000 elemsize = optGetElemsize(opt);
4001 assert(elemsize != EA_8BYTE); // No encoding for type D
4007 assert(isVectorRegister(reg1));
4008 assert(isVectorRegister(reg2));
4009 assert(isValidVectorDatasize(size));
4010 assert(isValidArrangement(size, opt));
4011 elemsize = optGetElemsize(opt);
4012 // size is determined by instruction
4015 assert(size == EA_8BYTE);
4017 else // ins == INS_xtn2
4019 assert(size == EA_16BYTE);
4021 assert(elemsize != EA_8BYTE); // Narrowing must not end with 8 byte data
4029 assert(isValidGeneralDatasize(size));
4041 assert(isValidGeneralLSDatasize(size));
4042 assert(isGeneralRegisterOrZR(reg1));
4043 assert(isGeneralRegisterOrSP(reg2));
4044 assert(insOptsNone(opt));
4046 reg2 = encodingSPtoZR(reg2);
4064 assert(insOptsNone(opt));
4065 emitIns_R_R_I(ins, attr, reg1, reg2, 0, INS_OPTS_NONE);
4069 emitIns_R_R_R(INS_ldaddb, attr, reg1, REG_ZR, reg2);
4072 emitIns_R_R_R(INS_ldaddlb, attr, reg1, REG_ZR, reg2);
4075 emitIns_R_R_R(INS_ldaddh, attr, reg1, REG_ZR, reg2);
4078 emitIns_R_R_R(INS_ldaddlh, attr, reg1, REG_ZR, reg2);
4081 emitIns_R_R_R(INS_ldadd, attr, reg1, REG_ZR, reg2);
4084 emitIns_R_R_R(INS_ldaddl, attr, reg1, REG_ZR, reg2);
4088 assert(isValidVectorElemsizeFloat(size));
4090 // Is the mov even necessary?
4096 if (isVectorRegister(reg1))
4098 if (isVectorRegister(reg2))
4100 assert(insOptsNone(opt));
4105 assert(isGeneralRegister(reg2));
4107 // if the optional conversion specifier is not present we calculate it
4108 if (opt == INS_OPTS_NONE)
4110 opt = (size == EA_4BYTE) ? INS_OPTS_4BYTE_TO_S : INS_OPTS_8BYTE_TO_D;
4112 assert(insOptsConvertIntToFloat(opt));
4119 assert(isGeneralRegister(reg1));
4120 assert(isVectorRegister(reg2));
4122 // if the optional conversion specifier is not present we calculate it
4123 if (opt == INS_OPTS_NONE)
4125 opt = (size == EA_4BYTE) ? INS_OPTS_S_TO_4BYTE : INS_OPTS_D_TO_8BYTE;
4127 assert(insOptsConvertFloatToInt(opt));
4135 assert(insOptsNone(opt));
4136 assert(isValidVectorElemsizeFloat(size));
4137 assert(isVectorRegister(reg1));
4138 assert(isVectorRegister(reg2));
4152 if (insOptsAnyArrangement(opt))
4155 assert(isVectorRegister(reg1));
4156 assert(isVectorRegister(reg2));
4157 assert(isValidVectorDatasize(size));
4158 assert(isValidArrangement(size, opt));
4159 elemsize = optGetElemsize(opt);
4160 assert(isValidVectorElemsizeFloat(elemsize));
4161 assert(opt != INS_OPTS_1D); // Reserved encoding
4167 assert(isVectorRegister(reg2));
4168 if (isVectorRegister(reg1))
4170 assert(insOptsNone(opt));
4171 assert(isValidVectorElemsizeFloat(size));
4176 assert(isGeneralRegister(reg1));
4177 assert(insOptsConvertFloatToInt(opt));
4178 assert(isValidVectorElemsizeFloat(size));
4188 assert(isVectorRegister(reg1));
4189 assert(isVectorRegister(reg2));
4190 assert(isValidVectorDatasize(size));
4191 assert(insOptsNone(opt));
4192 assert(size == EA_8BYTE); // Narrowing from Double or Widening to Double (Half not supported)
4198 if (insOptsAnyArrangement(opt))
4201 assert(isVectorRegister(reg1));
4202 assert(isVectorRegister(reg2));
4203 assert(isValidVectorDatasize(size));
4204 assert(isValidArrangement(size, opt));
4205 elemsize = optGetElemsize(opt);
4206 assert(isValidVectorElemsizeFloat(elemsize));
4207 assert(opt != INS_OPTS_1D); // Reserved encoding
4213 assert(isVectorRegister(reg1));
4214 if (isVectorRegister(reg2))
4216 assert(insOptsNone(opt));
4217 assert(isValidVectorElemsizeFloat(size));
4222 assert(isGeneralRegister(reg2));
4223 assert(insOptsConvertIntToFloat(opt));
4224 assert(isValidVectorElemsizeFloat(size));
4240 if (insOptsAnyArrangement(opt))
4243 assert(isVectorRegister(reg1));
4244 assert(isVectorRegister(reg2));
4245 assert(isValidVectorDatasize(size));
4246 assert(isValidArrangement(size, opt));
4247 elemsize = optGetElemsize(opt);
4248 assert(isValidVectorElemsizeFloat(elemsize));
4249 assert(opt != INS_OPTS_1D); // Reserved encoding
4255 assert(insOptsNone(opt));
4256 assert(isValidVectorElemsizeFloat(size));
4257 assert(isVectorRegister(reg1));
4258 assert(isVectorRegister(reg2));
4265 assert(insOptsNone(opt));
4266 assert(isValidVectorElemsizeFloat(size));
4267 assert(isVectorRegister(reg1));
4268 assert(isVectorRegister(reg2));
4273 assert(insOptsConvertFloatToFloat(opt));
4274 assert(isValidVectorFcvtsize(size));
4275 assert(isVectorRegister(reg1));
4276 assert(isVectorRegister(reg2));
4285 assert(isVectorRegister(reg1));
4286 assert(isVectorRegister(reg2));
4288 if (isValidVectorDatasize(size))
4291 assert(insOptsAnyArrangement(opt));
4292 assert(isValidArrangement(size, opt));
4293 elemsize = optGetElemsize(opt);
4300 assert(size == EA_8BYTE); // Only Double supported
4310 assert(isVectorRegister(reg1));
4311 assert(isVectorRegister(reg2));
4313 if (isValidVectorDatasize(size))
4316 assert(insOptsAnyArrangement(opt));
4317 assert(isValidArrangement(size, opt));
4318 elemsize = optGetElemsize(opt);
4319 assert((elemsize == EA_8BYTE) || (elemsize == EA_4BYTE)); // Only Double/Float supported
4320 assert(opt != INS_OPTS_1D); // Reserved encoding
4327 assert((size == EA_8BYTE) || (size == EA_4BYTE)); // Only Double/Float supported
4335 assert(isVectorRegister(reg1));
4336 assert(isVectorRegister(reg2));
4337 assert(isValidVectorDatasize(size));
4338 elemsize = optGetElemsize(opt);
4339 assert(elemsize == EA_1BYTE);
4344 assert(insOptsNone(opt));
4345 assert(isVectorRegister(reg1));
4346 assert(isVectorRegister(reg2));
4352 assert(isVectorRegister(reg1));
4353 assert(isVectorRegister(reg2));
4354 assert(isValidVectorDatasize(size));
4355 elemsize = optGetElemsize(opt);
4356 assert(elemsize == EA_4BYTE);
4364 } // end switch (ins)
4366 assert(fmt != IF_NONE);
4368 instrDesc* id = emitNewInstrSmall(attr);
4381 /*****************************************************************************
4383 * Add an instruction referencing a register and two constants.
4386 void emitter::emitIns_R_I_I(
4387 instruction ins, emitAttr attr, regNumber reg, ssize_t imm1, ssize_t imm2, insOpts opt /* = INS_OPTS_NONE */)
4389 emitAttr size = EA_SIZE(attr);
4390 insFormat fmt = IF_NONE;
4391 size_t immOut = 0; // composed from imm1 and imm2 and stored in the instrDesc
4393 /* Figure out the encoding format of the instruction */
4400 ins = INS_movz; // INS_mov with LSL is an alias for INS_movz LSL
4406 assert(isValidGeneralDatasize(size));
4407 assert(isGeneralRegister(reg));
4408 assert(isValidUimm16(imm1));
4409 assert(insOptsLSL(opt)); // Must be INS_OPTS_LSL
4411 if (size == EA_8BYTE)
4413 assert((imm2 == 0) || (imm2 == 16) || // shift amount: 0, 16, 32 or 48
4414 (imm2 == 32) || (imm2 == 48));
4418 assert((imm2 == 0) || (imm2 == 16)); // shift amount: 0 or 16
4453 immOut = hwi.immHWVal;
4454 assert(isValidImmHWVal(immOut, size));
4463 } // end switch (ins)
4465 assert(fmt != IF_NONE);
4467 instrDesc* id = emitNewInstrSC(attr, immOut);
4478 /*****************************************************************************
4480 * Add an instruction referencing two registers and a constant.
4483 void emitter::emitIns_R_R_I(
4484 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm, insOpts opt /* = INS_OPTS_NONE */)
4486 emitAttr size = EA_SIZE(attr);
4487 emitAttr elemsize = EA_UNKNOWN;
4488 insFormat fmt = IF_NONE;
4489 bool isLdSt = false;
4490 bool isSIMD = false;
4491 bool isAddSub = false;
4492 bool setFlags = false;
4494 bool unscaledOp = false;
4496 /* Figure out the encoding format of the instruction */
4503 // Check for the 'mov' aliases for the vector registers
4504 assert(insOptsNone(opt));
4505 assert(isValidVectorElemsize(size));
4507 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4509 if (isVectorRegister(reg1))
4511 if (isGeneralRegisterOrZR(reg2))
4513 fmt = IF_DV_2C; // Alias for 'ins'
4516 else if (isVectorRegister(reg2))
4518 fmt = IF_DV_2E; // Alias for 'dup'
4522 else // isGeneralRegister(reg1)
4524 assert(isGeneralRegister(reg1));
4525 if (isVectorRegister(reg2))
4527 fmt = IF_DV_2B; // Alias for 'umov'
4531 assert(!" invalid INS_mov operands");
4537 assert(insOptsNone(opt));
4538 assert(isValidGeneralDatasize(size));
4539 assert(isGeneralRegister(reg1));
4540 assert(isGeneralRegister(reg2));
4541 assert(isValidImmShift(imm, size));
4546 assert(insOptsNone(opt));
4547 assert(isValidGeneralDatasize(size));
4548 assert(isGeneralRegister(reg1));
4549 assert(isGeneralRegister(reg2));
4550 assert(isValidImmShift(imm, size));
4565 assert(isVectorRegister(reg1));
4566 assert(isVectorRegister(reg2));
4567 if (insOptsAnyArrangement(opt))
4570 assert(isValidVectorDatasize(size));
4571 assert(isValidArrangement(size, opt));
4572 elemsize = optGetElemsize(opt);
4573 assert(isValidVectorElemsize(elemsize));
4574 assert(isValidImmShift(imm, elemsize));
4575 assert(opt != INS_OPTS_1D); // Reserved encoding
4582 assert(insOptsNone(opt));
4583 assert(size == EA_8BYTE); // only supported size
4584 assert(isValidImmShift(imm, size));
4598 assert(isVectorRegister(reg1));
4599 assert(isVectorRegister(reg2));
4601 assert(size == EA_8BYTE);
4602 assert(isValidArrangement(size, opt));
4603 elemsize = optGetElemsize(opt);
4604 assert(elemsize != EA_8BYTE); // Reserved encodings
4605 assert(isValidVectorElemsize(elemsize));
4606 assert(isValidImmShift(imm, elemsize));
4619 assert(isVectorRegister(reg1));
4620 assert(isVectorRegister(reg2));
4622 assert(size == EA_16BYTE);
4623 assert(isValidArrangement(size, opt));
4624 elemsize = optGetElemsize(opt);
4625 assert(elemsize != EA_8BYTE); // Reserved encodings
4626 assert(isValidVectorElemsize(elemsize));
4627 assert(isValidImmShift(imm, elemsize));
4634 assert(isValidGeneralDatasize(size));
4635 assert(isGeneralRegister(reg1));
4636 assert(isGeneralRegisterOrZR(reg2));
4640 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4648 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
4652 assert(insOptsAluShift(opt)); // a non-zero imm, must select shift kind, can't use ROR
4654 assert(isValidImmShift(imm, size));
4660 assert(isValidGeneralDatasize(size));
4661 assert(isGeneralRegisterOrZR(reg1));
4662 assert(isGeneralRegister(reg2));
4664 if (insOptsAnyShift(opt))
4666 assert(isValidImmShift(imm, size) && (imm != 0));
4671 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4679 assert(isValidGeneralDatasize(size));
4680 assert(isGeneralRegisterOrSP(reg1));
4681 assert(isGeneralRegister(reg2));
4683 reg1 = encodingSPtoZR(reg1);
4684 if (insOptsAnyExtend(opt))
4686 assert((imm >= 0) && (imm <= 4));
4692 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4698 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
4699 assert(isValidImmShift(imm, size));
4708 assert(insOptsNone(opt));
4709 assert(isGeneralRegister(reg2));
4710 if (ins == INS_ands)
4712 assert(isGeneralRegister(reg1));
4716 assert(isGeneralRegisterOrSP(reg1));
4717 reg1 = encodingSPtoZR(reg1);
4721 canEncode = canEncodeBitMaskImm(imm, size, &bmi);
4725 assert(isValidImmNRS(imm, size));
4730 case INS_dup: // by element, imm selects the element of reg2
4731 assert(isVectorRegister(reg1));
4732 if (isVectorRegister(reg2))
4734 if (insOptsAnyArrangement(opt))
4737 assert(isValidVectorDatasize(size));
4738 assert(isValidArrangement(size, opt));
4739 elemsize = optGetElemsize(opt);
4740 assert(isValidVectorElemsize(elemsize));
4741 assert(isValidVectorIndex(size, elemsize, imm));
4742 assert(opt != INS_OPTS_1D); // Reserved encoding
4749 assert(insOptsNone(opt));
4751 assert(isValidVectorElemsize(elemsize));
4752 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4759 case INS_ins: // (MOV from general)
4760 assert(insOptsNone(opt));
4761 assert(isValidVectorElemsize(size));
4762 assert(isVectorRegister(reg1));
4763 assert(isGeneralRegisterOrZR(reg2));
4765 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4769 case INS_umov: // (MOV to general)
4770 assert(insOptsNone(opt));
4771 assert(isValidVectorElemsize(size));
4772 assert(isGeneralRegister(reg1));
4773 assert(isVectorRegister(reg2));
4775 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4780 assert(insOptsNone(opt));
4781 assert(isValidVectorElemsize(size));
4782 assert(size != EA_8BYTE); // no encoding, use INS_umov
4783 assert(isGeneralRegister(reg1));
4784 assert(isVectorRegister(reg2));
4786 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4804 // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4805 assert(isValidGeneralDatasize(size));
4806 unscaledOp = (ins == INS_ldursb);
4813 // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4814 assert(isValidGeneralDatasize(size));
4815 unscaledOp = (ins == INS_ldursh);
4822 // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4823 assert(size == EA_8BYTE);
4824 unscaledOp = (ins == INS_ldursw);
4863 // Is the target a vector register?
4864 if (isVectorRegister(reg1))
4866 assert(isValidVectorLSDatasize(size));
4867 assert(isGeneralRegisterOrSP(reg2));
4872 assert(isValidGeneralDatasize(size));
4875 scale = NaturalScale_helper(size);
4881 // Is the target a vector register?
4882 if (isVectorRegister(reg1))
4884 assert(isValidVectorLSDatasize(size));
4885 assert(isGeneralRegisterOrSP(reg2));
4890 assert(isValidGeneralDatasize(size));
4901 } // end switch (ins)
4909 assert(isValidVectorLSDatasize(size));
4910 assert(isVectorRegister(reg1));
4911 assert((scale >= 0) && (scale <= 4));
4915 assert(isValidGeneralLSDatasize(size));
4916 assert(isGeneralRegisterOrZR(reg1));
4917 assert((scale >= 0) && (scale <= 3));
4920 assert(isGeneralRegisterOrSP(reg2));
4922 // Load/Store reserved encodings:
4923 if (insOptsIndexed(opt))
4925 assert(reg1 != reg2);
4928 reg2 = encodingSPtoZR(reg2);
4930 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
4933 assert(insOptsNone(opt)); // PRE/POST Index doesn't make sense with an immediate of zero
4937 else if (insOptsIndexed(opt) || unscaledOp || (imm < 0) || ((imm & mask) != 0))
4939 if ((imm >= -256) && (imm <= 255))
4945 assert(!"Instruction cannot be encoded: IF_LS_2C");
4950 assert(insOptsNone(opt));
4951 assert(!unscaledOp);
4953 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
4955 imm >>= scale; // The immediate is scaled by the size of the ld/st
4961 assert(!"Instruction cannot be encoded: IF_LS_2B");
4968 assert(insOptsNone(opt));
4970 if (setFlags) // Can't encode SP with setFlags
4972 assert(isGeneralRegister(reg1));
4973 assert(isGeneralRegister(reg2));
4977 assert(isGeneralRegisterOrSP(reg1));
4978 assert(isGeneralRegisterOrSP(reg2));
4980 // Is it just a mov?
4983 // Is the mov even necessary?
4986 emitIns_R_R(INS_mov, attr, reg1, reg2);
4991 reg1 = encodingSPtoZR(reg1);
4992 reg2 = encodingSPtoZR(reg2);
4995 if (unsigned_abs(imm) <= 0x0fff)
4999 ins = insReverse(ins);
5002 assert(isValidUimm12(imm));
5005 else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
5007 // Encoding will use a 12-bit left shift of the immediate
5008 opt = INS_OPTS_LSL12;
5011 ins = insReverse(ins);
5014 assert((imm & 0xfff) == 0);
5016 assert(isValidUimm12(imm));
5021 assert(!"Instruction cannot be encoded: IF_DI_2A");
5025 assert(fmt != IF_NONE);
5027 instrDesc* id = emitNewInstrSC(attr, imm);
5040 /*****************************************************************************
5042 * Add an instruction referencing two registers and a constant.
5043 * Also checks for a large immediate that needs a second instruction
5044 * and will load it in reg1
5046 * - Supports instructions: add, adds, sub, subs, and, ands, eor and orr
5047 * - Requires that reg1 is a general register and not SP or ZR
5048 * - Requires that reg1 != reg2
5050 void emitter::emitIns_R_R_Imm(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm)
5052 assert(isGeneralRegister(reg1));
5053 assert(reg1 != reg2);
5055 bool immFits = true;
5063 immFits = emitter::emitIns_valid_imm_for_add(imm, attr);
5070 immFits = emitter::emitIns_valid_imm_for_alu(imm, attr);
5074 assert(!"Unsupported instruction in emitIns_R_R_Imm");
5079 emitIns_R_R_I(ins, attr, reg1, reg2, imm);
5083 // Load 'imm' into the reg1 register
5084 // then issue: 'ins' reg1, reg2, reg1
5086 codeGen->instGen_Set_Reg_To_Imm(attr, reg1, imm);
5087 emitIns_R_R_R(ins, attr, reg1, reg2, reg1);
5091 /*****************************************************************************
5093 * Add an instruction referencing three registers.
5096 void emitter::emitIns_R_R_R(
5097 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insOpts opt) /* = INS_OPTS_NONE */
5099 emitAttr size = EA_SIZE(attr);
5100 emitAttr elemsize = EA_UNKNOWN;
5101 insFormat fmt = IF_NONE;
5103 /* Figure out the encoding format of the instruction */
5127 assert(insOptsNone(opt));
5128 assert(isValidGeneralDatasize(size));
5129 assert(isGeneralRegister(reg1));
5130 assert(isGeneralRegister(reg2));
5131 assert(isGeneralRegister(reg3));
5136 if (insOptsNone(opt))
5139 assert(isValidGeneralDatasize(size));
5140 assert(isGeneralRegister(reg1));
5141 assert(isGeneralRegister(reg2));
5142 assert(isGeneralRegister(reg3));
5151 assert(insOptsAnyArrangement(opt));
5152 assert(isVectorRegister(reg1));
5153 assert(isVectorRegister(reg2));
5154 assert(isVectorRegister(reg3));
5155 assert(isValidVectorDatasize(size));
5156 assert(isValidArrangement(size, opt));
5157 elemsize = optGetElemsize(opt);
5158 if (ins == INS_pmul)
5160 assert(elemsize == EA_1BYTE); // only supports 8B or 16B
5162 else // INS_mul, INS_mla, INS_mls
5164 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
5171 if (isVectorRegister(reg1))
5173 assert(isVectorRegister(reg2));
5174 assert(isVectorRegister(reg3));
5176 if (insOptsAnyArrangement(opt))
5179 assert(opt != INS_OPTS_1D); // Reserved encoding
5180 assert(isValidVectorDatasize(size));
5181 assert(isValidArrangement(size, opt));
5187 assert(insOptsNone(opt));
5188 assert(size == EA_8BYTE);
5197 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, INS_OPTS_NONE);
5206 assert(isVectorRegister(reg1));
5207 assert(isVectorRegister(reg2));
5208 assert(isVectorRegister(reg3));
5210 if (isValidVectorDatasize(size))
5213 assert(insOptsAnyArrangement(opt));
5214 assert(isValidArrangement(size, opt));
5215 elemsize = optGetElemsize(opt);
5222 assert(size == EA_8BYTE); // Only Double supported
5230 assert(isVectorRegister(reg1));
5231 assert(isVectorRegister(reg2));
5232 assert(isVectorRegister(reg3));
5234 if (isValidVectorDatasize(size))
5237 assert(insOptsAnyArrangement(opt));
5238 assert(isValidArrangement(size, opt));
5239 elemsize = optGetElemsize(opt);
5240 assert((elemsize == EA_8BYTE) || (elemsize == EA_4BYTE)); // Only Double/Float supported
5241 assert(opt != INS_OPTS_1D); // Reserved encoding
5248 assert((size == EA_8BYTE) || (size == EA_4BYTE)); // Only Double/Float supported
5261 assert(isVectorRegister(reg1));
5262 assert(isVectorRegister(reg2));
5263 assert(isVectorRegister(reg3));
5264 assert(insOptsAnyArrangement(opt));
5267 assert(isValidVectorDatasize(size));
5268 assert(isValidArrangement(size, opt));
5269 elemsize = optGetElemsize(opt);
5270 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
5276 assert(isVectorRegister(reg1));
5277 assert(isVectorRegister(reg2));
5278 assert(reg2 == reg3);
5279 assert(isValidVectorDatasize(size));
5280 // INS_mov is an alias for INS_orr (vector register)
5281 if (opt == INS_OPTS_NONE)
5283 elemsize = EA_1BYTE;
5284 opt = optMakeArrangement(size, elemsize);
5286 assert(isValidArrangement(size, opt));
5295 if (isVectorRegister(reg1))
5297 assert(isValidVectorDatasize(size));
5298 assert(isVectorRegister(reg2));
5299 assert(isVectorRegister(reg3));
5300 if (opt == INS_OPTS_NONE)
5302 elemsize = EA_1BYTE;
5303 opt = optMakeArrangement(size, elemsize);
5305 assert(isValidArrangement(size, opt));
5314 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, INS_OPTS_NONE);
5320 assert(isValidVectorDatasize(size));
5321 assert(isVectorRegister(reg1));
5322 assert(isVectorRegister(reg2));
5323 assert(isVectorRegister(reg3));
5324 if (opt == INS_OPTS_NONE)
5326 elemsize = EA_1BYTE;
5327 opt = optMakeArrangement(size, elemsize);
5329 assert(isValidArrangement(size, opt));
5341 assert(isVectorRegister(reg1));
5342 assert(isVectorRegister(reg2));
5343 assert(isVectorRegister(reg3));
5344 if (insOptsAnyArrangement(opt))
5347 assert(isValidVectorDatasize(size));
5348 assert(isValidArrangement(size, opt));
5349 elemsize = optGetElemsize(opt);
5350 assert(isValidVectorElemsizeFloat(elemsize));
5351 assert(opt != INS_OPTS_1D); // Reserved encoding
5357 assert(insOptsNone(opt));
5358 assert(isValidScalarDatasize(size));
5365 assert(insOptsNone(opt));
5366 assert(isVectorRegister(reg1));
5367 assert(isVectorRegister(reg2));
5368 assert(isVectorRegister(reg3));
5369 assert(isValidScalarDatasize(size));
5376 assert(isVectorRegister(reg1));
5377 assert(isVectorRegister(reg2));
5378 assert(isVectorRegister(reg3));
5379 assert(insOptsAnyArrangement(opt)); // no scalar encoding, use 4-operand 'fmadd' or 'fmsub'
5382 assert(isValidVectorDatasize(size));
5383 assert(isValidArrangement(size, opt));
5384 elemsize = optGetElemsize(opt);
5385 assert(isValidVectorElemsizeFloat(elemsize));
5386 assert(opt != INS_OPTS_1D); // Reserved encoding
5399 emitIns_R_R_R_Ext(ins, attr, reg1, reg2, reg3, opt);
5407 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0);
5416 assert(isGeneralRegisterOrZR(reg1));
5417 assert(isGeneralRegisterOrZR(reg2));
5418 assert(isGeneralRegisterOrSP(reg3));
5458 assert(isGeneralRegisterOrZR(reg1));
5459 assert(isGeneralRegisterOrZR(reg2));
5460 assert(isGeneralRegisterOrSP(reg3));
5471 assert(isValidVectorDatasize(size));
5472 assert(isVectorRegister(reg1));
5473 assert(isVectorRegister(reg2));
5474 assert(isVectorRegister(reg3));
5475 if (opt == INS_OPTS_NONE)
5477 elemsize = EA_4BYTE;
5478 opt = optMakeArrangement(size, elemsize);
5480 assert(isValidArrangement(size, opt));
5488 } // end switch (ins)
5490 assert(fmt != IF_NONE);
5492 instrDesc* id = emitNewInstr(attr);
5506 /*****************************************************************************
5508 * Add an instruction referencing three registers and a constant.
5511 void emitter::emitIns_R_R_R_I(instruction ins,
5517 insOpts opt /* = INS_OPTS_NONE */,
5518 emitAttr attrReg2 /* = EA_UNKNOWN */)
5520 emitAttr size = EA_SIZE(attr);
5521 emitAttr elemsize = EA_UNKNOWN;
5522 insFormat fmt = IF_NONE;
5523 bool isLdSt = false;
5524 bool isSIMD = false;
5525 bool isAddSub = false;
5526 bool setFlags = false;
5529 /* Figure out the encoding format of the instruction */
5533 assert(insOptsNone(opt));
5534 assert(isValidGeneralDatasize(size));
5535 assert(isGeneralRegister(reg1));
5536 assert(isGeneralRegister(reg2));
5537 assert(isGeneralRegister(reg3));
5538 assert(isValidImmShift(imm, size));
5550 assert(isValidGeneralDatasize(size));
5551 assert(isGeneralRegister(reg1));
5552 assert(isGeneralRegister(reg2));
5553 assert(isGeneralRegister(reg3));
5554 assert(isValidImmShift(imm, size));
5557 assert(insOptsNone(opt)); // a zero imm, means no shift kind
5562 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
5567 case INS_fmul: // by element, imm[0..3] selects the element of reg3
5571 assert(isVectorRegister(reg1));
5572 assert(isVectorRegister(reg2));
5573 assert(isVectorRegister(reg3));
5574 if (insOptsAnyArrangement(opt))
5577 assert(isValidVectorDatasize(size));
5578 assert(isValidArrangement(size, opt));
5579 elemsize = optGetElemsize(opt);
5580 assert(isValidVectorElemsizeFloat(elemsize));
5581 assert(isValidVectorIndex(size, elemsize, imm));
5582 assert(opt != INS_OPTS_1D); // Reserved encoding
5588 assert(insOptsNone(opt));
5589 assert(isValidScalarDatasize(size));
5591 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
5596 case INS_mul: // by element, imm[0..7] selects the element of reg3
5599 assert(isVectorRegister(reg1));
5600 assert(isVectorRegister(reg2));
5601 assert(isVectorRegister(reg3));
5603 assert(insOptsAnyArrangement(opt));
5604 assert(isValidVectorDatasize(size));
5605 assert(isValidArrangement(size, opt));
5606 elemsize = optGetElemsize(opt);
5607 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
5608 // Only has encodings for H or S elemsize
5609 assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE));
5610 // Only has encodings for V0..V15
5611 if ((elemsize == EA_2BYTE) && (reg3 >= REG_V16))
5613 noway_assert(!"Invalid reg3");
5637 assert(insOptsNone(opt)); // Can't use Pre/Post index on these two instructions
5642 // Is the target a vector register?
5643 if (isVectorRegister(reg1))
5645 scale = NaturalScale_helper(size);
5650 scale = (size == EA_8BYTE) ? 3 : 2;
5659 } // end switch (ins)
5664 assert(isGeneralRegisterOrSP(reg3));
5665 assert(insOptsNone(opt) || insOptsIndexed(opt));
5669 assert(isValidVectorLSPDatasize(size));
5670 assert(isVectorRegister(reg1));
5671 assert(isVectorRegister(reg2));
5672 assert((scale >= 2) && (scale <= 4));
5676 assert(isValidGeneralDatasize(size));
5677 assert(isGeneralRegisterOrZR(reg1));
5678 assert(isGeneralRegisterOrZR(reg2));
5679 assert((scale == 2) || (scale == 3));
5682 // Load/Store Pair reserved encodings:
5683 if (emitInsIsLoad(ins))
5685 assert(reg1 != reg2);
5687 if (insOptsIndexed(opt))
5689 assert(reg1 != reg3);
5690 assert(reg2 != reg3);
5693 reg3 = encodingSPtoZR(reg3);
5695 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
5698 assert(insOptsNone(opt)); // PRE/POST Index doesn't make sense with an immediate of zero
5704 if ((imm & mask) == 0)
5706 imm >>= scale; // The immediate is scaled by the size of the ld/st
5708 if ((imm >= -64) && (imm <= 63))
5714 if (fmt != IF_LS_3C)
5716 assert(!"Instruction cannot be encoded: IF_LS_3C");
5723 bool reg2IsSP = (reg2 == REG_SP);
5725 assert(isValidGeneralDatasize(size));
5726 assert(isGeneralRegister(reg3));
5728 if (setFlags || insOptsAluShift(opt)) // Can't encode SP in reg1 with setFlags or AluShift option
5730 assert(isGeneralRegisterOrZR(reg1));
5734 assert(isGeneralRegisterOrSP(reg1));
5735 reg1 = encodingSPtoZR(reg1);
5738 if (insOptsAluShift(opt)) // Can't encode SP in reg2 with AluShift option
5740 assert(isGeneralRegister(reg2));
5744 assert(isGeneralRegisterOrSP(reg2));
5745 reg2 = encodingSPtoZR(reg2);
5748 if (insOptsAnyExtend(opt))
5750 assert((imm >= 0) && (imm <= 4));
5754 else if (insOptsAluShift(opt))
5756 // imm should be non-zero and in [1..63]
5757 assert(isValidImmShift(imm, size) && (imm != 0));
5762 assert(insOptsNone(opt));
5766 // To encode the SP register as reg2 we must use the IF_DR_3C encoding
5767 // and also specify a LSL of zero (imm == 0)
5778 assert(!"Instruction cannot be encoded: Add/Sub IF_DR_3A");
5781 assert(fmt != IF_NONE);
5783 instrDesc* id = emitNewInstrCns(attr, imm);
5793 // Record the attribute for the second register in the pair
5794 id->idGCrefReg2(GCT_NONE);
5795 if (attrReg2 != EA_UNKNOWN)
5797 // Record the attribute for the second register in the pair
5798 assert((fmt == IF_LS_3B) || (fmt == IF_LS_3C));
5799 if (EA_IS_GCREF(attrReg2))
5801 id->idGCrefReg2(GCT_GCREF);
5803 else if (EA_IS_BYREF(attrReg2))
5805 id->idGCrefReg2(GCT_BYREF);
5813 /*****************************************************************************
5815 * Add an instruction referencing three registers, with an extend option
5818 void emitter::emitIns_R_R_R_Ext(instruction ins,
5823 insOpts opt, /* = INS_OPTS_NONE */
5824 int shiftAmount) /* = -1 -- unset */
5826 emitAttr size = EA_SIZE(attr);
5827 insFormat fmt = IF_NONE;
5828 bool isSIMD = false;
5831 /* Figure out the encoding format of the instruction */
5852 // Is the target a vector register?
5853 if (isVectorRegister(reg1))
5855 assert(isValidVectorLSDatasize(size));
5856 scale = NaturalScale_helper(size);
5861 assert(isValidGeneralDatasize(size));
5862 scale = (size == EA_8BYTE) ? 3 : 2;
5871 } // end switch (ins)
5873 assert(scale != -1);
5874 assert(insOptsLSExtend(opt));
5878 assert(isValidVectorLSDatasize(size));
5879 assert(isVectorRegister(reg1));
5883 assert(isValidGeneralLSDatasize(size));
5884 assert(isGeneralRegisterOrZR(reg1));
5887 assert(isGeneralRegisterOrSP(reg2));
5888 assert(isGeneralRegister(reg3));
5890 // Load/Store reserved encodings:
5891 if (insOptsIndexed(opt))
5893 assert(reg1 != reg2);
5896 if (shiftAmount == -1)
5898 shiftAmount = insOptsLSL(opt) ? scale : 0;
5900 assert((shiftAmount == scale) || (shiftAmount == 0));
5902 reg2 = encodingSPtoZR(reg2);
5905 instrDesc* id = emitNewInstr(attr);
5914 id->idReg3Scaled(shiftAmount == scale);
5920 /*****************************************************************************
5922 * Add an instruction referencing two registers and two constants.
5925 void emitter::emitIns_R_R_I_I(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, int imm1, int imm2)
5927 emitAttr size = EA_SIZE(attr);
5928 emitAttr elemsize = EA_UNKNOWN;
5929 insFormat fmt = IF_NONE;
5930 size_t immOut = 0; // composed from imm1 and imm2 and stored in the instrDesc
5932 /* Figure out the encoding format of the instruction */
5942 assert(isGeneralRegister(reg1));
5943 assert(isGeneralRegister(reg2));
5944 assert(isValidImmShift(imm1, size));
5945 assert(isValidImmShift(imm2, size));
5947 bmi.immN = (size == EA_8BYTE);
5950 immOut = bmi.immNRS;
5957 assert(isGeneralRegister(reg1));
5958 assert(isGeneralRegister(reg2));
5959 lsb = getBitWidth(size) - imm1;
5961 assert(isValidImmShift(lsb, size));
5962 assert(isValidImmShift(width, size));
5964 bmi.immN = (size == EA_8BYTE);
5967 immOut = bmi.immNRS;
5974 assert(isGeneralRegister(reg1));
5975 assert(isGeneralRegister(reg2));
5977 width = imm2 + imm1 - 1;
5978 assert(isValidImmShift(lsb, size));
5979 assert(isValidImmShift(width, size));
5981 bmi.immN = (size == EA_8BYTE);
5983 bmi.immS = imm2 + imm1 - 1;
5984 immOut = bmi.immNRS;
5990 assert(isVectorRegister(reg1));
5991 assert(isVectorRegister(reg2));
5993 assert(isValidVectorElemsize(elemsize));
5994 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm1));
5995 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm2));
5996 immOut = (imm1 << 4) + imm2;
6004 assert(fmt != IF_NONE);
6006 instrDesc* id = emitNewInstrSC(attr, immOut);
6018 /*****************************************************************************
6020 * Add an instruction referencing four registers.
6023 void emitter::emitIns_R_R_R_R(
6024 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, regNumber reg4)
6026 emitAttr size = EA_SIZE(attr);
6027 insFormat fmt = IF_NONE;
6029 /* Figure out the encoding format of the instruction */
6038 assert(isValidGeneralDatasize(size));
6039 assert(isGeneralRegister(reg1));
6040 assert(isGeneralRegister(reg2));
6041 assert(isGeneralRegister(reg3));
6042 assert(isGeneralRegister(reg4));
6051 assert(isValidScalarDatasize(size));
6052 assert(isVectorRegister(reg1));
6053 assert(isVectorRegister(reg2));
6054 assert(isVectorRegister(reg3));
6055 assert(isVectorRegister(reg4));
6067 assert(fmt != IF_NONE);
6069 instrDesc* id = emitNewInstr(attr);
6083 /*****************************************************************************
6085 * Add an instruction referencing a register and a condition code
6088 void emitter::emitIns_R_COND(instruction ins, emitAttr attr, regNumber reg, insCond cond)
6090 insFormat fmt = IF_NONE;
6094 /* Figure out the encoding format of the instruction */
6099 assert(isGeneralRegister(reg));
6108 } // end switch (ins)
6110 assert(fmt != IF_NONE);
6111 assert(isValidImmCond(cfi.immCFVal));
6113 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6117 id->idInsOpt(INS_OPTS_NONE);
6125 /*****************************************************************************
6127 * Add an instruction referencing two registers and a condition code
6130 void emitter::emitIns_R_R_COND(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insCond cond)
6132 insFormat fmt = IF_NONE;
6136 /* Figure out the encoding format of the instruction */
6142 assert(isGeneralRegister(reg1));
6143 assert(isGeneralRegister(reg2));
6151 } // end switch (ins)
6153 assert(fmt != IF_NONE);
6154 assert(isValidImmCond(cfi.immCFVal));
6156 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6160 id->idInsOpt(INS_OPTS_NONE);
6169 /*****************************************************************************
6171 * Add an instruction referencing two registers and a condition code
6174 void emitter::emitIns_R_R_R_COND(
6175 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insCond cond)
6177 insFormat fmt = IF_NONE;
6181 /* Figure out the encoding format of the instruction */
6188 assert(isGeneralRegister(reg1));
6189 assert(isGeneralRegister(reg2));
6190 assert(isGeneralRegister(reg3));
6199 } // end switch (ins)
6201 assert(fmt != IF_NONE);
6202 assert(isValidImmCond(cfi.immCFVal));
6204 instrDesc* id = emitNewInstr(attr);
6208 id->idInsOpt(INS_OPTS_NONE);
6213 id->idSmallCns(cfi.immCFVal);
6219 /*****************************************************************************
6221 * Add an instruction referencing two registers the flags and a condition code
6224 void emitter::emitIns_R_R_FLAGS_COND(
6225 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insCflags flags, insCond cond)
6227 insFormat fmt = IF_NONE;
6231 /* Figure out the encoding format of the instruction */
6236 assert(isGeneralRegister(reg1));
6237 assert(isGeneralRegister(reg2));
6245 } // end switch (ins)
6247 assert(fmt != IF_NONE);
6248 assert(isValidImmCondFlags(cfi.immCFVal));
6250 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6254 id->idInsOpt(INS_OPTS_NONE);
6263 /*****************************************************************************
6265 * Add an instruction referencing a register, an immediate, the flags and a condition code
6268 void emitter::emitIns_R_I_FLAGS_COND(
6269 instruction ins, emitAttr attr, regNumber reg, int imm, insCflags flags, insCond cond)
6271 insFormat fmt = IF_NONE;
6275 /* Figure out the encoding format of the instruction */
6280 assert(isGeneralRegister(reg));
6283 ins = insReverse(ins);
6286 if ((imm >= 0) && (imm <= 31))
6295 assert(!"Instruction cannot be encoded: ccmp/ccmn imm5");
6301 } // end switch (ins)
6303 assert(fmt != IF_NONE);
6304 assert(isValidImmCondFlagsImm5(cfi.immCFVal));
6306 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6310 id->idInsOpt(INS_OPTS_NONE);
6318 /*****************************************************************************
6320 * Add a memory barrier instruction with a 'barrier' immediate
6323 void emitter::emitIns_BARR(instruction ins, insBarrier barrier)
6325 insFormat fmt = IF_NONE;
6328 /* Figure out the encoding format of the instruction */
6336 imm = (ssize_t)barrier;
6341 } // end switch (ins)
6343 assert(fmt != IF_NONE);
6345 instrDesc* id = emitNewInstrSC(EA_8BYTE, imm);
6349 id->idInsOpt(INS_OPTS_NONE);
6355 /*****************************************************************************
6357 * Add an instruction with a static data member operand. If 'size' is 0, the
6358 * instruction operates on the address of the static member instead of its
6359 * value (e.g. "push offset clsvar", rather than "push dword ptr [clsvar]").
6362 void emitter::emitIns_C(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, int offs)
6367 /*****************************************************************************
6369 * Add an instruction referencing stack-based local variable.
6372 void emitter::emitIns_S(instruction ins, emitAttr attr, int varx, int offs)
6377 /*****************************************************************************
6379 * Add an instruction referencing a register and a stack-based local variable.
6381 void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
6383 emitAttr size = EA_SIZE(attr);
6384 insFormat fmt = IF_NONE;
6390 // TODO-ARM64-CQ: use unscaled loads?
6391 /* Figure out the encoding format of the instruction */
6412 assert(isValidGeneralDatasize(size) || isValidVectorDatasize(size));
6413 scale = genLog2(EA_SIZE_IN_BYTES(size));
6417 assert(size == EA_8BYTE);
6422 NYI("emitIns_R_S"); // FP locals?
6425 } // end switch (ins)
6427 /* Figure out the variable's frame position */
6432 base = emitComp->lvaFrameAddress(varx, &FPbased);
6434 assert((scale >= 0) && (scale <= 4));
6436 regNumber reg2 = FPbased ? REG_FPBASE : REG_SPBASE;
6437 reg2 = encodingSPtoZR(reg2);
6454 fmt = IF_DI_2A; // add reg1,reg2,#disp
6458 regNumber rsvdReg = codeGen->rsGetRsvdReg();
6459 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6460 fmt = IF_DR_3A; // add reg1,reg2,rsvdReg
6465 bool useRegForImm = false;
6466 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6473 else if ((imm < 0) || ((imm & mask) != 0))
6475 if ((imm >= -256) && (imm <= 255))
6481 useRegForImm = true;
6486 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
6488 imm >>= scale; // The immediate is scaled by the size of the ld/st
6494 useRegForImm = true;
6500 regNumber rsvdReg = codeGen->rsGetRsvdReg();
6501 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6506 assert(fmt != IF_NONE);
6508 instrDesc* id = emitNewInstrCns(attr, imm);
6512 id->idInsOpt(INS_OPTS_NONE);
6516 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6517 id->idSetIsLclVar();
6520 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6527 /*****************************************************************************
6529 * Add an instruction referencing two register and consectutive stack-based local variable slots.
6531 void emitter::emitIns_R_R_S_S(
6532 instruction ins, emitAttr attr1, emitAttr attr2, regNumber reg1, regNumber reg2, int varx, int offs)
6534 assert((ins == INS_ldp) || (ins == INS_ldnp));
6535 assert(EA_8BYTE == EA_SIZE(attr1));
6536 assert(EA_8BYTE == EA_SIZE(attr2));
6537 assert(isGeneralRegisterOrZR(reg1));
6538 assert(isGeneralRegisterOrZR(reg2));
6541 insFormat fmt = IF_LS_3B;
6543 const unsigned scale = 3;
6545 /* Figure out the variable's frame position */
6549 base = emitComp->lvaFrameAddress(varx, &FPbased);
6552 // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6553 regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE;
6554 reg3 = encodingSPtoZR(reg3);
6556 bool useRegForAdr = true;
6558 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6561 useRegForAdr = false;
6565 if ((imm & mask) == 0)
6567 ssize_t immShift = imm >> scale; // The immediate is scaled by the size of the ld/st
6569 if ((immShift >= -64) && (immShift <= 63))
6572 useRegForAdr = false;
6580 regNumber rsvd = codeGen->rsGetRsvdReg();
6581 emitIns_R_R_Imm(INS_add, EA_PTRSIZE, rsvd, reg3, imm);
6586 assert(fmt != IF_NONE);
6588 instrDesc* id = emitNewInstrCns(attr1, imm);
6592 id->idInsOpt(INS_OPTS_NONE);
6594 // Record the attribute for the second register in the pair
6595 if (EA_IS_GCREF(attr2))
6597 id->idGCrefReg2(GCT_GCREF);
6599 else if (EA_IS_BYREF(attr2))
6601 id->idGCrefReg2(GCT_BYREF);
6605 id->idGCrefReg2(GCT_NONE);
6611 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6612 id->idSetIsLclVar();
6615 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6622 /*****************************************************************************
6624 * Add an instruction referencing a stack-based local variable and a register
6626 void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
6629 emitAttr size = EA_SIZE(attr);
6630 insFormat fmt = IF_NONE;
6633 bool isVectorStore = false;
6635 // TODO-ARM64-CQ: use unscaled loads?
6636 /* Figure out the encoding format of the instruction */
6641 assert(isGeneralRegisterOrZR(reg1));
6646 assert(isGeneralRegisterOrZR(reg1));
6650 if (isGeneralRegisterOrZR(reg1))
6652 assert(isValidGeneralDatasize(size));
6653 scale = (size == EA_8BYTE) ? 3 : 2;
6657 assert(isVectorRegister(reg1));
6658 assert(isValidVectorLSDatasize(size));
6659 scale = NaturalScale_helper(size);
6660 isVectorStore = true;
6665 NYI("emitIns_S_R"); // FP locals?
6668 } // end switch (ins)
6670 /* Figure out the variable's frame position */
6674 base = emitComp->lvaFrameAddress(varx, &FPbased);
6686 // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6687 regNumber reg2 = FPbased ? REG_FPBASE : REG_SPBASE;
6688 reg2 = encodingSPtoZR(reg2);
6690 bool useRegForImm = false;
6692 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6697 else if ((imm < 0) || ((imm & mask) != 0))
6699 if ((imm >= -256) && (imm <= 255))
6705 useRegForImm = true;
6710 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
6712 imm >>= scale; // The immediate is scaled by the size of the ld/st
6718 useRegForImm = true;
6724 // The reserved register is not stored in idReg3() since that field overlaps with iiaLclVar.
6725 // It is instead implicit when idSetIsLclVar() is set, with this encoding format.
6726 regNumber rsvdReg = codeGen->rsGetRsvdReg();
6727 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6731 assert(fmt != IF_NONE);
6733 instrDesc* id = emitNewInstrCns(attr, imm);
6737 id->idInsOpt(INS_OPTS_NONE);
6741 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6742 id->idSetIsLclVar();
6745 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6752 /*****************************************************************************
6754 * Add an instruction referencing consecutive stack-based local variable slots and two registers
6756 void emitter::emitIns_S_S_R_R(
6757 instruction ins, emitAttr attr1, emitAttr attr2, regNumber reg1, regNumber reg2, int varx, int offs)
6759 assert((ins == INS_stp) || (ins == INS_stnp));
6760 assert(EA_8BYTE == EA_SIZE(attr1));
6761 assert(EA_8BYTE == EA_SIZE(attr2));
6762 assert(isGeneralRegisterOrZR(reg1));
6763 assert(isGeneralRegisterOrZR(reg2));
6766 insFormat fmt = IF_LS_3B;
6768 const unsigned scale = 3;
6770 /* Figure out the variable's frame position */
6774 base = emitComp->lvaFrameAddress(varx, &FPbased);
6777 // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6778 regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE;
6780 bool useRegForAdr = true;
6782 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6785 useRegForAdr = false;
6789 if ((imm & mask) == 0)
6791 ssize_t immShift = imm >> scale; // The immediate is scaled by the size of the ld/st
6793 if ((immShift >= -64) && (immShift <= 63))
6796 useRegForAdr = false;
6804 regNumber rsvd = codeGen->rsGetRsvdReg();
6805 emitIns_R_R_Imm(INS_add, EA_PTRSIZE, rsvd, reg3, imm);
6810 assert(fmt != IF_NONE);
6812 instrDesc* id = emitNewInstrCns(attr1, imm);
6816 id->idInsOpt(INS_OPTS_NONE);
6818 // Record the attribute for the second register in the pair
6819 if (EA_IS_GCREF(attr2))
6821 id->idGCrefReg2(GCT_GCREF);
6823 else if (EA_IS_BYREF(attr2))
6825 id->idGCrefReg2(GCT_BYREF);
6829 id->idGCrefReg2(GCT_NONE);
6832 reg3 = encodingSPtoZR(reg3);
6837 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6838 id->idSetIsLclVar();
6841 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6848 /*****************************************************************************
6850 * Add an instruction referencing stack-based local variable and an immediate
6852 void emitter::emitIns_S_I(instruction ins, emitAttr attr, int varx, int offs, int val)
6857 /*****************************************************************************
6859 * Add an instruction with a register + static member operands.
6860 * Constant is stored into JIT data which is adjacent to code.
6861 * No relocation is needed. PC-relative offset will be encoded directly into instruction.
6864 void emitter::emitIns_R_C(
6865 instruction ins, emitAttr attr, regNumber reg, regNumber addrReg, CORINFO_FIELD_HANDLE fldHnd, int offs)
6868 assert(instrDesc::fitsInSmallCns(offs));
6870 emitAttr size = EA_SIZE(attr);
6871 insFormat fmt = IF_NONE;
6872 instrDescJmp* id = emitNewInstrJmp();
6877 // This is case to get address to the constant data.
6879 assert(isGeneralRegister(reg));
6880 assert(isValidGeneralDatasize(size));
6885 if (isVectorRegister(reg))
6887 assert(isValidScalarDatasize(size));
6888 // For vector (float/double) register, we should have an integer address reg to
6889 // compute long address which consists of page address and page offset.
6890 // For integer constant, this is not needed since the dest reg can be used to
6891 // compute address as well as contain the final contents.
6892 assert(isGeneralRegister(reg) || (addrReg != REG_NA));
6896 assert(isGeneralRegister(reg));
6897 assert(isValidGeneralDatasize(size));
6904 assert(fmt != IF_NONE);
6908 id->idInsOpt(INS_OPTS_NONE);
6909 id->idSmallCns(offs);
6911 id->idAddr()->iiaFieldHnd = fldHnd;
6912 id->idSetIsBound(); // We won't patch address since we will know the exact distance once JIT code and data are
6913 // allocated together.
6915 id->idReg1(reg); // destination register that will get the constant value.
6916 if (addrReg != REG_NA)
6918 id->idReg2(addrReg); // integer register to compute long address (used for vector dest when we end up with long
6921 id->idjShort = false; // Assume loading constant from long address
6923 // Keep it long if it's in cold code.
6924 id->idjKeepLong = emitComp->fgIsBlockCold(emitComp->compCurBB);
6927 if (emitComp->opts.compLongAddress)
6928 id->idjKeepLong = 1;
6931 // If it's possible to be shortened, then put it in jump list
6932 // to be revisited by emitJumpDistBind.
6933 if (!id->idjKeepLong)
6935 /* Record the jump's IG and offset within it */
6936 id->idjIG = emitCurIG;
6937 id->idjOffs = emitCurIGsize;
6939 /* Append this jump to this IG's jump list */
6940 id->idjNext = emitCurIGjmpList;
6941 emitCurIGjmpList = id;
6952 /*****************************************************************************
6954 * Add an instruction with a static member + constant.
6957 void emitter::emitIns_C_I(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, ssize_t offs, ssize_t val)
6962 /*****************************************************************************
6964 * Add an instruction with a static member + register operands.
6967 void emitter::emitIns_C_R(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, regNumber reg, int offs)
6969 assert(!"emitIns_C_R not supported for RyuJIT backend");
6972 void emitter::emitIns_R_AR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
6974 NYI("emitIns_R_AR");
6977 // This computes address from the immediate which is relocatable.
6978 void emitter::emitIns_R_AI(instruction ins, emitAttr attr, regNumber ireg, ssize_t addr)
6980 assert(EA_IS_RELOC(attr));
6981 emitAttr size = EA_SIZE(attr);
6982 insFormat fmt = IF_DI_1E;
6983 bool needAdd = false;
6984 instrDescJmp* id = emitNewInstrJmp();
6989 // This computes page address.
6990 // page offset is needed using add.
7001 id->idInsOpt(INS_OPTS_NONE);
7003 id->idAddr()->iiaAddr = (BYTE*)addr;
7005 id->idSetIsDspReloc();
7012 // add reg, reg, imm
7015 instrDesc* id = emitNewInstr(attr);
7016 assert(id->idIsReloc());
7020 id->idInsOpt(INS_OPTS_NONE);
7022 id->idAddr()->iiaAddr = (BYTE*)addr;
7031 void emitter::emitIns_AR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
7033 NYI("emitIns_AR_R");
7036 void emitter::emitIns_R_ARR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
7038 NYI("emitIns_R_ARR");
7041 void emitter::emitIns_ARR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
7043 NYI("emitIns_R_ARR");
7046 void emitter::emitIns_R_ARX(
7047 instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, unsigned mul, int disp)
7049 NYI("emitIns_R_ARR");
7052 /*****************************************************************************
7054 * Record that a jump instruction uses the short encoding
7057 void emitter::emitSetShortJump(instrDescJmp* id)
7059 if (id->idjKeepLong)
7062 insFormat fmt = IF_NONE;
7063 if (emitIsCondJump(id))
7065 switch (id->idIns())
7080 else if (emitIsLoadLabel(id))
7084 else if (emitIsLoadConstant(id))
7094 id->idjShort = true;
7097 /*****************************************************************************
7099 * Add a label instruction.
7102 void emitter::emitIns_R_L(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
7104 assert(dst->bbFlags & BBF_JMP_TARGET);
7106 insFormat fmt = IF_NONE;
7117 instrDescJmp* id = emitNewInstrJmp();
7121 id->idjShort = false;
7122 id->idAddr()->iiaBBlabel = dst;
7124 id->idOpSize(EA_PTRSIZE);
7127 // Mark the catch return
7128 if (emitComp->compCurBB->bbJumpKind == BBJ_EHCATCHRET)
7130 id->idDebugOnlyInfo()->idCatchRet = true;
7134 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7137 if (emitComp->opts.compLongAddress)
7138 id->idjKeepLong = 1;
7141 /* Record the jump's IG and offset within it */
7143 id->idjIG = emitCurIG;
7144 id->idjOffs = emitCurIGsize;
7146 /* Append this jump to this IG's jump list */
7148 id->idjNext = emitCurIGjmpList;
7149 emitCurIGjmpList = id;
7159 /*****************************************************************************
7161 * Add a data label instruction.
7164 void emitter::emitIns_R_D(instruction ins, emitAttr attr, unsigned offs, regNumber reg)
7169 void emitter::emitIns_J_R(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
7171 assert((ins == INS_cbz) || (ins == INS_cbnz));
7173 assert(dst != nullptr);
7174 assert((dst->bbFlags & BBF_JMP_TARGET) != 0);
7176 insFormat fmt = IF_LARGEJMP;
7178 instrDescJmp* id = emitNewInstrJmp();
7183 id->idjShort = false;
7184 id->idOpSize(EA_SIZE(attr));
7186 id->idAddr()->iiaBBlabel = dst;
7187 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7189 /* Record the jump's IG and offset within it */
7191 id->idjIG = emitCurIG;
7192 id->idjOffs = emitCurIGsize;
7194 /* Append this jump to this IG's jump list */
7196 id->idjNext = emitCurIGjmpList;
7197 emitCurIGjmpList = id;
7207 void emitter::emitIns_J_R_I(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg, int imm)
7209 assert((ins == INS_tbz) || (ins == INS_tbnz));
7211 assert(dst != nullptr);
7212 assert((dst->bbFlags & BBF_JMP_TARGET) != 0);
7213 assert((EA_SIZE(attr) == EA_4BYTE) || (EA_SIZE(attr) == EA_8BYTE));
7214 assert(imm < ((EA_SIZE(attr) == EA_4BYTE) ? 32 : 64));
7216 insFormat fmt = IF_LARGEJMP;
7218 instrDescJmp* id = emitNewInstrJmp();
7223 id->idjShort = false;
7224 id->idSmallCns(imm);
7225 id->idOpSize(EA_SIZE(attr));
7227 id->idAddr()->iiaBBlabel = dst;
7228 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7230 /* Record the jump's IG and offset within it */
7232 id->idjIG = emitCurIG;
7233 id->idjOffs = emitCurIGsize;
7235 /* Append this jump to this IG's jump list */
7237 id->idjNext = emitCurIGjmpList;
7238 emitCurIGjmpList = id;
7248 void emitter::emitIns_J(instruction ins, BasicBlock* dst, int instrCount)
7250 insFormat fmt = IF_NONE;
7254 assert(dst->bbFlags & BBF_JMP_TARGET);
7258 assert(instrCount != 0);
7261 /* Figure out the encoding format of the instruction */
7263 bool idjShort = false;
7268 // Unconditional jump is a single form.
7287 // Assume conditional jump is long.
7296 instrDescJmp* id = emitNewInstrJmp();
7300 id->idjShort = idjShort;
7303 // Mark the finally call
7304 if (ins == INS_bl_local && emitComp->compCurBB->bbJumpKind == BBJ_CALLFINALLY)
7306 id->idDebugOnlyInfo()->idFinallyCall = true;
7312 id->idAddr()->iiaBBlabel = dst;
7314 // Skip unconditional jump that has a single form.
7315 // TODO-ARM64-NYI: enable hot/cold splittingNYI.
7316 // The target needs to be relocated.
7319 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7322 if (emitComp->opts.compLongAddress) // Force long branches
7323 id->idjKeepLong = 1;
7329 id->idAddr()->iiaSetInstrCount(instrCount);
7330 id->idjKeepLong = false;
7331 /* This jump must be short */
7332 emitSetShortJump(id);
7336 /* Record the jump's IG and offset within it */
7338 id->idjIG = emitCurIG;
7339 id->idjOffs = emitCurIGsize;
7341 /* Append this jump to this IG's jump list */
7343 id->idjNext = emitCurIGjmpList;
7344 emitCurIGjmpList = id;
7354 /*****************************************************************************
7356 * Add a call instruction (direct or indirect).
7357 * argSize<0 means that the caller will pop the arguments
7359 * The other arguments are interpreted depending on callType as shown:
7360 * Unless otherwise specified, ireg,xreg,xmul,disp should have default values.
7362 * EC_FUNC_TOKEN : addr is the method address
7363 * EC_FUNC_ADDR : addr is the absolute address of the function
7365 * If callType is one of these emitCallTypes, addr has to be NULL.
7366 * EC_INDIR_R : "call ireg".
7368 * For ARM xreg, xmul and disp are never used and should always be 0/REG_NA.
7370 * Please consult the "debugger team notification" comment in genFnProlog().
7373 void emitter::emitIns_Call(EmitCallType callType,
7374 CORINFO_METHOD_HANDLE methHnd,
7375 INDEBUG_LDISASM_COMMA(CORINFO_SIG_INFO* sigInfo) // used to report call sites to the EE
7379 emitAttr secondRetSize,
7380 VARSET_VALARG_TP ptrVars,
7381 regMaskTP gcrefRegs,
7382 regMaskTP byrefRegs,
7383 IL_OFFSETX ilOffset /* = BAD_IL_OFFSET */,
7384 regNumber ireg /* = REG_NA */,
7385 regNumber xreg /* = REG_NA */,
7386 unsigned xmul /* = 0 */,
7387 ssize_t disp /* = 0 */,
7388 bool isJump /* = false */)
7390 /* Sanity check the arguments depending on callType */
7392 assert(callType < EC_COUNT);
7393 assert((callType != EC_FUNC_TOKEN && callType != EC_FUNC_ADDR) ||
7394 (ireg == REG_NA && xreg == REG_NA && xmul == 0 && disp == 0));
7395 assert(callType < EC_INDIR_R || addr == NULL);
7396 assert(callType != EC_INDIR_R || (ireg < REG_COUNT && xreg == REG_NA && xmul == 0 && disp == 0));
7398 // ARM never uses these
7399 assert(xreg == REG_NA && xmul == 0 && disp == 0);
7401 // Our stack level should be always greater than the bytes of arguments we push. Just
7403 assert((unsigned)abs(argSize) <= codeGen->genStackLevel);
7405 // Trim out any callee-trashed registers from the live set.
7406 regMaskTP savedSet = emitGetGCRegsSavedOrModified(methHnd);
7407 gcrefRegs &= savedSet;
7408 byrefRegs &= savedSet;
7411 if (EMIT_GC_VERBOSE)
7413 printf("Call: GCvars=%s ", VarSetOps::ToString(emitComp, ptrVars));
7414 dumpConvertedVarSet(emitComp, ptrVars);
7415 printf(", gcrefRegs=");
7416 printRegMaskInt(gcrefRegs);
7417 emitDispRegSet(gcrefRegs);
7418 printf(", byrefRegs=");
7419 printRegMaskInt(byrefRegs);
7420 emitDispRegSet(byrefRegs);
7425 /* Managed RetVal: emit sequence point for the call */
7426 if (emitComp->opts.compDbgInfo && ilOffset != BAD_IL_OFFSET)
7428 codeGen->genIPmappingAdd(ilOffset, false);
7432 We need to allocate the appropriate instruction descriptor based
7433 on whether this is a direct/indirect call, and whether we need to
7434 record an updated set of live GC variables.
7438 assert(argSize % REGSIZE_BYTES == 0);
7439 int argCnt = (int)(argSize / (int)REGSIZE_BYTES);
7441 if (callType >= EC_INDIR_R)
7443 /* Indirect call, virtual calls */
7445 assert(callType == EC_INDIR_R);
7447 id = emitNewInstrCallInd(argCnt, disp, ptrVars, gcrefRegs, byrefRegs, retSize, secondRetSize);
7451 /* Helper/static/nonvirtual/function calls (direct or through handle),
7452 and calls to an absolute addr. */
7454 assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
7456 id = emitNewInstrCallDir(argCnt, ptrVars, gcrefRegs, byrefRegs, retSize, secondRetSize);
7459 /* Update the emitter's live GC ref sets */
7461 VarSetOps::Assign(emitComp, emitThisGCrefVars, ptrVars);
7462 emitThisGCrefRegs = gcrefRegs;
7463 emitThisByrefRegs = byrefRegs;
7465 id->idSetIsNoGC(emitNoGChelper(methHnd));
7467 /* Set the instruction - special case jumping a function */
7469 insFormat fmt = IF_NONE;
7471 /* Record the address: method, indirection, or funcptr */
7473 if (callType > EC_FUNC_ADDR)
7475 /* This is an indirect call (either a virtual call or func ptr call) */
7479 case EC_INDIR_R: // the address is in a register
7481 id->idSetIsCallRegPtr();
7485 ins = INS_br_tail; // INS_br_tail Reg
7489 ins = INS_blr; // INS_blr Reg
7497 assert(xreg == REG_NA);
7501 NO_WAY("unexpected instruction");
7507 /* This is a simple direct call: "call helper/method/addr" */
7509 assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
7511 assert(addr != NULL);
7515 ins = INS_b_tail; // INS_b_tail imm28
7519 ins = INS_bl; // INS_bl imm28
7526 id->idAddr()->iiaAddr = (BYTE*)addr;
7528 if (callType == EC_FUNC_ADDR)
7530 id->idSetIsCallAddr();
7533 if (emitComp->opts.compReloc)
7535 id->idSetIsDspReloc();
7540 if (EMIT_GC_VERBOSE)
7542 if (id->idIsLargeCall())
7544 printf("[%02u] Rec call GC vars = %s\n", id->idDebugOnlyInfo()->idNum,
7545 VarSetOps::ToString(emitComp, ((instrDescCGCA*)id)->idcGCvars));
7549 id->idDebugOnlyInfo()->idMemCookie = (size_t)methHnd; // method token
7550 id->idDebugOnlyInfo()->idCallSig = sigInfo;
7554 if (addr != nullptr)
7556 codeGen->getDisAssembler().disSetMethod((size_t)addr, methHnd);
7558 #endif // LATE_DISASM
7564 /*****************************************************************************
7566 * Returns true if 'imm' is valid Cond encoding
7569 /*static*/ bool emitter::isValidImmCond(ssize_t imm)
7571 // range check the ssize_t value, to make sure it is a small unsigned value
7572 // and that only the bits in the cfi.cond are set
7573 if ((imm < 0) || (imm > 0xF))
7577 cfi.immCFVal = (unsigned)imm;
7579 return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7582 /*****************************************************************************
7584 * Returns true if 'imm' is valid Cond/Flags encoding
7587 /*static*/ bool emitter::isValidImmCondFlags(ssize_t imm)
7589 // range check the ssize_t value, to make sure it is a small unsigned value
7590 // and that only the bits in the cfi.cond or cfi.flags are set
7591 if ((imm < 0) || (imm > 0xFF))
7595 cfi.immCFVal = (unsigned)imm;
7597 return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7600 /*****************************************************************************
7602 * Returns true if 'imm' is valid Cond/Flags/Imm5 encoding
7605 /*static*/ bool emitter::isValidImmCondFlagsImm5(ssize_t imm)
7607 // range check the ssize_t value, to make sure it is a small unsigned value
7608 // and that only the bits in the cfi.cond, cfi.flags or cfi.imm5 are set
7609 if ((imm < 0) || (imm > 0x1FFF))
7613 cfi.immCFVal = (unsigned)imm;
7615 return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7618 /*****************************************************************************
7620 * Returns an encoding for the specified register used in the 'Rd' position
7623 /*static*/ emitter::code_t emitter::insEncodeReg_Rd(regNumber reg)
7625 assert(isIntegerRegister(reg));
7626 emitter::code_t ureg = (emitter::code_t)reg;
7627 assert((ureg >= 0) && (ureg <= 31));
7631 /*****************************************************************************
7633 * Returns an encoding for the specified register used in the 'Rt' position
7636 /*static*/ emitter::code_t emitter::insEncodeReg_Rt(regNumber reg)
7638 assert(isIntegerRegister(reg));
7639 emitter::code_t ureg = (emitter::code_t)reg;
7640 assert((ureg >= 0) && (ureg <= 31));
7644 /*****************************************************************************
7646 * Returns an encoding for the specified register used in the 'Rn' position
7649 /*static*/ emitter::code_t emitter::insEncodeReg_Rn(regNumber reg)
7651 assert(isIntegerRegister(reg));
7652 emitter::code_t ureg = (emitter::code_t)reg;
7653 assert((ureg >= 0) && (ureg <= 31));
7657 /*****************************************************************************
7659 * Returns an encoding for the specified register used in the 'Rm' position
7662 /*static*/ emitter::code_t emitter::insEncodeReg_Rm(regNumber reg)
7664 assert(isIntegerRegister(reg));
7665 emitter::code_t ureg = (emitter::code_t)reg;
7666 assert((ureg >= 0) && (ureg <= 31));
7670 /*****************************************************************************
7672 * Returns an encoding for the specified register used in the 'Ra' position
7675 /*static*/ emitter::code_t emitter::insEncodeReg_Ra(regNumber reg)
7677 assert(isIntegerRegister(reg));
7678 emitter::code_t ureg = (emitter::code_t)reg;
7679 assert((ureg >= 0) && (ureg <= 31));
7683 /*****************************************************************************
7685 * Returns an encoding for the specified register used in the 'Vd' position
7688 /*static*/ emitter::code_t emitter::insEncodeReg_Vd(regNumber reg)
7690 assert(emitter::isVectorRegister(reg));
7691 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7692 assert((ureg >= 0) && (ureg <= 31));
7696 /*****************************************************************************
7698 * Returns an encoding for the specified register used in the 'Vt' position
7701 /*static*/ emitter::code_t emitter::insEncodeReg_Vt(regNumber reg)
7703 assert(emitter::isVectorRegister(reg));
7704 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7705 assert((ureg >= 0) && (ureg <= 31));
7709 /*****************************************************************************
7711 * Returns an encoding for the specified register used in the 'Vn' position
7714 /*static*/ emitter::code_t emitter::insEncodeReg_Vn(regNumber reg)
7716 assert(emitter::isVectorRegister(reg));
7717 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7718 assert((ureg >= 0) && (ureg <= 31));
7722 /*****************************************************************************
7724 * Returns an encoding for the specified register used in the 'Vm' position
7727 /*static*/ emitter::code_t emitter::insEncodeReg_Vm(regNumber reg)
7729 assert(emitter::isVectorRegister(reg));
7730 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7731 assert((ureg >= 0) && (ureg <= 31));
7735 /*****************************************************************************
7737 * Returns an encoding for the specified register used in the 'Va' position
7740 /*static*/ emitter::code_t emitter::insEncodeReg_Va(regNumber reg)
7742 assert(emitter::isVectorRegister(reg));
7743 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7744 assert((ureg >= 0) && (ureg <= 31));
7748 /*****************************************************************************
7750 * Returns an encoding for the specified condition code.
7753 /*static*/ emitter::code_t emitter::insEncodeCond(insCond cond)
7755 emitter::code_t uimm = (emitter::code_t)cond;
7759 /*****************************************************************************
7761 * Returns an encoding for the condition code with the lowest bit inverted (marked by invert(<cond>) in the
7762 * architecture manual).
7765 /*static*/ emitter::code_t emitter::insEncodeInvertedCond(insCond cond)
7767 emitter::code_t uimm = (emitter::code_t)cond;
7768 uimm ^= 1; // invert the lowest bit
7772 /*****************************************************************************
7774 * Returns an encoding for the specified flags.
7777 /*static*/ emitter::code_t emitter::insEncodeFlags(insCflags flags)
7779 emitter::code_t uimm = (emitter::code_t)flags;
7783 /*****************************************************************************
7785 * Returns the encoding for the Shift Count bits to be used for Arm64 encodings
7788 /*static*/ emitter::code_t emitter::insEncodeShiftCount(ssize_t imm, emitAttr size)
7790 assert((imm & 0x003F) == imm);
7791 assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
7793 return (emitter::code_t)imm << 10;
7796 /*****************************************************************************
7798 * Returns the encoding to select a 64-bit datasize for an Arm64 instruction
7801 /*static*/ emitter::code_t emitter::insEncodeDatasize(emitAttr size)
7803 if (size == EA_8BYTE)
7805 return 0x80000000; // set the bit at location 31
7809 assert(size == EA_4BYTE);
7814 /*****************************************************************************
7816 * Returns the encoding to select the datasize for the general load/store Arm64 instructions
7820 /*static*/ emitter::code_t emitter::insEncodeDatasizeLS(emitter::code_t code, emitAttr size)
7822 bool exclusive = ((code & 0x35000000) == 0);
7823 bool atomic = ((code & 0x31200C00) == 0x30200000);
7825 if ((code & 0x00800000) && !exclusive && !atomic) // Is this a sign-extending opcode? (i.e. ldrsw, ldrsh, ldrsb)
7827 if ((code & 0x80000000) == 0) // Is it a ldrsh or ldrsb and not ldrsw ?
7829 if (EA_SIZE(size) != EA_8BYTE) // Do we need to encode the 32-bit Rt size bit?
7831 return 0x00400000; // set the bit at location 22
7835 else if (code & 0x80000000) // Is this a ldr/str/ldur/stur opcode?
7837 if (EA_SIZE(size) == EA_8BYTE) // Do we need to encode the 64-bit size bit?
7839 return 0x40000000; // set the bit at location 30
7845 /*****************************************************************************
7847 * Returns the encoding to select the datasize for the vector load/store Arm64 instructions
7851 /*static*/ emitter::code_t emitter::insEncodeDatasizeVLS(emitter::code_t code, emitAttr size)
7856 if ((code & 0x20000000) == 0)
7860 if (size == EA_16BYTE)
7862 // set the operation size in bit 31
7863 result = 0x80000000;
7865 else if (size == EA_8BYTE)
7867 // set the operation size in bit 30
7868 result = 0x40000000;
7872 assert(size == EA_4BYTE);
7874 result = 0x00000000;
7881 if (size == EA_16BYTE)
7883 // The operation size in bits 31 and 30 are zero
7884 // Bit 23 specifies a 128-bit Load/Store
7885 result = 0x00800000;
7887 else if (size == EA_8BYTE)
7889 // set the operation size in bits 31 and 30
7890 result = 0xC0000000;
7892 else if (size == EA_4BYTE)
7894 // set the operation size in bit 31
7895 result = 0x80000000;
7897 else if (size == EA_2BYTE)
7899 // set the operation size in bit 30
7900 result = 0x40000000;
7904 assert(size == EA_1BYTE);
7905 // The operation size in bits 31 and 30 are zero
7906 result = 0x00000000;
7910 // Or in bit 26 to indicate a Vector register is used as 'target'
7911 result |= 0x04000000;
7916 /*****************************************************************************
7918 * Returns the encoding to select the datasize for the vector load/store Arm64 instructions
7922 /*static*/ emitter::code_t emitter::insEncodeDatasizeVPLS(emitter::code_t code, emitAttr size)
7926 if (size == EA_16BYTE)
7928 // The operation size in bits 31 and 30 are zero
7929 // Bit 23 specifies a 128-bit Load/Store
7930 result = 0x80000000;
7932 else if (size == EA_8BYTE)
7934 // set the operation size in bits 31 and 30
7935 result = 0x40000000;
7937 else if (size == EA_4BYTE)
7939 // set the operation size in bit 31
7940 result = 0x00000000;
7943 // Or in bit 26 to indicate a Vector register is used as 'target'
7944 result |= 0x04000000;
7949 /*****************************************************************************
7951 * Returns the encoding to set the size bit and the N bits for a 'bitfield' instruction
7955 /*static*/ emitter::code_t emitter::insEncodeDatasizeBF(emitter::code_t code, emitAttr size)
7957 // is bit 30 equal to 0?
7958 if ((code & 0x40000000) == 0) // is the opcode one of extr, sxtb, sxth or sxtw
7960 if (size == EA_8BYTE) // Do we need to set the sf and N bits?
7962 return 0x80400000; // set the sf-bit at location 31 and the N-bit at location 22
7965 return 0; // don't set any bits
7968 /*****************************************************************************
7970 * Returns the encoding to select the 64/128-bit datasize for an Arm64 vector instruction
7973 /*static*/ emitter::code_t emitter::insEncodeVectorsize(emitAttr size)
7975 if (size == EA_16BYTE)
7977 return 0x40000000; // set the bit at location 30
7981 assert(size == EA_8BYTE);
7986 /*****************************************************************************
7988 * Returns the encoding to select 'index' for an Arm64 vector elem instruction
7990 /*static*/ emitter::code_t emitter::insEncodeVectorIndex(emitAttr elemsize, ssize_t index)
7992 code_t bits = (code_t)index;
7993 if (elemsize == EA_1BYTE)
7998 else if (elemsize == EA_2BYTE)
8003 else if (elemsize == EA_4BYTE)
8010 assert(elemsize == EA_8BYTE);
8014 assert((bits >= 1) && (bits <= 0x1f));
8016 return (bits << 16); // bits at locations [20,19,18,17,16]
8019 /*****************************************************************************
8021 * Returns the encoding to select 'index2' for an Arm64 'ins' elem instruction
8023 /*static*/ emitter::code_t emitter::insEncodeVectorIndex2(emitAttr elemsize, ssize_t index2)
8025 code_t bits = (code_t)index2;
8026 if (elemsize == EA_1BYTE)
8030 else if (elemsize == EA_2BYTE)
8034 else if (elemsize == EA_4BYTE)
8040 assert(elemsize == EA_8BYTE);
8043 assert((bits >= 0) && (bits <= 0xf));
8045 return (bits << 11); // bits at locations [14,13,12,11]
8048 /*****************************************************************************
8050 * Returns the encoding to select the 'index' for an Arm64 'mul' by elem instruction
8052 /*static*/ emitter::code_t emitter::insEncodeVectorIndexLMH(emitAttr elemsize, ssize_t index)
8056 if (elemsize == EA_2BYTE)
8058 assert((index >= 0) && (index <= 7));
8061 bits |= (1 << 11); // set bit 11 'H'
8065 bits |= (1 << 21); // set bit 21 'L'
8069 bits |= (1 << 20); // set bit 20 'M'
8072 else if (elemsize == EA_4BYTE)
8074 assert((index >= 0) && (index <= 3));
8077 bits |= (1 << 11); // set bit 11 'H'
8081 bits |= (1 << 21); // set bit 21 'L'
8086 assert(!"Invalid 'elemsize' value");
8092 /*****************************************************************************
8094 * Returns the encoding to shift by 'shift' for an Arm64 vector or scalar instruction
8097 /*static*/ emitter::code_t emitter::insEncodeVectorShift(emitAttr size, ssize_t shift)
8099 assert(shift < getBitWidth(size));
8101 code_t imm = (code_t)(getBitWidth(size) + shift);
8106 /*****************************************************************************
8108 * Returns the encoding to select the 1/2/4/8 byte elemsize for an Arm64 vector instruction
8111 /*static*/ emitter::code_t emitter::insEncodeElemsize(emitAttr size)
8113 if (size == EA_8BYTE)
8115 return 0x00C00000; // set the bit at location 23 and 22
8117 else if (size == EA_4BYTE)
8119 return 0x00800000; // set the bit at location 23
8121 else if (size == EA_2BYTE)
8123 return 0x00400000; // set the bit at location 22
8125 assert(size == EA_1BYTE);
8129 /*****************************************************************************
8131 * Returns the encoding to select the 4/8 byte elemsize for an Arm64 float vector instruction
8134 /*static*/ emitter::code_t emitter::insEncodeFloatElemsize(emitAttr size)
8136 if (size == EA_8BYTE)
8138 return 0x00400000; // set the bit at location 22
8140 assert(size == EA_4BYTE);
8144 // Returns the encoding to select the index for an Arm64 float vector by elem instruction
8145 /*static*/ emitter::code_t emitter::insEncodeFloatIndex(emitAttr elemsize, ssize_t index)
8147 code_t result = 0x00000000;
8148 if (elemsize == EA_8BYTE)
8150 assert((index >= 0) && (index <= 1));
8153 result |= 0x00000800; // 'H' - set the bit at location 11
8158 assert(elemsize == EA_4BYTE);
8159 assert((index >= 0) && (index <= 3));
8162 result |= 0x00000800; // 'H' - set the bit at location 11
8166 result |= 0x00200000; // 'L' - set the bit at location 21
8172 /*****************************************************************************
8174 * Returns the encoding to select the fcvt operation for Arm64 instructions
8176 /*static*/ emitter::code_t emitter::insEncodeConvertOpt(insFormat fmt, insOpts conversion)
8181 case INS_OPTS_S_TO_D: // Single to Double
8182 assert(fmt == IF_DV_2J);
8183 result = 0x00008000; // type=00, opc=01
8186 case INS_OPTS_D_TO_S: // Double to Single
8187 assert(fmt == IF_DV_2J);
8188 result = 0x00400000; // type=01, opc=00
8191 case INS_OPTS_H_TO_S: // Half to Single
8192 assert(fmt == IF_DV_2J);
8193 result = 0x00C00000; // type=11, opc=00
8196 case INS_OPTS_H_TO_D: // Half to Double
8197 assert(fmt == IF_DV_2J);
8198 result = 0x00C08000; // type=11, opc=01
8201 case INS_OPTS_S_TO_H: // Single to Half
8202 assert(fmt == IF_DV_2J);
8203 result = 0x00018000; // type=00, opc=11
8206 case INS_OPTS_D_TO_H: // Double to Half
8207 assert(fmt == IF_DV_2J);
8208 result = 0x00418000; // type=01, opc=11
8211 case INS_OPTS_S_TO_4BYTE: // Single to INT32
8212 assert(fmt == IF_DV_2H);
8213 result = 0x00000000; // sf=0, type=00
8216 case INS_OPTS_D_TO_4BYTE: // Double to INT32
8217 assert(fmt == IF_DV_2H);
8218 result = 0x00400000; // sf=0, type=01
8221 case INS_OPTS_S_TO_8BYTE: // Single to INT64
8222 assert(fmt == IF_DV_2H);
8223 result = 0x80000000; // sf=1, type=00
8226 case INS_OPTS_D_TO_8BYTE: // Double to INT64
8227 assert(fmt == IF_DV_2H);
8228 result = 0x80400000; // sf=1, type=01
8231 case INS_OPTS_4BYTE_TO_S: // INT32 to Single
8232 assert(fmt == IF_DV_2I);
8233 result = 0x00000000; // sf=0, type=00
8236 case INS_OPTS_4BYTE_TO_D: // INT32 to Double
8237 assert(fmt == IF_DV_2I);
8238 result = 0x00400000; // sf=0, type=01
8241 case INS_OPTS_8BYTE_TO_S: // INT64 to Single
8242 assert(fmt == IF_DV_2I);
8243 result = 0x80000000; // sf=1, type=00
8246 case INS_OPTS_8BYTE_TO_D: // INT64 to Double
8247 assert(fmt == IF_DV_2I);
8248 result = 0x80400000; // sf=1, type=01
8252 assert(!"Invalid 'conversion' value");
8258 /*****************************************************************************
8260 * Returns the encoding to have the Rn register be updated Pre/Post indexed
8264 /*static*/ emitter::code_t emitter::insEncodeIndexedOpt(insOpts opt)
8266 assert(emitter::insOptsNone(opt) || emitter::insOptsIndexed(opt));
8268 if (emitter::insOptsIndexed(opt))
8270 if (emitter::insOptsPostIndex(opt))
8272 return 0x00000400; // set the bit at location 10
8276 assert(emitter::insOptsPreIndex(opt));
8277 return 0x00000C00; // set the bit at location 10 and 11
8282 assert(emitter::insOptsNone(opt));
8283 return 0; // bits 10 and 11 are zero
8287 /*****************************************************************************
8289 * Returns the encoding for a ldp/stp instruction to have the Rn register
8290 * be updated Pre/Post indexed or not updated
8293 /*static*/ emitter::code_t emitter::insEncodePairIndexedOpt(instruction ins, insOpts opt)
8295 assert(emitter::insOptsNone(opt) || emitter::insOptsIndexed(opt));
8297 if ((ins == INS_ldnp) || (ins == INS_stnp))
8299 assert(emitter::insOptsNone(opt));
8300 return 0; // bits 23 and 24 are zero
8304 if (emitter::insOptsIndexed(opt))
8306 if (emitter::insOptsPostIndex(opt))
8308 return 0x00800000; // set the bit at location 23
8312 assert(emitter::insOptsPreIndex(opt));
8313 return 0x01800000; // set the bit at location 24 and 23
8318 assert(emitter::insOptsNone(opt));
8319 return 0x01000000; // set the bit at location 24
8324 /*****************************************************************************
8326 * Returns the encoding to apply a Shift Type on the Rm register
8329 /*static*/ emitter::code_t emitter::insEncodeShiftType(insOpts opt)
8331 if (emitter::insOptsNone(opt))
8333 // None implies the we encode LSL (with a zero immediate)
8336 assert(emitter::insOptsAnyShift(opt));
8338 emitter::code_t option = (emitter::code_t)opt - (emitter::code_t)INS_OPTS_LSL;
8339 assert(option <= 3);
8341 return option << 22; // bits 23, 22
8344 /*****************************************************************************
8346 * Returns the encoding to apply a 12 bit left shift to the immediate
8349 /*static*/ emitter::code_t emitter::insEncodeShiftImm12(insOpts opt)
8351 if (emitter::insOptsLSL12(opt))
8353 return 0x00400000; // set the bit at location 22
8358 /*****************************************************************************
8360 * Returns the encoding to have the Rm register use an extend operation
8363 /*static*/ emitter::code_t emitter::insEncodeExtend(insOpts opt)
8365 if (emitter::insOptsNone(opt) || (opt == INS_OPTS_LSL))
8367 // None or LSL implies the we encode UXTX
8368 opt = INS_OPTS_UXTX;
8370 assert(emitter::insOptsAnyExtend(opt));
8372 emitter::code_t option = (emitter::code_t)opt - (emitter::code_t)INS_OPTS_UXTB;
8373 assert(option <= 7);
8375 return option << 13; // bits 15,14,13
8378 /*****************************************************************************
8380 * Returns the encoding to scale the Rm register by {0,1,2,3,4}
8381 * when using an extend operation
8384 /*static*/ emitter::code_t emitter::insEncodeExtendScale(ssize_t imm)
8386 assert((imm >= 0) && (imm <= 4));
8388 return (emitter::code_t)imm << 10; // bits 12,11,10
8391 /*****************************************************************************
8393 * Returns the encoding to have the Rm register be auto scaled by the ld/st size
8396 /*static*/ emitter::code_t emitter::insEncodeReg3Scale(bool isScaled)
8400 return 0x00001000; // set the bit at location 12
8408 BYTE* emitter::emitOutputLoadLabel(BYTE* dst, BYTE* srcAddr, BYTE* dstAddr, instrDescJmp* id)
8410 instruction ins = id->idIns();
8411 insFormat fmt = id->idInsFmt();
8412 regNumber dstReg = id->idReg1();
8415 // adr x, [rel addr] -- compute address: current addr(ip) + rel addr.
8416 assert(ins == INS_adr);
8417 assert(fmt == IF_DI_1E);
8418 ssize_t distVal = (ssize_t)(dstAddr - srcAddr);
8419 dst = emitOutputShortAddress(dst, ins, fmt, distVal, dstReg);
8423 // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8424 assert(fmt == IF_LARGEADR);
8425 ssize_t relPageAddr =
8426 (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8427 dst = emitOutputShortAddress(dst, INS_adrp, IF_DI_1E, relPageAddr, dstReg);
8429 // add x, x, page offs -- compute address = page addr + page offs
8430 ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8431 assert(isValidUimm12(imm12));
8433 emitInsCode(INS_add, IF_DI_2A); // DI_2A X0010001shiiiiii iiiiiinnnnnddddd 1100 0000 imm(i12, sh)
8434 code |= insEncodeDatasize(EA_8BYTE); // X
8435 code |= ((code_t)imm12 << 10); // iiiiiiiiiiii
8436 code |= insEncodeReg_Rd(dstReg); // ddddd
8437 code |= insEncodeReg_Rn(dstReg); // nnnnn
8438 dst += emitOutput_Instr(dst, code);
8443 /*****************************************************************************
8445 * Output a local jump or other instruction with a pc-relative immediate.
8446 * Note that this may be invoked to overwrite an existing jump instruction at 'dst'
8447 * to handle forward branch patching.
8450 BYTE* emitter::emitOutputLJ(insGroup* ig, BYTE* dst, instrDesc* i)
8452 instrDescJmp* id = (instrDescJmp*)i;
8460 // Set default ins/fmt from id.
8461 instruction ins = id->idIns();
8462 insFormat fmt = id->idInsFmt();
8464 bool loadLabel = false;
8465 bool isJump = false;
8466 bool loadConstant = false;
8483 loadConstant = true;
8492 /* Figure out the distance to the target */
8494 srcOffs = emitCurCodeOffs(dst);
8495 srcAddr = emitOffsetToPtr(srcOffs);
8497 if (id->idAddr()->iiaIsJitDataOffset())
8499 assert(loadConstant || loadLabel);
8500 int doff = id->idAddr()->iiaGetJitDataOffset();
8502 ssize_t imm = emitGetInsSC(id);
8503 assert((imm >= 0) && (imm < 0x1000)); // 0x1000 is arbitrary, currently 'imm' is always 0
8505 unsigned dataOffs = (unsigned)(doff + imm);
8506 assert(dataOffs < emitDataSize());
8507 dstAddr = emitDataOffsetToPtr(dataOffs);
8509 regNumber dstReg = id->idReg1();
8510 regNumber addrReg = dstReg; // an integer register to compute long address.
8511 emitAttr opSize = id->idOpSize();
8517 // ldr x/v, [rel addr] -- load constant from current addr(ip) + rel addr.
8518 assert(ins == INS_ldr);
8519 assert(fmt == IF_LS_1A);
8520 distVal = (ssize_t)(dstAddr - srcAddr);
8521 dst = emitOutputShortConstant(dst, ins, fmt, distVal, dstReg, opSize);
8525 // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8526 assert(fmt == IF_LARGELDC);
8527 ssize_t relPageAddr =
8528 (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8529 if (isVectorRegister(dstReg))
8531 // Update addrReg with the reserved integer register
8532 // since we cannot use dstReg (vector) to load constant directly from memory.
8533 addrReg = id->idReg2();
8534 assert(isGeneralRegister(addrReg));
8538 dst = emitOutputShortAddress(dst, ins, fmt, relPageAddr, addrReg);
8540 // ldr x, [x, page offs] -- load constant from page address + page offset into integer register.
8541 ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8542 assert(isValidUimm12(imm12));
8545 dst = emitOutputShortConstant(dst, ins, fmt, imm12, addrReg, opSize);
8547 // fmov v, d -- copy constant in integer register to vector register.
8548 // This is needed only for vector constant.
8549 if (addrReg != dstReg)
8551 // fmov Vd,Rn DV_2I X00111100X100111 000000nnnnnddddd 1E27 0000 Vd,Rn
8552 // (scalar, from general)
8553 assert(isVectorRegister(dstReg) && isGeneralRegister(addrReg));
8556 code_t code = emitInsCode(ins, fmt);
8558 code |= insEncodeReg_Vd(dstReg); // ddddd
8559 code |= insEncodeReg_Rn(addrReg); // nnnnn
8560 if (id->idOpSize() == EA_8BYTE)
8562 code |= 0x80400000; // X ... X
8564 dst += emitOutput_Instr(dst, code);
8571 dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8577 assert(loadLabel || isJump);
8579 if (id->idAddr()->iiaHasInstrCount())
8582 int instrCount = id->idAddr()->iiaGetInstrCount();
8583 unsigned insNum = emitFindInsNum(ig, id);
8586 // Backward branches using instruction count must be within the same instruction group.
8587 assert(insNum + 1 >= (unsigned)(-instrCount));
8589 dstOffs = ig->igOffs + emitFindOffset(ig, (insNum + 1 + instrCount));
8590 dstAddr = emitOffsetToPtr(dstOffs);
8594 dstOffs = id->idAddr()->iiaIGlabel->igOffs;
8595 dstAddr = emitOffsetToPtr(dstOffs);
8598 distVal = (ssize_t)(dstAddr - srcAddr);
8600 if (dstOffs <= srcOffs)
8603 /* This is a backward jump - distance is known at this point */
8605 if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8607 size_t blkOffs = id->idjIG->igOffs;
8609 if (INTERESTING_JUMP_NUM == 0)
8610 printf("[3] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8611 printf("[3] Jump block is at %08X - %02X = %08X\n", blkOffs, emitOffsAdj, blkOffs - emitOffsAdj);
8612 printf("[3] Jump is at %08X - %02X = %08X\n", srcOffs, emitOffsAdj, srcOffs - emitOffsAdj);
8613 printf("[3] Label block is at %08X - %02X = %08X\n", dstOffs, emitOffsAdj, dstOffs - emitOffsAdj);
8619 /* This is a forward jump - distance will be an upper limit */
8621 emitFwdJumps = true;
8623 /* The target offset will be closer by at least 'emitOffsAdj', but only if this
8624 jump doesn't cross the hot-cold boundary. */
8626 if (!emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8628 dstOffs -= emitOffsAdj;
8629 distVal -= emitOffsAdj;
8632 /* Record the location of the jump for later patching */
8634 id->idjOffs = dstOffs;
8636 /* Are we overflowing the id->idjOffs bitfield? */
8637 if (id->idjOffs != dstOffs)
8638 IMPL_LIMITATION("Method is too large");
8641 if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8643 size_t blkOffs = id->idjIG->igOffs;
8645 if (INTERESTING_JUMP_NUM == 0)
8646 printf("[4] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8647 printf("[4] Jump block is at %08X\n", blkOffs);
8648 printf("[4] Jump is at %08X\n", srcOffs);
8649 printf("[4] Label block is at %08X - %02X = %08X\n", dstOffs + emitOffsAdj, emitOffsAdj, dstOffs);
8655 if (0 && emitComp->verbose)
8658 int distValSize = id->idjShort ? 4 : 8;
8659 printf("; %s jump [%08X/%03u] from %0*X to %0*X: dist = %08XH\n", (dstOffs <= srcOffs) ? "Fwd" : "Bwd",
8660 dspPtr(id), id->idDebugOnlyInfo()->idNum, distValSize, srcOffs + sz, distValSize, dstOffs, distVal);
8664 /* For forward jumps, record the address of the distance value */
8665 id->idjTemp.idjAddr = (distVal > 0) ? dst : NULL;
8667 if (emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8669 assert(!id->idjShort);
8670 NYI_ARM64("Relocation Support for long address");
8673 assert(insOptsNone(id->idInsOpt()));
8679 // Short conditional/unconditional jump
8680 assert(!id->idjKeepLong);
8681 assert(emitJumpCrossHotColdBoundary(srcOffs, dstOffs) == false);
8682 assert((fmt == IF_BI_0A) || (fmt == IF_BI_0B) || (fmt == IF_BI_1A) || (fmt == IF_BI_1B));
8686 // Long conditional jump
8687 assert(fmt == IF_LARGEJMP);
8688 // This is a pseudo-instruction format representing a large conditional branch, to allow
8689 // us to get a greater branch target range than we can get by using a straightforward conditional
8690 // branch. It is encoded as a short conditional branch that branches around a long unconditional
8693 // Conceptually, we have:
8697 // The code we emit is:
8699 // b<!cond> L_not // 4 bytes. Note that we reverse the condition.
8700 // b L_target // 4 bytes
8703 // Note that we don't actually insert any blocks: we simply encode "b <!cond> L_not" as a branch with
8704 // the correct offset. Note also that this works for both integer and floating-point conditions, because
8705 // the condition inversion takes ordered/unordered into account, preserving NaN behavior. For example,
8706 // "GT" (greater than) is inverted to "LE" (less than, equal, or unordered).
8708 instruction reverseIns;
8709 insFormat reverseFmt;
8714 reverseIns = INS_cbnz;
8715 reverseFmt = IF_BI_1A;
8718 reverseIns = INS_cbz;
8719 reverseFmt = IF_BI_1A;
8722 reverseIns = INS_tbnz;
8723 reverseFmt = IF_BI_1B;
8726 reverseIns = INS_tbz;
8727 reverseFmt = IF_BI_1B;
8730 reverseIns = emitJumpKindToIns(emitReverseJumpKind(emitInsToJumpKind(ins)));
8731 reverseFmt = IF_BI_0B;
8735 emitOutputShortBranch(dst,
8736 reverseIns, // reverse the conditional instruction
8738 8, /* 8 bytes from start of this large conditional pseudo-instruction to L_not. */
8741 // Now, pretend we've got a normal unconditional branch, and fall through to the code to emit that.
8745 // The distVal was computed based on the beginning of the pseudo-instruction,
8746 // So subtract the size of the conditional branch so that it is relative to the
8747 // unconditional branch.
8751 dst = emitOutputShortBranch(dst, ins, fmt, distVal, id);
8755 dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8761 /*****************************************************************************
8763 * Output a short branch instruction.
8765 BYTE* emitter::emitOutputShortBranch(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, instrDescJmp* id)
8767 code_t code = emitInsCode(ins, fmt);
8769 ssize_t loBits = (distVal & 3);
8770 noway_assert(loBits == 0);
8771 distVal >>= 2; // branch offset encodings are scaled by 4.
8773 if (fmt == IF_BI_0A)
8775 // INS_b or INS_bl_local
8776 noway_assert(isValidSimm26(distVal));
8777 distVal &= 0x3FFFFFFLL;
8780 else if (fmt == IF_BI_0B) // BI_0B 01010100iiiiiiii iiiiiiiiiiiXXXXX simm19:00
8782 // INS_beq, INS_bne, etc...
8783 noway_assert(isValidSimm19(distVal));
8784 distVal &= 0x7FFFFLL;
8785 code |= distVal << 5;
8787 else if (fmt == IF_BI_1A) // BI_1A X.......iiiiiiii iiiiiiiiiiittttt Rt simm19:00
8789 // INS_cbz or INS_cbnz
8790 assert(id != nullptr);
8791 code |= insEncodeDatasize(id->idOpSize()); // X
8792 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
8794 noway_assert(isValidSimm19(distVal));
8795 distVal &= 0x7FFFFLL; // 19 bits
8796 code |= distVal << 5;
8798 else if (fmt == IF_BI_1B) // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
8800 // INS_tbz or INS_tbnz
8801 assert(id != nullptr);
8802 ssize_t imm = emitGetInsSC(id);
8803 assert(isValidImmShift(imm, id->idOpSize()));
8805 if (imm & 0x20) // test bit 32-63 ?
8807 code |= 0x80000000; // B
8809 code |= ((imm & 0x1F) << 19); // bbbbb
8810 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
8812 noway_assert(isValidSimm14(distVal));
8813 distVal &= 0x3FFFLL; // 14 bits
8814 code |= distVal << 5;
8818 assert(!"Unknown fmt for emitOutputShortBranch");
8821 dst += emitOutput_Instr(dst, code);
8826 /*****************************************************************************
8828 * Output a short address instruction.
8830 BYTE* emitter::emitOutputShortAddress(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, regNumber reg)
8832 ssize_t loBits = (distVal & 3);
8835 code_t code = emitInsCode(ins, fmt);
8836 if (fmt == IF_DI_1E) // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
8838 // INS_adr or INS_adrp
8839 code |= insEncodeReg_Rd(reg); // ddddd
8841 noway_assert(isValidSimm19(distVal));
8842 distVal &= 0x7FFFFLL; // 19 bits
8843 code |= distVal << 5;
8844 code |= loBits << 29; // 2 bits
8848 assert(!"Unknown fmt for emitOutputShortAddress");
8851 dst += emitOutput_Instr(dst, code);
8856 /*****************************************************************************
8858 * Output a short constant instruction.
8860 BYTE* emitter::emitOutputShortConstant(
8861 BYTE* dst, instruction ins, insFormat fmt, ssize_t imm, regNumber reg, emitAttr opSize)
8863 code_t code = emitInsCode(ins, fmt);
8865 if (fmt == IF_LS_1A)
8867 // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt simm21
8868 // INS_ldr or INS_ldrsw (PC-Relative)
8870 ssize_t loBits = (imm & 3);
8871 noway_assert(loBits == 0);
8872 ssize_t distVal = imm >>= 2; // load offset encodings are scaled by 4.
8874 noway_assert(isValidSimm19(distVal));
8876 // Is the target a vector register?
8877 if (isVectorRegister(reg))
8879 code |= insEncodeDatasizeVLS(code, opSize); // XX V
8880 code |= insEncodeReg_Vt(reg); // ttttt
8884 assert(isGeneralRegister(reg));
8885 // insEncodeDatasizeLS is not quite right for this case.
8886 // So just specialize it.
8887 if ((ins == INS_ldr) && (opSize == EA_8BYTE))
8889 // set the operation size in bit 30
8893 code |= insEncodeReg_Rt(reg); // ttttt
8896 distVal &= 0x7FFFFLL; // 19 bits
8897 code |= distVal << 5;
8899 else if (fmt == IF_LS_2B)
8901 // ldr Rt,[Xn+pimm12] LS_2B 1X11100101iiiiii iiiiiinnnnnttttt B940 0000 imm(0-4095<<{2,3})
8902 // INS_ldr or INS_ldrsw (PC-Relative)
8903 noway_assert(isValidUimm12(imm));
8904 assert(isGeneralRegister(reg));
8906 if (opSize == EA_8BYTE)
8908 // insEncodeDatasizeLS is not quite right for this case.
8909 // So just specialize it.
8912 // set the operation size in bit 30
8915 // Low 3 bits should be 0 -- 8 byte JIT data should be aligned on 8 byte.
8916 assert((imm & 7) == 0);
8921 assert(opSize == EA_4BYTE);
8922 // Low 2 bits should be 0 -- 4 byte aligned data.
8923 assert((imm & 3) == 0);
8927 code |= insEncodeReg_Rt(reg); // ttttt
8928 code |= insEncodeReg_Rn(reg); // nnnnn
8933 assert(!"Unknown fmt for emitOutputShortConstant");
8936 dst += emitOutput_Instr(dst, code);
8940 /*****************************************************************************
8942 * Output a call instruction.
8945 unsigned emitter::emitOutputCall(insGroup* ig, BYTE* dst, instrDesc* id, code_t code)
8947 const unsigned char callInstrSize = sizeof(code_t); // 4 bytes
8948 regMaskTP gcrefRegs;
8949 regMaskTP byrefRegs;
8951 VARSET_TP GCvars(VarSetOps::UninitVal());
8953 // Is this a "fat" call descriptor?
8954 if (id->idIsLargeCall())
8956 instrDescCGCA* idCall = (instrDescCGCA*)id;
8957 gcrefRegs = idCall->idcGcrefRegs;
8958 byrefRegs = idCall->idcByrefRegs;
8959 VarSetOps::Assign(emitComp, GCvars, idCall->idcGCvars);
8963 assert(!id->idIsLargeDsp());
8964 assert(!id->idIsLargeCns());
8966 gcrefRegs = emitDecodeCallGCregs(id);
8968 VarSetOps::AssignNoCopy(emitComp, GCvars, VarSetOps::MakeEmpty(emitComp));
8971 /* We update the GC info before the call as the variables cannot be
8972 used by the call. Killing variables before the call helps with
8973 boundary conditions if the call is CORINFO_HELP_THROW - see bug 50029.
8974 If we ever track aliased variables (which could be used by the
8975 call), we would have to keep them alive past the call. */
8977 emitUpdateLiveGCvars(GCvars, dst);
8979 // Now output the call instruction and update the 'dst' pointer
8981 unsigned outputInstrSize = emitOutput_Instr(dst, code);
8982 dst += outputInstrSize;
8984 // All call instructions are 4-byte in size on ARM64
8986 assert(outputInstrSize == callInstrSize);
8988 // If the method returns a GC ref, mark INTRET (R0) appropriately.
8989 if (id->idGCref() == GCT_GCREF)
8991 gcrefRegs |= RBM_INTRET;
8993 else if (id->idGCref() == GCT_BYREF)
8995 byrefRegs |= RBM_INTRET;
8998 // If is a multi-register return method is called, mark INTRET_1 (X1) appropriately
8999 if (id->idIsLargeCall())
9001 instrDescCGCA* idCall = (instrDescCGCA*)id;
9002 if (idCall->idSecondGCref() == GCT_GCREF)
9004 gcrefRegs |= RBM_INTRET_1;
9006 else if (idCall->idSecondGCref() == GCT_BYREF)
9008 byrefRegs |= RBM_INTRET_1;
9012 // If the GC register set has changed, report the new set.
9013 if (gcrefRegs != emitThisGCrefRegs)
9015 emitUpdateLiveGCregs(GCT_GCREF, gcrefRegs, dst);
9017 // If the Byref register set has changed, report the new set.
9018 if (byrefRegs != emitThisByrefRegs)
9020 emitUpdateLiveGCregs(GCT_BYREF, byrefRegs, dst);
9023 // Some helper calls may be marked as not requiring GC info to be recorded.
9024 if ((!id->idIsNoGC()))
9026 // On ARM64, as on AMD64, we don't change the stack pointer to push/pop args.
9027 // So we're not really doing a "stack pop" here (note that "args" is 0), but we use this mechanism
9028 // to record the call for GC info purposes. (It might be best to use an alternate call,
9029 // and protect "emitStackPop" under the EMIT_TRACK_STACK_DEPTH preprocessor variable.)
9030 emitStackPop(dst, /*isCall*/ true, callInstrSize, /*args*/ 0);
9032 // Do we need to record a call location for GC purposes?
9034 if (!emitFullGCinfo)
9036 emitRecordGCcall(dst, callInstrSize);
9039 return callInstrSize;
9042 /*****************************************************************************
9044 * Emit a 32-bit Arm64 instruction
9047 /*static*/ unsigned emitter::emitOutput_Instr(BYTE* dst, code_t code)
9049 assert(sizeof(code_t) == 4);
9050 *((code_t*)dst) = code;
9052 return sizeof(code_t);
9055 /*****************************************************************************
9057 * Append the machine code corresponding to the given instruction descriptor
9058 * to the code block at '*dp'; the base of the code block is 'bp', and 'ig'
9059 * is the instruction group that contains the instruction. Updates '*dp' to
9060 * point past the generated code, and returns the size of the instruction
9061 * descriptor in bytes.
9064 size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
9069 size_t sz = emitGetInstrDescSize(id); // TODO-ARM64-Cleanup: on ARM, this is set in each case. why?
9070 instruction ins = id->idIns();
9071 insFormat fmt = id->idInsFmt();
9072 emitAttr size = id->idOpSize();
9076 bool dspOffs = emitComp->opts.dspGCtbls;
9078 bool dspOffs = !emitComp->opts.disDiffable;
9082 assert(REG_NA == (int)REG_NA);
9084 /* What instruction format have we got? */
9096 case IF_BI_0A: // BI_0A ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
9097 case IF_BI_0B: // BI_0B ......iiiiiiiiii iiiiiiiiiii..... simm19:00
9099 assert(id->idGCref() == GCT_NONE);
9100 assert(id->idIsBound());
9101 dst = emitOutputLJ(ig, dst, id);
9102 sz = sizeof(instrDescJmp);
9105 case IF_BI_0C: // BI_0C ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
9106 code = emitInsCode(ins, fmt);
9107 sz = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
9108 dst += emitOutputCall(ig, dst, id, code);
9109 // Always call RecordRelocation so that we wire in a JumpStub when we don't reach
9110 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_BRANCH26);
9113 case IF_BI_1A: // BI_1A ......iiiiiiiiii iiiiiiiiiiittttt Rt simm19:00
9114 assert(insOptsNone(id->idInsOpt()));
9115 assert(id->idIsBound());
9117 dst = emitOutputLJ(ig, dst, id);
9118 sz = sizeof(instrDescJmp);
9121 case IF_BI_1B: // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
9122 assert(insOptsNone(id->idInsOpt()));
9123 assert(id->idIsBound());
9125 dst = emitOutputLJ(ig, dst, id);
9126 sz = sizeof(instrDescJmp);
9129 case IF_BR_1A: // BR_1A ................ ......nnnnn..... Rn
9130 assert(insOptsNone(id->idInsOpt()));
9131 assert((ins == INS_ret) || (ins == INS_br));
9132 code = emitInsCode(ins, fmt);
9133 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9135 dst += emitOutput_Instr(dst, code);
9138 case IF_BR_1B: // BR_1B ................ ......nnnnn..... Rn
9139 assert(insOptsNone(id->idInsOpt()));
9140 assert((ins == INS_br_tail) || (ins == INS_blr));
9141 code = emitInsCode(ins, fmt);
9142 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9144 sz = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
9145 dst += emitOutputCall(ig, dst, id, code);
9148 case IF_LS_1A: // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB)
9150 assert(insOptsNone(id->idInsOpt()));
9151 assert(id->idIsBound());
9153 dst = emitOutputLJ(ig, dst, id);
9154 sz = sizeof(instrDescJmp);
9157 case IF_LS_2A: // LS_2A .X.......X...... ......nnnnnttttt Rt Rn
9158 assert(insOptsNone(id->idInsOpt()));
9159 code = emitInsCode(ins, fmt);
9160 // Is the target a vector register?
9161 if (isVectorRegister(id->idReg1()))
9163 code &= 0x3FFFFFFF; // clear the size bits
9164 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9165 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9169 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9170 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9172 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9173 dst += emitOutput_Instr(dst, code);
9176 case IF_LS_2B: // LS_2B .X.......Xiiiiii iiiiiinnnnnttttt Rt Rn imm(0-4095)
9177 assert(insOptsNone(id->idInsOpt()));
9178 imm = emitGetInsSC(id);
9179 assert(isValidUimm12(imm));
9180 code = emitInsCode(ins, fmt);
9181 // Is the target a vector register?
9182 if (isVectorRegister(id->idReg1()))
9184 code &= 0x3FFFFFFF; // clear the size bits
9185 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9186 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9190 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9191 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9193 code |= ((code_t)imm << 10); // iiiiiiiiiiii
9194 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9195 dst += emitOutput_Instr(dst, code);
9198 case IF_LS_2C: // LS_2C .X.......X.iiiii iiiiPPnnnnnttttt Rt Rn imm(-256..+255) no/pre/post inc
9199 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9200 imm = emitGetInsSC(id);
9201 assert((imm >= -256) && (imm <= 255)); // signed 9 bits
9202 imm &= 0x1ff; // force into unsigned 9 bit representation
9203 code = emitInsCode(ins, fmt);
9204 // Is the target a vector register?
9205 if (isVectorRegister(id->idReg1()))
9207 code &= 0x3FFFFFFF; // clear the size bits
9208 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9209 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9213 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9214 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9216 code |= insEncodeIndexedOpt(id->idInsOpt()); // PP
9217 code |= ((code_t)imm << 12); // iiiiiiiii
9218 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9219 dst += emitOutput_Instr(dst, code);
9222 case IF_LS_3A: // LS_3A .X.......X.mmmmm oooS..nnnnnttttt Rt Rn Rm ext(Rm) LSL {}
9223 assert(insOptsLSExtend(id->idInsOpt()));
9224 code = emitInsCode(ins, fmt);
9225 // Is the target a vector register?
9226 if (isVectorRegister(id->idReg1()))
9228 code &= 0x3FFFFFFF; // clear the size bits
9229 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9230 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9234 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9235 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9237 code |= insEncodeExtend(id->idInsOpt()); // ooo
9238 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9239 if (id->idIsLclVar())
9241 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9245 code |= insEncodeReg3Scale(id->idReg3Scaled()); // S
9246 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9248 dst += emitOutput_Instr(dst, code);
9251 case IF_LS_3B: // LS_3B X............... .aaaaannnnnddddd Rd Ra Rn
9252 assert(insOptsNone(id->idInsOpt()));
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 |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9269 dst += emitOutput_Instr(dst, code);
9272 case IF_LS_3C: // LS_3C X......PP.iiiiii iaaaaannnnnddddd Rd Ra Rn imm(im7,sh)
9273 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9274 imm = emitGetInsSC(id);
9275 assert((imm >= -64) && (imm <= 63)); // signed 7 bits
9276 imm &= 0x7f; // force into unsigned 7 bit representation
9277 code = emitInsCode(ins, fmt);
9278 // Is the target a vector register?
9279 if (isVectorRegister(id->idReg1()))
9281 code &= 0x3FFFFFFF; // clear the size bits
9282 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9283 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9284 code |= insEncodeReg_Va(id->idReg2()); // aaaaa
9288 code |= insEncodeDatasize(id->idOpSize()); // X
9289 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9290 code |= insEncodeReg_Ra(id->idReg2()); // aaaaa
9292 code |= insEncodePairIndexedOpt(ins, id->idInsOpt()); // PP
9293 code |= ((code_t)imm << 15); // iiiiiiiii
9294 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9295 dst += emitOutput_Instr(dst, code);
9298 case IF_LS_3D: // LS_3D .X.......X.mmmmm ......nnnnnttttt Wm Rt Rn
9299 code = emitInsCode(ins, fmt);
9300 // Arm64 store exclusive unpredictable cases
9301 assert(id->idReg1() != id->idReg2());
9302 assert(id->idReg1() != id->idReg3());
9303 code |= insEncodeDatasizeLS(code, id->idOpSize()); // X
9304 code |= insEncodeReg_Rm(id->idReg1()); // mmmmm
9305 code |= insEncodeReg_Rt(id->idReg2()); // ttttt
9306 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9307 dst += emitOutput_Instr(dst, code);
9310 case IF_LS_3E: // LS_3E .X.........mmmmm ......nnnnnttttt Rm Rt Rn ARMv8.1 LSE Atomics
9311 code = emitInsCode(ins, fmt);
9312 code |= insEncodeDatasizeLS(code, id->idOpSize()); // X
9313 code |= insEncodeReg_Rm(id->idReg1()); // mmmmm
9314 code |= insEncodeReg_Rt(id->idReg2()); // ttttt
9315 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9316 dst += emitOutput_Instr(dst, code);
9319 case IF_DI_1A: // DI_1A X.......shiiiiii iiiiiinnnnn..... Rn imm(i12,sh)
9320 assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9321 imm = emitGetInsSC(id);
9322 assert(isValidUimm12(imm));
9323 code = emitInsCode(ins, fmt);
9324 code |= insEncodeDatasize(id->idOpSize()); // X
9325 code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9326 code |= ((code_t)imm << 10); // iiiiiiiiiiii
9327 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9328 dst += emitOutput_Instr(dst, code);
9331 case IF_DI_1B: // DI_1B X........hwiiiii iiiiiiiiiiiddddd Rd imm(i16,hw)
9332 imm = emitGetInsSC(id);
9333 assert(isValidImmHWVal(imm, id->idOpSize()));
9334 code = emitInsCode(ins, fmt);
9335 code |= insEncodeDatasize(id->idOpSize()); // X
9336 code |= ((code_t)imm << 5); // hwiiiii iiiiiiiiiii
9337 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9338 dst += emitOutput_Instr(dst, code);
9341 case IF_DI_1C: // DI_1C X........Nrrrrrr ssssssnnnnn..... Rn imm(N,r,s)
9342 imm = emitGetInsSC(id);
9343 assert(isValidImmNRS(imm, id->idOpSize()));
9344 code = emitInsCode(ins, fmt);
9345 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9346 code |= insEncodeDatasize(id->idOpSize()); // X
9347 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9348 dst += emitOutput_Instr(dst, code);
9351 case IF_DI_1D: // DI_1D X........Nrrrrrr ssssss.....ddddd Rd imm(N,r,s)
9352 imm = emitGetInsSC(id);
9353 assert(isValidImmNRS(imm, id->idOpSize()));
9354 code = emitInsCode(ins, fmt);
9355 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9356 code |= insEncodeDatasize(id->idOpSize()); // X
9357 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9358 dst += emitOutput_Instr(dst, code);
9361 case IF_DI_1E: // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
9363 assert(insOptsNone(id->idInsOpt()));
9364 if (id->idIsReloc())
9366 code = emitInsCode(ins, fmt);
9367 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9368 dst += emitOutput_Instr(dst, code);
9369 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEBASE_REL21);
9373 // Local jmp/load case which does not need a relocation.
9374 assert(id->idIsBound());
9375 dst = emitOutputLJ(ig, dst, id);
9377 sz = sizeof(instrDescJmp);
9380 case IF_DI_1F: // DI_1F X..........iiiii cccc..nnnnn.nzcv Rn imm5 nzcv cond
9381 imm = emitGetInsSC(id);
9382 assert(isValidImmCondFlagsImm5(imm));
9385 cfi.immCFVal = (unsigned)imm;
9386 code = emitInsCode(ins, fmt);
9387 code |= insEncodeDatasize(id->idOpSize()); // X
9388 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9389 code |= ((code_t)cfi.imm5 << 16); // iiiii
9390 code |= insEncodeFlags(cfi.flags); // nzcv
9391 code |= insEncodeCond(cfi.cond); // cccc
9392 dst += emitOutput_Instr(dst, code);
9396 case IF_DI_2A: // DI_2A X.......shiiiiii iiiiiinnnnnddddd Rd Rn imm(i12,sh)
9397 assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9398 imm = emitGetInsSC(id);
9399 assert(isValidUimm12(imm));
9400 code = emitInsCode(ins, fmt);
9401 code |= insEncodeDatasize(id->idOpSize()); // X
9402 code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9403 code |= ((code_t)imm << 10); // iiiiiiiiiiii
9404 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9405 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9406 dst += emitOutput_Instr(dst, code);
9408 if (id->idIsReloc())
9410 assert(sz == sizeof(instrDesc));
9411 assert(id->idAddr()->iiaAddr != nullptr);
9412 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEOFFSET_12A);
9416 case IF_DI_2B: // DI_2B X.........Xnnnnn ssssssnnnnnddddd Rd Rn imm(0-63)
9417 code = emitInsCode(ins, fmt);
9418 imm = emitGetInsSC(id);
9419 assert(isValidImmShift(imm, id->idOpSize()));
9420 code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9421 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9422 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9423 code |= insEncodeReg_Rm(id->idReg2()); // Reg2 also in mmmmm
9424 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9425 dst += emitOutput_Instr(dst, code);
9428 case IF_DI_2C: // DI_2C X........Nrrrrrr ssssssnnnnnddddd Rd Rn imm(N,r,s)
9429 imm = emitGetInsSC(id);
9430 assert(isValidImmNRS(imm, id->idOpSize()));
9431 code = emitInsCode(ins, fmt);
9432 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9433 code |= insEncodeDatasize(id->idOpSize()); // X
9434 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9435 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9436 dst += emitOutput_Instr(dst, code);
9439 case IF_DI_2D: // DI_2D X........Nrrrrrr ssssssnnnnnddddd Rd Rn imr, imms (N,r,s)
9440 if (ins == INS_asr || ins == INS_lsl || ins == INS_lsr)
9442 imm = emitGetInsSC(id);
9443 assert(isValidImmShift(imm, id->idOpSize()));
9445 // Shift immediates are aliases of the SBFM/UBFM instructions
9446 // that actually take 2 registers and 2 constants,
9447 // Since we stored the shift immediate value
9448 // we need to calculate the N,R and S values here.
9453 bmi.immN = (size == EA_8BYTE) ? 1 : 0;
9455 bmi.immS = (size == EA_8BYTE) ? 0x3f : 0x1f;
9457 // immR and immS are now set correctly for INS_asr and INS_lsr
9458 // but for INS_lsl we have to adjust the values for immR and immS
9462 bmi.immR = -imm & bmi.immS;
9463 bmi.immS = bmi.immS - imm;
9466 // setup imm with the proper 13 bit value N:R:S
9472 // The other instructions have already have encoded N,R and S values
9473 imm = emitGetInsSC(id);
9475 assert(isValidImmNRS(imm, id->idOpSize()));
9477 code = emitInsCode(ins, fmt);
9478 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9479 code |= insEncodeDatasize(id->idOpSize()); // X
9480 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9481 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9482 dst += emitOutput_Instr(dst, code);
9485 case IF_DR_1D: // DR_1D X............... cccc.......ddddd Rd cond
9486 imm = emitGetInsSC(id);
9487 assert(isValidImmCond(imm));
9490 cfi.immCFVal = (unsigned)imm;
9491 code = emitInsCode(ins, fmt);
9492 code |= insEncodeDatasize(id->idOpSize()); // X
9493 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9494 code |= insEncodeInvertedCond(cfi.cond); // cccc
9495 dst += emitOutput_Instr(dst, code);
9499 case IF_DR_2A: // DR_2A X..........mmmmm ......nnnnn..... Rn Rm
9500 assert(insOptsNone(id->idInsOpt()));
9501 code = emitInsCode(ins, fmt);
9502 code |= insEncodeDatasize(id->idOpSize()); // X
9503 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9504 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9505 dst += emitOutput_Instr(dst, code);
9508 case IF_DR_2B: // DR_2B X.......sh.mmmmm ssssssnnnnn..... Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
9509 code = emitInsCode(ins, fmt);
9510 imm = emitGetInsSC(id);
9511 assert(isValidImmShift(imm, id->idOpSize()));
9512 code |= insEncodeDatasize(id->idOpSize()); // X
9513 code |= insEncodeShiftType(id->idInsOpt()); // sh
9514 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9515 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9516 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9517 dst += emitOutput_Instr(dst, code);
9520 case IF_DR_2C: // DR_2C X..........mmmmm ooosssnnnnn..... Rn Rm ext(Rm) LSL imm(0-4)
9521 code = emitInsCode(ins, fmt);
9522 imm = emitGetInsSC(id);
9523 assert((imm >= 0) && (imm <= 4)); // imm [0..4]
9524 code |= insEncodeDatasize(id->idOpSize()); // X
9525 code |= insEncodeExtend(id->idInsOpt()); // ooo
9526 code |= insEncodeExtendScale(imm); // sss
9527 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9528 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9529 dst += emitOutput_Instr(dst, code);
9532 case IF_DR_2D: // DR_2D X..........nnnnn cccc..nnnnnddddd Rd Rn cond
9533 imm = emitGetInsSC(id);
9534 assert(isValidImmCond(imm));
9537 cfi.immCFVal = (unsigned)imm;
9538 code = emitInsCode(ins, fmt);
9539 code |= insEncodeDatasize(id->idOpSize()); // X
9540 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9541 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9542 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9543 code |= insEncodeInvertedCond(cfi.cond); // cccc
9544 dst += emitOutput_Instr(dst, code);
9548 case IF_DR_2E: // DR_2E X..........mmmmm ...........ddddd Rd Rm
9549 code = emitInsCode(ins, fmt);
9550 code |= insEncodeDatasize(id->idOpSize()); // X
9551 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9552 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9553 dst += emitOutput_Instr(dst, code);
9556 case IF_DR_2F: // DR_2F X.......sh.mmmmm ssssss.....ddddd Rd Rm {LSL,LSR,ASR} imm(0-63)
9557 code = emitInsCode(ins, fmt);
9558 imm = emitGetInsSC(id);
9559 assert(isValidImmShift(imm, id->idOpSize()));
9560 code |= insEncodeDatasize(id->idOpSize()); // X
9561 code |= insEncodeShiftType(id->idInsOpt()); // sh
9562 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9563 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9564 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9565 dst += emitOutput_Instr(dst, code);
9568 case IF_DR_2G: // DR_2G X............... .....xnnnnnddddd Rd Rn
9569 code = emitInsCode(ins, fmt);
9570 code |= insEncodeDatasize(id->idOpSize()); // X
9573 if (size == EA_8BYTE)
9575 code |= 0x00000400; // x - bit at location 10
9578 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9579 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9580 dst += emitOutput_Instr(dst, code);
9583 case IF_DR_2H: // DR_2H X........X...... ......nnnnnddddd Rd Rn
9584 code = emitInsCode(ins, fmt);
9585 code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9586 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9587 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9588 dst += emitOutput_Instr(dst, code);
9591 case IF_DR_2I: // DR_2I X..........mmmmm cccc..nnnnn.nzcv Rn Rm nzcv cond
9592 imm = emitGetInsSC(id);
9593 assert(isValidImmCondFlags(imm));
9596 cfi.immCFVal = (unsigned)imm;
9597 code = emitInsCode(ins, fmt);
9598 code |= insEncodeDatasize(id->idOpSize()); // X
9599 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9600 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9601 code |= insEncodeFlags(cfi.flags); // nzcv
9602 code |= insEncodeCond(cfi.cond); // cccc
9603 dst += emitOutput_Instr(dst, code);
9607 case IF_DR_2J: // DR_2J ................ ......nnnnnddddd Sd Sn (sha1h)
9608 code = emitInsCode(ins, fmt);
9609 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9610 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9611 dst += emitOutput_Instr(dst, code);
9614 case IF_DR_3A: // DR_3A X..........mmmmm ......nnnnnmmmmm Rd Rn Rm
9615 code = emitInsCode(ins, fmt);
9616 code |= insEncodeDatasize(id->idOpSize()); // X
9617 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9618 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9619 if (id->idIsLclVar())
9621 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9625 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9627 dst += emitOutput_Instr(dst, code);
9630 case IF_DR_3B: // DR_3B X.......sh.mmmmm ssssssnnnnnddddd Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
9631 code = emitInsCode(ins, fmt);
9632 imm = emitGetInsSC(id);
9633 assert(isValidImmShift(imm, id->idOpSize()));
9634 code |= insEncodeDatasize(id->idOpSize()); // X
9635 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9636 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9637 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9638 code |= insEncodeShiftType(id->idInsOpt()); // sh
9639 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9640 dst += emitOutput_Instr(dst, code);
9643 case IF_DR_3C: // DR_3C X..........mmmmm ooosssnnnnnddddd Rd Rn Rm ext(Rm) LSL imm(0-4)
9644 code = emitInsCode(ins, fmt);
9645 imm = emitGetInsSC(id);
9646 assert((imm >= 0) && (imm <= 4)); // imm [0..4]
9647 code |= insEncodeDatasize(id->idOpSize()); // X
9648 code |= insEncodeExtend(id->idInsOpt()); // ooo
9649 code |= insEncodeExtendScale(imm); // sss
9650 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9651 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9652 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9653 dst += emitOutput_Instr(dst, code);
9656 case IF_DR_3D: // DR_3D X..........mmmmm cccc..nnnnnddddd Rd Rn Rm cond
9657 imm = emitGetInsSC(id);
9658 assert(isValidImmCond(imm));
9661 cfi.immCFVal = (unsigned)imm;
9662 code = emitInsCode(ins, fmt);
9663 code |= insEncodeDatasize(id->idOpSize()); // X
9664 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9665 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9666 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9667 code |= insEncodeCond(cfi.cond); // cccc
9668 dst += emitOutput_Instr(dst, code);
9672 case IF_DR_3E: // DR_3E X........X.mmmmm ssssssnnnnnddddd Rd Rn Rm imm(0-63)
9673 code = emitInsCode(ins, fmt);
9674 imm = emitGetInsSC(id);
9675 assert(isValidImmShift(imm, id->idOpSize()));
9676 code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9677 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9678 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9679 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9680 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9681 dst += emitOutput_Instr(dst, code);
9684 case IF_DR_4A: // DR_4A X..........mmmmm .aaaaannnnnmmmmm Rd Rn Rm Ra
9685 code = emitInsCode(ins, fmt);
9686 code |= insEncodeDatasize(id->idOpSize()); // X
9687 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9688 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9689 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9690 code |= insEncodeReg_Ra(id->idReg4()); // aaaaa
9691 dst += emitOutput_Instr(dst, code);
9694 case IF_DV_1A: // DV_1A .........X.iiiii iii........ddddd Vd imm8 (fmov - immediate scalar)
9695 imm = emitGetInsSC(id);
9696 elemsize = id->idOpSize();
9697 code = emitInsCode(ins, fmt);
9698 code |= insEncodeFloatElemsize(elemsize); // X
9699 code |= ((code_t)imm << 13); // iiiii iii
9700 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9701 dst += emitOutput_Instr(dst, code);
9704 case IF_DV_1B: // DV_1B .QX..........iii cmod..iiiiiddddd Vd imm8 (immediate vector)
9705 imm = emitGetInsSC(id) & 0x0ff;
9706 immShift = (emitGetInsSC(id) & 0x700) >> 8;
9707 elemsize = optGetElemsize(id->idInsOpt());
9712 cmode = 0xE; // 1110
9716 cmode |= (immShift << 1); // 10x0
9722 cmode |= (immShift << 1); // 0xx0
9732 cmode = 0xE; // 1110
9739 code = emitInsCode(ins, fmt);
9740 code |= insEncodeVectorsize(id->idOpSize()); // Q
9741 if ((ins == INS_fmov) || (ins == INS_movi))
9743 if (elemsize == EA_8BYTE)
9745 code |= 0x20000000; // X
9748 if (ins != INS_fmov)
9750 assert((cmode >= 0) && (cmode <= 0xF));
9751 code |= (cmode << 12); // cmod
9753 code |= (((code_t)imm >> 5) << 16); // iii
9754 code |= (((code_t)imm & 0x1f) << 5); // iiiii
9755 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9756 dst += emitOutput_Instr(dst, code);
9759 case IF_DV_1C: // DV_1C .........X...... ......nnnnn..... Vn #0.0 (fcmp - with zero)
9760 elemsize = id->idOpSize();
9761 code = emitInsCode(ins, fmt);
9762 code |= insEncodeFloatElemsize(elemsize); // X
9763 code |= insEncodeReg_Vn(id->idReg1()); // nnnnn
9764 dst += emitOutput_Instr(dst, code);
9767 case IF_DV_2A: // DV_2A .Q.......X...... ......nnnnnddddd Vd Vn (fabs, fcvt - vector)
9768 elemsize = optGetElemsize(id->idInsOpt());
9769 code = emitInsCode(ins, fmt);
9770 code |= insEncodeVectorsize(id->idOpSize()); // Q
9771 code |= insEncodeFloatElemsize(elemsize); // X
9772 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9773 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9774 dst += emitOutput_Instr(dst, code);
9777 case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov/smov - to general)
9778 elemsize = id->idOpSize();
9779 index = emitGetInsSC(id);
9780 datasize = (elemsize == EA_8BYTE) ? EA_16BYTE : EA_8BYTE;
9781 if (ins == INS_smov)
9783 datasize = EA_16BYTE;
9785 code = emitInsCode(ins, fmt);
9786 code |= insEncodeVectorsize(datasize); // Q
9787 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9788 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9789 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9790 dst += emitOutput_Instr(dst, code);
9793 case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
9796 datasize = id->idOpSize();
9797 elemsize = optGetElemsize(id->idInsOpt());
9802 datasize = EA_16BYTE;
9803 elemsize = id->idOpSize();
9804 index = emitGetInsSC(id);
9806 code = emitInsCode(ins, fmt);
9807 code |= insEncodeVectorsize(datasize); // Q
9808 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9809 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9810 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9811 dst += emitOutput_Instr(dst, code);
9814 case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
9815 index = emitGetInsSC(id);
9816 elemsize = optGetElemsize(id->idInsOpt());
9817 code = emitInsCode(ins, fmt);
9818 code |= insEncodeVectorsize(id->idOpSize()); // Q
9819 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9820 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9821 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9822 dst += emitOutput_Instr(dst, code);
9825 case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
9826 index = emitGetInsSC(id);
9827 elemsize = id->idOpSize();
9828 code = emitInsCode(ins, fmt);
9829 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9830 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9831 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9832 dst += emitOutput_Instr(dst, code);
9835 case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
9836 elemsize = id->idOpSize();
9837 imm = emitGetInsSC(id);
9838 index = (imm >> 4) & 0xf;
9840 code = emitInsCode(ins, fmt);
9841 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9842 code |= insEncodeVectorIndex2(elemsize, index2); // jjjj
9843 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9844 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9845 dst += emitOutput_Instr(dst, code);
9848 case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov,fcvtXX - register)
9849 elemsize = id->idOpSize();
9850 code = emitInsCode(ins, fmt);
9851 code |= insEncodeFloatElemsize(elemsize); // X
9852 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9853 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9854 dst += emitOutput_Instr(dst, code);
9857 case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov - to general)
9858 elemsize = id->idOpSize();
9859 code = emitInsCode(ins, fmt);
9860 code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X X
9861 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9862 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9863 dst += emitOutput_Instr(dst, code);
9866 case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov - from general)
9867 elemsize = id->idOpSize();
9868 code = emitInsCode(ins, fmt);
9869 code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X X
9870 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9871 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9872 dst += emitOutput_Instr(dst, code);
9875 case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
9876 code = emitInsCode(ins, fmt);
9877 code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // SS DD
9878 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9879 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9880 dst += emitOutput_Instr(dst, code);
9883 case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
9884 elemsize = id->idOpSize();
9885 code = emitInsCode(ins, fmt);
9886 code |= insEncodeFloatElemsize(elemsize); // X
9887 code |= insEncodeReg_Vn(id->idReg1()); // nnnnn
9888 code |= insEncodeReg_Vm(id->idReg2()); // mmmmm
9889 dst += emitOutput_Instr(dst, code);
9892 case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
9893 elemsize = id->idOpSize();
9894 code = emitInsCode(ins, fmt);
9895 code |= insEncodeElemsize(elemsize); // XX
9896 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9897 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9898 dst += emitOutput_Instr(dst, code);
9901 case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
9902 elemsize = optGetElemsize(id->idInsOpt());
9903 code = emitInsCode(ins, fmt);
9904 code |= insEncodeVectorsize(id->idOpSize()); // Q
9905 code |= insEncodeElemsize(elemsize); // XX
9906 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9907 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9908 dst += emitOutput_Instr(dst, code);
9911 case IF_DV_2N: // DV_2N .........iiiiiii ......nnnnnddddd Vd Vn imm (shift - scalar)
9912 imm = emitGetInsSC(id);
9913 code = emitInsCode(ins, fmt);
9914 code |= insEncodeVectorShift(EA_8BYTE, imm); // iiiiiii
9915 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9916 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9917 dst += emitOutput_Instr(dst, code);
9920 case IF_DV_2O: // DV_2O .Q.......iiiiiii ......nnnnnddddd Vd Vn imm (shift - vector)
9921 imm = emitGetInsSC(id);
9922 elemsize = optGetElemsize(id->idInsOpt());
9923 code = emitInsCode(ins, fmt);
9924 code |= insEncodeVectorsize(id->idOpSize()); // Q
9925 code |= insEncodeVectorShift(elemsize, imm); // iiiiiii
9926 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9927 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9928 dst += emitOutput_Instr(dst, code);
9931 case IF_DV_2P: // DV_2P ............... ......nnnnnddddd Vd Vn (aes*, sha1su1)
9932 elemsize = optGetElemsize(id->idInsOpt());
9933 code = emitInsCode(ins, fmt);
9934 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9935 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9936 dst += emitOutput_Instr(dst, code);
9939 case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
9940 code = emitInsCode(ins, fmt);
9941 elemsize = optGetElemsize(id->idInsOpt());
9942 code |= insEncodeVectorsize(id->idOpSize()); // Q
9943 code |= insEncodeElemsize(elemsize); // XX
9944 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9945 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9946 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9947 dst += emitOutput_Instr(dst, code);
9950 case IF_DV_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector)
9951 code = emitInsCode(ins, fmt);
9952 imm = emitGetInsSC(id);
9953 elemsize = optGetElemsize(id->idInsOpt());
9954 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
9955 code |= insEncodeVectorsize(id->idOpSize()); // Q
9956 code |= insEncodeElemsize(elemsize); // XX
9957 code |= insEncodeVectorIndexLMH(elemsize, imm); // LM H
9958 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9959 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9960 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9961 dst += emitOutput_Instr(dst, code);
9964 case IF_DV_3B: // DV_3B .Q.......X.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
9965 code = emitInsCode(ins, fmt);
9966 elemsize = optGetElemsize(id->idInsOpt());
9967 code |= insEncodeVectorsize(id->idOpSize()); // Q
9968 code |= insEncodeFloatElemsize(elemsize); // X
9969 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9970 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9971 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9972 dst += emitOutput_Instr(dst, code);
9975 case IF_DV_3BI: // DV_3BI .Q.......XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
9976 code = emitInsCode(ins, fmt);
9977 imm = emitGetInsSC(id);
9978 elemsize = optGetElemsize(id->idInsOpt());
9979 assert(isValidVectorIndex(id->idOpSize(), elemsize, imm));
9980 code |= insEncodeVectorsize(id->idOpSize()); // Q
9981 code |= insEncodeFloatElemsize(elemsize); // X
9982 code |= insEncodeFloatIndex(elemsize, imm); // L H
9983 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9984 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9985 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9986 dst += emitOutput_Instr(dst, code);
9989 case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
9990 code = emitInsCode(ins, fmt);
9991 code |= insEncodeVectorsize(id->idOpSize()); // Q
9992 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9993 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9994 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9995 dst += emitOutput_Instr(dst, code);
9998 case IF_DV_3D: // DV_3D .........X.mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
9999 code = emitInsCode(ins, fmt);
10000 code |= insEncodeFloatElemsize(id->idOpSize()); // X
10001 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
10002 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
10003 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
10004 dst += emitOutput_Instr(dst, code);
10007 case IF_DV_3DI: // DV_3DI .........XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (scalar by elem)
10008 code = emitInsCode(ins, fmt);
10009 imm = emitGetInsSC(id);
10010 elemsize = id->idOpSize();
10011 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
10012 code |= insEncodeFloatElemsize(elemsize); // X
10013 code |= insEncodeFloatIndex(elemsize, imm); // L H
10014 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
10015 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
10016 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
10017 dst += emitOutput_Instr(dst, code);
10020 case IF_DV_3E: // DV_3E ...........mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
10021 case IF_DV_3F: // DV_3F ...........mmmmm ......nnnnnddddd Vd Vn Vm (vector) - source dest regs overlap
10022 code = emitInsCode(ins, fmt);
10023 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
10024 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
10025 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
10026 dst += emitOutput_Instr(dst, code);
10029 case IF_DV_4A: // DV_4A .........X.mmmmm .aaaaannnnnddddd Vd Va Vn Vm (scalar)
10030 code = emitInsCode(ins, fmt);
10031 elemsize = id->idOpSize();
10032 code |= insEncodeFloatElemsize(elemsize); // X
10033 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
10034 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
10035 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
10036 code |= insEncodeReg_Va(id->idReg4()); // aaaaa
10037 dst += emitOutput_Instr(dst, code);
10040 case IF_SN_0A: // SN_0A ................ ................
10041 code = emitInsCode(ins, fmt);
10042 dst += emitOutput_Instr(dst, code);
10045 case IF_SI_0A: // SI_0A ...........iiiii iiiiiiiiiii..... imm16
10046 imm = emitGetInsSC(id);
10047 assert(isValidUimm16(imm));
10048 code = emitInsCode(ins, fmt);
10049 code |= ((code_t)imm << 5); // iiiii iiiiiiiiiii
10050 dst += emitOutput_Instr(dst, code);
10053 case IF_SI_0B: // SI_0B ................ ....bbbb........ imm4 - barrier
10054 imm = emitGetInsSC(id);
10055 assert((imm >= 0) && (imm <= 15));
10056 code = emitInsCode(ins, fmt);
10057 code |= ((code_t)imm << 8); // bbbb
10058 dst += emitOutput_Instr(dst, code);
10062 assert(!"Unexpected format");
10066 // Determine if any registers now hold GC refs, or whether a register that was overwritten held a GC ref.
10067 // We assume here that "id->idGCref()" is not GC_NONE only if the instruction described by "id" writes a
10068 // GC ref to register "id->idReg1()". (It may, apparently, also not be GC_NONE in other cases, such as
10069 // for stores, but we ignore those cases here.)
10070 if (emitInsMayWriteToGCReg(id)) // True if "id->idIns()" writes to a register than can hold GC ref.
10072 // We assume that "idReg1" is the primary destination register for all instructions
10073 if (id->idGCref() != GCT_NONE)
10075 emitGCregLiveUpd(id->idGCref(), id->idReg1(), dst);
10079 emitGCregDeadUpd(id->idReg1(), dst);
10082 if (emitInsMayWriteMultipleRegs(id))
10085 // "idReg2" is the secondary destination register
10086 if (id->idGCrefReg2() != GCT_NONE)
10088 emitGCregLiveUpd(id->idGCrefReg2(), id->idReg2(), dst);
10092 emitGCregDeadUpd(id->idReg2(), dst);
10097 // Now we determine if the instruction has written to a (local variable) stack location, and either written a GC
10098 // ref or overwritten one.
10099 if (emitInsWritesToLclVarStackLoc(id) || emitInsWritesToLclVarStackLocPair(id))
10101 int varNum = id->idAddr()->iiaLclVar.lvaVarNum();
10102 unsigned ofs = AlignDown(id->idAddr()->iiaLclVar.lvaOffset(), TARGET_POINTER_SIZE);
10104 int adr = emitComp->lvaFrameAddress(varNum, &FPbased);
10105 if (id->idGCref() != GCT_NONE)
10107 emitGCvarLiveUpd(adr + ofs, varNum, id->idGCref(), dst);
10111 // If the type of the local is a gc ref type, update the liveness.
10115 // "Regular" (non-spill-temp) local.
10116 vt = var_types(emitComp->lvaTable[varNum].lvType);
10120 TempDsc* tmpDsc = codeGen->regSet.tmpFindNum(varNum);
10121 vt = tmpDsc->tdTempType();
10123 if (vt == TYP_REF || vt == TYP_BYREF)
10124 emitGCvarDeadUpd(adr + ofs, dst);
10126 if (emitInsWritesToLclVarStackLocPair(id))
10128 unsigned ofs2 = ofs + TARGET_POINTER_SIZE;
10129 if (id->idGCrefReg2() != GCT_NONE)
10131 emitGCvarLiveUpd(adr + ofs2, varNum, id->idGCrefReg2(), dst);
10135 // If the type of the local is a gc ref type, update the liveness.
10139 // "Regular" (non-spill-temp) local.
10140 vt = var_types(emitComp->lvaTable[varNum].lvType);
10144 TempDsc* tmpDsc = codeGen->regSet.tmpFindNum(varNum);
10145 vt = tmpDsc->tdTempType();
10147 if (vt == TYP_REF || vt == TYP_BYREF)
10148 emitGCvarDeadUpd(adr + ofs2, dst);
10154 /* Make sure we set the instruction descriptor size correctly */
10156 size_t expected = emitSizeOfInsDsc(id);
10157 assert(sz == expected);
10159 if (emitComp->opts.disAsm || emitComp->opts.dspEmit || emitComp->verbose)
10161 emitDispIns(id, false, dspOffs, true, emitCurCodeOffs(odst), *dp, (dst - *dp), ig);
10164 if (emitComp->compDebugBreak)
10166 // For example, set JitBreakEmitOutputInstr=a6 will break when this method is called for
10167 // emitting instruction a6, (i.e. IN00a6 in jitdump).
10168 if ((unsigned)JitConfig.JitBreakEmitOutputInstr() == id->idDebugOnlyInfo()->idNum)
10170 assert(!"JitBreakEmitOutputInstr reached");
10175 /* All instructions are expected to generate code */
10177 assert(*dp != dst);
10184 /*****************************************************************************/
10185 /*****************************************************************************/
10189 /*****************************************************************************
10191 * Display the instruction name
10193 void emitter::emitDispInst(instruction ins)
10195 const char* insstr = codeGen->genInsName(ins);
10196 size_t len = strlen(insstr);
10198 /* Display the instruction name */
10200 printf("%s", insstr);
10203 // Add at least one space after the instruction name
10204 // and add spaces until we have reach the normal size of 8
10212 /*****************************************************************************
10214 * Display an immediate value
10216 void emitter::emitDispImm(ssize_t imm, bool addComma, bool alwaysHex /* =false */)
10223 // Munge any pointers if we want diff-able disassembly.
10224 // Since some may be emitted as partial words, print as diffable anything that has
10225 // significant bits beyond the lowest 8-bits.
10226 if (emitComp->opts.disDiffable)
10228 ssize_t top56bits = (imm >> 8);
10229 if ((top56bits != 0) && (top56bits != -1))
10233 if (!alwaysHex && (imm > -1000) && (imm < 1000))
10239 if ((imm < 0) && ((imm & 0xFFFFFFFF00000000LL) == 0xFFFFFFFF00000000LL))
10245 if ((imm & 0xFFFFFFFF00000000LL) != 0)
10247 printf("0x%llx", imm);
10251 printf("0x%02x", imm);
10259 /*****************************************************************************
10261 * Display a float zero constant
10263 void emitter::emitDispFloatZero()
10272 /*****************************************************************************
10274 * Display an encoded float constant value
10276 void emitter::emitDispFloatImm(ssize_t imm8)
10278 assert((0 <= imm8) && (imm8 <= 0x0ff));
10285 fpImm.immFPIVal = (unsigned)imm8;
10286 double result = emitDecodeFloatImm8(fpImm);
10288 printf("%.4f", result);
10291 /*****************************************************************************
10293 * Display an immediate that is optionally LSL12.
10295 void emitter::emitDispImmOptsLSL12(ssize_t imm, insOpts opt)
10297 if (!strictArmAsm && insOptsLSL12(opt))
10301 emitDispImm(imm, false);
10302 if (strictArmAsm && insOptsLSL12(opt))
10304 printf(", LSL #12");
10308 /*****************************************************************************
10310 * Display an ARM64 condition code for the conditional instructions
10312 void emitter::emitDispCond(insCond cond)
10314 const static char* armCond[16] = {"eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc",
10315 "hi", "ls", "ge", "lt", "gt", "le", "AL", "NV"}; // The last two are invalid
10316 unsigned imm = (unsigned)cond;
10317 assert((0 <= imm) && (imm < ArrLen(armCond)));
10318 printf(armCond[imm]);
10321 /*****************************************************************************
10323 * Display an ARM64 flags for the conditional instructions
10325 void emitter::emitDispFlags(insCflags flags)
10327 const static char* armFlags[16] = {"0", "v", "c", "cv", "z", "zv", "zc", "zcv",
10328 "n", "nv", "nc", "ncv", "nz", "nzv", "nzc", "nzcv"};
10329 unsigned imm = (unsigned)flags;
10330 assert((0 <= imm) && (imm < ArrLen(armFlags)));
10331 printf(armFlags[imm]);
10334 /*****************************************************************************
10336 * Display an ARM64 'barrier' for the memory barrier instructions
10338 void emitter::emitDispBarrier(insBarrier barrier)
10340 const static char* armBarriers[16] = {"#0", "oshld", "oshst", "osh", "#4", "nshld", "nshst", "nsh",
10341 "#8", "ishld", "ishst", "ish", "#12", "ld", "st", "sy"};
10342 unsigned imm = (unsigned)barrier;
10343 assert((0 <= imm) && (imm < ArrLen(armBarriers)));
10344 printf(armBarriers[imm]);
10347 /*****************************************************************************
10349 * Prints the encoding for the Shift Type encoding
10352 void emitter::emitDispShiftOpts(insOpts opt)
10354 if (opt == INS_OPTS_LSL)
10356 else if (opt == INS_OPTS_LSR)
10358 else if (opt == INS_OPTS_ASR)
10360 else if (opt == INS_OPTS_ROR)
10362 else if (opt == INS_OPTS_MSL)
10365 assert(!"Bad value");
10368 /*****************************************************************************
10370 * Prints the encoding for the Extend Type encoding
10373 void emitter::emitDispExtendOpts(insOpts opt)
10375 if (opt == INS_OPTS_UXTB)
10377 else if (opt == INS_OPTS_UXTH)
10379 else if (opt == INS_OPTS_UXTW)
10381 else if (opt == INS_OPTS_UXTX)
10383 else if (opt == INS_OPTS_SXTB)
10385 else if (opt == INS_OPTS_SXTH)
10387 else if (opt == INS_OPTS_SXTW)
10389 else if (opt == INS_OPTS_SXTX)
10392 assert(!"Bad value");
10395 /*****************************************************************************
10397 * Prints the encoding for the Extend Type encoding in loads/stores
10400 void emitter::emitDispLSExtendOpts(insOpts opt)
10402 if (opt == INS_OPTS_LSL)
10404 else if (opt == INS_OPTS_UXTW)
10406 else if (opt == INS_OPTS_UXTX)
10408 else if (opt == INS_OPTS_SXTW)
10410 else if (opt == INS_OPTS_SXTX)
10413 assert(!"Bad value");
10416 /*****************************************************************************
10418 * Display a register
10420 void emitter::emitDispReg(regNumber reg, emitAttr attr, bool addComma)
10422 emitAttr size = EA_SIZE(attr);
10423 printf(emitRegName(reg, size));
10429 /*****************************************************************************
10431 * Display a vector register with an arrangement suffix
10433 void emitter::emitDispVectorReg(regNumber reg, insOpts opt, bool addComma)
10435 assert(isVectorRegister(reg));
10436 printf(emitVectorRegName(reg));
10437 emitDispArrangement(opt);
10443 /*****************************************************************************
10445 * Display an vector register index suffix
10447 void emitter::emitDispVectorRegIndex(regNumber reg, emitAttr elemsize, ssize_t index, bool addComma)
10449 assert(isVectorRegister(reg));
10450 printf(emitVectorRegName(reg));
10467 assert(!"invalid elemsize");
10471 printf("[%d]", index);
10477 /*****************************************************************************
10479 * Display an arrangement suffix
10481 void emitter::emitDispArrangement(insOpts opt)
10483 const char* str = "???";
10513 assert(!"Invalid insOpt for vector register");
10519 /*****************************************************************************
10521 * Display a register with an optional shift operation
10523 void emitter::emitDispShiftedReg(regNumber reg, insOpts opt, ssize_t imm, emitAttr attr)
10525 emitAttr size = EA_SIZE(attr);
10526 assert((imm & 0x003F) == imm);
10527 assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
10529 printf(emitRegName(reg, size));
10537 emitDispShiftOpts(opt);
10538 emitDispImm(imm, false);
10542 /*****************************************************************************
10544 * Display a register with an optional extend and scale operations
10546 void emitter::emitDispExtendReg(regNumber reg, insOpts opt, ssize_t imm)
10548 assert((imm >= 0) && (imm <= 4));
10549 assert(insOptsNone(opt) || insOptsAnyExtend(opt) || (opt == INS_OPTS_LSL));
10551 // size is based on the extend option, not the instr size.
10552 emitAttr size = insOpts32BitExtend(opt) ? EA_4BYTE : EA_8BYTE;
10556 if (insOptsNone(opt))
10558 emitDispReg(reg, size, false);
10562 emitDispReg(reg, size, true);
10563 if (opt == INS_OPTS_LSL)
10566 emitDispExtendOpts(opt);
10567 if ((imm > 0) || (opt == INS_OPTS_LSL))
10570 emitDispImm(imm, false);
10574 else // !strictArmAsm
10576 if (insOptsNone(opt))
10578 emitDispReg(reg, size, false);
10582 if (opt != INS_OPTS_LSL)
10584 emitDispExtendOpts(opt);
10586 emitDispReg(reg, size, false);
10593 emitDispImm(ssize_t{1} << imm, false);
10598 /*****************************************************************************
10600 * Display an addressing operand [reg + imm]
10602 void emitter::emitDispAddrRI(regNumber reg, insOpts opt, ssize_t imm)
10604 reg = encodingZRtoSP(reg); // ZR (R31) encodes the SP register
10610 emitDispReg(reg, EA_8BYTE, false);
10612 if (!insOptsPostIndex(opt) && (imm != 0))
10615 emitDispImm(imm, false);
10619 if (insOptsPreIndex(opt))
10623 else if (insOptsPostIndex(opt))
10626 emitDispImm(imm, false);
10629 else // !strictArmAsm
10633 const char* operStr = "++";
10640 if (insOptsPreIndex(opt))
10645 emitDispReg(reg, EA_8BYTE, false);
10647 if (insOptsPostIndex(opt))
10652 if (insOptsIndexed(opt))
10658 printf("%c", operStr[1]);
10660 emitDispImm(imm, false);
10665 /*****************************************************************************
10667 * Display an addressing operand [reg + extended reg]
10669 void emitter::emitDispAddrRRExt(regNumber reg1, regNumber reg2, insOpts opt, bool isScaled, emitAttr size)
10671 reg1 = encodingZRtoSP(reg1); // ZR (R31) encodes the SP register
10673 unsigned scale = 0;
10676 scale = NaturalScale_helper(size);
10683 emitDispReg(reg1, EA_8BYTE, true);
10684 emitDispExtendReg(reg2, opt, scale);
10686 else // !strictArmAsm
10688 emitDispReg(reg1, EA_8BYTE, false);
10690 emitDispExtendReg(reg2, opt, scale);
10696 /*****************************************************************************
10698 * Display (optionally) the instruction encoding in hex
10701 void emitter::emitDispInsHex(BYTE* code, size_t sz)
10703 // We do not display the instruction hex if we want diff-able disassembly
10704 if (!emitComp->opts.disDiffable)
10708 printf(" %08X ", (*((code_t*)code)));
10717 /****************************************************************************
10719 * Display the given instruction.
10722 void emitter::emitDispIns(
10723 instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* pCode, size_t sz, insGroup* ig)
10728 id->idDebugOnlyInfo()->idNum; // Do not remove this! It is needed for VisualStudio conditional breakpoints
10730 printf("IN%04x: ", idNum);
10736 if (!emitComp->opts.dspEmit && !isNew && !asmfm && sz)
10739 /* Display the instruction offset */
10741 emitDispInsOffs(offset, doffs);
10743 /* Display the instruction hex code */
10745 emitDispInsHex(pCode, sz);
10749 /* Get the instruction and format */
10751 instruction ins = id->idIns();
10752 insFormat fmt = id->idInsFmt();
10756 /* If this instruction has just been added, check its size */
10758 assert(isNew == false || (int)emitSizeOfInsDsc(id) == emitCurIGfreeNext - (BYTE*)id);
10760 /* Figure out the operand size */
10761 emitAttr size = id->idOpSize();
10762 emitAttr attr = size;
10763 if (id->idGCref() == GCT_GCREF)
10765 else if (id->idGCref() == GCT_BYREF)
10773 bool isExtendAlias;
10781 const char* methodName;
10789 case IF_BI_0A: // BI_0A ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
10790 case IF_BI_0B: // BI_0B ......iiiiiiiiii iiiiiiiiiii..... simm19:00
10793 if (fmt == IF_LARGEJMP)
10795 printf("(LARGEJMP)");
10797 if (id->idAddr()->iiaHasInstrCount())
10799 int instrCount = id->idAddr()->iiaGetInstrCount();
10803 printf("pc%s%d instructions", (instrCount >= 0) ? "+" : "", instrCount);
10807 unsigned insNum = emitFindInsNum(ig, id);
10808 UNATIVE_OFFSET srcOffs = ig->igOffs + emitFindOffset(ig, insNum + 1);
10809 UNATIVE_OFFSET dstOffs = ig->igOffs + emitFindOffset(ig, insNum + 1 + instrCount);
10810 ssize_t relOffs = (ssize_t)(emitOffsetToPtr(dstOffs) - emitOffsetToPtr(srcOffs));
10811 printf("pc%s%d (%d instructions)", (relOffs >= 0) ? "+" : "", relOffs, instrCount);
10814 else if (id->idIsBound())
10816 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10820 printf("L_M%03u_" FMT_BB, Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10825 case IF_BI_0C: // BI_0C ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
10826 if (id->idIsCallAddr())
10828 offs = (ssize_t)id->idAddr()->iiaAddr;
10834 methodName = emitComp->eeGetMethodFullName((CORINFO_METHOD_HANDLE)id->idDebugOnlyInfo()->idMemCookie);
10839 if (id->idIsDspReloc())
10841 printf("%08X", offs);
10845 printf("%s", methodName);
10849 case IF_BI_1A: // BI_1A ......iiiiiiiiii iiiiiiiiiiittttt Rt simm19:00
10850 assert(insOptsNone(id->idInsOpt()));
10851 emitDispReg(id->idReg1(), size, true);
10852 if (id->idIsBound())
10854 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10858 printf("L_M%03u_" FMT_BB, Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10862 case IF_BI_1B: // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
10863 assert(insOptsNone(id->idInsOpt()));
10864 emitDispReg(id->idReg1(), size, true);
10865 emitDispImm(emitGetInsSC(id), true);
10866 if (id->idIsBound())
10868 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10872 printf("L_M%03u_" FMT_BB, Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10876 case IF_BR_1A: // BR_1A ................ ......nnnnn..... Rn
10877 assert(insOptsNone(id->idInsOpt()));
10878 emitDispReg(id->idReg1(), size, false);
10881 case IF_BR_1B: // BR_1B ................ ......nnnnn..... Rn
10882 assert(insOptsNone(id->idInsOpt()));
10883 emitDispReg(id->idReg3(), size, false);
10886 case IF_LS_1A: // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB)
10887 case IF_DI_1E: // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
10890 assert(insOptsNone(id->idInsOpt()));
10891 emitDispReg(id->idReg1(), size, true);
10892 imm = emitGetInsSC(id);
10894 /* Is this actually a reference to a data section? */
10895 if (fmt == IF_LARGEADR)
10897 printf("(LARGEADR)");
10899 else if (fmt == IF_LARGELDC)
10901 printf("(LARGELDC)");
10905 if (id->idAddr()->iiaIsJitDataOffset())
10907 doffs = Compiler::eeGetJitDataOffs(id->idAddr()->iiaFieldHnd);
10908 /* Display a data section reference */
10911 printf("@CNS%02u", doffs - 1);
10913 printf("@RWD%02u", doffs);
10916 printf("%+Id", imm);
10921 if (id->idIsReloc())
10924 emitDispImm((ssize_t)id->idAddr()->iiaAddr, false);
10926 else if (id->idIsBound())
10928 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10932 printf("L_M%03u_" FMT_BB, Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10938 case IF_LS_2A: // LS_2A .X.......X...... ......nnnnnttttt Rt Rn
10939 assert(insOptsNone(id->idInsOpt()));
10940 assert(emitGetInsSC(id) == 0);
10941 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10942 emitDispAddrRI(id->idReg2(), id->idInsOpt(), 0);
10945 case IF_LS_2B: // LS_2B .X.......Xiiiiii iiiiiinnnnnttttt Rt Rn imm(0-4095)
10946 assert(insOptsNone(id->idInsOpt()));
10947 imm = emitGetInsSC(id);
10948 scale = NaturalScale_helper(emitInsLoadStoreSize(id));
10949 imm <<= scale; // The immediate is scaled by the size of the ld/st
10950 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10951 emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
10954 case IF_LS_2C: // LS_2C .X.......X.iiiii iiiiPPnnnnnttttt Rt Rn imm(-256..+255) no/pre/post inc
10955 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
10956 imm = emitGetInsSC(id);
10957 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10958 emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
10961 case IF_LS_3A: // LS_3A .X.......X.mmmmm oooS..nnnnnttttt Rt Rn Rm ext(Rm) LSL {}
10962 assert(insOptsLSExtend(id->idInsOpt()));
10963 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10964 if (id->idIsLclVar())
10966 emitDispAddrRRExt(id->idReg2(), codeGen->rsGetRsvdReg(), id->idInsOpt(), false, size);
10970 emitDispAddrRRExt(id->idReg2(), id->idReg3(), id->idInsOpt(), id->idReg3Scaled(), size);
10974 case IF_LS_3B: // LS_3B X............... .aaaaannnnnddddd Rt Ra Rn
10975 assert(insOptsNone(id->idInsOpt()));
10976 assert(emitGetInsSC(id) == 0);
10977 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10978 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10979 emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
10982 case IF_LS_3C: // LS_3C X.........iiiiii iaaaaannnnnddddd Rt Ra Rn imm(im7,sh)
10983 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
10984 imm = emitGetInsSC(id);
10985 scale = NaturalScale_helper(emitInsLoadStoreSize(id));
10987 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10988 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10989 emitDispAddrRI(id->idReg3(), id->idInsOpt(), imm);
10992 case IF_LS_3D: // LS_3D .X.......X.mmmmm ......nnnnnttttt Wm Rt Rn
10993 assert(insOptsNone(id->idInsOpt()));
10994 emitDispReg(id->idReg1(), EA_4BYTE, true);
10995 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10996 emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
10999 case IF_LS_3E: // LS_3E .X.........mmmmm ......nnnnnttttt Rm Rt Rn ARMv8.1 LSE Atomics
11000 assert(insOptsNone(id->idInsOpt()));
11001 assert((EA_SIZE(size) == 4) || (EA_SIZE(size) == 8));
11002 emitDispReg(id->idReg1(), size, true);
11003 emitDispReg(id->idReg2(), size, true);
11004 emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
11007 case IF_DI_1A: // DI_1A X.......shiiiiii iiiiiinnnnn..... Rn imm(i12,sh)
11008 emitDispReg(id->idReg1(), size, true);
11009 emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
11012 case IF_DI_1B: // DI_1B X........hwiiiii iiiiiiiiiiiddddd Rd imm(i16,hw)
11013 emitDispReg(id->idReg1(), size, true);
11014 hwi.immHWVal = (unsigned)emitGetInsSC(id);
11015 if (ins == INS_mov)
11017 emitDispImm(emitDecodeHalfwordImm(hwi, size), false);
11019 else // movz, movn, movk
11021 emitDispImm(hwi.immVal, false);
11022 if (hwi.immHW != 0)
11024 emitDispShiftOpts(INS_OPTS_LSL);
11025 emitDispImm(hwi.immHW * 16, false);
11030 case IF_DI_1C: // DI_1C X........Nrrrrrr ssssssnnnnn..... Rn imm(N,r,s)
11031 emitDispReg(id->idReg1(), size, true);
11032 bmi.immNRS = (unsigned)emitGetInsSC(id);
11033 emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
11036 case IF_DI_1D: // DI_1D X........Nrrrrrr ssssss.....ddddd Rd imm(N,r,s)
11037 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11038 bmi.immNRS = (unsigned)emitGetInsSC(id);
11039 emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
11042 case IF_DI_2A: // DI_2A X.......shiiiiii iiiiiinnnnnddddd Rd Rn imm(i12,sh)
11043 if ((ins == INS_add) || (ins == INS_sub))
11045 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11046 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11050 emitDispReg(id->idReg1(), size, true);
11051 emitDispReg(id->idReg2(), size, true);
11053 emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
11056 case IF_DI_2B: // DI_2B X........X.nnnnn ssssssnnnnnddddd Rd Rn imm(0-63)
11057 emitDispReg(id->idReg1(), size, true);
11058 emitDispReg(id->idReg2(), size, true);
11059 emitDispImm(emitGetInsSC(id), false);
11062 case IF_DI_2C: // DI_2C X........Nrrrrrr ssssssnnnnnddddd Rd Rn imm(N,r,s)
11063 if (ins == INS_ands)
11065 emitDispReg(id->idReg1(), size, true);
11069 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11071 emitDispReg(id->idReg2(), size, true);
11072 bmi.immNRS = (unsigned)emitGetInsSC(id);
11073 emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
11076 case IF_DI_2D: // DI_2D X........Nrrrrrr ssssssnnnnnddddd Rd Rn imr, ims (N,r,s)
11077 emitDispReg(id->idReg1(), size, true);
11078 emitDispReg(id->idReg2(), size, true);
11080 imm = emitGetInsSC(id);
11081 bmi.immNRS = (unsigned)imm;
11088 emitDispImm(bmi.immR, true);
11089 emitDispImm(bmi.immS, false);
11095 emitDispImm(getBitWidth(size) - bmi.immR, true);
11096 emitDispImm(bmi.immS + 1, false);
11102 emitDispImm(bmi.immR, true);
11103 emitDispImm(bmi.immS - bmi.immR + 1, false);
11109 emitDispImm(imm, false);
11113 assert(!"Unexpected instruction in IF_DI_2D");
11118 case IF_DI_1F: // DI_1F X..........iiiii cccc..nnnnn.nzcv Rn imm5 nzcv cond
11119 emitDispReg(id->idReg1(), size, true);
11120 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11121 emitDispImm(cfi.imm5, true);
11122 emitDispFlags(cfi.flags);
11124 emitDispCond(cfi.cond);
11127 case IF_DR_1D: // DR_1D X............... cccc.......mmmmm Rd cond
11128 emitDispReg(id->idReg1(), size, true);
11129 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11130 emitDispCond(cfi.cond);
11133 case IF_DR_2A: // DR_2A X..........mmmmm ......nnnnn..... Rn Rm
11134 emitDispReg(id->idReg1(), size, true);
11135 emitDispReg(id->idReg2(), size, false);
11138 case IF_DR_2B: // DR_2B X.......sh.mmmmm ssssssnnnnn..... Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
11139 emitDispReg(id->idReg1(), size, true);
11140 emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
11143 case IF_DR_2C: // DR_2C X..........mmmmm ooosssnnnnn..... Rn Rm ext(Rm) LSL imm(0-4)
11144 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11145 imm = emitGetInsSC(id);
11146 emitDispExtendReg(id->idReg2(), id->idInsOpt(), imm);
11149 case IF_DR_2D: // DR_2D X..........nnnnn cccc..nnnnnddddd Rd Rn cond
11150 emitDispReg(id->idReg1(), size, true);
11151 emitDispReg(id->idReg2(), size, true);
11152 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11153 emitDispCond(cfi.cond);
11156 case IF_DR_2E: // DR_2E X..........mmmmm ...........ddddd Rd Rm
11157 case IF_DR_2J: // DR_2J ................ ......nnnnnddddd Sd Sn
11158 emitDispReg(id->idReg1(), size, true);
11159 emitDispReg(id->idReg2(), size, false);
11162 case IF_DR_2F: // DR_2F X.......sh.mmmmm ssssss.....ddddd Rd Rm {LSL,LSR,ASR} imm(0-63)
11163 emitDispReg(id->idReg1(), size, true);
11164 emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
11167 case IF_DR_2G: // DR_2G X............... ......nnnnnddddd Rd Rn
11168 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11169 emitDispReg(encodingZRtoSP(id->idReg2()), size, false);
11172 case IF_DR_2H: // DR_2H X........X...... ......nnnnnddddd Rd Rn
11173 emitDispReg(id->idReg1(), size, true);
11174 emitDispReg(id->idReg2(), size, false);
11177 case IF_DR_2I: // DR_2I X..........mmmmm cccc..nnnnn.nzcv Rn Rm nzcv cond
11178 emitDispReg(id->idReg1(), size, true);
11179 emitDispReg(id->idReg2(), size, true);
11180 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11181 emitDispFlags(cfi.flags);
11183 emitDispCond(cfi.cond);
11186 case IF_DR_3A: // DR_3A X..........mmmmm ......nnnnnmmmmm Rd Rn Rm
11187 if ((ins == INS_add) || (ins == INS_sub))
11189 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11190 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11192 else if ((ins == INS_smull) || (ins == INS_smulh))
11194 // Rd is always 8 bytes
11195 emitDispReg(id->idReg1(), EA_8BYTE, true);
11197 // Rn, Rm effective size depends on instruction type
11198 size = (ins == INS_smulh) ? EA_8BYTE : EA_4BYTE;
11199 emitDispReg(id->idReg2(), size, true);
11203 emitDispReg(id->idReg1(), size, true);
11204 emitDispReg(id->idReg2(), size, true);
11206 if (id->idIsLclVar())
11208 emitDispReg(codeGen->rsGetRsvdReg(), size, false);
11212 emitDispReg(id->idReg3(), size, false);
11217 case IF_DR_3B: // DR_3B X.......sh.mmmmm ssssssnnnnnddddd Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
11218 emitDispReg(id->idReg1(), size, true);
11219 emitDispReg(id->idReg2(), size, true);
11220 emitDispShiftedReg(id->idReg3(), id->idInsOpt(), emitGetInsSC(id), size);
11223 case IF_DR_3C: // DR_3C X..........mmmmm ooosssnnnnnddddd Rd Rn Rm ext(Rm) LSL imm(0-4)
11224 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11225 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11226 imm = emitGetInsSC(id);
11227 emitDispExtendReg(id->idReg3(), id->idInsOpt(), imm);
11230 case IF_DR_3D: // DR_3D X..........mmmmm cccc..nnnnnmmmmm Rd Rn Rm cond
11231 emitDispReg(id->idReg1(), size, true);
11232 emitDispReg(id->idReg2(), size, true);
11233 emitDispReg(id->idReg3(), size, true);
11234 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11235 emitDispCond(cfi.cond);
11238 case IF_DR_3E: // DR_3E X........X.mmmmm ssssssnnnnnddddd Rd Rn Rm imm(0-63)
11239 emitDispReg(id->idReg1(), size, true);
11240 emitDispReg(id->idReg2(), size, true);
11241 emitDispReg(id->idReg3(), size, true);
11242 emitDispImm(emitGetInsSC(id), false);
11245 case IF_DR_4A: // DR_4A X..........mmmmm .aaaaannnnnmmmmm Rd Rn Rm Ra
11246 emitDispReg(id->idReg1(), size, true);
11247 emitDispReg(id->idReg2(), size, true);
11248 emitDispReg(id->idReg3(), size, true);
11249 emitDispReg(id->idReg4(), size, false);
11252 case IF_DV_1A: // DV_1A .........X.iiiii iii........ddddd Vd imm8 (fmov - immediate scalar)
11253 elemsize = id->idOpSize();
11254 emitDispReg(id->idReg1(), elemsize, true);
11255 emitDispFloatImm(emitGetInsSC(id));
11258 case IF_DV_1B: // DV_1B .QX..........iii cmod..iiiiiddddd Vd imm8 (immediate vector)
11259 imm = emitGetInsSC(id) & 0x0ff;
11260 immShift = (emitGetInsSC(id) & 0x700) >> 8;
11261 hasShift = (immShift != 0);
11262 elemsize = optGetElemsize(id->idInsOpt());
11263 if (id->idInsOpt() == INS_OPTS_1D)
11265 assert(elemsize == size);
11266 emitDispReg(id->idReg1(), size, true);
11270 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11272 if (ins == INS_fmov)
11274 emitDispFloatImm(imm);
11275 assert(hasShift == false);
11279 if (elemsize == EA_8BYTE)
11281 assert(ins == INS_movi);
11283 const ssize_t mask8 = 0xFF;
11284 for (unsigned b = 0; b < 8; b++)
11286 if (imm & (ssize_t{1} << b))
11288 imm64 |= (mask8 << (b * 8));
11291 emitDispImm(imm64, hasShift, true);
11295 emitDispImm(imm, hasShift, true);
11299 insOpts opt = (immShift & 0x4) ? INS_OPTS_MSL : INS_OPTS_LSL;
11300 unsigned shift = (immShift & 0x3) * 8;
11301 emitDispShiftOpts(opt);
11302 emitDispImm(shift, false);
11307 case IF_DV_1C: // DV_1C .........X...... ......nnnnn..... Vn #0.0 (fcmp - with zero)
11308 elemsize = id->idOpSize();
11309 emitDispReg(id->idReg1(), elemsize, true);
11310 emitDispFloatZero();
11313 case IF_DV_2A: // DV_2A .Q.......X...... ......nnnnnddddd Vd Vn (fabs, fcvt - vector)
11314 case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
11315 case IF_DV_2P: // DV_2P ................ ......nnnnnddddd Vd Vn (aes*, sha1su1)
11316 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11317 emitDispVectorReg(id->idReg2(), id->idInsOpt(), false);
11320 case IF_DV_2N: // DV_2N .........iiiiiii ......nnnnnddddd Vd Vn imm (shift - scalar)
11321 elemsize = id->idOpSize();
11322 emitDispReg(id->idReg1(), elemsize, true);
11323 emitDispReg(id->idReg2(), elemsize, true);
11324 emitDispImm(emitGetInsSC(id), false);
11327 case IF_DV_2O: // DV_2O .Q.......iiiiiii ......nnnnnddddd Vd Vn imm (shift - vector)
11328 imm = emitGetInsSC(id);
11329 // Do we have a sxtl or uxtl instruction?
11330 isExtendAlias = ((ins == INS_sxtl) || (ins == INS_sxtl2) || (ins == INS_uxtl) || (ins == INS_uxtl2));
11331 code = emitInsCode(ins, fmt);
11332 if (code & 0x00008000) // widen/narrow opcodes
11334 if (code & 0x00002000) // SHL opcodes
11336 emitDispVectorReg(id->idReg1(), optWidenElemsize(id->idInsOpt()), true);
11337 emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11339 else // SHR opcodes
11341 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11342 emitDispVectorReg(id->idReg2(), optWidenElemsize(id->idInsOpt()), !isExtendAlias);
11347 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11348 emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11350 // Print the immediate unless we have a sxtl or uxtl instruction
11351 if (!isExtendAlias)
11353 emitDispImm(imm, false);
11357 case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov/smov - to general)
11358 srcsize = id->idOpSize();
11359 index = emitGetInsSC(id);
11360 if (ins == INS_smov)
11362 dstsize = EA_8BYTE;
11364 else // INS_umov or INS_mov
11366 dstsize = (srcsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE;
11368 emitDispReg(id->idReg1(), dstsize, true);
11369 emitDispVectorRegIndex(id->idReg2(), srcsize, index, false);
11372 case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
11373 if (ins == INS_dup)
11375 datasize = id->idOpSize();
11376 assert(isValidVectorDatasize(datasize));
11377 assert(isValidArrangement(datasize, id->idInsOpt()));
11378 elemsize = optGetElemsize(id->idInsOpt());
11379 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11383 elemsize = id->idOpSize();
11384 index = emitGetInsSC(id);
11385 assert(isValidVectorElemsize(elemsize));
11386 emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11388 emitDispReg(id->idReg2(), (elemsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE, false);
11391 case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
11392 datasize = id->idOpSize();
11393 assert(isValidVectorDatasize(datasize));
11394 assert(isValidArrangement(datasize, id->idInsOpt()));
11395 elemsize = optGetElemsize(id->idInsOpt());
11396 index = emitGetInsSC(id);
11397 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11398 emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11401 case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
11402 elemsize = id->idOpSize();
11403 index = emitGetInsSC(id);
11404 emitDispReg(id->idReg1(), elemsize, true);
11405 emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11408 case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
11409 imm = emitGetInsSC(id);
11410 index = (imm >> 4) & 0xf;
11411 index2 = imm & 0xf;
11412 elemsize = id->idOpSize();
11413 emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11414 emitDispVectorRegIndex(id->idReg2(), elemsize, index2, false);
11417 case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov, fcvtXX - register)
11418 case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
11419 case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
11420 elemsize = id->idOpSize();
11421 emitDispReg(id->idReg1(), elemsize, true);
11422 emitDispReg(id->idReg2(), elemsize, false);
11425 case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov, fcvtXX - to general)
11426 case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov, Xcvtf - from general)
11427 case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
11428 dstsize = optGetDstsize(id->idInsOpt());
11429 srcsize = optGetSrcsize(id->idInsOpt());
11431 emitDispReg(id->idReg1(), dstsize, true);
11432 emitDispReg(id->idReg2(), srcsize, false);
11435 case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11436 case IF_DV_3B: // DV_3B .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11437 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11438 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11439 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11442 case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11443 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11444 if (ins != INS_mov)
11446 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11448 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11451 case IF_DV_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
11452 case IF_DV_3BI: // DV_3BI .Q........Lmmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
11453 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11454 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11455 elemsize = optGetElemsize(id->idInsOpt());
11456 emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11459 case IF_DV_3D: // DV_3D .........X.mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
11460 case IF_DV_3E: // DV_3E ...........mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
11461 emitDispReg(id->idReg1(), size, true);
11462 emitDispReg(id->idReg2(), size, true);
11463 emitDispReg(id->idReg3(), size, false);
11466 case IF_DV_3F: // DV_3F ..........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11467 if ((ins == INS_sha1c) || (ins == INS_sha1m) || (ins == INS_sha1p))
11469 // Qd, Sn, Vm (vector)
11470 emitDispReg(id->idReg1(), size, true);
11471 emitDispReg(id->idReg2(), EA_4BYTE, true);
11472 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11474 else if ((ins == INS_sha256h) || (ins == INS_sha256h2))
11476 // Qd Qn Vm (vector)
11477 emitDispReg(id->idReg1(), size, true);
11478 emitDispReg(id->idReg2(), size, true);
11479 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11481 else // INS_sha1su0, INS_sha256su1
11483 // Vd, Vn, Vm (vector)
11484 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11485 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11486 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11490 case IF_DV_3DI: // DV_3DI .........XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (scalar by elem)
11491 emitDispReg(id->idReg1(), size, true);
11492 emitDispReg(id->idReg2(), size, true);
11494 emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11497 case IF_DV_4A: // DV_4A .........X.mmmmm .aaaaannnnnddddd Vd Va Vn Vm (scalar)
11498 emitDispReg(id->idReg1(), size, true);
11499 emitDispReg(id->idReg2(), size, true);
11500 emitDispReg(id->idReg3(), size, true);
11501 emitDispReg(id->idReg4(), size, false);
11504 case IF_SN_0A: // SN_0A ................ ................
11507 case IF_SI_0A: // SI_0A ...........iiiii iiiiiiiiiii..... imm16
11508 emitDispImm(emitGetInsSC(id), false);
11511 case IF_SI_0B: // SI_0B ................ ....bbbb........ imm4 - barrier
11512 emitDispBarrier((insBarrier)emitGetInsSC(id));
11516 printf("unexpected format %s", emitIfName(id->idInsFmt()));
11517 assert(!"unexpectedFormat");
11521 if (id->idDebugOnlyInfo()->idVarRefOffs)
11524 emitDispFrameRef(id->idAddr()->iiaLclVar.lvaVarNum(), id->idAddr()->iiaLclVar.lvaOffset(),
11525 id->idDebugOnlyInfo()->idVarRefOffs, asmfm);
11531 /*****************************************************************************
11533 * Display a stack frame reference.
11536 void emitter::emitDispFrameRef(int varx, int disp, int offs, bool asmfm)
11541 printf("TEMP_%02u", -varx);
11543 emitComp->gtDispLclVar(+varx, false);
11546 printf("-0x%02x", -disp);
11548 printf("+0x%02x", +disp);
11552 if (varx >= 0 && emitComp->opts.varNames)
11555 const char* varName;
11557 assert((unsigned)varx < emitComp->lvaCount);
11558 varDsc = emitComp->lvaTable + varx;
11559 varName = emitComp->compLocalVarName(varx, offs);
11563 printf("'%s", varName);
11566 printf("-%d", -disp);
11568 printf("+%d", +disp);
11577 // Generate code for a load or store operation with a potentially complex addressing mode
11578 // This method handles the case of a GT_IND with contained GT_LEA op1 of the x86 form [base + index*sccale + offset]
11579 // Since Arm64 does not directly support this complex of an addressing mode
11580 // we may generates up to three instructions for this for Arm64
11582 void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataReg, GenTreeIndir* indir)
11584 emitAttr ldstAttr = isVectorRegister(dataReg) ? attr : emitInsAdjustLoadStoreAttr(ins, attr);
11586 GenTree* addr = indir->Addr();
11588 if (addr->isContained())
11590 assert(addr->OperGet() == GT_LCL_VAR_ADDR || addr->OperGet() == GT_LEA);
11595 if (addr->OperGet() == GT_LEA)
11597 offset = addr->AsAddrMode()->Offset();
11598 if (addr->AsAddrMode()->gtScale > 0)
11600 assert(isPow2(addr->AsAddrMode()->gtScale));
11601 BitScanForward(&lsl, addr->AsAddrMode()->gtScale);
11605 GenTree* memBase = indir->Base();
11607 if (indir->HasIndex())
11609 GenTree* index = indir->Index();
11613 regNumber tmpReg = indir->GetSingleTempReg();
11615 emitAttr addType = varTypeIsGC(memBase) ? EA_BYREF : EA_PTRSIZE;
11617 if (emitIns_valid_imm_for_add(offset, EA_8BYTE))
11621 // Generate code to set tmpReg = base + index*scale
11622 emitIns_R_R_R_I(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum, lsl,
11627 // Generate code to set tmpReg = base + index
11628 emitIns_R_R_R(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum);
11631 noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11633 // Then load/store dataReg from/to [tmpReg + offset]
11634 emitIns_R_R_I(ins, ldstAttr, dataReg, tmpReg, offset);
11636 else // large offset
11638 // First load/store tmpReg with the large offset constant
11639 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11640 // Then add the base register
11642 emitIns_R_R_R(INS_add, addType, tmpReg, tmpReg, memBase->gtRegNum);
11644 noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11645 noway_assert(tmpReg != index->gtRegNum);
11647 // Then load/store dataReg from/to [tmpReg + index*scale]
11648 emitIns_R_R_R_I(ins, ldstAttr, dataReg, tmpReg, index->gtRegNum, lsl, INS_OPTS_LSL);
11651 else // (offset == 0)
11655 // Then load/store dataReg from/to [memBase + index*scale]
11656 emitIns_R_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum, lsl, INS_OPTS_LSL);
11660 // Then load/store dataReg from/to [memBase + index]
11661 emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum);
11665 else // no Index register
11667 if (emitIns_valid_imm_for_ldst_offset(offset, EA_SIZE(attr)))
11669 // Then load/store dataReg from/to [memBase + offset]
11670 emitIns_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, offset);
11674 // We require a tmpReg to hold the offset
11675 regNumber tmpReg = indir->GetSingleTempReg();
11677 // First load/store tmpReg with the large offset constant
11678 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11680 // Then load/store dataReg from/to [memBase + tmpReg]
11681 emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, tmpReg);
11685 else // addr is not contained, so we evaluate it into a register
11687 // Then load/store dataReg from/to [addrReg]
11688 emitIns_R_R(ins, ldstAttr, dataReg, addr->gtRegNum);
11692 // The callee must call genConsumeReg() for any non-contained srcs
11693 // and genProduceReg() for any non-contained dsts.
11695 regNumber emitter::emitInsBinary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src)
11697 // dst can only be a reg
11698 assert(!dst->isContained());
11700 // src can be immed or reg
11701 assert(!src->isContained() || src->isContainedIntOrIImmed());
11703 // find immed (if any) - it cannot be a dst
11704 GenTreeIntConCommon* intConst = nullptr;
11705 if (src->isContainedIntOrIImmed())
11707 intConst = src->AsIntConCommon();
11712 emitIns_R_I(ins, attr, dst->gtRegNum, intConst->IconValue());
11713 return dst->gtRegNum;
11717 emitIns_R_R(ins, attr, dst->gtRegNum, src->gtRegNum);
11718 return dst->gtRegNum;
11722 // The callee must call genConsumeReg() for any non-contained srcs
11723 // and genProduceReg() for any non-contained dsts.
11725 regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src1, GenTree* src2)
11727 // dst can only be a reg
11728 assert(!dst->isContained());
11730 // find immed (if any) - it cannot be a dst
11731 // Only one src can be an int.
11732 GenTreeIntConCommon* intConst = nullptr;
11733 GenTree* nonIntReg = nullptr;
11735 if (varTypeIsFloating(dst))
11737 // src1 can only be a reg
11738 assert(!src1->isContained());
11739 // src2 can only be a reg
11740 assert(!src2->isContained());
11742 else // not floating point
11744 // src2 can be immed or reg
11745 assert(!src2->isContained() || src2->isContainedIntOrIImmed());
11747 // Check src2 first as we can always allow it to be a contained immediate
11748 if (src2->isContainedIntOrIImmed())
11750 intConst = src2->AsIntConCommon();
11753 // Only for commutative operations do we check src1 and allow it to be a contained immediate
11754 else if (dst->OperIsCommutative())
11756 // src1 can be immed or reg
11757 assert(!src1->isContained() || src1->isContainedIntOrIImmed());
11759 // Check src1 and allow it to be a contained immediate
11760 if (src1->isContainedIntOrIImmed())
11762 assert(!src2->isContainedIntOrIImmed());
11763 intConst = src1->AsIntConCommon();
11769 // src1 can only be a reg
11770 assert(!src1->isContained());
11774 bool isMulOverflow = false;
11775 if (dst->gtOverflowEx())
11777 if ((ins == INS_add) || (ins == INS_adds))
11781 else if ((ins == INS_sub) || (ins == INS_subs))
11785 else if (ins == INS_mul)
11787 isMulOverflow = true;
11788 assert(intConst == nullptr); // overflow format doesn't support an int constant operand
11792 assert(!"Invalid ins for overflow check");
11795 if (intConst != nullptr)
11797 emitIns_R_R_I(ins, attr, dst->gtRegNum, nonIntReg->gtRegNum, intConst->IconValue());
11803 regNumber extraReg = dst->GetSingleTempReg();
11804 assert(extraReg != dst->gtRegNum);
11806 if ((dst->gtFlags & GTF_UNSIGNED) != 0)
11808 if (attr == EA_4BYTE)
11810 // Compute 8 byte results from 4 byte by 4 byte multiplication.
11811 emitIns_R_R_R(INS_umull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11813 // Get the high result by shifting dst.
11814 emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11818 assert(attr == EA_8BYTE);
11819 // Compute the high result.
11820 emitIns_R_R_R(INS_umulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11822 // Now multiply without skewing the high result.
11823 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11826 // zero-sign bit comparison to detect overflow.
11827 emitIns_R_I(INS_cmp, attr, extraReg, 0);
11832 if (attr == EA_4BYTE)
11834 // Compute 8 byte results from 4 byte by 4 byte multiplication.
11835 emitIns_R_R_R(INS_smull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11837 // Get the high result by shifting dst.
11838 emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11844 assert(attr == EA_8BYTE);
11845 // Save the high result in a temporary register.
11846 emitIns_R_R_R(INS_smulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11848 // Now multiply without skewing the high result.
11849 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11854 // Sign bit comparison to detect overflow.
11855 emitIns_R_R_I(INS_cmp, attr, extraReg, dst->gtRegNum, bitShift, INS_OPTS_ASR);
11860 // We can just multiply.
11861 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11865 if (dst->gtOverflowEx())
11867 assert(!varTypeIsFloating(dst));
11868 codeGen->genCheckOverflow(dst);
11871 return dst->gtRegNum;
11874 #endif // defined(_TARGET_ARM64_)