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_DV_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 immN == 1
2332 if (bmImm.immN == 0) // find the smaller elemWidth when immN == 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 emitAttr size = EA_SIZE(attr);
3397 insFormat fmt = IF_NONE;
3398 instrDesc* id = nullptr;
3400 /* Figure out the encoding format of the instruction */
3405 assert(isGeneralRegister(reg));
3406 id = emitNewInstrSmall(attr);
3415 assert(fmt != IF_NONE);
3424 /*****************************************************************************
3426 * Add an instruction referencing a register and a constant.
3429 void emitter::emitIns_R_I(instruction ins, emitAttr attr, regNumber reg, ssize_t imm, insOpts opt /* = INS_OPTS_NONE */)
3431 emitAttr size = EA_SIZE(attr);
3432 emitAttr elemsize = EA_UNKNOWN;
3433 insFormat fmt = IF_NONE;
3434 bool canEncode = false;
3436 /* Figure out the encoding format of the instruction */
3445 assert(insOptsNone(opt));
3446 assert(isGeneralRegister(reg));
3448 canEncode = canEncodeBitMaskImm(imm, size, &bmi);
3452 assert(isValidImmNRS(imm, size));
3460 assert(isValidGeneralDatasize(size));
3461 assert(insOptsNone(opt)); // No LSL here (you must use emitIns_R_I_I if a shift is needed)
3462 assert(isGeneralRegister(reg));
3463 assert(isValidUimm16(imm));
3467 assert(imm == emitDecodeHalfwordImm(hwi, size));
3475 assert(isValidGeneralDatasize(size));
3476 assert(insOptsNone(opt)); // No explicit LSL here
3477 // We will automatically determine the shift based upon the imm
3479 // First try the standard 'halfword immediate' imm(i16,hw)
3481 canEncode = canEncodeHalfwordImm(imm, size, &hwi);
3484 // uses a movz encoding
3485 assert(isGeneralRegister(reg));
3487 assert(isValidImmHWVal(imm, size));
3492 // Next try the ones-complement form of 'halfword immediate' imm(i16,hw)
3493 notOfImm = NOT_helper(imm, getBitWidth(size));
3494 canEncode = canEncodeHalfwordImm(notOfImm, size, &hwi);
3497 assert(isGeneralRegister(reg));
3499 ins = INS_movn; // uses a movn encoding
3500 assert(isValidImmHWVal(imm, size));
3505 // Finally try the 'bitmask immediate' imm(N,r,s)
3507 canEncode = canEncodeBitMaskImm(imm, size, &bmi);
3510 assert(isGeneralRegisterOrSP(reg));
3511 reg = encodingSPtoZR(reg);
3513 assert(isValidImmNRS(imm, size));
3519 assert(!"Instruction cannot be encoded: mov imm");
3525 assert(isValidVectorDatasize(size));
3526 assert(isVectorRegister(reg));
3527 if (insOptsNone(opt) && (size == EA_8BYTE))
3531 assert(isValidArrangement(size, opt));
3532 elemsize = optGetElemsize(opt);
3534 if (elemsize == EA_8BYTE)
3540 bool failed = false;
3543 INT64 loByte = uimm & 0xFF;
3544 if (((loByte == 0) || (loByte == 0xFF)) && (pos < 8))
3560 assert(isValidUimm8(imm));
3568 // No explicit LSL/MSL is used for the immediate
3569 // We will automatically determine the shift based upon the value of imm
3571 // First try the standard 'byteShifted immediate' imm(i8,bySh)
3573 canEncode = canEncodeByteShiftedImm(imm, elemsize, true, &bsi);
3577 assert(isValidImmBSVal(imm, size));
3582 // Next try the ones-complement form of the 'immediate' imm(i8,bySh)
3583 if ((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE)) // Only EA_2BYTE or EA_4BYTE forms
3585 notOfImm = NOT_helper(imm, getBitWidth(elemsize));
3586 canEncode = canEncodeByteShiftedImm(notOfImm, elemsize, true, &bsi);
3590 ins = INS_mvni; // uses a mvni encoding
3591 assert(isValidImmBSVal(imm, size));
3602 assert(isValidVectorDatasize(size));
3603 assert(isVectorRegister(reg));
3604 assert(isValidArrangement(size, opt));
3605 elemsize = optGetElemsize(opt);
3606 assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE)); // Only EA_2BYTE or EA_4BYTE forms
3610 // No explicit LSL/MSL is used for the immediate
3611 // We will automatically determine the shift based upon the value of imm
3613 // First try the standard 'byteShifted immediate' imm(i8,bySh)
3615 canEncode = canEncodeByteShiftedImm(imm, elemsize,
3616 (ins == INS_mvni), // mvni supports the ones shifting variant (aka MSL)
3621 assert(isValidImmBSVal(imm, size));
3629 assert(insOptsNone(opt));
3630 assert(isGeneralRegister(reg));
3632 if (unsigned_abs(imm) <= 0x0fff)
3636 ins = insReverse(ins);
3639 assert(isValidUimm12(imm));
3643 else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
3645 // Encoding will use a 12-bit left shift of the immediate
3646 opt = INS_OPTS_LSL12;
3649 ins = insReverse(ins);
3652 assert((imm & 0xfff) == 0);
3654 assert(isValidUimm12(imm));
3660 assert(!"Instruction cannot be encoded: IF_DI_1A");
3668 } // end switch (ins)
3671 assert(fmt != IF_NONE);
3673 instrDesc* id = emitNewInstrSC(attr, imm);
3685 /*****************************************************************************
3687 * Add an instruction referencing a register and a floating point constant.
3690 void emitter::emitIns_R_F(
3691 instruction ins, emitAttr attr, regNumber reg, double immDbl, insOpts opt /* = INS_OPTS_NONE */)
3694 emitAttr size = EA_SIZE(attr);
3695 emitAttr elemsize = EA_UNKNOWN;
3696 insFormat fmt = IF_NONE;
3698 bool canEncode = false;
3700 /* Figure out the encoding format of the instruction */
3707 assert(insOptsNone(opt));
3708 assert(isValidVectorElemsizeFloat(size));
3709 assert(isVectorRegister(reg));
3718 assert(isVectorRegister(reg));
3720 canEncode = canEncodeFloatImm8(immDbl, &fpi);
3722 if (insOptsAnyArrangement(opt))
3725 assert(isValidVectorDatasize(size));
3726 assert(isValidArrangement(size, opt));
3727 elemsize = optGetElemsize(opt);
3728 assert(isValidVectorElemsizeFloat(elemsize));
3729 assert(opt != INS_OPTS_1D); // Reserved encoding
3733 imm = fpi.immFPIVal;
3734 assert((imm >= 0) && (imm <= 0xff));
3741 assert(insOptsNone(opt));
3742 assert(isValidVectorElemsizeFloat(size));
3746 imm = fpi.immFPIVal;
3747 assert((imm >= 0) && (imm <= 0xff));
3757 } // end switch (ins)
3760 assert(fmt != IF_NONE);
3762 instrDesc* id = emitNewInstrSC(attr, imm);
3774 /*****************************************************************************
3776 * Add an instruction referencing two registers
3779 void emitter::emitIns_R_R(
3780 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insOpts opt /* = INS_OPTS_NONE */)
3782 emitAttr size = EA_SIZE(attr);
3783 emitAttr elemsize = EA_UNKNOWN;
3784 insFormat fmt = IF_NONE;
3786 /* Figure out the encoding format of the instruction */
3790 assert(insOptsNone(opt));
3791 // Is the mov even necessary?
3794 // A mov with a EA_4BYTE has the side-effect of clearing the upper bits
3795 // So only eliminate mov instructions that are not clearing the upper bits
3797 if (isGeneralRegisterOrSP(reg1) && (size == EA_8BYTE))
3801 else if (isVectorRegister(reg1) && (size == EA_16BYTE))
3807 // Check for the 'mov' aliases for the vector registers
3808 if (isVectorRegister(reg1))
3810 if (isVectorRegister(reg2) && isValidVectorDatasize(size))
3812 return emitIns_R_R_R(INS_mov, size, reg1, reg2, reg2);
3816 return emitIns_R_R_I(INS_mov, size, reg1, reg2, 0);
3821 if (isVectorRegister(reg2))
3823 assert(isGeneralRegister(reg1));
3824 return emitIns_R_R_I(INS_mov, size, reg1, reg2, 0);
3828 // Is this a MOV to/from SP instruction?
3829 if ((reg1 == REG_SP) || (reg2 == REG_SP))
3831 assert(isGeneralRegisterOrSP(reg1));
3832 assert(isGeneralRegisterOrSP(reg2));
3833 reg1 = encodingSPtoZR(reg1);
3834 reg2 = encodingSPtoZR(reg2);
3839 assert(insOptsNone(opt));
3840 assert(isGeneralRegister(reg1));
3841 assert(isGeneralRegisterOrZR(reg2));
3848 assert(insOptsAnyArrangement(opt));
3849 assert(isVectorRegister(reg1));
3850 assert(isGeneralRegisterOrZR(reg2));
3851 assert(isValidVectorDatasize(size));
3852 assert(isValidArrangement(size, opt));
3858 assert(isVectorRegister(reg1));
3859 assert(isVectorRegister(reg2));
3862 assert(isValidVectorDatasize(size));
3863 // Bitwise behavior is independent of element size, but is always encoded as 1 Byte
3864 opt = optMakeArrangement(size, EA_1BYTE);
3866 if (insOptsNone(opt))
3869 assert(size == EA_8BYTE); // Only type D is supported
3875 assert(insOptsAnyArrangement(opt));
3876 assert(isValidVectorDatasize(size));
3877 assert(isValidArrangement(size, opt));
3878 elemsize = optGetElemsize(opt);
3885 if (isVectorRegister(reg1))
3887 assert(isVectorRegister(reg2));
3890 assert(isValidVectorDatasize(size));
3891 // Bitwise behavior is independent of element size, but is always encoded as 1 Byte
3892 opt = optMakeArrangement(size, EA_1BYTE);
3894 if (insOptsNone(opt))
3897 assert(size == EA_8BYTE); // Only type D is supported
3903 assert(isValidVectorDatasize(size));
3904 assert(isValidArrangement(size, opt));
3905 elemsize = optGetElemsize(opt);
3913 assert(insOptsNone(opt));
3914 assert(isGeneralRegister(reg1));
3915 assert(isGeneralRegisterOrZR(reg2));
3920 assert(size == EA_8BYTE);
3927 assert(insOptsNone(opt));
3928 assert(isValidGeneralDatasize(size));
3929 assert(isGeneralRegister(reg1));
3930 assert(isGeneralRegister(reg2));
3938 return emitIns_R_R_I(ins, size, reg1, reg2, 0, opt);
3946 if (isVectorRegister(reg1))
3948 assert(isVectorRegister(reg2));
3949 assert(isValidVectorDatasize(size));
3950 assert(isValidArrangement(size, opt));
3951 elemsize = optGetElemsize(opt);
3952 if ((ins == INS_cls) || (ins == INS_clz))
3954 assert(elemsize != EA_8BYTE); // No encoding for type D
3956 else if (ins == INS_rev32)
3958 assert((elemsize == EA_2BYTE) || (elemsize == EA_1BYTE));
3962 assert(elemsize == EA_1BYTE); // Only supports 8B or 16B
3969 // Doesn't have general register version(s)
3976 assert(insOptsNone(opt));
3977 assert(isGeneralRegister(reg1));
3978 assert(isGeneralRegister(reg2));
3979 if (ins == INS_rev32)
3981 assert(size == EA_8BYTE);
3985 assert(isValidGeneralDatasize(size));
3998 assert(isVectorRegister(reg1));
3999 assert(isVectorRegister(reg2));
4000 assert(isValidVectorDatasize(size));
4001 assert(isValidArrangement(size, opt));
4002 elemsize = optGetElemsize(opt);
4003 assert(elemsize != EA_8BYTE); // No encoding for type D
4009 assert(isVectorRegister(reg1));
4010 assert(isVectorRegister(reg2));
4011 assert(isValidVectorDatasize(size));
4012 assert(isValidArrangement(size, opt));
4013 elemsize = optGetElemsize(opt);
4014 // size is determined by instruction
4017 assert(size == EA_8BYTE);
4019 else // ins == INS_xtn2
4021 assert(size == EA_16BYTE);
4023 assert(elemsize != EA_8BYTE); // Narrowing must not end with 8 byte data
4031 assert(isValidGeneralDatasize(size));
4043 assert(isValidGeneralLSDatasize(size));
4044 assert(isGeneralRegisterOrZR(reg1));
4045 assert(isGeneralRegisterOrSP(reg2));
4046 assert(insOptsNone(opt));
4048 reg2 = encodingSPtoZR(reg2);
4066 assert(insOptsNone(opt));
4067 emitIns_R_R_I(ins, attr, reg1, reg2, 0, INS_OPTS_NONE);
4071 emitIns_R_R_R(INS_ldaddb, attr, reg1, REG_ZR, reg2);
4074 emitIns_R_R_R(INS_ldaddlb, attr, reg1, REG_ZR, reg2);
4077 emitIns_R_R_R(INS_ldaddh, attr, reg1, REG_ZR, reg2);
4080 emitIns_R_R_R(INS_ldaddlh, attr, reg1, REG_ZR, reg2);
4083 emitIns_R_R_R(INS_ldadd, attr, reg1, REG_ZR, reg2);
4086 emitIns_R_R_R(INS_ldaddl, attr, reg1, REG_ZR, reg2);
4090 assert(isValidVectorElemsizeFloat(size));
4092 // Is the mov even necessary?
4098 if (isVectorRegister(reg1))
4100 if (isVectorRegister(reg2))
4102 assert(insOptsNone(opt));
4107 assert(isGeneralRegister(reg2));
4109 // if the optional conversion specifier is not present we calculate it
4110 if (opt == INS_OPTS_NONE)
4112 opt = (size == EA_4BYTE) ? INS_OPTS_4BYTE_TO_S : INS_OPTS_8BYTE_TO_D;
4114 assert(insOptsConvertIntToFloat(opt));
4121 assert(isGeneralRegister(reg1));
4122 assert(isVectorRegister(reg2));
4124 // if the optional conversion specifier is not present we calculate it
4125 if (opt == INS_OPTS_NONE)
4127 opt = (size == EA_4BYTE) ? INS_OPTS_S_TO_4BYTE : INS_OPTS_D_TO_8BYTE;
4129 assert(insOptsConvertFloatToInt(opt));
4137 assert(insOptsNone(opt));
4138 assert(isValidVectorElemsizeFloat(size));
4139 assert(isVectorRegister(reg1));
4140 assert(isVectorRegister(reg2));
4154 if (insOptsAnyArrangement(opt))
4157 assert(isVectorRegister(reg1));
4158 assert(isVectorRegister(reg2));
4159 assert(isValidVectorDatasize(size));
4160 assert(isValidArrangement(size, opt));
4161 elemsize = optGetElemsize(opt);
4162 assert(isValidVectorElemsizeFloat(elemsize));
4163 assert(opt != INS_OPTS_1D); // Reserved encoding
4169 assert(isVectorRegister(reg2));
4170 if (isVectorRegister(reg1))
4172 assert(insOptsNone(opt));
4173 assert(isValidVectorElemsizeFloat(size));
4178 assert(isGeneralRegister(reg1));
4179 assert(insOptsConvertFloatToInt(opt));
4180 assert(isValidVectorElemsizeFloat(size));
4190 assert(isVectorRegister(reg1));
4191 assert(isVectorRegister(reg2));
4192 assert(isValidVectorDatasize(size));
4193 assert(insOptsNone(opt));
4194 assert(size == EA_8BYTE); // Narrowing from Double or Widening to Double (Half not supported)
4200 if (insOptsAnyArrangement(opt))
4203 assert(isVectorRegister(reg1));
4204 assert(isVectorRegister(reg2));
4205 assert(isValidVectorDatasize(size));
4206 assert(isValidArrangement(size, opt));
4207 elemsize = optGetElemsize(opt);
4208 assert(isValidVectorElemsizeFloat(elemsize));
4209 assert(opt != INS_OPTS_1D); // Reserved encoding
4215 assert(isVectorRegister(reg1));
4216 if (isVectorRegister(reg2))
4218 assert(insOptsNone(opt));
4219 assert(isValidVectorElemsizeFloat(size));
4224 assert(isGeneralRegister(reg2));
4225 assert(insOptsConvertIntToFloat(opt));
4226 assert(isValidVectorElemsizeFloat(size));
4242 if (insOptsAnyArrangement(opt))
4245 assert(isVectorRegister(reg1));
4246 assert(isVectorRegister(reg2));
4247 assert(isValidVectorDatasize(size));
4248 assert(isValidArrangement(size, opt));
4249 elemsize = optGetElemsize(opt);
4250 assert(isValidVectorElemsizeFloat(elemsize));
4251 assert(opt != INS_OPTS_1D); // Reserved encoding
4257 assert(insOptsNone(opt));
4258 assert(isValidVectorElemsizeFloat(size));
4259 assert(isVectorRegister(reg1));
4260 assert(isVectorRegister(reg2));
4267 assert(insOptsNone(opt));
4268 assert(isValidVectorElemsizeFloat(size));
4269 assert(isVectorRegister(reg1));
4270 assert(isVectorRegister(reg2));
4275 assert(insOptsConvertFloatToFloat(opt));
4276 assert(isValidVectorFcvtsize(size));
4277 assert(isVectorRegister(reg1));
4278 assert(isVectorRegister(reg2));
4287 assert(isVectorRegister(reg1));
4288 assert(isVectorRegister(reg2));
4290 if (isValidVectorDatasize(size))
4293 assert(insOptsAnyArrangement(opt));
4294 assert(isValidArrangement(size, opt));
4295 elemsize = optGetElemsize(opt);
4302 assert(size == EA_8BYTE); // Only Double supported
4312 assert(isVectorRegister(reg1));
4313 assert(isVectorRegister(reg2));
4315 if (isValidVectorDatasize(size))
4318 assert(insOptsAnyArrangement(opt));
4319 assert(isValidArrangement(size, opt));
4320 elemsize = optGetElemsize(opt);
4321 assert((elemsize == EA_8BYTE) || (elemsize == EA_4BYTE)); // Only Double/Float supported
4322 assert(opt != INS_OPTS_1D); // Reserved encoding
4329 assert((size == EA_8BYTE) || (size == EA_4BYTE)); // Only Double/Float supported
4337 assert(isVectorRegister(reg1));
4338 assert(isVectorRegister(reg2));
4339 assert(isValidVectorDatasize(size));
4340 elemsize = optGetElemsize(opt);
4341 assert(elemsize == EA_1BYTE);
4346 assert(insOptsNone(opt));
4347 assert(isVectorRegister(reg1));
4348 assert(isVectorRegister(reg2));
4354 assert(isVectorRegister(reg1));
4355 assert(isVectorRegister(reg2));
4356 assert(isValidVectorDatasize(size));
4357 elemsize = optGetElemsize(opt);
4358 assert(elemsize == EA_4BYTE);
4366 } // end switch (ins)
4368 assert(fmt != IF_NONE);
4370 instrDesc* id = emitNewInstrSmall(attr);
4383 /*****************************************************************************
4385 * Add an instruction referencing a register and two constants.
4388 void emitter::emitIns_R_I_I(
4389 instruction ins, emitAttr attr, regNumber reg, ssize_t imm1, ssize_t imm2, insOpts opt /* = INS_OPTS_NONE */)
4391 emitAttr size = EA_SIZE(attr);
4392 insFormat fmt = IF_NONE;
4393 size_t immOut = 0; // composed from imm1 and imm2 and stored in the instrDesc
4395 /* Figure out the encoding format of the instruction */
4402 ins = INS_movz; // INS_mov with LSL is an alias for INS_movz LSL
4408 assert(isValidGeneralDatasize(size));
4409 assert(isGeneralRegister(reg));
4410 assert(isValidUimm16(imm1));
4411 assert(insOptsLSL(opt)); // Must be INS_OPTS_LSL
4413 if (size == EA_8BYTE)
4415 assert((imm2 == 0) || (imm2 == 16) || // shift amount: 0, 16, 32 or 48
4416 (imm2 == 32) || (imm2 == 48));
4420 assert((imm2 == 0) || (imm2 == 16)); // shift amount: 0 or 16
4455 immOut = hwi.immHWVal;
4456 assert(isValidImmHWVal(immOut, size));
4465 } // end switch (ins)
4467 assert(fmt != IF_NONE);
4469 instrDesc* id = emitNewInstrSC(attr, immOut);
4480 /*****************************************************************************
4482 * Add an instruction referencing two registers and a constant.
4485 void emitter::emitIns_R_R_I(
4486 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm, insOpts opt /* = INS_OPTS_NONE */)
4488 emitAttr size = EA_SIZE(attr);
4489 emitAttr elemsize = EA_UNKNOWN;
4490 insFormat fmt = IF_NONE;
4491 bool isLdSt = false;
4492 bool isSIMD = false;
4493 bool isAddSub = false;
4494 bool setFlags = false;
4496 bool unscaledOp = false;
4498 /* Figure out the encoding format of the instruction */
4505 // Check for the 'mov' aliases for the vector registers
4506 assert(insOptsNone(opt));
4507 assert(isValidVectorElemsize(size));
4509 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4511 if (isVectorRegister(reg1))
4513 if (isGeneralRegisterOrZR(reg2))
4515 fmt = IF_DV_2C; // Alias for 'ins'
4518 else if (isVectorRegister(reg2))
4520 fmt = IF_DV_2E; // Alias for 'dup'
4524 else // isGeneralRegister(reg1)
4526 assert(isGeneralRegister(reg1));
4527 if (isVectorRegister(reg2))
4529 fmt = IF_DV_2B; // Alias for 'umov'
4533 assert(!" invalid INS_mov operands");
4539 assert(insOptsNone(opt));
4540 assert(isValidGeneralDatasize(size));
4541 assert(isGeneralRegister(reg1));
4542 assert(isGeneralRegister(reg2));
4543 assert(isValidImmShift(imm, size));
4548 assert(insOptsNone(opt));
4549 assert(isValidGeneralDatasize(size));
4550 assert(isGeneralRegister(reg1));
4551 assert(isGeneralRegister(reg2));
4552 assert(isValidImmShift(imm, size));
4567 assert(isVectorRegister(reg1));
4568 assert(isVectorRegister(reg2));
4569 if (insOptsAnyArrangement(opt))
4572 assert(isValidVectorDatasize(size));
4573 assert(isValidArrangement(size, opt));
4574 elemsize = optGetElemsize(opt);
4575 assert(isValidVectorElemsize(elemsize));
4576 assert(isValidImmShift(imm, elemsize));
4577 assert(opt != INS_OPTS_1D); // Reserved encoding
4584 assert(insOptsNone(opt));
4585 assert(size == EA_8BYTE); // only supported size
4586 assert(isValidImmShift(imm, size));
4600 assert(isVectorRegister(reg1));
4601 assert(isVectorRegister(reg2));
4603 assert(size == EA_8BYTE);
4604 assert(isValidArrangement(size, opt));
4605 elemsize = optGetElemsize(opt);
4606 assert(elemsize != EA_8BYTE); // Reserved encodings
4607 assert(isValidVectorElemsize(elemsize));
4608 assert(isValidImmShift(imm, elemsize));
4621 assert(isVectorRegister(reg1));
4622 assert(isVectorRegister(reg2));
4624 assert(size == EA_16BYTE);
4625 assert(isValidArrangement(size, opt));
4626 elemsize = optGetElemsize(opt);
4627 assert(elemsize != EA_8BYTE); // Reserved encodings
4628 assert(isValidVectorElemsize(elemsize));
4629 assert(isValidImmShift(imm, elemsize));
4636 assert(isValidGeneralDatasize(size));
4637 assert(isGeneralRegister(reg1));
4638 assert(isGeneralRegisterOrZR(reg2));
4642 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4650 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
4654 assert(insOptsAluShift(opt)); // a non-zero imm, must select shift kind, can't use ROR
4656 assert(isValidImmShift(imm, size));
4662 assert(isValidGeneralDatasize(size));
4663 assert(isGeneralRegisterOrZR(reg1));
4664 assert(isGeneralRegister(reg2));
4666 if (insOptsAnyShift(opt))
4668 assert(isValidImmShift(imm, size) && (imm != 0));
4673 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4681 assert(isValidGeneralDatasize(size));
4682 assert(isGeneralRegisterOrSP(reg1));
4683 assert(isGeneralRegister(reg2));
4685 reg1 = encodingSPtoZR(reg1);
4686 if (insOptsAnyExtend(opt))
4688 assert((imm >= 0) && (imm <= 4));
4694 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4700 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
4701 assert(isValidImmShift(imm, size));
4710 assert(insOptsNone(opt));
4711 assert(isGeneralRegister(reg2));
4712 if (ins == INS_ands)
4714 assert(isGeneralRegister(reg1));
4718 assert(isGeneralRegisterOrSP(reg1));
4719 reg1 = encodingSPtoZR(reg1);
4723 canEncode = canEncodeBitMaskImm(imm, size, &bmi);
4727 assert(isValidImmNRS(imm, size));
4732 case INS_dup: // by element, imm selects the element of reg2
4733 assert(isVectorRegister(reg1));
4734 if (isVectorRegister(reg2))
4736 if (insOptsAnyArrangement(opt))
4739 assert(isValidVectorDatasize(size));
4740 assert(isValidArrangement(size, opt));
4741 elemsize = optGetElemsize(opt);
4742 assert(isValidVectorElemsize(elemsize));
4743 assert(isValidVectorIndex(size, elemsize, imm));
4744 assert(opt != INS_OPTS_1D); // Reserved encoding
4751 assert(insOptsNone(opt));
4753 assert(isValidVectorElemsize(elemsize));
4754 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4761 case INS_ins: // (MOV from general)
4762 assert(insOptsNone(opt));
4763 assert(isValidVectorElemsize(size));
4764 assert(isVectorRegister(reg1));
4765 assert(isGeneralRegisterOrZR(reg2));
4767 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4771 case INS_umov: // (MOV to general)
4772 assert(insOptsNone(opt));
4773 assert(isValidVectorElemsize(size));
4774 assert(isGeneralRegister(reg1));
4775 assert(isVectorRegister(reg2));
4777 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4782 assert(insOptsNone(opt));
4783 assert(isValidVectorElemsize(size));
4784 assert(size != EA_8BYTE); // no encoding, use INS_umov
4785 assert(isGeneralRegister(reg1));
4786 assert(isVectorRegister(reg2));
4788 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4806 // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4807 assert(isValidGeneralDatasize(size));
4808 unscaledOp = (ins == INS_ldursb);
4815 // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4816 assert(isValidGeneralDatasize(size));
4817 unscaledOp = (ins == INS_ldursh);
4824 // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4825 assert(size == EA_8BYTE);
4826 unscaledOp = (ins == INS_ldursw);
4865 // Is the target a vector register?
4866 if (isVectorRegister(reg1))
4868 assert(isValidVectorLSDatasize(size));
4869 assert(isGeneralRegisterOrSP(reg2));
4874 assert(isValidGeneralDatasize(size));
4877 scale = NaturalScale_helper(size);
4883 // Is the target a vector register?
4884 if (isVectorRegister(reg1))
4886 assert(isValidVectorLSDatasize(size));
4887 assert(isGeneralRegisterOrSP(reg2));
4892 assert(isValidGeneralDatasize(size));
4903 } // end switch (ins)
4911 assert(isValidVectorLSDatasize(size));
4912 assert(isVectorRegister(reg1));
4913 assert((scale >= 0) && (scale <= 4));
4917 assert(isValidGeneralLSDatasize(size));
4918 assert(isGeneralRegisterOrZR(reg1));
4919 assert((scale >= 0) && (scale <= 3));
4922 assert(isGeneralRegisterOrSP(reg2));
4924 // Load/Store reserved encodings:
4925 if (insOptsIndexed(opt))
4927 assert(reg1 != reg2);
4930 reg2 = encodingSPtoZR(reg2);
4932 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
4935 assert(insOptsNone(opt)); // PRE/POST Index doesn't make sense with an immediate of zero
4939 else if (insOptsIndexed(opt) || unscaledOp || (imm < 0) || ((imm & mask) != 0))
4941 if ((imm >= -256) && (imm <= 255))
4947 assert(!"Instruction cannot be encoded: IF_LS_2C");
4952 assert(insOptsNone(opt));
4953 assert(!unscaledOp);
4955 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
4957 imm >>= scale; // The immediate is scaled by the size of the ld/st
4963 assert(!"Instruction cannot be encoded: IF_LS_2B");
4970 assert(insOptsNone(opt));
4972 if (setFlags) // Can't encode SP with setFlags
4974 assert(isGeneralRegister(reg1));
4975 assert(isGeneralRegister(reg2));
4979 assert(isGeneralRegisterOrSP(reg1));
4980 assert(isGeneralRegisterOrSP(reg2));
4982 // Is it just a mov?
4985 // Is the mov even necessary?
4988 emitIns_R_R(INS_mov, attr, reg1, reg2);
4993 reg1 = encodingSPtoZR(reg1);
4994 reg2 = encodingSPtoZR(reg2);
4997 if (unsigned_abs(imm) <= 0x0fff)
5001 ins = insReverse(ins);
5004 assert(isValidUimm12(imm));
5007 else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
5009 // Encoding will use a 12-bit left shift of the immediate
5010 opt = INS_OPTS_LSL12;
5013 ins = insReverse(ins);
5016 assert((imm & 0xfff) == 0);
5018 assert(isValidUimm12(imm));
5023 assert(!"Instruction cannot be encoded: IF_DI_2A");
5027 assert(fmt != IF_NONE);
5029 instrDesc* id = emitNewInstrSC(attr, imm);
5042 /*****************************************************************************
5044 * Add an instruction referencing two registers and a constant.
5045 * Also checks for a large immediate that needs a second instruction
5046 * and will load it in reg1
5048 * - Supports instructions: add, adds, sub, subs, and, ands, eor and orr
5049 * - Requires that reg1 is a general register and not SP or ZR
5050 * - Requires that reg1 != reg2
5052 void emitter::emitIns_R_R_Imm(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm)
5054 assert(isGeneralRegister(reg1));
5055 assert(reg1 != reg2);
5057 bool immFits = true;
5065 immFits = emitter::emitIns_valid_imm_for_add(imm, attr);
5072 immFits = emitter::emitIns_valid_imm_for_alu(imm, attr);
5076 assert(!"Unsupported instruction in emitIns_R_R_Imm");
5081 emitIns_R_R_I(ins, attr, reg1, reg2, imm);
5085 // Load 'imm' into the reg1 register
5086 // then issue: 'ins' reg1, reg2, reg1
5088 codeGen->instGen_Set_Reg_To_Imm(attr, reg1, imm);
5089 emitIns_R_R_R(ins, attr, reg1, reg2, reg1);
5093 /*****************************************************************************
5095 * Add an instruction referencing three registers.
5098 void emitter::emitIns_R_R_R(
5099 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insOpts opt) /* = INS_OPTS_NONE */
5101 emitAttr size = EA_SIZE(attr);
5102 emitAttr elemsize = EA_UNKNOWN;
5103 insFormat fmt = IF_NONE;
5105 /* Figure out the encoding format of the instruction */
5129 assert(insOptsNone(opt));
5130 assert(isValidGeneralDatasize(size));
5131 assert(isGeneralRegister(reg1));
5132 assert(isGeneralRegister(reg2));
5133 assert(isGeneralRegister(reg3));
5138 if (insOptsNone(opt))
5141 assert(isValidGeneralDatasize(size));
5142 assert(isGeneralRegister(reg1));
5143 assert(isGeneralRegister(reg2));
5144 assert(isGeneralRegister(reg3));
5153 assert(insOptsAnyArrangement(opt));
5154 assert(isVectorRegister(reg1));
5155 assert(isVectorRegister(reg2));
5156 assert(isVectorRegister(reg3));
5157 assert(isValidVectorDatasize(size));
5158 assert(isValidArrangement(size, opt));
5159 elemsize = optGetElemsize(opt);
5160 if (ins == INS_pmul)
5162 assert(elemsize == EA_1BYTE); // only supports 8B or 16B
5164 else // INS_mul, INS_mla, INS_mls
5166 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
5173 if (isVectorRegister(reg1))
5175 assert(isVectorRegister(reg2));
5176 assert(isVectorRegister(reg3));
5178 if (insOptsAnyArrangement(opt))
5181 assert(opt != INS_OPTS_1D); // Reserved encoding
5182 assert(isValidVectorDatasize(size));
5183 assert(isValidArrangement(size, opt));
5189 assert(insOptsNone(opt));
5190 assert(size == EA_8BYTE);
5199 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, INS_OPTS_NONE);
5208 assert(isVectorRegister(reg1));
5209 assert(isVectorRegister(reg2));
5210 assert(isVectorRegister(reg3));
5212 if (isValidVectorDatasize(size))
5215 assert(insOptsAnyArrangement(opt));
5216 assert(isValidArrangement(size, opt));
5217 elemsize = optGetElemsize(opt);
5224 assert(size == EA_8BYTE); // Only Double supported
5232 assert(isVectorRegister(reg1));
5233 assert(isVectorRegister(reg2));
5234 assert(isVectorRegister(reg3));
5236 if (isValidVectorDatasize(size))
5239 assert(insOptsAnyArrangement(opt));
5240 assert(isValidArrangement(size, opt));
5241 elemsize = optGetElemsize(opt);
5242 assert((elemsize == EA_8BYTE) || (elemsize == EA_4BYTE)); // Only Double/Float supported
5243 assert(opt != INS_OPTS_1D); // Reserved encoding
5250 assert((size == EA_8BYTE) || (size == EA_4BYTE)); // Only Double/Float supported
5263 assert(isVectorRegister(reg1));
5264 assert(isVectorRegister(reg2));
5265 assert(isVectorRegister(reg3));
5266 assert(insOptsAnyArrangement(opt));
5269 assert(isValidVectorDatasize(size));
5270 assert(isValidArrangement(size, opt));
5271 elemsize = optGetElemsize(opt);
5272 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
5278 assert(isVectorRegister(reg1));
5279 assert(isVectorRegister(reg2));
5280 assert(reg2 == reg3);
5281 assert(isValidVectorDatasize(size));
5282 // INS_mov is an alias for INS_orr (vector register)
5283 if (opt == INS_OPTS_NONE)
5285 elemsize = EA_1BYTE;
5286 opt = optMakeArrangement(size, elemsize);
5288 assert(isValidArrangement(size, opt));
5297 if (isVectorRegister(reg1))
5299 assert(isValidVectorDatasize(size));
5300 assert(isVectorRegister(reg2));
5301 assert(isVectorRegister(reg3));
5302 if (opt == INS_OPTS_NONE)
5304 elemsize = EA_1BYTE;
5305 opt = optMakeArrangement(size, elemsize);
5307 assert(isValidArrangement(size, opt));
5316 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, INS_OPTS_NONE);
5322 assert(isValidVectorDatasize(size));
5323 assert(isVectorRegister(reg1));
5324 assert(isVectorRegister(reg2));
5325 assert(isVectorRegister(reg3));
5326 if (opt == INS_OPTS_NONE)
5328 elemsize = EA_1BYTE;
5329 opt = optMakeArrangement(size, elemsize);
5331 assert(isValidArrangement(size, opt));
5343 assert(isVectorRegister(reg1));
5344 assert(isVectorRegister(reg2));
5345 assert(isVectorRegister(reg3));
5346 if (insOptsAnyArrangement(opt))
5349 assert(isValidVectorDatasize(size));
5350 assert(isValidArrangement(size, opt));
5351 elemsize = optGetElemsize(opt);
5352 assert(isValidVectorElemsizeFloat(elemsize));
5353 assert(opt != INS_OPTS_1D); // Reserved encoding
5359 assert(insOptsNone(opt));
5360 assert(isValidScalarDatasize(size));
5367 assert(insOptsNone(opt));
5368 assert(isVectorRegister(reg1));
5369 assert(isVectorRegister(reg2));
5370 assert(isVectorRegister(reg3));
5371 assert(isValidScalarDatasize(size));
5378 assert(isVectorRegister(reg1));
5379 assert(isVectorRegister(reg2));
5380 assert(isVectorRegister(reg3));
5381 assert(insOptsAnyArrangement(opt)); // no scalar encoding, use 4-operand 'fmadd' or 'fmsub'
5384 assert(isValidVectorDatasize(size));
5385 assert(isValidArrangement(size, opt));
5386 elemsize = optGetElemsize(opt);
5387 assert(isValidVectorElemsizeFloat(elemsize));
5388 assert(opt != INS_OPTS_1D); // Reserved encoding
5401 emitIns_R_R_R_Ext(ins, attr, reg1, reg2, reg3, opt);
5409 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0);
5418 assert(isGeneralRegisterOrZR(reg1));
5419 assert(isGeneralRegisterOrZR(reg2));
5420 assert(isGeneralRegisterOrSP(reg3));
5460 assert(isGeneralRegisterOrZR(reg1));
5461 assert(isGeneralRegisterOrZR(reg2));
5462 assert(isGeneralRegisterOrSP(reg3));
5473 assert(isValidVectorDatasize(size));
5474 assert(isVectorRegister(reg1));
5475 assert(isVectorRegister(reg2));
5476 assert(isVectorRegister(reg3));
5477 if (opt == INS_OPTS_NONE)
5479 elemsize = EA_4BYTE;
5480 opt = optMakeArrangement(size, elemsize);
5482 assert(isValidArrangement(size, opt));
5490 } // end switch (ins)
5492 assert(fmt != IF_NONE);
5494 instrDesc* id = emitNewInstr(attr);
5508 /*****************************************************************************
5510 * Add an instruction referencing three registers and a constant.
5513 void emitter::emitIns_R_R_R_I(instruction ins,
5519 insOpts opt /* = INS_OPTS_NONE */,
5520 emitAttr attrReg2 /* = EA_UNKNOWN */)
5522 emitAttr size = EA_SIZE(attr);
5523 emitAttr elemsize = EA_UNKNOWN;
5524 insFormat fmt = IF_NONE;
5525 bool isLdSt = false;
5526 bool isSIMD = false;
5527 bool isAddSub = false;
5528 bool setFlags = false;
5531 /* Figure out the encoding format of the instruction */
5535 assert(insOptsNone(opt));
5536 assert(isValidGeneralDatasize(size));
5537 assert(isGeneralRegister(reg1));
5538 assert(isGeneralRegister(reg2));
5539 assert(isGeneralRegister(reg3));
5540 assert(isValidImmShift(imm, size));
5552 assert(isValidGeneralDatasize(size));
5553 assert(isGeneralRegister(reg1));
5554 assert(isGeneralRegister(reg2));
5555 assert(isGeneralRegister(reg3));
5556 assert(isValidImmShift(imm, size));
5559 assert(insOptsNone(opt)); // a zero imm, means no shift kind
5564 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
5569 case INS_fmul: // by element, imm[0..3] selects the element of reg3
5573 assert(isVectorRegister(reg1));
5574 assert(isVectorRegister(reg2));
5575 assert(isVectorRegister(reg3));
5576 if (insOptsAnyArrangement(opt))
5579 assert(isValidVectorDatasize(size));
5580 assert(isValidArrangement(size, opt));
5581 elemsize = optGetElemsize(opt);
5582 assert(isValidVectorElemsizeFloat(elemsize));
5583 assert(isValidVectorIndex(size, elemsize, imm));
5584 assert(opt != INS_OPTS_1D); // Reserved encoding
5590 assert(insOptsNone(opt));
5591 assert(isValidScalarDatasize(size));
5593 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
5598 case INS_mul: // by element, imm[0..7] selects the element of reg3
5601 assert(isVectorRegister(reg1));
5602 assert(isVectorRegister(reg2));
5603 assert(isVectorRegister(reg3));
5605 assert(insOptsAnyArrangement(opt));
5606 assert(isValidVectorDatasize(size));
5607 assert(isValidArrangement(size, opt));
5608 elemsize = optGetElemsize(opt);
5609 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
5610 // Only has encodings for H or S elemsize
5611 assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE));
5612 // Only has encodings for V0..V15
5613 if ((elemsize == EA_2BYTE) && (reg3 >= REG_V16))
5615 noway_assert(!"Invalid reg3");
5639 assert(insOptsNone(opt)); // Can't use Pre/Post index on these two instructions
5644 // Is the target a vector register?
5645 if (isVectorRegister(reg1))
5647 scale = NaturalScale_helper(size);
5652 scale = (size == EA_8BYTE) ? 3 : 2;
5661 } // end switch (ins)
5666 assert(isGeneralRegisterOrSP(reg3));
5667 assert(insOptsNone(opt) || insOptsIndexed(opt));
5671 assert(isValidVectorLSPDatasize(size));
5672 assert(isVectorRegister(reg1));
5673 assert(isVectorRegister(reg2));
5674 assert((scale >= 2) && (scale <= 4));
5678 assert(isValidGeneralDatasize(size));
5679 assert(isGeneralRegisterOrZR(reg1));
5680 assert(isGeneralRegisterOrZR(reg2));
5681 assert((scale == 2) || (scale == 3));
5684 // Load/Store Pair reserved encodings:
5685 if (emitInsIsLoad(ins))
5687 assert(reg1 != reg2);
5689 if (insOptsIndexed(opt))
5691 assert(reg1 != reg3);
5692 assert(reg2 != reg3);
5695 reg3 = encodingSPtoZR(reg3);
5697 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
5700 assert(insOptsNone(opt)); // PRE/POST Index doesn't make sense with an immediate of zero
5706 if ((imm & mask) == 0)
5708 imm >>= scale; // The immediate is scaled by the size of the ld/st
5710 if ((imm >= -64) && (imm <= 63))
5716 if (fmt != IF_LS_3C)
5718 assert(!"Instruction cannot be encoded: IF_LS_3C");
5725 bool reg2IsSP = (reg2 == REG_SP);
5727 assert(isValidGeneralDatasize(size));
5728 assert(isGeneralRegister(reg3));
5730 if (setFlags || insOptsAluShift(opt)) // Can't encode SP in reg1 with setFlags or AluShift option
5732 assert(isGeneralRegisterOrZR(reg1));
5736 assert(isGeneralRegisterOrSP(reg1));
5737 reg1 = encodingSPtoZR(reg1);
5740 if (insOptsAluShift(opt)) // Can't encode SP in reg2 with AluShift option
5742 assert(isGeneralRegister(reg2));
5746 assert(isGeneralRegisterOrSP(reg2));
5747 reg2 = encodingSPtoZR(reg2);
5750 if (insOptsAnyExtend(opt))
5752 assert((imm >= 0) && (imm <= 4));
5756 else if (insOptsAluShift(opt))
5758 // imm should be non-zero and in [1..63]
5759 assert(isValidImmShift(imm, size) && (imm != 0));
5764 assert(insOptsNone(opt));
5768 // To encode the SP register as reg2 we must use the IF_DR_3C encoding
5769 // and also specify a LSL of zero (imm == 0)
5780 assert(!"Instruction cannot be encoded: Add/Sub IF_DR_3A");
5783 assert(fmt != IF_NONE);
5785 instrDesc* id = emitNewInstrCns(attr, imm);
5795 // Record the attribute for the second register in the pair
5796 id->idGCrefReg2(GCT_NONE);
5797 if (attrReg2 != EA_UNKNOWN)
5799 // Record the attribute for the second register in the pair
5800 assert((fmt == IF_LS_3B) || (fmt == IF_LS_3C));
5801 if (EA_IS_GCREF(attrReg2))
5803 id->idGCrefReg2(GCT_GCREF);
5805 else if (EA_IS_BYREF(attrReg2))
5807 id->idGCrefReg2(GCT_BYREF);
5815 /*****************************************************************************
5817 * Add an instruction referencing three registers, with an extend option
5820 void emitter::emitIns_R_R_R_Ext(instruction ins,
5825 insOpts opt, /* = INS_OPTS_NONE */
5826 int shiftAmount) /* = -1 -- unset */
5828 emitAttr size = EA_SIZE(attr);
5829 insFormat fmt = IF_NONE;
5830 bool isSIMD = false;
5833 /* Figure out the encoding format of the instruction */
5854 // Is the target a vector register?
5855 if (isVectorRegister(reg1))
5857 assert(isValidVectorLSDatasize(size));
5858 scale = NaturalScale_helper(size);
5863 assert(isValidGeneralDatasize(size));
5864 scale = (size == EA_8BYTE) ? 3 : 2;
5873 } // end switch (ins)
5875 assert(scale != -1);
5876 assert(insOptsLSExtend(opt));
5880 assert(isValidVectorLSDatasize(size));
5881 assert(isVectorRegister(reg1));
5885 assert(isValidGeneralLSDatasize(size));
5886 assert(isGeneralRegisterOrZR(reg1));
5889 assert(isGeneralRegisterOrSP(reg2));
5890 assert(isGeneralRegister(reg3));
5892 // Load/Store reserved encodings:
5893 if (insOptsIndexed(opt))
5895 assert(reg1 != reg2);
5898 if (shiftAmount == -1)
5900 shiftAmount = insOptsLSL(opt) ? scale : 0;
5902 assert((shiftAmount == scale) || (shiftAmount == 0));
5904 reg2 = encodingSPtoZR(reg2);
5907 instrDesc* id = emitNewInstr(attr);
5916 id->idReg3Scaled(shiftAmount == scale);
5922 /*****************************************************************************
5924 * Add an instruction referencing two registers and two constants.
5927 void emitter::emitIns_R_R_I_I(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, int imm1, int imm2)
5929 emitAttr size = EA_SIZE(attr);
5930 emitAttr elemsize = EA_UNKNOWN;
5931 insFormat fmt = IF_NONE;
5932 size_t immOut = 0; // composed from imm1 and imm2 and stored in the instrDesc
5934 /* Figure out the encoding format of the instruction */
5944 assert(isGeneralRegister(reg1));
5945 assert(isGeneralRegister(reg2));
5946 assert(isValidImmShift(imm1, size));
5947 assert(isValidImmShift(imm2, size));
5949 bmi.immN = (size == EA_8BYTE);
5952 immOut = bmi.immNRS;
5959 assert(isGeneralRegister(reg1));
5960 assert(isGeneralRegister(reg2));
5961 lsb = getBitWidth(size) - imm1;
5963 assert(isValidImmShift(lsb, size));
5964 assert(isValidImmShift(width, size));
5966 bmi.immN = (size == EA_8BYTE);
5969 immOut = bmi.immNRS;
5976 assert(isGeneralRegister(reg1));
5977 assert(isGeneralRegister(reg2));
5979 width = imm2 + imm1 - 1;
5980 assert(isValidImmShift(lsb, size));
5981 assert(isValidImmShift(width, size));
5983 bmi.immN = (size == EA_8BYTE);
5985 bmi.immS = imm2 + imm1 - 1;
5986 immOut = bmi.immNRS;
5992 assert(isVectorRegister(reg1));
5993 assert(isVectorRegister(reg2));
5995 assert(isValidVectorElemsize(elemsize));
5996 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm1));
5997 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm2));
5998 immOut = (imm1 << 4) + imm2;
6006 assert(fmt != IF_NONE);
6008 instrDesc* id = emitNewInstrSC(attr, immOut);
6020 /*****************************************************************************
6022 * Add an instruction referencing four registers.
6025 void emitter::emitIns_R_R_R_R(
6026 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, regNumber reg4)
6028 emitAttr size = EA_SIZE(attr);
6029 insFormat fmt = IF_NONE;
6031 /* Figure out the encoding format of the instruction */
6040 assert(isValidGeneralDatasize(size));
6041 assert(isGeneralRegister(reg1));
6042 assert(isGeneralRegister(reg2));
6043 assert(isGeneralRegister(reg3));
6044 assert(isGeneralRegister(reg4));
6053 assert(isValidScalarDatasize(size));
6054 assert(isVectorRegister(reg1));
6055 assert(isVectorRegister(reg2));
6056 assert(isVectorRegister(reg3));
6057 assert(isVectorRegister(reg4));
6069 assert(fmt != IF_NONE);
6071 instrDesc* id = emitNewInstr(attr);
6085 /*****************************************************************************
6087 * Add an instruction referencing a register and a condition code
6090 void emitter::emitIns_R_COND(instruction ins, emitAttr attr, regNumber reg, insCond cond)
6092 emitAttr size = EA_SIZE(attr);
6093 insFormat fmt = IF_NONE;
6097 /* Figure out the encoding format of the instruction */
6102 assert(isGeneralRegister(reg));
6111 } // end switch (ins)
6113 assert(fmt != IF_NONE);
6114 assert(isValidImmCond(cfi.immCFVal));
6116 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6120 id->idInsOpt(INS_OPTS_NONE);
6128 /*****************************************************************************
6130 * Add an instruction referencing two registers and a condition code
6133 void emitter::emitIns_R_R_COND(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insCond cond)
6135 emitAttr size = EA_SIZE(attr);
6136 insFormat fmt = IF_NONE;
6140 /* Figure out the encoding format of the instruction */
6146 assert(isGeneralRegister(reg1));
6147 assert(isGeneralRegister(reg2));
6155 } // end switch (ins)
6157 assert(fmt != IF_NONE);
6158 assert(isValidImmCond(cfi.immCFVal));
6160 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6164 id->idInsOpt(INS_OPTS_NONE);
6173 /*****************************************************************************
6175 * Add an instruction referencing two registers and a condition code
6178 void emitter::emitIns_R_R_R_COND(
6179 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insCond cond)
6181 emitAttr size = EA_SIZE(attr);
6182 insFormat fmt = IF_NONE;
6186 /* Figure out the encoding format of the instruction */
6193 assert(isGeneralRegister(reg1));
6194 assert(isGeneralRegister(reg2));
6195 assert(isGeneralRegister(reg3));
6204 } // end switch (ins)
6206 assert(fmt != IF_NONE);
6207 assert(isValidImmCond(cfi.immCFVal));
6209 instrDesc* id = emitNewInstr(attr);
6213 id->idInsOpt(INS_OPTS_NONE);
6218 id->idSmallCns(cfi.immCFVal);
6224 /*****************************************************************************
6226 * Add an instruction referencing two registers the flags and a condition code
6229 void emitter::emitIns_R_R_FLAGS_COND(
6230 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insCflags flags, insCond cond)
6232 emitAttr size = EA_SIZE(attr);
6233 insFormat fmt = IF_NONE;
6237 /* Figure out the encoding format of the instruction */
6242 assert(isGeneralRegister(reg1));
6243 assert(isGeneralRegister(reg2));
6251 } // end switch (ins)
6253 assert(fmt != IF_NONE);
6254 assert(isValidImmCondFlags(cfi.immCFVal));
6256 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6260 id->idInsOpt(INS_OPTS_NONE);
6269 /*****************************************************************************
6271 * Add an instruction referencing a register, an immediate, the flags and a condition code
6274 void emitter::emitIns_R_I_FLAGS_COND(
6275 instruction ins, emitAttr attr, regNumber reg, int imm, insCflags flags, insCond cond)
6277 emitAttr size = EA_SIZE(attr);
6278 insFormat fmt = IF_NONE;
6282 /* Figure out the encoding format of the instruction */
6287 assert(isGeneralRegister(reg));
6290 ins = insReverse(ins);
6293 if ((imm >= 0) && (imm <= 31))
6302 assert(!"Instruction cannot be encoded: ccmp/ccmn imm5");
6308 } // end switch (ins)
6310 assert(fmt != IF_NONE);
6311 assert(isValidImmCondFlagsImm5(cfi.immCFVal));
6313 instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6317 id->idInsOpt(INS_OPTS_NONE);
6325 /*****************************************************************************
6327 * Add a memory barrier instruction with a 'barrier' immediate
6330 void emitter::emitIns_BARR(instruction ins, insBarrier barrier)
6332 insFormat fmt = IF_NONE;
6335 /* Figure out the encoding format of the instruction */
6343 imm = (ssize_t)barrier;
6348 } // end switch (ins)
6350 assert(fmt != IF_NONE);
6352 instrDesc* id = emitNewInstrSC(EA_8BYTE, imm);
6356 id->idInsOpt(INS_OPTS_NONE);
6362 /*****************************************************************************
6364 * Add an instruction with a static data member operand. If 'size' is 0, the
6365 * instruction operates on the address of the static member instead of its
6366 * value (e.g. "push offset clsvar", rather than "push dword ptr [clsvar]").
6369 void emitter::emitIns_C(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, int offs)
6374 /*****************************************************************************
6376 * Add an instruction referencing stack-based local variable.
6379 void emitter::emitIns_S(instruction ins, emitAttr attr, int varx, int offs)
6384 /*****************************************************************************
6386 * Add an instruction referencing a register and a stack-based local variable.
6388 void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
6390 emitAttr size = EA_SIZE(attr);
6391 insFormat fmt = IF_NONE;
6397 // TODO-ARM64-CQ: use unscaled loads?
6398 /* Figure out the encoding format of the instruction */
6419 assert(isValidGeneralDatasize(size) || isValidVectorDatasize(size));
6420 scale = genLog2(EA_SIZE_IN_BYTES(size));
6424 assert(size == EA_8BYTE);
6429 NYI("emitIns_R_S"); // FP locals?
6432 } // end switch (ins)
6434 /* Figure out the variable's frame position */
6439 base = emitComp->lvaFrameAddress(varx, &FPbased);
6441 assert((scale >= 0) && (scale <= 4));
6443 regNumber reg2 = FPbased ? REG_FPBASE : REG_SPBASE;
6444 reg2 = encodingSPtoZR(reg2);
6461 fmt = IF_DI_2A; // add reg1,reg2,#disp
6465 regNumber rsvdReg = codeGen->rsGetRsvdReg();
6466 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6467 fmt = IF_DR_3A; // add reg1,reg2,rsvdReg
6472 bool useRegForImm = false;
6473 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6480 else if ((imm < 0) || ((imm & mask) != 0))
6482 if ((imm >= -256) && (imm <= 255))
6488 useRegForImm = true;
6493 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
6495 imm >>= scale; // The immediate is scaled by the size of the ld/st
6501 useRegForImm = true;
6507 regNumber rsvdReg = codeGen->rsGetRsvdReg();
6508 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6513 assert(fmt != IF_NONE);
6515 instrDesc* id = emitNewInstrCns(attr, imm);
6519 id->idInsOpt(INS_OPTS_NONE);
6523 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6524 id->idSetIsLclVar();
6527 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6534 /*****************************************************************************
6536 * Add an instruction referencing two register and consectutive stack-based local variable slots.
6538 void emitter::emitIns_R_R_S_S(
6539 instruction ins, emitAttr attr1, emitAttr attr2, regNumber reg1, regNumber reg2, int varx, int offs)
6541 assert((ins == INS_ldp) || (ins == INS_ldnp));
6542 assert(EA_8BYTE == EA_SIZE(attr1));
6543 assert(EA_8BYTE == EA_SIZE(attr2));
6544 assert(isGeneralRegisterOrZR(reg1));
6545 assert(isGeneralRegisterOrZR(reg2));
6548 insFormat fmt = IF_LS_3B;
6550 const unsigned scale = 3;
6552 /* Figure out the variable's frame position */
6556 base = emitComp->lvaFrameAddress(varx, &FPbased);
6559 // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6560 regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE;
6561 reg3 = encodingSPtoZR(reg3);
6563 bool useRegForAdr = true;
6565 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6568 useRegForAdr = false;
6572 if ((imm & mask) == 0)
6574 ssize_t immShift = imm >> scale; // The immediate is scaled by the size of the ld/st
6576 if ((immShift >= -64) && (immShift <= 63))
6579 useRegForAdr = false;
6587 regNumber rsvd = codeGen->rsGetRsvdReg();
6588 emitIns_R_R_Imm(INS_add, EA_PTRSIZE, rsvd, reg3, imm);
6593 assert(fmt != IF_NONE);
6595 instrDesc* id = emitNewInstrCns(attr1, imm);
6599 id->idInsOpt(INS_OPTS_NONE);
6601 // Record the attribute for the second register in the pair
6602 if (EA_IS_GCREF(attr2))
6604 id->idGCrefReg2(GCT_GCREF);
6606 else if (EA_IS_BYREF(attr2))
6608 id->idGCrefReg2(GCT_BYREF);
6612 id->idGCrefReg2(GCT_NONE);
6618 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6619 id->idSetIsLclVar();
6622 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6629 /*****************************************************************************
6631 * Add an instruction referencing a stack-based local variable and a register
6633 void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
6636 emitAttr size = EA_SIZE(attr);
6637 insFormat fmt = IF_NONE;
6640 bool isVectorStore = false;
6642 // TODO-ARM64-CQ: use unscaled loads?
6643 /* Figure out the encoding format of the instruction */
6648 assert(isGeneralRegisterOrZR(reg1));
6653 assert(isGeneralRegisterOrZR(reg1));
6657 if (isGeneralRegisterOrZR(reg1))
6659 assert(isValidGeneralDatasize(size));
6660 scale = (size == EA_8BYTE) ? 3 : 2;
6664 assert(isVectorRegister(reg1));
6665 assert(isValidVectorLSDatasize(size));
6666 scale = NaturalScale_helper(size);
6667 isVectorStore = true;
6672 NYI("emitIns_S_R"); // FP locals?
6675 } // end switch (ins)
6677 /* Figure out the variable's frame position */
6681 base = emitComp->lvaFrameAddress(varx, &FPbased);
6693 // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6694 regNumber reg2 = FPbased ? REG_FPBASE : REG_SPBASE;
6695 reg2 = encodingSPtoZR(reg2);
6697 bool useRegForImm = false;
6699 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6704 else if ((imm < 0) || ((imm & mask) != 0))
6706 if ((imm >= -256) && (imm <= 255))
6712 useRegForImm = true;
6717 if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
6719 imm >>= scale; // The immediate is scaled by the size of the ld/st
6725 useRegForImm = true;
6731 // The reserved register is not stored in idReg3() since that field overlaps with iiaLclVar.
6732 // It is instead implicit when idSetIsLclVar() is set, with this encoding format.
6733 regNumber rsvdReg = codeGen->rsGetRsvdReg();
6734 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6738 assert(fmt != IF_NONE);
6740 instrDesc* id = emitNewInstrCns(attr, imm);
6744 id->idInsOpt(INS_OPTS_NONE);
6748 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6749 id->idSetIsLclVar();
6752 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6759 /*****************************************************************************
6761 * Add an instruction referencing consecutive stack-based local variable slots and two registers
6763 void emitter::emitIns_S_S_R_R(
6764 instruction ins, emitAttr attr1, emitAttr attr2, regNumber reg1, regNumber reg2, int varx, int offs)
6766 assert((ins == INS_stp) || (ins == INS_stnp));
6767 assert(EA_8BYTE == EA_SIZE(attr1));
6768 assert(EA_8BYTE == EA_SIZE(attr2));
6769 assert(isGeneralRegisterOrZR(reg1));
6770 assert(isGeneralRegisterOrZR(reg2));
6773 insFormat fmt = IF_LS_3B;
6775 const unsigned scale = 3;
6777 /* Figure out the variable's frame position */
6781 base = emitComp->lvaFrameAddress(varx, &FPbased);
6784 // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6785 regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE;
6786 reg3 = encodingSPtoZR(reg3);
6788 bool useRegForAdr = true;
6790 ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6793 useRegForAdr = false;
6797 if ((imm & mask) == 0)
6799 ssize_t immShift = imm >> scale; // The immediate is scaled by the size of the ld/st
6801 if ((immShift >= -64) && (immShift <= 63))
6804 useRegForAdr = false;
6812 regNumber rsvd = codeGen->rsGetRsvdReg();
6813 emitIns_R_R_Imm(INS_add, EA_PTRSIZE, rsvd, reg3, imm);
6818 assert(fmt != IF_NONE);
6820 instrDesc* id = emitNewInstrCns(attr1, imm);
6824 id->idInsOpt(INS_OPTS_NONE);
6826 // Record the attribute for the second register in the pair
6827 if (EA_IS_GCREF(attr2))
6829 id->idGCrefReg2(GCT_GCREF);
6831 else if (EA_IS_BYREF(attr2))
6833 id->idGCrefReg2(GCT_BYREF);
6837 id->idGCrefReg2(GCT_NONE);
6843 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6844 id->idSetIsLclVar();
6847 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6854 /*****************************************************************************
6856 * Add an instruction referencing stack-based local variable and an immediate
6858 void emitter::emitIns_S_I(instruction ins, emitAttr attr, int varx, int offs, int val)
6863 /*****************************************************************************
6865 * Add an instruction with a register + static member operands.
6866 * Constant is stored into JIT data which is adjacent to code.
6867 * No relocation is needed. PC-relative offset will be encoded directly into instruction.
6870 void emitter::emitIns_R_C(
6871 instruction ins, emitAttr attr, regNumber reg, regNumber addrReg, CORINFO_FIELD_HANDLE fldHnd, int offs)
6874 assert(instrDesc::fitsInSmallCns(offs));
6876 emitAttr size = EA_SIZE(attr);
6877 insFormat fmt = IF_NONE;
6879 instrDescJmp* id = emitNewInstrJmp();
6884 // This is case to get address to the constant data.
6886 assert(isGeneralRegister(reg));
6887 assert(isValidGeneralDatasize(size));
6892 if (isVectorRegister(reg))
6894 assert(isValidScalarDatasize(size));
6895 // For vector (float/double) register, we should have an integer address reg to
6896 // compute long address which consists of page address and page offset.
6897 // For integer constant, this is not needed since the dest reg can be used to
6898 // compute address as well as contain the final contents.
6899 assert(isGeneralRegister(reg) || (addrReg != REG_NA));
6903 assert(isGeneralRegister(reg));
6904 assert(isValidGeneralDatasize(size));
6911 assert(fmt != IF_NONE);
6915 id->idInsOpt(INS_OPTS_NONE);
6916 id->idSmallCns(offs);
6918 id->idAddr()->iiaFieldHnd = fldHnd;
6919 id->idSetIsBound(); // We won't patch address since we will know the exact distance once JIT code and data are
6920 // allocated together.
6922 id->idReg1(reg); // destination register that will get the constant value.
6923 if (addrReg != REG_NA)
6925 id->idReg2(addrReg); // integer register to compute long address (used for vector dest when we end up with long
6928 id->idjShort = false; // Assume loading constant from long address
6930 // Keep it long if it's in cold code.
6931 id->idjKeepLong = emitComp->fgIsBlockCold(emitComp->compCurBB);
6934 if (emitComp->opts.compLongAddress)
6935 id->idjKeepLong = 1;
6938 // If it's possible to be shortened, then put it in jump list
6939 // to be revisited by emitJumpDistBind.
6940 if (!id->idjKeepLong)
6942 /* Record the jump's IG and offset within it */
6943 id->idjIG = emitCurIG;
6944 id->idjOffs = emitCurIGsize;
6946 /* Append this jump to this IG's jump list */
6947 id->idjNext = emitCurIGjmpList;
6948 emitCurIGjmpList = id;
6959 /*****************************************************************************
6961 * Add an instruction with a static member + constant.
6964 void emitter::emitIns_C_I(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, ssize_t offs, ssize_t val)
6969 /*****************************************************************************
6971 * Add an instruction with a static member + register operands.
6974 void emitter::emitIns_C_R(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, regNumber reg, int offs)
6976 assert(!"emitIns_C_R not supported for RyuJIT backend");
6979 void emitter::emitIns_R_AR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
6981 NYI("emitIns_R_AR");
6984 // This computes address from the immediate which is relocatable.
6985 void emitter::emitIns_R_AI(instruction ins, emitAttr attr, regNumber ireg, ssize_t addr)
6987 assert(EA_IS_RELOC(attr));
6988 emitAttr size = EA_SIZE(attr);
6989 insFormat fmt = IF_DI_1E;
6990 bool needAdd = false;
6991 instrDescJmp* id = emitNewInstrJmp();
6996 // This computes page address.
6997 // page offset is needed using add.
7008 id->idInsOpt(INS_OPTS_NONE);
7010 id->idAddr()->iiaAddr = (BYTE*)addr;
7012 id->idSetIsDspReloc();
7019 // add reg, reg, imm
7022 instrDesc* id = emitAllocInstr(attr);
7023 assert(id->idIsReloc());
7027 id->idInsOpt(INS_OPTS_NONE);
7029 id->idAddr()->iiaAddr = (BYTE*)addr;
7038 void emitter::emitIns_AR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
7040 NYI("emitIns_AR_R");
7043 void emitter::emitIns_R_ARR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
7045 NYI("emitIns_R_ARR");
7048 void emitter::emitIns_ARR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
7050 NYI("emitIns_R_ARR");
7053 void emitter::emitIns_R_ARX(
7054 instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, unsigned mul, int disp)
7056 NYI("emitIns_R_ARR");
7059 /*****************************************************************************
7061 * Record that a jump instruction uses the short encoding
7064 void emitter::emitSetShortJump(instrDescJmp* id)
7066 if (id->idjKeepLong)
7069 insFormat fmt = IF_NONE;
7070 if (emitIsCondJump(id))
7072 switch (id->idIns())
7087 else if (emitIsLoadLabel(id))
7091 else if (emitIsLoadConstant(id))
7101 id->idjShort = true;
7104 /*****************************************************************************
7106 * Add a label instruction.
7109 void emitter::emitIns_R_L(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
7111 assert(dst->bbFlags & BBF_JMP_TARGET);
7113 insFormat fmt = IF_NONE;
7124 instrDescJmp* id = emitNewInstrJmp();
7128 id->idjShort = false;
7129 id->idAddr()->iiaBBlabel = dst;
7131 id->idOpSize(EA_PTRSIZE);
7134 // Mark the catch return
7135 if (emitComp->compCurBB->bbJumpKind == BBJ_EHCATCHRET)
7137 id->idDebugOnlyInfo()->idCatchRet = true;
7141 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7144 if (emitComp->opts.compLongAddress)
7145 id->idjKeepLong = 1;
7148 /* Record the jump's IG and offset within it */
7150 id->idjIG = emitCurIG;
7151 id->idjOffs = emitCurIGsize;
7153 /* Append this jump to this IG's jump list */
7155 id->idjNext = emitCurIGjmpList;
7156 emitCurIGjmpList = id;
7166 /*****************************************************************************
7168 * Add a data label instruction.
7171 void emitter::emitIns_R_D(instruction ins, emitAttr attr, unsigned offs, regNumber reg)
7176 void emitter::emitIns_J_R(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
7178 assert((ins == INS_cbz) || (ins == INS_cbnz));
7180 assert(dst != nullptr);
7181 assert((dst->bbFlags & BBF_JMP_TARGET) != 0);
7183 insFormat fmt = IF_LARGEJMP;
7185 instrDescJmp* id = emitNewInstrJmp();
7190 id->idjShort = false;
7191 id->idOpSize(EA_SIZE(attr));
7193 id->idAddr()->iiaBBlabel = dst;
7194 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7196 /* Record the jump's IG and offset within it */
7198 id->idjIG = emitCurIG;
7199 id->idjOffs = emitCurIGsize;
7201 /* Append this jump to this IG's jump list */
7203 id->idjNext = emitCurIGjmpList;
7204 emitCurIGjmpList = id;
7214 void emitter::emitIns_J_R_I(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg, int imm)
7216 assert((ins == INS_tbz) || (ins == INS_tbnz));
7218 assert(dst != nullptr);
7219 assert((dst->bbFlags & BBF_JMP_TARGET) != 0);
7220 assert((EA_SIZE(attr) == EA_4BYTE) || (EA_SIZE(attr) == EA_8BYTE));
7221 assert(imm < ((EA_SIZE(attr) == EA_4BYTE) ? 32 : 64));
7223 insFormat fmt = IF_LARGEJMP;
7225 instrDescJmp* id = emitNewInstrJmp();
7230 id->idjShort = false;
7231 id->idSmallCns(imm);
7232 id->idOpSize(EA_SIZE(attr));
7234 id->idAddr()->iiaBBlabel = dst;
7235 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7237 /* Record the jump's IG and offset within it */
7239 id->idjIG = emitCurIG;
7240 id->idjOffs = emitCurIGsize;
7242 /* Append this jump to this IG's jump list */
7244 id->idjNext = emitCurIGjmpList;
7245 emitCurIGjmpList = id;
7255 void emitter::emitIns_J(instruction ins, BasicBlock* dst, int instrCount)
7257 insFormat fmt = IF_NONE;
7261 assert(dst->bbFlags & BBF_JMP_TARGET);
7265 assert(instrCount != 0);
7268 /* Figure out the encoding format of the instruction */
7270 bool idjShort = false;
7275 // Unconditional jump is a single form.
7294 // Assume conditional jump is long.
7303 instrDescJmp* id = emitNewInstrJmp();
7307 id->idjShort = idjShort;
7310 // Mark the finally call
7311 if (ins == INS_bl_local && emitComp->compCurBB->bbJumpKind == BBJ_CALLFINALLY)
7313 id->idDebugOnlyInfo()->idFinallyCall = true;
7319 id->idAddr()->iiaBBlabel = dst;
7321 // Skip unconditional jump that has a single form.
7322 // TODO-ARM64-NYI: enable hot/cold splittingNYI.
7323 // The target needs to be relocated.
7326 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7329 if (emitComp->opts.compLongAddress) // Force long branches
7330 id->idjKeepLong = 1;
7336 id->idAddr()->iiaSetInstrCount(instrCount);
7337 id->idjKeepLong = false;
7338 /* This jump must be short */
7339 emitSetShortJump(id);
7343 /* Record the jump's IG and offset within it */
7345 id->idjIG = emitCurIG;
7346 id->idjOffs = emitCurIGsize;
7348 /* Append this jump to this IG's jump list */
7350 id->idjNext = emitCurIGjmpList;
7351 emitCurIGjmpList = id;
7361 /*****************************************************************************
7363 * Add a call instruction (direct or indirect).
7364 * argSize<0 means that the caller will pop the arguments
7366 * The other arguments are interpreted depending on callType as shown:
7367 * Unless otherwise specified, ireg,xreg,xmul,disp should have default values.
7369 * EC_FUNC_TOKEN : addr is the method address
7370 * EC_FUNC_ADDR : addr is the absolute address of the function
7372 * If callType is one of these emitCallTypes, addr has to be NULL.
7373 * EC_INDIR_R : "call ireg".
7375 * For ARM xreg, xmul and disp are never used and should always be 0/REG_NA.
7377 * Please consult the "debugger team notification" comment in genFnProlog().
7380 void emitter::emitIns_Call(EmitCallType callType,
7381 CORINFO_METHOD_HANDLE methHnd,
7382 INDEBUG_LDISASM_COMMA(CORINFO_SIG_INFO* sigInfo) // used to report call sites to the EE
7386 emitAttr secondRetSize,
7387 VARSET_VALARG_TP ptrVars,
7388 regMaskTP gcrefRegs,
7389 regMaskTP byrefRegs,
7390 IL_OFFSETX ilOffset /* = BAD_IL_OFFSET */,
7391 regNumber ireg /* = REG_NA */,
7392 regNumber xreg /* = REG_NA */,
7393 unsigned xmul /* = 0 */,
7394 ssize_t disp /* = 0 */,
7395 bool isJump /* = false */,
7396 bool isNoGC /* = false */,
7397 bool isProfLeaveCB /* = false */)
7399 /* Sanity check the arguments depending on callType */
7401 assert(callType < EC_COUNT);
7402 assert((callType != EC_FUNC_TOKEN && callType != EC_FUNC_ADDR) ||
7403 (ireg == REG_NA && xreg == REG_NA && xmul == 0 && disp == 0));
7404 assert(callType < EC_INDIR_R || addr == NULL);
7405 assert(callType != EC_INDIR_R || (ireg < REG_COUNT && xreg == REG_NA && xmul == 0 && disp == 0));
7407 // ARM never uses these
7408 assert(xreg == REG_NA && xmul == 0 && disp == 0);
7410 // Our stack level should be always greater than the bytes of arguments we push. Just
7412 assert((unsigned)abs(argSize) <= codeGen->genStackLevel);
7417 /* This is the saved set of registers after a normal call */
7418 regMaskTP savedSet = RBM_CALLEE_SAVED;
7420 /* some special helper calls have a different saved set registers */
7424 assert(emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
7426 // Get the set of registers that this call kills and remove it from the saved set.
7427 savedSet = RBM_ALLINT & ~emitComp->compNoGCHelperCallKillSet(Compiler::eeGetHelperNum(methHnd));
7429 // In case of Leave profiler callback, we need to preserve liveness of REG_PROFILER_RET_SCRATCH
7432 savedSet |= RBM_PROFILER_RET_SCRATCH;
7436 if (emitComp->verbose)
7438 printf("NOGC Call: savedSet=");
7439 printRegMaskInt(savedSet);
7440 emitDispRegSet(savedSet);
7447 assert(!emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
7450 /* Trim out any callee-trashed registers from the live set */
7452 gcrefRegs &= savedSet;
7453 byrefRegs &= savedSet;
7456 if (EMIT_GC_VERBOSE)
7458 printf("Call: GCvars=%s ", VarSetOps::ToString(emitComp, ptrVars));
7459 dumpConvertedVarSet(emitComp, ptrVars);
7460 printf(", gcrefRegs=");
7461 printRegMaskInt(gcrefRegs);
7462 emitDispRegSet(gcrefRegs);
7463 printf(", byrefRegs=");
7464 printRegMaskInt(byrefRegs);
7465 emitDispRegSet(byrefRegs);
7470 assert(argSize % REGSIZE_BYTES == 0);
7471 argCnt = (int)(argSize / (int)REGSIZE_BYTES);
7473 /* Managed RetVal: emit sequence point for the call */
7474 if (emitComp->opts.compDbgInfo && ilOffset != BAD_IL_OFFSET)
7476 codeGen->genIPmappingAdd(ilOffset, false);
7480 We need to allocate the appropriate instruction descriptor based
7481 on whether this is a direct/indirect call, and whether we need to
7482 record an updated set of live GC variables.
7485 if (callType >= EC_INDIR_R)
7487 /* Indirect call, virtual calls */
7489 assert(callType == EC_INDIR_R);
7491 id = emitNewInstrCallInd(argCnt, disp, ptrVars, gcrefRegs, byrefRegs, retSize, secondRetSize);
7495 /* Helper/static/nonvirtual/function calls (direct or through handle),
7496 and calls to an absolute addr. */
7498 assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
7500 id = emitNewInstrCallDir(argCnt, ptrVars, gcrefRegs, byrefRegs, retSize, secondRetSize);
7503 /* Update the emitter's live GC ref sets */
7505 VarSetOps::Assign(emitComp, emitThisGCrefVars, ptrVars);
7506 emitThisGCrefRegs = gcrefRegs;
7507 emitThisByrefRegs = byrefRegs;
7509 /* Set the instruction - special case jumping a function */
7511 insFormat fmt = IF_NONE;
7513 id->idSetIsNoGC(isNoGC);
7515 /* Record the address: method, indirection, or funcptr */
7517 if (callType > EC_FUNC_ADDR)
7519 /* This is an indirect call (either a virtual call or func ptr call) */
7523 case EC_INDIR_R: // the address is in a register
7525 id->idSetIsCallRegPtr();
7529 ins = INS_br_tail; // INS_br_tail Reg
7533 ins = INS_blr; // INS_blr Reg
7541 assert(xreg == REG_NA);
7545 NO_WAY("unexpected instruction");
7551 /* This is a simple direct call: "call helper/method/addr" */
7553 assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
7555 assert(addr != NULL);
7559 ins = INS_b_tail; // INS_b_tail imm28
7563 ins = INS_bl; // INS_bl imm28
7570 id->idAddr()->iiaAddr = (BYTE*)addr;
7572 if (callType == EC_FUNC_ADDR)
7574 id->idSetIsCallAddr();
7577 if (emitComp->opts.compReloc)
7579 id->idSetIsDspReloc();
7584 if (EMIT_GC_VERBOSE)
7586 if (id->idIsLargeCall())
7588 printf("[%02u] Rec call GC vars = %s\n", id->idDebugOnlyInfo()->idNum,
7589 VarSetOps::ToString(emitComp, ((instrDescCGCA*)id)->idcGCvars));
7593 id->idDebugOnlyInfo()->idMemCookie = (size_t)methHnd; // method token
7594 id->idDebugOnlyInfo()->idCallSig = sigInfo;
7598 if (addr != nullptr)
7600 codeGen->getDisAssembler().disSetMethod((size_t)addr, methHnd);
7602 #endif // LATE_DISASM
7608 /*****************************************************************************
7610 * Returns true if 'imm' is valid Cond encoding
7613 /*static*/ bool emitter::isValidImmCond(ssize_t imm)
7615 // range check the ssize_t value, to make sure it is a small unsigned value
7616 // and that only the bits in the cfi.cond are set
7617 if ((imm < 0) || (imm > 0xF))
7621 cfi.immCFVal = (unsigned)imm;
7623 return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7626 /*****************************************************************************
7628 * Returns true if 'imm' is valid Cond/Flags encoding
7631 /*static*/ bool emitter::isValidImmCondFlags(ssize_t imm)
7633 // range check the ssize_t value, to make sure it is a small unsigned value
7634 // and that only the bits in the cfi.cond or cfi.flags are set
7635 if ((imm < 0) || (imm > 0xFF))
7639 cfi.immCFVal = (unsigned)imm;
7641 return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7644 /*****************************************************************************
7646 * Returns true if 'imm' is valid Cond/Flags/Imm5 encoding
7649 /*static*/ bool emitter::isValidImmCondFlagsImm5(ssize_t imm)
7651 // range check the ssize_t value, to make sure it is a small unsigned value
7652 // and that only the bits in the cfi.cond, cfi.flags or cfi.imm5 are set
7653 if ((imm < 0) || (imm > 0x1FFF))
7657 cfi.immCFVal = (unsigned)imm;
7659 return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7662 /*****************************************************************************
7664 * Returns an encoding for the specified register used in the 'Rd' position
7667 /*static*/ emitter::code_t emitter::insEncodeReg_Rd(regNumber reg)
7669 assert(isIntegerRegister(reg));
7670 emitter::code_t ureg = (emitter::code_t)reg;
7671 assert((ureg >= 0) && (ureg <= 31));
7675 /*****************************************************************************
7677 * Returns an encoding for the specified register used in the 'Rt' position
7680 /*static*/ emitter::code_t emitter::insEncodeReg_Rt(regNumber reg)
7682 assert(isIntegerRegister(reg));
7683 emitter::code_t ureg = (emitter::code_t)reg;
7684 assert((ureg >= 0) && (ureg <= 31));
7688 /*****************************************************************************
7690 * Returns an encoding for the specified register used in the 'Rn' position
7693 /*static*/ emitter::code_t emitter::insEncodeReg_Rn(regNumber reg)
7695 assert(isIntegerRegister(reg));
7696 emitter::code_t ureg = (emitter::code_t)reg;
7697 assert((ureg >= 0) && (ureg <= 31));
7701 /*****************************************************************************
7703 * Returns an encoding for the specified register used in the 'Rm' position
7706 /*static*/ emitter::code_t emitter::insEncodeReg_Rm(regNumber reg)
7708 assert(isIntegerRegister(reg));
7709 emitter::code_t ureg = (emitter::code_t)reg;
7710 assert((ureg >= 0) && (ureg <= 31));
7714 /*****************************************************************************
7716 * Returns an encoding for the specified register used in the 'Ra' position
7719 /*static*/ emitter::code_t emitter::insEncodeReg_Ra(regNumber reg)
7721 assert(isIntegerRegister(reg));
7722 emitter::code_t ureg = (emitter::code_t)reg;
7723 assert((ureg >= 0) && (ureg <= 31));
7727 /*****************************************************************************
7729 * Returns an encoding for the specified register used in the 'Vd' position
7732 /*static*/ emitter::code_t emitter::insEncodeReg_Vd(regNumber reg)
7734 assert(emitter::isVectorRegister(reg));
7735 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7736 assert((ureg >= 0) && (ureg <= 31));
7740 /*****************************************************************************
7742 * Returns an encoding for the specified register used in the 'Vt' position
7745 /*static*/ emitter::code_t emitter::insEncodeReg_Vt(regNumber reg)
7747 assert(emitter::isVectorRegister(reg));
7748 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7749 assert((ureg >= 0) && (ureg <= 31));
7753 /*****************************************************************************
7755 * Returns an encoding for the specified register used in the 'Vn' position
7758 /*static*/ emitter::code_t emitter::insEncodeReg_Vn(regNumber reg)
7760 assert(emitter::isVectorRegister(reg));
7761 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7762 assert((ureg >= 0) && (ureg <= 31));
7766 /*****************************************************************************
7768 * Returns an encoding for the specified register used in the 'Vm' position
7771 /*static*/ emitter::code_t emitter::insEncodeReg_Vm(regNumber reg)
7773 assert(emitter::isVectorRegister(reg));
7774 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7775 assert((ureg >= 0) && (ureg <= 31));
7779 /*****************************************************************************
7781 * Returns an encoding for the specified register used in the 'Va' position
7784 /*static*/ emitter::code_t emitter::insEncodeReg_Va(regNumber reg)
7786 assert(emitter::isVectorRegister(reg));
7787 emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7788 assert((ureg >= 0) && (ureg <= 31));
7792 /*****************************************************************************
7794 * Returns an encoding for the specified condition code.
7797 /*static*/ emitter::code_t emitter::insEncodeCond(insCond cond)
7799 emitter::code_t uimm = (emitter::code_t)cond;
7803 /*****************************************************************************
7805 * Returns an encoding for the condition code with the lowest bit inverted (marked by invert(<cond>) in the
7806 * architecture manual).
7809 /*static*/ emitter::code_t emitter::insEncodeInvertedCond(insCond cond)
7811 emitter::code_t uimm = (emitter::code_t)cond;
7812 uimm ^= 1; // invert the lowest bit
7816 /*****************************************************************************
7818 * Returns an encoding for the specified flags.
7821 /*static*/ emitter::code_t emitter::insEncodeFlags(insCflags flags)
7823 emitter::code_t uimm = (emitter::code_t)flags;
7827 /*****************************************************************************
7829 * Returns the encoding for the Shift Count bits to be used for Arm64 encodings
7832 /*static*/ emitter::code_t emitter::insEncodeShiftCount(ssize_t imm, emitAttr size)
7834 assert((imm & 0x003F) == imm);
7835 assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
7837 return (emitter::code_t)imm << 10;
7840 /*****************************************************************************
7842 * Returns the encoding to select a 64-bit datasize for an Arm64 instruction
7845 /*static*/ emitter::code_t emitter::insEncodeDatasize(emitAttr size)
7847 if (size == EA_8BYTE)
7849 return 0x80000000; // set the bit at location 31
7853 assert(size == EA_4BYTE);
7858 /*****************************************************************************
7860 * Returns the encoding to select the datasize for the general load/store Arm64 instructions
7864 /*static*/ emitter::code_t emitter::insEncodeDatasizeLS(emitter::code_t code, emitAttr size)
7866 bool exclusive = ((code & 0x35000000) == 0);
7867 bool atomic = ((code & 0x31200C00) == 0x30200000);
7869 if ((code & 0x00800000) && !exclusive && !atomic) // Is this a sign-extending opcode? (i.e. ldrsw, ldrsh, ldrsb)
7871 if ((code & 0x80000000) == 0) // Is it a ldrsh or ldrsb and not ldrsw ?
7873 if (EA_SIZE(size) != EA_8BYTE) // Do we need to encode the 32-bit Rt size bit?
7875 return 0x00400000; // set the bit at location 22
7879 else if (code & 0x80000000) // Is this a ldr/str/ldur/stur opcode?
7881 if (EA_SIZE(size) == EA_8BYTE) // Do we need to encode the 64-bit size bit?
7883 return 0x40000000; // set the bit at location 30
7889 /*****************************************************************************
7891 * Returns the encoding to select the datasize for the vector load/store Arm64 instructions
7895 /*static*/ emitter::code_t emitter::insEncodeDatasizeVLS(emitter::code_t code, emitAttr size)
7900 if ((code & 0x20000000) == 0)
7904 if (size == EA_16BYTE)
7906 // set the operation size in bit 31
7907 result = 0x80000000;
7909 else if (size == EA_8BYTE)
7911 // set the operation size in bit 30
7912 result = 0x40000000;
7916 assert(size == EA_4BYTE);
7918 result = 0x00000000;
7925 if (size == EA_16BYTE)
7927 // The operation size in bits 31 and 30 are zero
7928 // Bit 23 specifies a 128-bit Load/Store
7929 result = 0x00800000;
7931 else if (size == EA_8BYTE)
7933 // set the operation size in bits 31 and 30
7934 result = 0xC0000000;
7936 else if (size == EA_4BYTE)
7938 // set the operation size in bit 31
7939 result = 0x80000000;
7941 else if (size == EA_2BYTE)
7943 // set the operation size in bit 30
7944 result = 0x40000000;
7948 assert(size == EA_1BYTE);
7949 // The operation size in bits 31 and 30 are zero
7950 result = 0x00000000;
7954 // Or in bit 26 to indicate a Vector register is used as 'target'
7955 result |= 0x04000000;
7960 /*****************************************************************************
7962 * Returns the encoding to select the datasize for the vector load/store Arm64 instructions
7966 /*static*/ emitter::code_t emitter::insEncodeDatasizeVPLS(emitter::code_t code, emitAttr size)
7970 if (size == EA_16BYTE)
7972 // The operation size in bits 31 and 30 are zero
7973 // Bit 23 specifies a 128-bit Load/Store
7974 result = 0x80000000;
7976 else if (size == EA_8BYTE)
7978 // set the operation size in bits 31 and 30
7979 result = 0x40000000;
7981 else if (size == EA_4BYTE)
7983 // set the operation size in bit 31
7984 result = 0x00000000;
7987 // Or in bit 26 to indicate a Vector register is used as 'target'
7988 result |= 0x04000000;
7993 /*****************************************************************************
7995 * Returns the encoding to set the size bit and the N bits for a 'bitfield' instruction
7999 /*static*/ emitter::code_t emitter::insEncodeDatasizeBF(emitter::code_t code, emitAttr size)
8001 // is bit 30 equal to 0?
8002 if ((code & 0x40000000) == 0) // is the opcode one of extr, sxtb, sxth or sxtw
8004 if (size == EA_8BYTE) // Do we need to set the sf and N bits?
8006 return 0x80400000; // set the sf-bit at location 31 and the N-bit at location 22
8009 return 0; // don't set any bits
8012 /*****************************************************************************
8014 * Returns the encoding to select the 64/128-bit datasize for an Arm64 vector instruction
8017 /*static*/ emitter::code_t emitter::insEncodeVectorsize(emitAttr size)
8019 if (size == EA_16BYTE)
8021 return 0x40000000; // set the bit at location 30
8025 assert(size == EA_8BYTE);
8030 /*****************************************************************************
8032 * Returns the encoding to select 'index' for an Arm64 vector elem instruction
8034 /*static*/ emitter::code_t emitter::insEncodeVectorIndex(emitAttr elemsize, ssize_t index)
8036 code_t bits = (code_t)index;
8037 if (elemsize == EA_1BYTE)
8042 else if (elemsize == EA_2BYTE)
8047 else if (elemsize == EA_4BYTE)
8054 assert(elemsize == EA_8BYTE);
8058 assert((bits >= 1) && (bits <= 0x1f));
8060 return (bits << 16); // bits at locations [20,19,18,17,16]
8063 /*****************************************************************************
8065 * Returns the encoding to select 'index2' for an Arm64 'ins' elem instruction
8067 /*static*/ emitter::code_t emitter::insEncodeVectorIndex2(emitAttr elemsize, ssize_t index2)
8069 code_t bits = (code_t)index2;
8070 if (elemsize == EA_1BYTE)
8074 else if (elemsize == EA_2BYTE)
8078 else if (elemsize == EA_4BYTE)
8084 assert(elemsize == EA_8BYTE);
8087 assert((bits >= 0) && (bits <= 0xf));
8089 return (bits << 11); // bits at locations [14,13,12,11]
8092 /*****************************************************************************
8094 * Returns the encoding to select the 'index' for an Arm64 'mul' by elem instruction
8096 /*static*/ emitter::code_t emitter::insEncodeVectorIndexLMH(emitAttr elemsize, ssize_t index)
8100 if (elemsize == EA_2BYTE)
8102 assert((index >= 0) && (index <= 7));
8105 bits |= (1 << 11); // set bit 11 'H'
8109 bits |= (1 << 21); // set bit 21 'L'
8113 bits |= (1 << 20); // set bit 20 'M'
8116 else if (elemsize == EA_4BYTE)
8118 assert((index >= 0) && (index <= 3));
8121 bits |= (1 << 11); // set bit 11 'H'
8125 bits |= (1 << 21); // set bit 21 'L'
8130 assert(!"Invalid 'elemsize' value");
8136 /*****************************************************************************
8138 * Returns the encoding to shift by 'shift' for an Arm64 vector or scalar instruction
8141 /*static*/ emitter::code_t emitter::insEncodeVectorShift(emitAttr size, ssize_t shift)
8143 assert(shift < getBitWidth(size));
8145 code_t imm = (code_t)(getBitWidth(size) + shift);
8150 /*****************************************************************************
8152 * Returns the encoding to select the 1/2/4/8 byte elemsize for an Arm64 vector instruction
8155 /*static*/ emitter::code_t emitter::insEncodeElemsize(emitAttr size)
8157 if (size == EA_8BYTE)
8159 return 0x00C00000; // set the bit at location 23 and 22
8161 else if (size == EA_4BYTE)
8163 return 0x00800000; // set the bit at location 23
8165 else if (size == EA_2BYTE)
8167 return 0x00400000; // set the bit at location 22
8169 assert(size == EA_1BYTE);
8173 /*****************************************************************************
8175 * Returns the encoding to select the 4/8 byte elemsize for an Arm64 float vector instruction
8178 /*static*/ emitter::code_t emitter::insEncodeFloatElemsize(emitAttr size)
8180 if (size == EA_8BYTE)
8182 return 0x00400000; // set the bit at location 22
8184 assert(size == EA_4BYTE);
8188 // Returns the encoding to select the index for an Arm64 float vector by elem instruction
8189 /*static*/ emitter::code_t emitter::insEncodeFloatIndex(emitAttr elemsize, ssize_t index)
8191 code_t result = 0x00000000;
8192 if (elemsize == EA_8BYTE)
8194 assert((index >= 0) && (index <= 1));
8197 result |= 0x00000800; // 'H' - set the bit at location 11
8202 assert(elemsize == EA_4BYTE);
8203 assert((index >= 0) && (index <= 3));
8206 result |= 0x00000800; // 'H' - set the bit at location 11
8210 result |= 0x00200000; // 'L' - set the bit at location 21
8216 /*****************************************************************************
8218 * Returns the encoding to select the fcvt operation for Arm64 instructions
8220 /*static*/ emitter::code_t emitter::insEncodeConvertOpt(insFormat fmt, insOpts conversion)
8225 case INS_OPTS_S_TO_D: // Single to Double
8226 assert(fmt == IF_DV_2J);
8227 result = 0x00008000; // type=00, opc=01
8230 case INS_OPTS_D_TO_S: // Double to Single
8231 assert(fmt == IF_DV_2J);
8232 result = 0x00400000; // type=01, opc=00
8235 case INS_OPTS_H_TO_S: // Half to Single
8236 assert(fmt == IF_DV_2J);
8237 result = 0x00C00000; // type=11, opc=00
8240 case INS_OPTS_H_TO_D: // Half to Double
8241 assert(fmt == IF_DV_2J);
8242 result = 0x00C08000; // type=11, opc=01
8245 case INS_OPTS_S_TO_H: // Single to Half
8246 assert(fmt == IF_DV_2J);
8247 result = 0x00018000; // type=00, opc=11
8250 case INS_OPTS_D_TO_H: // Double to Half
8251 assert(fmt == IF_DV_2J);
8252 result = 0x00418000; // type=01, opc=11
8255 case INS_OPTS_S_TO_4BYTE: // Single to INT32
8256 assert(fmt == IF_DV_2H);
8257 result = 0x00000000; // sf=0, type=00
8260 case INS_OPTS_D_TO_4BYTE: // Double to INT32
8261 assert(fmt == IF_DV_2H);
8262 result = 0x00400000; // sf=0, type=01
8265 case INS_OPTS_S_TO_8BYTE: // Single to INT64
8266 assert(fmt == IF_DV_2H);
8267 result = 0x80000000; // sf=1, type=00
8270 case INS_OPTS_D_TO_8BYTE: // Double to INT64
8271 assert(fmt == IF_DV_2H);
8272 result = 0x80400000; // sf=1, type=01
8275 case INS_OPTS_4BYTE_TO_S: // INT32 to Single
8276 assert(fmt == IF_DV_2I);
8277 result = 0x00000000; // sf=0, type=00
8280 case INS_OPTS_4BYTE_TO_D: // INT32 to Double
8281 assert(fmt == IF_DV_2I);
8282 result = 0x00400000; // sf=0, type=01
8285 case INS_OPTS_8BYTE_TO_S: // INT64 to Single
8286 assert(fmt == IF_DV_2I);
8287 result = 0x80000000; // sf=1, type=00
8290 case INS_OPTS_8BYTE_TO_D: // INT64 to Double
8291 assert(fmt == IF_DV_2I);
8292 result = 0x80400000; // sf=1, type=01
8296 assert(!"Invalid 'conversion' value");
8302 /*****************************************************************************
8304 * Returns the encoding to have the Rn register be updated Pre/Post indexed
8308 /*static*/ emitter::code_t emitter::insEncodeIndexedOpt(insOpts opt)
8310 assert(emitter::insOptsNone(opt) || emitter::insOptsIndexed(opt));
8312 if (emitter::insOptsIndexed(opt))
8314 if (emitter::insOptsPostIndex(opt))
8316 return 0x00000400; // set the bit at location 10
8320 assert(emitter::insOptsPreIndex(opt));
8321 return 0x00000C00; // set the bit at location 10 and 11
8326 assert(emitter::insOptsNone(opt));
8327 return 0; // bits 10 and 11 are zero
8331 /*****************************************************************************
8333 * Returns the encoding for a ldp/stp instruction to have the Rn register
8334 * be updated Pre/Post indexed or not updated
8337 /*static*/ emitter::code_t emitter::insEncodePairIndexedOpt(instruction ins, insOpts opt)
8339 assert(emitter::insOptsNone(opt) || emitter::insOptsIndexed(opt));
8341 if ((ins == INS_ldnp) || (ins == INS_stnp))
8343 assert(emitter::insOptsNone(opt));
8344 return 0; // bits 23 and 24 are zero
8348 if (emitter::insOptsIndexed(opt))
8350 if (emitter::insOptsPostIndex(opt))
8352 return 0x00800000; // set the bit at location 23
8356 assert(emitter::insOptsPreIndex(opt));
8357 return 0x01800000; // set the bit at location 24 and 23
8362 assert(emitter::insOptsNone(opt));
8363 return 0x01000000; // set the bit at location 24
8368 /*****************************************************************************
8370 * Returns the encoding to apply a Shift Type on the Rm register
8373 /*static*/ emitter::code_t emitter::insEncodeShiftType(insOpts opt)
8375 if (emitter::insOptsNone(opt))
8377 // None implies the we encode LSL (with a zero immediate)
8380 assert(emitter::insOptsAnyShift(opt));
8382 emitter::code_t option = (emitter::code_t)opt - (emitter::code_t)INS_OPTS_LSL;
8383 assert(option <= 3);
8385 return option << 22; // bits 23, 22
8388 /*****************************************************************************
8390 * Returns the encoding to apply a 12 bit left shift to the immediate
8393 /*static*/ emitter::code_t emitter::insEncodeShiftImm12(insOpts opt)
8395 if (emitter::insOptsLSL12(opt))
8397 return 0x00400000; // set the bit at location 22
8402 /*****************************************************************************
8404 * Returns the encoding to have the Rm register use an extend operation
8407 /*static*/ emitter::code_t emitter::insEncodeExtend(insOpts opt)
8409 if (emitter::insOptsNone(opt) || (opt == INS_OPTS_LSL))
8411 // None or LSL implies the we encode UXTX
8412 opt = INS_OPTS_UXTX;
8414 assert(emitter::insOptsAnyExtend(opt));
8416 emitter::code_t option = (emitter::code_t)opt - (emitter::code_t)INS_OPTS_UXTB;
8417 assert(option <= 7);
8419 return option << 13; // bits 15,14,13
8422 /*****************************************************************************
8424 * Returns the encoding to scale the Rm register by {0,1,2,3,4}
8425 * when using an extend operation
8428 /*static*/ emitter::code_t emitter::insEncodeExtendScale(ssize_t imm)
8430 assert((imm >= 0) && (imm <= 4));
8432 return (emitter::code_t)imm << 10; // bits 12,11,10
8435 /*****************************************************************************
8437 * Returns the encoding to have the Rm register be auto scaled by the ld/st size
8440 /*static*/ emitter::code_t emitter::insEncodeReg3Scale(bool isScaled)
8444 return 0x00001000; // set the bit at location 12
8452 BYTE* emitter::emitOutputLoadLabel(BYTE* dst, BYTE* srcAddr, BYTE* dstAddr, instrDescJmp* id)
8454 instruction ins = id->idIns();
8455 insFormat fmt = id->idInsFmt();
8456 regNumber dstReg = id->idReg1();
8459 // adr x, [rel addr] -- compute address: current addr(ip) + rel addr.
8460 assert(ins == INS_adr);
8461 assert(fmt == IF_DI_1E);
8462 ssize_t distVal = (ssize_t)(dstAddr - srcAddr);
8463 dst = emitOutputShortAddress(dst, ins, fmt, distVal, dstReg);
8467 // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8468 assert(fmt == IF_LARGEADR);
8469 ssize_t relPageAddr =
8470 (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8471 dst = emitOutputShortAddress(dst, INS_adrp, IF_DI_1E, relPageAddr, dstReg);
8473 // add x, x, page offs -- compute address = page addr + page offs
8474 ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8475 assert(isValidUimm12(imm12));
8477 emitInsCode(INS_add, IF_DI_2A); // DI_2A X0010001shiiiiii iiiiiinnnnnddddd 1100 0000 imm(i12, sh)
8478 code |= insEncodeDatasize(EA_8BYTE); // X
8479 code |= ((code_t)imm12 << 10); // iiiiiiiiiiii
8480 code |= insEncodeReg_Rd(dstReg); // ddddd
8481 code |= insEncodeReg_Rn(dstReg); // nnnnn
8482 dst += emitOutput_Instr(dst, code);
8487 /*****************************************************************************
8489 * Output a local jump or other instruction with a pc-relative immediate.
8490 * Note that this may be invoked to overwrite an existing jump instruction at 'dst'
8491 * to handle forward branch patching.
8494 BYTE* emitter::emitOutputLJ(insGroup* ig, BYTE* dst, instrDesc* i)
8496 instrDescJmp* id = (instrDescJmp*)i;
8505 // Set default ins/fmt from id.
8506 instruction ins = id->idIns();
8507 insFormat fmt = id->idInsFmt();
8509 bool loadLabel = false;
8510 bool isJump = false;
8511 bool loadConstant = false;
8528 loadConstant = true;
8537 /* Figure out the distance to the target */
8539 srcOffs = emitCurCodeOffs(dst);
8540 srcAddr = emitOffsetToPtr(srcOffs);
8542 if (id->idAddr()->iiaIsJitDataOffset())
8544 assert(loadConstant || loadLabel);
8545 int doff = id->idAddr()->iiaGetJitDataOffset();
8547 ssize_t imm = emitGetInsSC(id);
8548 assert((imm >= 0) && (imm < 0x1000)); // 0x1000 is arbitrary, currently 'imm' is always 0
8550 unsigned dataOffs = (unsigned)(doff + imm);
8551 assert(dataOffs < emitDataSize());
8552 dstAddr = emitDataOffsetToPtr(dataOffs);
8554 regNumber dstReg = id->idReg1();
8555 regNumber addrReg = dstReg; // an integer register to compute long address.
8556 emitAttr opSize = id->idOpSize();
8562 // ldr x/v, [rel addr] -- load constant from current addr(ip) + rel addr.
8563 assert(ins == INS_ldr);
8564 assert(fmt == IF_LS_1A);
8565 distVal = (ssize_t)(dstAddr - srcAddr);
8566 dst = emitOutputShortConstant(dst, ins, fmt, distVal, dstReg, opSize);
8570 // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8571 assert(fmt == IF_LARGELDC);
8572 ssize_t relPageAddr =
8573 (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8574 if (isVectorRegister(dstReg))
8576 // Update addrReg with the reserved integer register
8577 // since we cannot use dstReg (vector) to load constant directly from memory.
8578 addrReg = id->idReg2();
8579 assert(isGeneralRegister(addrReg));
8583 dst = emitOutputShortAddress(dst, ins, fmt, relPageAddr, addrReg);
8585 // ldr x, [x, page offs] -- load constant from page address + page offset into integer register.
8586 ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8587 assert(isValidUimm12(imm12));
8590 dst = emitOutputShortConstant(dst, ins, fmt, imm12, addrReg, opSize);
8592 // fmov v, d -- copy constant in integer register to vector register.
8593 // This is needed only for vector constant.
8594 if (addrReg != dstReg)
8596 // fmov Vd,Rn DV_2I X00111100X100111 000000nnnnnddddd 1E27 0000 Vd,Rn
8597 // (scalar, from general)
8598 assert(isVectorRegister(dstReg) && isGeneralRegister(addrReg));
8601 code_t code = emitInsCode(ins, fmt);
8603 code |= insEncodeReg_Vd(dstReg); // ddddd
8604 code |= insEncodeReg_Rn(addrReg); // nnnnn
8605 if (id->idOpSize() == EA_8BYTE)
8607 code |= 0x80400000; // X ... X
8609 dst += emitOutput_Instr(dst, code);
8616 dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8622 assert(loadLabel || isJump);
8624 if (id->idAddr()->iiaHasInstrCount())
8627 int instrCount = id->idAddr()->iiaGetInstrCount();
8628 unsigned insNum = emitFindInsNum(ig, id);
8631 // Backward branches using instruction count must be within the same instruction group.
8632 assert(insNum + 1 >= (unsigned)(-instrCount));
8634 dstOffs = ig->igOffs + emitFindOffset(ig, (insNum + 1 + instrCount));
8635 dstAddr = emitOffsetToPtr(dstOffs);
8639 dstOffs = id->idAddr()->iiaIGlabel->igOffs;
8640 dstAddr = emitOffsetToPtr(dstOffs);
8643 distVal = (ssize_t)(dstAddr - srcAddr);
8645 if (dstOffs <= srcOffs)
8648 /* This is a backward jump - distance is known at this point */
8650 if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8652 size_t blkOffs = id->idjIG->igOffs;
8654 if (INTERESTING_JUMP_NUM == 0)
8655 printf("[3] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8656 printf("[3] Jump block is at %08X - %02X = %08X\n", blkOffs, emitOffsAdj, blkOffs - emitOffsAdj);
8657 printf("[3] Jump is at %08X - %02X = %08X\n", srcOffs, emitOffsAdj, srcOffs - emitOffsAdj);
8658 printf("[3] Label block is at %08X - %02X = %08X\n", dstOffs, emitOffsAdj, dstOffs - emitOffsAdj);
8664 /* This is a forward jump - distance will be an upper limit */
8666 emitFwdJumps = true;
8668 /* The target offset will be closer by at least 'emitOffsAdj', but only if this
8669 jump doesn't cross the hot-cold boundary. */
8671 if (!emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8673 dstOffs -= emitOffsAdj;
8674 distVal -= emitOffsAdj;
8677 /* Record the location of the jump for later patching */
8679 id->idjOffs = dstOffs;
8681 /* Are we overflowing the id->idjOffs bitfield? */
8682 if (id->idjOffs != dstOffs)
8683 IMPL_LIMITATION("Method is too large");
8686 if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8688 size_t blkOffs = id->idjIG->igOffs;
8690 if (INTERESTING_JUMP_NUM == 0)
8691 printf("[4] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8692 printf("[4] Jump block is at %08X\n", blkOffs);
8693 printf("[4] Jump is at %08X\n", srcOffs);
8694 printf("[4] Label block is at %08X - %02X = %08X\n", dstOffs + emitOffsAdj, emitOffsAdj, dstOffs);
8700 if (0 && emitComp->verbose)
8703 int distValSize = id->idjShort ? 4 : 8;
8704 printf("; %s jump [%08X/%03u] from %0*X to %0*X: dist = %08XH\n", (dstOffs <= srcOffs) ? "Fwd" : "Bwd",
8705 dspPtr(id), id->idDebugOnlyInfo()->idNum, distValSize, srcOffs + sz, distValSize, dstOffs, distVal);
8709 /* For forward jumps, record the address of the distance value */
8710 id->idjTemp.idjAddr = (distVal > 0) ? dst : NULL;
8712 if (emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8714 assert(!id->idjShort);
8715 NYI_ARM64("Relocation Support for long address");
8718 assert(insOptsNone(id->idInsOpt()));
8724 // Short conditional/unconditional jump
8725 assert(!id->idjKeepLong);
8726 assert(emitJumpCrossHotColdBoundary(srcOffs, dstOffs) == false);
8727 assert((fmt == IF_BI_0A) || (fmt == IF_BI_0B) || (fmt == IF_BI_1A) || (fmt == IF_BI_1B));
8731 // Long conditional jump
8732 assert(fmt == IF_LARGEJMP);
8733 // This is a pseudo-instruction format representing a large conditional branch, to allow
8734 // us to get a greater branch target range than we can get by using a straightforward conditional
8735 // branch. It is encoded as a short conditional branch that branches around a long unconditional
8738 // Conceptually, we have:
8742 // The code we emit is:
8744 // b<!cond> L_not // 4 bytes. Note that we reverse the condition.
8745 // b L_target // 4 bytes
8748 // Note that we don't actually insert any blocks: we simply encode "b <!cond> L_not" as a branch with
8749 // the correct offset. Note also that this works for both integer and floating-point conditions, because
8750 // the condition inversion takes ordered/unordered into account, preserving NaN behavior. For example,
8751 // "GT" (greater than) is inverted to "LE" (less than, equal, or unordered).
8753 instruction reverseIns;
8754 insFormat reverseFmt;
8759 reverseIns = INS_cbnz;
8760 reverseFmt = IF_BI_1A;
8763 reverseIns = INS_cbz;
8764 reverseFmt = IF_BI_1A;
8767 reverseIns = INS_tbnz;
8768 reverseFmt = IF_BI_1B;
8771 reverseIns = INS_tbz;
8772 reverseFmt = IF_BI_1B;
8775 reverseIns = emitJumpKindToIns(emitReverseJumpKind(emitInsToJumpKind(ins)));
8776 reverseFmt = IF_BI_0B;
8780 emitOutputShortBranch(dst,
8781 reverseIns, // reverse the conditional instruction
8783 8, /* 8 bytes from start of this large conditional pseudo-instruction to L_not. */
8786 // Now, pretend we've got a normal unconditional branch, and fall through to the code to emit that.
8790 // The distVal was computed based on the beginning of the pseudo-instruction,
8791 // So subtract the size of the conditional branch so that it is relative to the
8792 // unconditional branch.
8796 dst = emitOutputShortBranch(dst, ins, fmt, distVal, id);
8800 dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8806 /*****************************************************************************
8808 * Output a short branch instruction.
8810 BYTE* emitter::emitOutputShortBranch(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, instrDescJmp* id)
8812 code_t code = emitInsCode(ins, fmt);
8814 ssize_t loBits = (distVal & 3);
8815 noway_assert(loBits == 0);
8816 distVal >>= 2; // branch offset encodings are scaled by 4.
8818 if (fmt == IF_BI_0A)
8820 // INS_b or INS_bl_local
8821 noway_assert(isValidSimm26(distVal));
8822 distVal &= 0x3FFFFFFLL;
8825 else if (fmt == IF_BI_0B) // BI_0B 01010100iiiiiiii iiiiiiiiiiiXXXXX simm19:00
8827 // INS_beq, INS_bne, etc...
8828 noway_assert(isValidSimm19(distVal));
8829 distVal &= 0x7FFFFLL;
8830 code |= distVal << 5;
8832 else if (fmt == IF_BI_1A) // BI_1A X.......iiiiiiii iiiiiiiiiiittttt Rt simm19:00
8834 // INS_cbz or INS_cbnz
8835 assert(id != nullptr);
8836 code |= insEncodeDatasize(id->idOpSize()); // X
8837 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
8839 noway_assert(isValidSimm19(distVal));
8840 distVal &= 0x7FFFFLL; // 19 bits
8841 code |= distVal << 5;
8843 else if (fmt == IF_BI_1B) // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
8845 // INS_tbz or INS_tbnz
8846 assert(id != nullptr);
8847 ssize_t imm = emitGetInsSC(id);
8848 assert(isValidImmShift(imm, id->idOpSize()));
8850 if (imm & 0x20) // test bit 32-63 ?
8852 code |= 0x80000000; // B
8854 code |= ((imm & 0x1F) << 19); // bbbbb
8855 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
8857 noway_assert(isValidSimm14(distVal));
8858 distVal &= 0x3FFFLL; // 14 bits
8859 code |= distVal << 5;
8863 assert(!"Unknown fmt for emitOutputShortBranch");
8866 dst += emitOutput_Instr(dst, code);
8871 /*****************************************************************************
8873 * Output a short address instruction.
8875 BYTE* emitter::emitOutputShortAddress(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, regNumber reg)
8877 ssize_t loBits = (distVal & 3);
8880 code_t code = emitInsCode(ins, fmt);
8881 if (fmt == IF_DI_1E) // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
8883 // INS_adr or INS_adrp
8884 code |= insEncodeReg_Rd(reg); // ddddd
8886 noway_assert(isValidSimm19(distVal));
8887 distVal &= 0x7FFFFLL; // 19 bits
8888 code |= distVal << 5;
8889 code |= loBits << 29; // 2 bits
8893 assert(!"Unknown fmt for emitOutputShortAddress");
8896 dst += emitOutput_Instr(dst, code);
8901 /*****************************************************************************
8903 * Output a short constant instruction.
8905 BYTE* emitter::emitOutputShortConstant(
8906 BYTE* dst, instruction ins, insFormat fmt, ssize_t imm, regNumber reg, emitAttr opSize)
8908 code_t code = emitInsCode(ins, fmt);
8910 if (fmt == IF_LS_1A)
8912 // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt simm21
8913 // INS_ldr or INS_ldrsw (PC-Relative)
8915 ssize_t loBits = (imm & 3);
8916 noway_assert(loBits == 0);
8917 ssize_t distVal = imm >>= 2; // load offset encodings are scaled by 4.
8919 noway_assert(isValidSimm19(distVal));
8921 // Is the target a vector register?
8922 if (isVectorRegister(reg))
8924 code |= insEncodeDatasizeVLS(code, opSize); // XX V
8925 code |= insEncodeReg_Vt(reg); // ttttt
8929 assert(isGeneralRegister(reg));
8930 // insEncodeDatasizeLS is not quite right for this case.
8931 // So just specialize it.
8932 if ((ins == INS_ldr) && (opSize == EA_8BYTE))
8934 // set the operation size in bit 30
8938 code |= insEncodeReg_Rt(reg); // ttttt
8941 distVal &= 0x7FFFFLL; // 19 bits
8942 code |= distVal << 5;
8944 else if (fmt == IF_LS_2B)
8946 // ldr Rt,[Xn+pimm12] LS_2B 1X11100101iiiiii iiiiiinnnnnttttt B940 0000 imm(0-4095<<{2,3})
8947 // INS_ldr or INS_ldrsw (PC-Relative)
8948 noway_assert(isValidUimm12(imm));
8949 assert(isGeneralRegister(reg));
8951 if (opSize == EA_8BYTE)
8953 // insEncodeDatasizeLS is not quite right for this case.
8954 // So just specialize it.
8957 // set the operation size in bit 30
8960 // Low 3 bits should be 0 -- 8 byte JIT data should be aligned on 8 byte.
8961 assert((imm & 7) == 0);
8966 assert(opSize == EA_4BYTE);
8967 // Low 2 bits should be 0 -- 4 byte aligned data.
8968 assert((imm & 3) == 0);
8972 code |= insEncodeReg_Rt(reg); // ttttt
8973 code |= insEncodeReg_Rn(reg); // nnnnn
8978 assert(!"Unknown fmt for emitOutputShortConstant");
8981 dst += emitOutput_Instr(dst, code);
8985 /*****************************************************************************
8987 * Output a call instruction.
8990 unsigned emitter::emitOutputCall(insGroup* ig, BYTE* dst, instrDesc* id, code_t code)
8992 const unsigned char callInstrSize = sizeof(code_t); // 4 bytes
8993 regMaskTP gcrefRegs;
8994 regMaskTP byrefRegs;
8996 VARSET_TP GCvars(VarSetOps::UninitVal());
8998 // Is this a "fat" call descriptor?
8999 if (id->idIsLargeCall())
9001 instrDescCGCA* idCall = (instrDescCGCA*)id;
9002 gcrefRegs = idCall->idcGcrefRegs;
9003 byrefRegs = idCall->idcByrefRegs;
9004 VarSetOps::Assign(emitComp, GCvars, idCall->idcGCvars);
9008 assert(!id->idIsLargeDsp());
9009 assert(!id->idIsLargeCns());
9011 gcrefRegs = emitDecodeCallGCregs(id);
9013 VarSetOps::AssignNoCopy(emitComp, GCvars, VarSetOps::MakeEmpty(emitComp));
9016 /* We update the GC info before the call as the variables cannot be
9017 used by the call. Killing variables before the call helps with
9018 boundary conditions if the call is CORINFO_HELP_THROW - see bug 50029.
9019 If we ever track aliased variables (which could be used by the
9020 call), we would have to keep them alive past the call. */
9022 emitUpdateLiveGCvars(GCvars, dst);
9024 // Now output the call instruction and update the 'dst' pointer
9026 unsigned outputInstrSize = emitOutput_Instr(dst, code);
9027 dst += outputInstrSize;
9029 // All call instructions are 4-byte in size on ARM64
9031 assert(outputInstrSize == callInstrSize);
9033 // If the method returns a GC ref, mark INTRET (R0) appropriately.
9034 if (id->idGCref() == GCT_GCREF)
9036 gcrefRegs |= RBM_INTRET;
9038 else if (id->idGCref() == GCT_BYREF)
9040 byrefRegs |= RBM_INTRET;
9043 // If is a multi-register return method is called, mark INTRET_1 (X1) appropriately
9044 if (id->idIsLargeCall())
9046 instrDescCGCA* idCall = (instrDescCGCA*)id;
9047 if (idCall->idSecondGCref() == GCT_GCREF)
9049 gcrefRegs |= RBM_INTRET_1;
9051 else if (idCall->idSecondGCref() == GCT_BYREF)
9053 byrefRegs |= RBM_INTRET_1;
9057 // If the GC register set has changed, report the new set.
9058 if (gcrefRegs != emitThisGCrefRegs)
9060 emitUpdateLiveGCregs(GCT_GCREF, gcrefRegs, dst);
9062 // If the Byref register set has changed, report the new set.
9063 if (byrefRegs != emitThisByrefRegs)
9065 emitUpdateLiveGCregs(GCT_BYREF, byrefRegs, dst);
9068 // Some helper calls may be marked as not requiring GC info to be recorded.
9069 if ((!id->idIsNoGC()))
9071 // On ARM64, as on AMD64, we don't change the stack pointer to push/pop args.
9072 // So we're not really doing a "stack pop" here (note that "args" is 0), but we use this mechanism
9073 // to record the call for GC info purposes. (It might be best to use an alternate call,
9074 // and protect "emitStackPop" under the EMIT_TRACK_STACK_DEPTH preprocessor variable.)
9075 emitStackPop(dst, /*isCall*/ true, callInstrSize, /*args*/ 0);
9077 // Do we need to record a call location for GC purposes?
9079 if (!emitFullGCinfo)
9081 emitRecordGCcall(dst, callInstrSize);
9084 return callInstrSize;
9087 /*****************************************************************************
9089 * Emit a 32-bit Arm64 instruction
9092 /*static*/ unsigned emitter::emitOutput_Instr(BYTE* dst, code_t code)
9094 assert(sizeof(code_t) == 4);
9095 *((code_t*)dst) = code;
9097 return sizeof(code_t);
9100 /*****************************************************************************
9102 * Append the machine code corresponding to the given instruction descriptor
9103 * to the code block at '*dp'; the base of the code block is 'bp', and 'ig'
9104 * is the instruction group that contains the instruction. Updates '*dp' to
9105 * point past the generated code, and returns the size of the instruction
9106 * descriptor in bytes.
9109 size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
9114 size_t sz = emitGetInstrDescSize(id); // TODO-ARM64-Cleanup: on ARM, this is set in each case. why?
9115 instruction ins = id->idIns();
9116 insFormat fmt = id->idInsFmt();
9117 emitAttr size = id->idOpSize();
9118 unsigned char callInstrSize = 0;
9123 bool dspOffs = emitComp->opts.dspGCtbls;
9125 bool dspOffs = !emitComp->opts.disDiffable;
9129 assert(REG_NA == (int)REG_NA);
9131 VARSET_TP GCvars(VarSetOps::UninitVal());
9133 /* What instruction format have we got? */
9148 case IF_BI_0A: // BI_0A ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
9149 case IF_BI_0B: // BI_0B ......iiiiiiiiii iiiiiiiiiii..... simm19:00
9151 assert(id->idGCref() == GCT_NONE);
9152 assert(id->idIsBound());
9153 dst = emitOutputLJ(ig, dst, id);
9154 sz = sizeof(instrDescJmp);
9157 case IF_BI_0C: // BI_0C ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
9158 code = emitInsCode(ins, fmt);
9159 sz = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
9160 dst += emitOutputCall(ig, dst, id, code);
9161 // Always call RecordRelocation so that we wire in a JumpStub when we don't reach
9162 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_BRANCH26);
9165 case IF_BI_1A: // BI_1A ......iiiiiiiiii iiiiiiiiiiittttt Rt simm19:00
9166 assert(insOptsNone(id->idInsOpt()));
9167 assert(id->idIsBound());
9169 dst = emitOutputLJ(ig, dst, id);
9170 sz = sizeof(instrDescJmp);
9173 case IF_BI_1B: // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
9174 assert(insOptsNone(id->idInsOpt()));
9175 assert(id->idIsBound());
9177 dst = emitOutputLJ(ig, dst, id);
9178 sz = sizeof(instrDescJmp);
9181 case IF_BR_1A: // BR_1A ................ ......nnnnn..... Rn
9182 assert(insOptsNone(id->idInsOpt()));
9183 assert((ins == INS_ret) || (ins == INS_br));
9184 code = emitInsCode(ins, fmt);
9185 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9187 dst += emitOutput_Instr(dst, code);
9190 case IF_BR_1B: // BR_1B ................ ......nnnnn..... Rn
9191 assert(insOptsNone(id->idInsOpt()));
9192 assert((ins == INS_br_tail) || (ins == INS_blr));
9193 code = emitInsCode(ins, fmt);
9194 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9196 sz = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
9197 dst += emitOutputCall(ig, dst, id, code);
9200 case IF_LS_1A: // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB)
9202 assert(insOptsNone(id->idInsOpt()));
9203 assert(id->idIsBound());
9205 dst = emitOutputLJ(ig, dst, id);
9206 sz = sizeof(instrDescJmp);
9209 case IF_LS_2A: // LS_2A .X.......X...... ......nnnnnttttt Rt Rn
9210 assert(insOptsNone(id->idInsOpt()));
9211 code = emitInsCode(ins, fmt);
9212 // Is the target a vector register?
9213 if (isVectorRegister(id->idReg1()))
9215 code &= 0x3FFFFFFF; // clear the size bits
9216 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9217 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9221 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9222 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9224 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9225 dst += emitOutput_Instr(dst, code);
9228 case IF_LS_2B: // LS_2B .X.......Xiiiiii iiiiiinnnnnttttt Rt Rn imm(0-4095)
9229 assert(insOptsNone(id->idInsOpt()));
9230 imm = emitGetInsSC(id);
9231 assert(isValidUimm12(imm));
9232 code = emitInsCode(ins, fmt);
9233 // Is the target a vector register?
9234 if (isVectorRegister(id->idReg1()))
9236 code &= 0x3FFFFFFF; // clear the size bits
9237 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9238 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9242 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9243 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9245 code |= ((code_t)imm << 10); // iiiiiiiiiiii
9246 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9247 dst += emitOutput_Instr(dst, code);
9250 case IF_LS_2C: // LS_2C .X.......X.iiiii iiiiPPnnnnnttttt Rt Rn imm(-256..+255) no/pre/post inc
9251 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9252 imm = emitGetInsSC(id);
9253 assert((imm >= -256) && (imm <= 255)); // signed 9 bits
9254 imm &= 0x1ff; // force into unsigned 9 bit representation
9255 code = emitInsCode(ins, fmt);
9256 // Is the target a vector register?
9257 if (isVectorRegister(id->idReg1()))
9259 code &= 0x3FFFFFFF; // clear the size bits
9260 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9261 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9265 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9266 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9268 code |= insEncodeIndexedOpt(id->idInsOpt()); // PP
9269 code |= ((code_t)imm << 12); // iiiiiiiii
9270 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9271 dst += emitOutput_Instr(dst, code);
9274 case IF_LS_3A: // LS_3A .X.......X.mmmmm oooS..nnnnnttttt Rt Rn Rm ext(Rm) LSL {}
9275 assert(insOptsLSExtend(id->idInsOpt()));
9276 code = emitInsCode(ins, fmt);
9277 // Is the target a vector register?
9278 if (isVectorRegister(id->idReg1()))
9280 code &= 0x3FFFFFFF; // clear the size bits
9281 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9282 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9286 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9287 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9289 code |= insEncodeExtend(id->idInsOpt()); // ooo
9290 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9291 if (id->idIsLclVar())
9293 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9297 code |= insEncodeReg3Scale(id->idReg3Scaled()); // S
9298 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9300 dst += emitOutput_Instr(dst, code);
9303 case IF_LS_3B: // LS_3B X............... .aaaaannnnnddddd Rd Ra Rn
9304 assert(insOptsNone(id->idInsOpt()));
9305 code = emitInsCode(ins, fmt);
9306 // Is the target a vector register?
9307 if (isVectorRegister(id->idReg1()))
9309 code &= 0x3FFFFFFF; // clear the size bits
9310 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9311 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9312 code |= insEncodeReg_Va(id->idReg2()); // aaaaa
9316 code |= insEncodeDatasize(id->idOpSize()); // X
9317 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9318 code |= insEncodeReg_Ra(id->idReg2()); // aaaaa
9320 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9321 dst += emitOutput_Instr(dst, code);
9324 case IF_LS_3C: // LS_3C X......PP.iiiiii iaaaaannnnnddddd Rd Ra Rn imm(im7,sh)
9325 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9326 imm = emitGetInsSC(id);
9327 assert((imm >= -64) && (imm <= 63)); // signed 7 bits
9328 imm &= 0x7f; // force into unsigned 7 bit representation
9329 code = emitInsCode(ins, fmt);
9330 // Is the target a vector register?
9331 if (isVectorRegister(id->idReg1()))
9333 code &= 0x3FFFFFFF; // clear the size bits
9334 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9335 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9336 code |= insEncodeReg_Va(id->idReg2()); // aaaaa
9340 code |= insEncodeDatasize(id->idOpSize()); // X
9341 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9342 code |= insEncodeReg_Ra(id->idReg2()); // aaaaa
9344 code |= insEncodePairIndexedOpt(ins, id->idInsOpt()); // PP
9345 code |= ((code_t)imm << 15); // iiiiiiiii
9346 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9347 dst += emitOutput_Instr(dst, code);
9350 case IF_LS_3D: // LS_3D .X.......X.mmmmm ......nnnnnttttt Wm Rt Rn
9351 code = emitInsCode(ins, fmt);
9352 // Arm64 store exclusive unpredictable cases
9353 assert(id->idReg1() != id->idReg2());
9354 assert(id->idReg1() != id->idReg3());
9355 code |= insEncodeDatasizeLS(code, id->idOpSize()); // X
9356 code |= insEncodeReg_Rm(id->idReg1()); // mmmmm
9357 code |= insEncodeReg_Rt(id->idReg2()); // ttttt
9358 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9359 dst += emitOutput_Instr(dst, code);
9362 case IF_LS_3E: // LS_3E .X.........mmmmm ......nnnnnttttt Rm Rt Rn ARMv8.1 LSE Atomics
9363 code = emitInsCode(ins, fmt);
9364 code |= insEncodeDatasizeLS(code, id->idOpSize()); // X
9365 code |= insEncodeReg_Rm(id->idReg1()); // mmmmm
9366 code |= insEncodeReg_Rt(id->idReg2()); // ttttt
9367 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9368 dst += emitOutput_Instr(dst, code);
9371 case IF_DI_1A: // DI_1A X.......shiiiiii iiiiiinnnnn..... Rn imm(i12,sh)
9372 assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9373 imm = emitGetInsSC(id);
9374 assert(isValidUimm12(imm));
9375 code = emitInsCode(ins, fmt);
9376 code |= insEncodeDatasize(id->idOpSize()); // X
9377 code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9378 code |= ((code_t)imm << 10); // iiiiiiiiiiii
9379 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9380 dst += emitOutput_Instr(dst, code);
9383 case IF_DI_1B: // DI_1B X........hwiiiii iiiiiiiiiiiddddd Rd imm(i16,hw)
9384 imm = emitGetInsSC(id);
9385 assert(isValidImmHWVal(imm, id->idOpSize()));
9386 code = emitInsCode(ins, fmt);
9387 code |= insEncodeDatasize(id->idOpSize()); // X
9388 code |= ((code_t)imm << 5); // hwiiiii iiiiiiiiiii
9389 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9390 dst += emitOutput_Instr(dst, code);
9393 case IF_DI_1C: // DI_1C X........Nrrrrrr ssssssnnnnn..... Rn imm(N,r,s)
9394 imm = emitGetInsSC(id);
9395 assert(isValidImmNRS(imm, id->idOpSize()));
9396 code = emitInsCode(ins, fmt);
9397 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9398 code |= insEncodeDatasize(id->idOpSize()); // X
9399 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9400 dst += emitOutput_Instr(dst, code);
9403 case IF_DI_1D: // DI_1D X........Nrrrrrr ssssss.....ddddd Rd imm(N,r,s)
9404 imm = emitGetInsSC(id);
9405 assert(isValidImmNRS(imm, id->idOpSize()));
9406 code = emitInsCode(ins, fmt);
9407 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9408 code |= insEncodeDatasize(id->idOpSize()); // X
9409 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9410 dst += emitOutput_Instr(dst, code);
9413 case IF_DI_1E: // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
9415 assert(insOptsNone(id->idInsOpt()));
9416 if (id->idIsReloc())
9418 code = emitInsCode(ins, fmt);
9419 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9420 dst += emitOutput_Instr(dst, code);
9421 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEBASE_REL21);
9425 // Local jmp/load case which does not need a relocation.
9426 assert(id->idIsBound());
9427 dst = emitOutputLJ(ig, dst, id);
9429 sz = sizeof(instrDescJmp);
9432 case IF_DI_1F: // DI_1F X..........iiiii cccc..nnnnn.nzcv Rn imm5 nzcv cond
9433 imm = emitGetInsSC(id);
9434 assert(isValidImmCondFlagsImm5(imm));
9437 cfi.immCFVal = (unsigned)imm;
9438 code = emitInsCode(ins, fmt);
9439 code |= insEncodeDatasize(id->idOpSize()); // X
9440 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9441 code |= ((code_t)cfi.imm5 << 16); // iiiii
9442 code |= insEncodeFlags(cfi.flags); // nzcv
9443 code |= insEncodeCond(cfi.cond); // cccc
9444 dst += emitOutput_Instr(dst, code);
9448 case IF_DI_2A: // DI_2A X.......shiiiiii iiiiiinnnnnddddd Rd Rn imm(i12,sh)
9449 assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9450 imm = emitGetInsSC(id);
9451 assert(isValidUimm12(imm));
9452 code = emitInsCode(ins, fmt);
9453 code |= insEncodeDatasize(id->idOpSize()); // X
9454 code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9455 code |= ((code_t)imm << 10); // iiiiiiiiiiii
9456 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9457 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9458 dst += emitOutput_Instr(dst, code);
9460 if (id->idIsReloc())
9462 assert(sz == sizeof(instrDesc));
9463 assert(id->idAddr()->iiaAddr != nullptr);
9464 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEOFFSET_12A);
9468 case IF_DI_2B: // DI_2B X.........Xnnnnn ssssssnnnnnddddd Rd Rn imm(0-63)
9469 code = emitInsCode(ins, fmt);
9470 imm = emitGetInsSC(id);
9471 assert(isValidImmShift(imm, id->idOpSize()));
9472 code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9473 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9474 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9475 code |= insEncodeReg_Rm(id->idReg2()); // Reg2 also in mmmmm
9476 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9477 dst += emitOutput_Instr(dst, code);
9480 case IF_DI_2C: // DI_2C X........Nrrrrrr ssssssnnnnnddddd Rd Rn imm(N,r,s)
9481 imm = emitGetInsSC(id);
9482 assert(isValidImmNRS(imm, id->idOpSize()));
9483 code = emitInsCode(ins, fmt);
9484 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9485 code |= insEncodeDatasize(id->idOpSize()); // X
9486 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9487 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9488 dst += emitOutput_Instr(dst, code);
9491 case IF_DI_2D: // DI_2D X........Nrrrrrr ssssssnnnnnddddd Rd Rn imr, imms (N,r,s)
9492 if (ins == INS_asr || ins == INS_lsl || ins == INS_lsr)
9494 imm = emitGetInsSC(id);
9495 assert(isValidImmShift(imm, id->idOpSize()));
9497 // Shift immediates are aliases of the SBFM/UBFM instructions
9498 // that actually take 2 registers and 2 constants,
9499 // Since we stored the shift immediate value
9500 // we need to calculate the N,R and S values here.
9505 bmi.immN = (size == EA_8BYTE) ? 1 : 0;
9507 bmi.immS = (size == EA_8BYTE) ? 0x3f : 0x1f;
9509 // immR and immS are now set correctly for INS_asr and INS_lsr
9510 // but for INS_lsl we have to adjust the values for immR and immS
9514 bmi.immR = -imm & bmi.immS;
9515 bmi.immS = bmi.immS - imm;
9518 // setup imm with the proper 13 bit value N:R:S
9524 // The other instructions have already have encoded N,R and S values
9525 imm = emitGetInsSC(id);
9527 assert(isValidImmNRS(imm, id->idOpSize()));
9529 code = emitInsCode(ins, fmt);
9530 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9531 code |= insEncodeDatasize(id->idOpSize()); // X
9532 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9533 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9534 dst += emitOutput_Instr(dst, code);
9537 case IF_DR_1D: // DR_1D X............... cccc.......ddddd Rd cond
9538 imm = emitGetInsSC(id);
9539 assert(isValidImmCond(imm));
9542 cfi.immCFVal = (unsigned)imm;
9543 code = emitInsCode(ins, fmt);
9544 code |= insEncodeDatasize(id->idOpSize()); // X
9545 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9546 code |= insEncodeInvertedCond(cfi.cond); // cccc
9547 dst += emitOutput_Instr(dst, code);
9551 case IF_DR_2A: // DR_2A X..........mmmmm ......nnnnn..... Rn Rm
9552 assert(insOptsNone(id->idInsOpt()));
9553 code = emitInsCode(ins, fmt);
9554 code |= insEncodeDatasize(id->idOpSize()); // X
9555 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9556 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9557 dst += emitOutput_Instr(dst, code);
9560 case IF_DR_2B: // DR_2B X.......sh.mmmmm ssssssnnnnn..... Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
9561 code = emitInsCode(ins, fmt);
9562 imm = emitGetInsSC(id);
9563 assert(isValidImmShift(imm, id->idOpSize()));
9564 code |= insEncodeDatasize(id->idOpSize()); // X
9565 code |= insEncodeShiftType(id->idInsOpt()); // sh
9566 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9567 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9568 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9569 dst += emitOutput_Instr(dst, code);
9572 case IF_DR_2C: // DR_2C X..........mmmmm ooosssnnnnn..... Rn Rm ext(Rm) LSL imm(0-4)
9573 code = emitInsCode(ins, fmt);
9574 imm = emitGetInsSC(id);
9575 assert((imm >= 0) && (imm <= 4)); // imm [0..4]
9576 code |= insEncodeDatasize(id->idOpSize()); // X
9577 code |= insEncodeExtend(id->idInsOpt()); // ooo
9578 code |= insEncodeExtendScale(imm); // sss
9579 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9580 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9581 dst += emitOutput_Instr(dst, code);
9584 case IF_DR_2D: // DR_2D X..........nnnnn cccc..nnnnnddddd Rd Rn cond
9585 imm = emitGetInsSC(id);
9586 assert(isValidImmCond(imm));
9589 cfi.immCFVal = (unsigned)imm;
9590 code = emitInsCode(ins, fmt);
9591 code |= insEncodeDatasize(id->idOpSize()); // X
9592 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9593 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9594 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9595 code |= insEncodeInvertedCond(cfi.cond); // cccc
9596 dst += emitOutput_Instr(dst, code);
9600 case IF_DR_2E: // DR_2E X..........mmmmm ...........ddddd Rd Rm
9601 code = emitInsCode(ins, fmt);
9602 code |= insEncodeDatasize(id->idOpSize()); // X
9603 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9604 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9605 dst += emitOutput_Instr(dst, code);
9608 case IF_DR_2F: // DR_2F X.......sh.mmmmm ssssss.....ddddd Rd Rm {LSL,LSR,ASR} imm(0-63)
9609 code = emitInsCode(ins, fmt);
9610 imm = emitGetInsSC(id);
9611 assert(isValidImmShift(imm, id->idOpSize()));
9612 code |= insEncodeDatasize(id->idOpSize()); // X
9613 code |= insEncodeShiftType(id->idInsOpt()); // sh
9614 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9615 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9616 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9617 dst += emitOutput_Instr(dst, code);
9620 case IF_DR_2G: // DR_2G X............... .....xnnnnnddddd Rd Rn
9621 code = emitInsCode(ins, fmt);
9622 code |= insEncodeDatasize(id->idOpSize()); // X
9625 if (size == EA_8BYTE)
9627 code |= 0x00000400; // x - bit at location 10
9630 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9631 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9632 dst += emitOutput_Instr(dst, code);
9635 case IF_DR_2H: // DR_2H X........X...... ......nnnnnddddd Rd Rn
9636 code = emitInsCode(ins, fmt);
9637 code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9638 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9639 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9640 dst += emitOutput_Instr(dst, code);
9643 case IF_DR_2I: // DR_2I X..........mmmmm cccc..nnnnn.nzcv Rn Rm nzcv cond
9644 imm = emitGetInsSC(id);
9645 assert(isValidImmCondFlags(imm));
9648 cfi.immCFVal = (unsigned)imm;
9649 code = emitInsCode(ins, fmt);
9650 code |= insEncodeDatasize(id->idOpSize()); // X
9651 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9652 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9653 code |= insEncodeFlags(cfi.flags); // nzcv
9654 code |= insEncodeCond(cfi.cond); // cccc
9655 dst += emitOutput_Instr(dst, code);
9659 case IF_DR_2J: // DR_2J ................ ......nnnnnddddd Sd Sn (sha1h)
9660 code = emitInsCode(ins, fmt);
9661 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9662 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9663 dst += emitOutput_Instr(dst, code);
9666 case IF_DR_3A: // DR_3A X..........mmmmm ......nnnnnmmmmm Rd Rn Rm
9667 code = emitInsCode(ins, fmt);
9668 code |= insEncodeDatasize(id->idOpSize()); // X
9669 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9670 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9671 if (id->idIsLclVar())
9673 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9677 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9679 dst += emitOutput_Instr(dst, code);
9682 case IF_DR_3B: // DR_3B X.......sh.mmmmm ssssssnnnnnddddd Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
9683 code = emitInsCode(ins, fmt);
9684 imm = emitGetInsSC(id);
9685 assert(isValidImmShift(imm, id->idOpSize()));
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 |= insEncodeShiftType(id->idInsOpt()); // sh
9691 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9692 dst += emitOutput_Instr(dst, code);
9695 case IF_DR_3C: // DR_3C X..........mmmmm ooosssnnnnnddddd Rd Rn Rm ext(Rm) LSL imm(0-4)
9696 code = emitInsCode(ins, fmt);
9697 imm = emitGetInsSC(id);
9698 assert((imm >= 0) && (imm <= 4)); // imm [0..4]
9699 code |= insEncodeDatasize(id->idOpSize()); // X
9700 code |= insEncodeExtend(id->idInsOpt()); // ooo
9701 code |= insEncodeExtendScale(imm); // sss
9702 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9703 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9704 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9705 dst += emitOutput_Instr(dst, code);
9708 case IF_DR_3D: // DR_3D X..........mmmmm cccc..nnnnnddddd Rd Rn Rm cond
9709 imm = emitGetInsSC(id);
9710 assert(isValidImmCond(imm));
9713 cfi.immCFVal = (unsigned)imm;
9714 code = emitInsCode(ins, fmt);
9715 code |= insEncodeDatasize(id->idOpSize()); // X
9716 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9717 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9718 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9719 code |= insEncodeCond(cfi.cond); // cccc
9720 dst += emitOutput_Instr(dst, code);
9724 case IF_DR_3E: // DR_3E X........X.mmmmm ssssssnnnnnddddd Rd Rn Rm imm(0-63)
9725 code = emitInsCode(ins, fmt);
9726 imm = emitGetInsSC(id);
9727 assert(isValidImmShift(imm, id->idOpSize()));
9728 code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9729 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9730 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9731 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9732 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9733 dst += emitOutput_Instr(dst, code);
9736 case IF_DR_4A: // DR_4A X..........mmmmm .aaaaannnnnmmmmm Rd Rn Rm Ra
9737 code = emitInsCode(ins, fmt);
9738 code |= insEncodeDatasize(id->idOpSize()); // X
9739 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9740 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9741 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9742 code |= insEncodeReg_Ra(id->idReg4()); // aaaaa
9743 dst += emitOutput_Instr(dst, code);
9746 case IF_DV_1A: // DV_1A .........X.iiiii iii........ddddd Vd imm8 (fmov - immediate scalar)
9747 imm = emitGetInsSC(id);
9748 elemsize = id->idOpSize();
9749 code = emitInsCode(ins, fmt);
9750 code |= insEncodeFloatElemsize(elemsize); // X
9751 code |= ((code_t)imm << 13); // iiiii iii
9752 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9753 dst += emitOutput_Instr(dst, code);
9756 case IF_DV_1B: // DV_1B .QX..........iii cmod..iiiiiddddd Vd imm8 (immediate vector)
9757 imm = emitGetInsSC(id) & 0x0ff;
9758 immShift = (emitGetInsSC(id) & 0x700) >> 8;
9759 elemsize = optGetElemsize(id->idInsOpt());
9764 cmode = 0xE; // 1110
9768 cmode |= (immShift << 1); // 10x0
9774 cmode |= (immShift << 1); // 0xx0
9784 cmode = 0xE; // 1110
9791 code = emitInsCode(ins, fmt);
9792 code |= insEncodeVectorsize(id->idOpSize()); // Q
9793 if ((ins == INS_fmov) || (ins == INS_movi))
9795 if (elemsize == EA_8BYTE)
9797 code |= 0x20000000; // X
9800 if (ins != INS_fmov)
9802 assert((cmode >= 0) && (cmode <= 0xF));
9803 code |= (cmode << 12); // cmod
9805 code |= (((code_t)imm >> 5) << 16); // iii
9806 code |= (((code_t)imm & 0x1f) << 5); // iiiii
9807 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9808 dst += emitOutput_Instr(dst, code);
9811 case IF_DV_1C: // DV_1C .........X...... ......nnnnn..... Vn #0.0 (fcmp - with zero)
9812 elemsize = id->idOpSize();
9813 code = emitInsCode(ins, fmt);
9814 code |= insEncodeFloatElemsize(elemsize); // X
9815 code |= insEncodeReg_Vn(id->idReg1()); // nnnnn
9816 dst += emitOutput_Instr(dst, code);
9819 case IF_DV_2A: // DV_2A .Q.......X...... ......nnnnnddddd Vd Vn (fabs, fcvt - vector)
9820 elemsize = optGetElemsize(id->idInsOpt());
9821 code = emitInsCode(ins, fmt);
9822 code |= insEncodeVectorsize(id->idOpSize()); // Q
9823 code |= insEncodeFloatElemsize(elemsize); // X
9824 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9825 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9826 dst += emitOutput_Instr(dst, code);
9829 case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov/smov - to general)
9830 elemsize = id->idOpSize();
9831 index = emitGetInsSC(id);
9832 datasize = (elemsize == EA_8BYTE) ? EA_16BYTE : EA_8BYTE;
9833 if (ins == INS_smov)
9835 datasize = EA_16BYTE;
9837 code = emitInsCode(ins, fmt);
9838 code |= insEncodeVectorsize(datasize); // Q
9839 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9840 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9841 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9842 dst += emitOutput_Instr(dst, code);
9845 case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
9848 datasize = id->idOpSize();
9849 elemsize = optGetElemsize(id->idInsOpt());
9854 datasize = EA_16BYTE;
9855 elemsize = id->idOpSize();
9856 index = emitGetInsSC(id);
9858 code = emitInsCode(ins, fmt);
9859 code |= insEncodeVectorsize(datasize); // Q
9860 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9861 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9862 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9863 dst += emitOutput_Instr(dst, code);
9866 case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
9867 index = emitGetInsSC(id);
9868 elemsize = optGetElemsize(id->idInsOpt());
9869 code = emitInsCode(ins, fmt);
9870 code |= insEncodeVectorsize(id->idOpSize()); // Q
9871 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9872 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9873 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9874 dst += emitOutput_Instr(dst, code);
9877 case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
9878 index = emitGetInsSC(id);
9879 elemsize = id->idOpSize();
9880 code = emitInsCode(ins, fmt);
9881 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9882 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9883 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9884 dst += emitOutput_Instr(dst, code);
9887 case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
9888 elemsize = id->idOpSize();
9889 imm = emitGetInsSC(id);
9890 index = (imm >> 4) & 0xf;
9892 code = emitInsCode(ins, fmt);
9893 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9894 code |= insEncodeVectorIndex2(elemsize, index2); // jjjj
9895 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9896 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9897 dst += emitOutput_Instr(dst, code);
9900 case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov,fcvtXX - register)
9901 elemsize = id->idOpSize();
9902 code = emitInsCode(ins, fmt);
9903 code |= insEncodeFloatElemsize(elemsize); // X
9904 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9905 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9906 dst += emitOutput_Instr(dst, code);
9909 case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov - to general)
9910 elemsize = id->idOpSize();
9911 code = emitInsCode(ins, fmt);
9912 code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X X
9913 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9914 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9915 dst += emitOutput_Instr(dst, code);
9918 case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov - from general)
9919 elemsize = id->idOpSize();
9920 code = emitInsCode(ins, fmt);
9921 code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X X
9922 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9923 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9924 dst += emitOutput_Instr(dst, code);
9927 case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
9928 code = emitInsCode(ins, fmt);
9929 code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // SS DD
9930 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9931 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9932 dst += emitOutput_Instr(dst, code);
9935 case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
9936 elemsize = id->idOpSize();
9937 code = emitInsCode(ins, fmt);
9938 code |= insEncodeFloatElemsize(elemsize); // X
9939 code |= insEncodeReg_Vn(id->idReg1()); // nnnnn
9940 code |= insEncodeReg_Vm(id->idReg2()); // mmmmm
9941 dst += emitOutput_Instr(dst, code);
9944 case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
9945 elemsize = id->idOpSize();
9946 code = emitInsCode(ins, fmt);
9947 code |= insEncodeElemsize(elemsize); // XX
9948 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9949 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9950 dst += emitOutput_Instr(dst, code);
9953 case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
9954 elemsize = optGetElemsize(id->idInsOpt());
9955 code = emitInsCode(ins, fmt);
9956 code |= insEncodeVectorsize(id->idOpSize()); // Q
9957 code |= insEncodeElemsize(elemsize); // XX
9958 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9959 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9960 dst += emitOutput_Instr(dst, code);
9963 case IF_DV_2N: // DV_2N .........iiiiiii ......nnnnnddddd Vd Vn imm (shift - scalar)
9964 imm = emitGetInsSC(id);
9965 code = emitInsCode(ins, fmt);
9966 code |= insEncodeVectorShift(EA_8BYTE, imm); // iiiiiii
9967 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9968 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9969 dst += emitOutput_Instr(dst, code);
9972 case IF_DV_2O: // DV_2O .Q.......iiiiiii ......nnnnnddddd Vd Vn imm (shift - vector)
9973 imm = emitGetInsSC(id);
9974 elemsize = optGetElemsize(id->idInsOpt());
9975 code = emitInsCode(ins, fmt);
9976 code |= insEncodeVectorsize(id->idOpSize()); // Q
9977 code |= insEncodeVectorShift(elemsize, imm); // iiiiiii
9978 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9979 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9980 dst += emitOutput_Instr(dst, code);
9983 case IF_DV_2P: // DV_2P ............... ......nnnnnddddd Vd Vn (aes*, sha1su1)
9984 elemsize = optGetElemsize(id->idInsOpt());
9985 code = emitInsCode(ins, fmt);
9986 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9987 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9988 dst += emitOutput_Instr(dst, code);
9991 case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
9992 code = emitInsCode(ins, fmt);
9993 elemsize = optGetElemsize(id->idInsOpt());
9994 code |= insEncodeVectorsize(id->idOpSize()); // Q
9995 code |= insEncodeElemsize(elemsize); // XX
9996 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9997 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9998 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9999 dst += emitOutput_Instr(dst, code);
10002 case IF_DV_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector)
10003 code = emitInsCode(ins, fmt);
10004 imm = emitGetInsSC(id);
10005 elemsize = optGetElemsize(id->idInsOpt());
10006 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
10007 code |= insEncodeVectorsize(id->idOpSize()); // Q
10008 code |= insEncodeElemsize(elemsize); // XX
10009 code |= insEncodeVectorIndexLMH(elemsize, imm); // LM H
10010 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
10011 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
10012 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
10013 dst += emitOutput_Instr(dst, code);
10016 case IF_DV_3B: // DV_3B .Q.......X.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
10017 code = emitInsCode(ins, fmt);
10018 elemsize = optGetElemsize(id->idInsOpt());
10019 code |= insEncodeVectorsize(id->idOpSize()); // Q
10020 code |= insEncodeFloatElemsize(elemsize); // X
10021 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
10022 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
10023 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
10024 dst += emitOutput_Instr(dst, code);
10027 case IF_DV_3BI: // DV_3BI .Q.......XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
10028 code = emitInsCode(ins, fmt);
10029 imm = emitGetInsSC(id);
10030 elemsize = optGetElemsize(id->idInsOpt());
10031 assert(isValidVectorIndex(id->idOpSize(), elemsize, imm));
10032 code |= insEncodeVectorsize(id->idOpSize()); // Q
10033 code |= insEncodeFloatElemsize(elemsize); // X
10034 code |= insEncodeFloatIndex(elemsize, imm); // L H
10035 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
10036 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
10037 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
10038 dst += emitOutput_Instr(dst, code);
10041 case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
10042 code = emitInsCode(ins, fmt);
10043 code |= insEncodeVectorsize(id->idOpSize()); // Q
10044 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
10045 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
10046 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
10047 dst += emitOutput_Instr(dst, code);
10050 case IF_DV_3D: // DV_3D .........X.mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
10051 code = emitInsCode(ins, fmt);
10052 code |= insEncodeFloatElemsize(id->idOpSize()); // X
10053 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
10054 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
10055 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
10056 dst += emitOutput_Instr(dst, code);
10059 case IF_DV_3DI: // DV_3DI .........XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (scalar by elem)
10060 code = emitInsCode(ins, fmt);
10061 imm = emitGetInsSC(id);
10062 elemsize = id->idOpSize();
10063 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
10064 code |= insEncodeFloatElemsize(elemsize); // X
10065 code |= insEncodeFloatIndex(elemsize, imm); // L H
10066 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
10067 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
10068 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
10069 dst += emitOutput_Instr(dst, code);
10072 case IF_DV_3E: // DV_3E ...........mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
10073 case IF_DV_3F: // DV_3F ...........mmmmm ......nnnnnddddd Vd Vn Vm (vector) - source dest regs overlap
10074 code = emitInsCode(ins, fmt);
10075 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
10076 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
10077 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
10078 dst += emitOutput_Instr(dst, code);
10081 case IF_DV_4A: // DV_4A .........X.mmmmm .aaaaannnnnddddd Vd Va Vn Vm (scalar)
10082 code = emitInsCode(ins, fmt);
10083 elemsize = id->idOpSize();
10084 code |= insEncodeFloatElemsize(elemsize); // X
10085 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
10086 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
10087 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
10088 code |= insEncodeReg_Va(id->idReg4()); // aaaaa
10089 dst += emitOutput_Instr(dst, code);
10092 case IF_SN_0A: // SN_0A ................ ................
10093 code = emitInsCode(ins, fmt);
10094 dst += emitOutput_Instr(dst, code);
10097 case IF_SI_0A: // SI_0A ...........iiiii iiiiiiiiiii..... imm16
10098 imm = emitGetInsSC(id);
10099 assert(isValidUimm16(imm));
10100 code = emitInsCode(ins, fmt);
10101 code |= ((code_t)imm << 5); // iiiii iiiiiiiiiii
10102 dst += emitOutput_Instr(dst, code);
10105 case IF_SI_0B: // SI_0B ................ ....bbbb........ imm4 - barrier
10106 imm = emitGetInsSC(id);
10107 assert((imm >= 0) && (imm <= 15));
10108 code = emitInsCode(ins, fmt);
10109 code |= ((code_t)imm << 8); // bbbb
10110 dst += emitOutput_Instr(dst, code);
10114 assert(!"Unexpected format");
10118 // Determine if any registers now hold GC refs, or whether a register that was overwritten held a GC ref.
10119 // We assume here that "id->idGCref()" is not GC_NONE only if the instruction described by "id" writes a
10120 // GC ref to register "id->idReg1()". (It may, apparently, also not be GC_NONE in other cases, such as
10121 // for stores, but we ignore those cases here.)
10122 if (emitInsMayWriteToGCReg(id)) // True if "id->idIns()" writes to a register than can hold GC ref.
10124 // We assume that "idReg1" is the primary destination register for all instructions
10125 if (id->idGCref() != GCT_NONE)
10127 emitGCregLiveUpd(id->idGCref(), id->idReg1(), dst);
10131 emitGCregDeadUpd(id->idReg1(), dst);
10134 if (emitInsMayWriteMultipleRegs(id))
10137 // "idReg2" is the secondary destination register
10138 if (id->idGCrefReg2() != GCT_NONE)
10140 emitGCregLiveUpd(id->idGCrefReg2(), id->idReg2(), dst);
10144 emitGCregDeadUpd(id->idReg2(), dst);
10149 // Now we determine if the instruction has written to a (local variable) stack location, and either written a GC
10150 // ref or overwritten one.
10151 if (emitInsWritesToLclVarStackLoc(id) || emitInsWritesToLclVarStackLocPair(id))
10153 int varNum = id->idAddr()->iiaLclVar.lvaVarNum();
10154 unsigned ofs = AlignDown(id->idAddr()->iiaLclVar.lvaOffset(), TARGET_POINTER_SIZE);
10156 int adr = emitComp->lvaFrameAddress(varNum, &FPbased);
10157 if (id->idGCref() != GCT_NONE)
10159 emitGCvarLiveUpd(adr + ofs, varNum, id->idGCref(), dst);
10163 // If the type of the local is a gc ref type, update the liveness.
10167 // "Regular" (non-spill-temp) local.
10168 vt = var_types(emitComp->lvaTable[varNum].lvType);
10172 TempDsc* tmpDsc = emitComp->tmpFindNum(varNum);
10173 vt = tmpDsc->tdTempType();
10175 if (vt == TYP_REF || vt == TYP_BYREF)
10176 emitGCvarDeadUpd(adr + ofs, dst);
10178 if (emitInsWritesToLclVarStackLocPair(id))
10180 unsigned ofs2 = ofs + TARGET_POINTER_SIZE;
10181 if (id->idGCrefReg2() != GCT_NONE)
10183 emitGCvarLiveUpd(adr + ofs2, varNum, id->idGCrefReg2(), dst);
10187 // If the type of the local is a gc ref type, update the liveness.
10191 // "Regular" (non-spill-temp) local.
10192 vt = var_types(emitComp->lvaTable[varNum].lvType);
10196 TempDsc* tmpDsc = emitComp->tmpFindNum(varNum);
10197 vt = tmpDsc->tdTempType();
10199 if (vt == TYP_REF || vt == TYP_BYREF)
10200 emitGCvarDeadUpd(adr + ofs2, dst);
10206 /* Make sure we set the instruction descriptor size correctly */
10208 size_t expected = emitSizeOfInsDsc(id);
10209 assert(sz == expected);
10211 if (emitComp->opts.disAsm || emitComp->opts.dspEmit || emitComp->verbose)
10213 emitDispIns(id, false, dspOffs, true, emitCurCodeOffs(odst), *dp, (dst - *dp), ig);
10216 if (emitComp->compDebugBreak)
10218 // For example, set JitBreakEmitOutputInstr=a6 will break when this method is called for
10219 // emitting instruction a6, (i.e. IN00a6 in jitdump).
10220 if ((unsigned)JitConfig.JitBreakEmitOutputInstr() == id->idDebugOnlyInfo()->idNum)
10222 assert(!"JitBreakEmitOutputInstr reached");
10227 /* All instructions are expected to generate code */
10229 assert(*dp != dst);
10236 /*****************************************************************************/
10237 /*****************************************************************************/
10241 /*****************************************************************************
10243 * Display the instruction name
10245 void emitter::emitDispInst(instruction ins)
10247 const char* insstr = codeGen->genInsName(ins);
10248 size_t len = strlen(insstr);
10250 /* Display the instruction name */
10252 printf("%s", insstr);
10255 // Add at least one space after the instruction name
10256 // and add spaces until we have reach the normal size of 8
10264 /*****************************************************************************
10266 * Display an reloc value
10267 * If we are formatting for an assembly listing don't print the hex value
10268 * since it will prevent us from doing assembly diffs
10270 void emitter::emitDispReloc(int value, bool addComma)
10272 if (emitComp->opts.disAsm)
10278 printf("(reloc 0x%x)", dspPtr(value));
10285 /*****************************************************************************
10287 * Display an immediate value
10289 void emitter::emitDispImm(ssize_t imm, bool addComma, bool alwaysHex /* =false */)
10296 // Munge any pointers if we want diff-able disassembly.
10297 // Since some may be emitted as partial words, print as diffable anything that has
10298 // significant bits beyond the lowest 8-bits.
10299 if (emitComp->opts.disDiffable)
10301 ssize_t top56bits = (imm >> 8);
10302 if ((top56bits != 0) && (top56bits != -1))
10306 if (!alwaysHex && (imm > -1000) && (imm < 1000))
10312 if ((imm < 0) && ((imm & 0xFFFFFFFF00000000LL) == 0xFFFFFFFF00000000LL))
10318 if ((imm & 0xFFFFFFFF00000000LL) != 0)
10320 printf("0x%llx", imm);
10324 printf("0x%02x", imm);
10332 /*****************************************************************************
10334 * Display a float zero constant
10336 void emitter::emitDispFloatZero()
10345 /*****************************************************************************
10347 * Display an encoded float constant value
10349 void emitter::emitDispFloatImm(ssize_t imm8)
10351 assert((0 <= imm8) && (imm8 <= 0x0ff));
10358 fpImm.immFPIVal = (unsigned)imm8;
10359 double result = emitDecodeFloatImm8(fpImm);
10361 printf("%.4f", result);
10364 /*****************************************************************************
10366 * Display an immediate that is optionally LSL12.
10368 void emitter::emitDispImmOptsLSL12(ssize_t imm, insOpts opt)
10370 if (!strictArmAsm && insOptsLSL12(opt))
10374 emitDispImm(imm, false);
10375 if (strictArmAsm && insOptsLSL12(opt))
10377 printf(", LSL #12");
10381 /*****************************************************************************
10383 * Display an ARM64 condition code for the conditional instructions
10385 void emitter::emitDispCond(insCond cond)
10387 const static char* armCond[16] = {"eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc",
10388 "hi", "ls", "ge", "lt", "gt", "le", "AL", "NV"}; // The last two are invalid
10389 unsigned imm = (unsigned)cond;
10390 assert((0 <= imm) && (imm < ArrLen(armCond)));
10391 printf(armCond[imm]);
10394 /*****************************************************************************
10396 * Display an ARM64 flags for the conditional instructions
10398 void emitter::emitDispFlags(insCflags flags)
10400 const static char* armFlags[16] = {"0", "v", "c", "cv", "z", "zv", "zc", "zcv",
10401 "n", "nv", "nc", "ncv", "nz", "nzv", "nzc", "nzcv"};
10402 unsigned imm = (unsigned)flags;
10403 assert((0 <= imm) && (imm < ArrLen(armFlags)));
10404 printf(armFlags[imm]);
10407 /*****************************************************************************
10409 * Display an ARM64 'barrier' for the memory barrier instructions
10411 void emitter::emitDispBarrier(insBarrier barrier)
10413 const static char* armBarriers[16] = {"#0", "oshld", "oshst", "osh", "#4", "nshld", "nshst", "nsh",
10414 "#8", "ishld", "ishst", "ish", "#12", "ld", "st", "sy"};
10415 unsigned imm = (unsigned)barrier;
10416 assert((0 <= imm) && (imm < ArrLen(armBarriers)));
10417 printf(armBarriers[imm]);
10420 /*****************************************************************************
10422 * Prints the encoding for the Shift Type encoding
10425 void emitter::emitDispShiftOpts(insOpts opt)
10427 if (opt == INS_OPTS_LSL)
10429 else if (opt == INS_OPTS_LSR)
10431 else if (opt == INS_OPTS_ASR)
10433 else if (opt == INS_OPTS_ROR)
10435 else if (opt == INS_OPTS_MSL)
10438 assert(!"Bad value");
10441 /*****************************************************************************
10443 * Prints the encoding for the Extend Type encoding
10446 void emitter::emitDispExtendOpts(insOpts opt)
10448 if (opt == INS_OPTS_UXTB)
10450 else if (opt == INS_OPTS_UXTH)
10452 else if (opt == INS_OPTS_UXTW)
10454 else if (opt == INS_OPTS_UXTX)
10456 else if (opt == INS_OPTS_SXTB)
10458 else if (opt == INS_OPTS_SXTH)
10460 else if (opt == INS_OPTS_SXTW)
10462 else if (opt == INS_OPTS_SXTX)
10465 assert(!"Bad value");
10468 /*****************************************************************************
10470 * Prints the encoding for the Extend Type encoding in loads/stores
10473 void emitter::emitDispLSExtendOpts(insOpts opt)
10475 if (opt == INS_OPTS_LSL)
10477 else if (opt == INS_OPTS_UXTW)
10479 else if (opt == INS_OPTS_UXTX)
10481 else if (opt == INS_OPTS_SXTW)
10483 else if (opt == INS_OPTS_SXTX)
10486 assert(!"Bad value");
10489 /*****************************************************************************
10491 * Display a register
10493 void emitter::emitDispReg(regNumber reg, emitAttr attr, bool addComma)
10495 emitAttr size = EA_SIZE(attr);
10496 printf(emitRegName(reg, size));
10502 /*****************************************************************************
10504 * Display a vector register with an arrangement suffix
10506 void emitter::emitDispVectorReg(regNumber reg, insOpts opt, bool addComma)
10508 assert(isVectorRegister(reg));
10509 printf(emitVectorRegName(reg));
10510 emitDispArrangement(opt);
10516 /*****************************************************************************
10518 * Display an vector register index suffix
10520 void emitter::emitDispVectorRegIndex(regNumber reg, emitAttr elemsize, ssize_t index, bool addComma)
10522 assert(isVectorRegister(reg));
10523 printf(emitVectorRegName(reg));
10540 assert(!"invalid elemsize");
10544 printf("[%d]", index);
10550 /*****************************************************************************
10552 * Display an arrangement suffix
10554 void emitter::emitDispArrangement(insOpts opt)
10556 const char* str = "???";
10586 assert(!"Invalid insOpt for vector register");
10592 /*****************************************************************************
10594 * Display a register with an optional shift operation
10596 void emitter::emitDispShiftedReg(regNumber reg, insOpts opt, ssize_t imm, emitAttr attr)
10598 emitAttr size = EA_SIZE(attr);
10599 assert((imm & 0x003F) == imm);
10600 assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
10602 printf(emitRegName(reg, size));
10610 emitDispShiftOpts(opt);
10611 emitDispImm(imm, false);
10615 /*****************************************************************************
10617 * Display a register with an optional extend and scale operations
10619 void emitter::emitDispExtendReg(regNumber reg, insOpts opt, ssize_t imm)
10621 assert((imm >= 0) && (imm <= 4));
10622 assert(insOptsNone(opt) || insOptsAnyExtend(opt) || (opt == INS_OPTS_LSL));
10624 // size is based on the extend option, not the instr size.
10625 emitAttr size = insOpts32BitExtend(opt) ? EA_4BYTE : EA_8BYTE;
10629 if (insOptsNone(opt))
10631 emitDispReg(reg, size, false);
10635 emitDispReg(reg, size, true);
10636 if (opt == INS_OPTS_LSL)
10639 emitDispExtendOpts(opt);
10640 if ((imm > 0) || (opt == INS_OPTS_LSL))
10643 emitDispImm(imm, false);
10647 else // !strictArmAsm
10649 if (insOptsNone(opt))
10651 emitDispReg(reg, size, false);
10655 if (opt != INS_OPTS_LSL)
10657 emitDispExtendOpts(opt);
10659 emitDispReg(reg, size, false);
10666 emitDispImm(1 << imm, false);
10671 /*****************************************************************************
10673 * Display an addressing operand [reg + imm]
10675 void emitter::emitDispAddrRI(regNumber reg, insOpts opt, ssize_t imm)
10677 reg = encodingZRtoSP(reg); // ZR (R31) encodes the SP register
10683 emitDispReg(reg, EA_8BYTE, false);
10685 if (!insOptsPostIndex(opt) && (imm != 0))
10688 emitDispImm(imm, false);
10692 if (insOptsPreIndex(opt))
10696 else if (insOptsPostIndex(opt))
10699 emitDispImm(imm, false);
10702 else // !strictArmAsm
10706 const char* operStr = "++";
10713 if (insOptsPreIndex(opt))
10718 emitDispReg(reg, EA_8BYTE, false);
10720 if (insOptsPostIndex(opt))
10725 if (insOptsIndexed(opt))
10731 printf("%c", operStr[1]);
10733 emitDispImm(imm, false);
10738 /*****************************************************************************
10740 * Display an addressing operand [reg + extended reg]
10742 void emitter::emitDispAddrRRExt(regNumber reg1, regNumber reg2, insOpts opt, bool isScaled, emitAttr size)
10744 reg1 = encodingZRtoSP(reg1); // ZR (R31) encodes the SP register
10746 unsigned scale = 0;
10749 scale = NaturalScale_helper(size);
10756 emitDispReg(reg1, EA_8BYTE, true);
10757 emitDispExtendReg(reg2, opt, scale);
10759 else // !strictArmAsm
10761 emitDispReg(reg1, EA_8BYTE, false);
10763 emitDispExtendReg(reg2, opt, scale);
10769 /*****************************************************************************
10771 * Display (optionally) the instruction encoding in hex
10774 void emitter::emitDispInsHex(BYTE* code, size_t sz)
10776 // We do not display the instruction hex if we want diff-able disassembly
10777 if (!emitComp->opts.disDiffable)
10781 printf(" %08X ", (*((code_t*)code)));
10790 /****************************************************************************
10792 * Display the given instruction.
10795 void emitter::emitDispIns(
10796 instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* pCode, size_t sz, insGroup* ig)
10801 id->idDebugOnlyInfo()->idNum; // Do not remove this! It is needed for VisualStudio conditional breakpoints
10803 printf("IN%04x: ", idNum);
10809 if (!emitComp->opts.dspEmit && !isNew && !asmfm && sz)
10812 /* Display the instruction offset */
10814 emitDispInsOffs(offset, doffs);
10816 /* Display the instruction hex code */
10818 emitDispInsHex(pCode, sz);
10822 /* Get the instruction and format */
10824 instruction ins = id->idIns();
10825 insFormat fmt = id->idInsFmt();
10829 /* If this instruction has just been added, check its size */
10831 assert(isNew == false || (int)emitSizeOfInsDsc(id) == emitCurIGfreeNext - (BYTE*)id);
10833 /* Figure out the operand size */
10834 emitAttr size = id->idOpSize();
10835 emitAttr attr = size;
10836 if (id->idGCref() == GCT_GCREF)
10838 else if (id->idGCref() == GCT_BYREF)
10846 bool isExtendAlias;
10855 const char* methodName;
10863 case IF_BI_0A: // BI_0A ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
10864 case IF_BI_0B: // BI_0B ......iiiiiiiiii iiiiiiiiiii..... simm19:00
10867 if (fmt == IF_LARGEJMP)
10869 printf("(LARGEJMP)");
10871 if (id->idAddr()->iiaHasInstrCount())
10873 int instrCount = id->idAddr()->iiaGetInstrCount();
10877 printf("pc%s%d instructions", (instrCount >= 0) ? "+" : "", instrCount);
10881 unsigned insNum = emitFindInsNum(ig, id);
10882 UNATIVE_OFFSET srcOffs = ig->igOffs + emitFindOffset(ig, insNum + 1);
10883 UNATIVE_OFFSET dstOffs = ig->igOffs + emitFindOffset(ig, insNum + 1 + instrCount);
10884 ssize_t relOffs = (ssize_t)(emitOffsetToPtr(dstOffs) - emitOffsetToPtr(srcOffs));
10885 printf("pc%s%d (%d instructions)", (relOffs >= 0) ? "+" : "", relOffs, instrCount);
10888 else if (id->idIsBound())
10890 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10894 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10899 case IF_BI_0C: // BI_0C ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
10900 if (id->idIsCallAddr())
10902 offs = (ssize_t)id->idAddr()->iiaAddr;
10908 methodName = emitComp->eeGetMethodFullName((CORINFO_METHOD_HANDLE)id->idDebugOnlyInfo()->idMemCookie);
10913 if (id->idIsDspReloc())
10915 printf("%08X", offs);
10919 printf("%s", methodName);
10923 case IF_BI_1A: // BI_1A ......iiiiiiiiii iiiiiiiiiiittttt Rt simm19:00
10924 assert(insOptsNone(id->idInsOpt()));
10925 emitDispReg(id->idReg1(), size, true);
10926 if (id->idIsBound())
10928 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10932 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10936 case IF_BI_1B: // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
10937 assert(insOptsNone(id->idInsOpt()));
10938 emitDispReg(id->idReg1(), size, true);
10939 emitDispImm(emitGetInsSC(id), true);
10940 if (id->idIsBound())
10942 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10946 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10950 case IF_BR_1A: // BR_1A ................ ......nnnnn..... Rn
10951 assert(insOptsNone(id->idInsOpt()));
10952 emitDispReg(id->idReg1(), size, false);
10955 case IF_BR_1B: // BR_1B ................ ......nnnnn..... Rn
10956 assert(insOptsNone(id->idInsOpt()));
10957 emitDispReg(id->idReg3(), size, false);
10960 case IF_LS_1A: // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB)
10961 case IF_DI_1E: // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
10964 assert(insOptsNone(id->idInsOpt()));
10965 emitDispReg(id->idReg1(), size, true);
10966 imm = emitGetInsSC(id);
10968 /* Is this actually a reference to a data section? */
10969 if (fmt == IF_LARGEADR)
10971 printf("(LARGEADR)");
10973 else if (fmt == IF_LARGELDC)
10975 printf("(LARGELDC)");
10979 if (id->idAddr()->iiaIsJitDataOffset())
10981 doffs = Compiler::eeGetJitDataOffs(id->idAddr()->iiaFieldHnd);
10982 /* Display a data section reference */
10985 printf("@CNS%02u", doffs - 1);
10987 printf("@RWD%02u", doffs);
10990 printf("%+Id", imm);
10995 if (id->idIsReloc())
10998 emitDispImm((ssize_t)id->idAddr()->iiaAddr, false);
11000 else if (id->idIsBound())
11002 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
11006 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
11012 case IF_LS_2A: // LS_2A .X.......X...... ......nnnnnttttt Rt Rn
11013 assert(insOptsNone(id->idInsOpt()));
11014 assert(emitGetInsSC(id) == 0);
11015 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
11016 emitDispAddrRI(id->idReg2(), id->idInsOpt(), 0);
11019 case IF_LS_2B: // LS_2B .X.......Xiiiiii iiiiiinnnnnttttt Rt Rn imm(0-4095)
11020 assert(insOptsNone(id->idInsOpt()));
11021 imm = emitGetInsSC(id);
11022 scale = NaturalScale_helper(emitInsLoadStoreSize(id));
11023 imm <<= scale; // The immediate is scaled by the size of the ld/st
11024 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
11025 emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
11028 case IF_LS_2C: // LS_2C .X.......X.iiiii iiiiPPnnnnnttttt Rt Rn imm(-256..+255) no/pre/post inc
11029 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
11030 imm = emitGetInsSC(id);
11031 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
11032 emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
11035 case IF_LS_3A: // LS_3A .X.......X.mmmmm oooS..nnnnnttttt Rt Rn Rm ext(Rm) LSL {}
11036 assert(insOptsLSExtend(id->idInsOpt()));
11037 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
11038 if (id->idIsLclVar())
11040 emitDispAddrRRExt(id->idReg2(), codeGen->rsGetRsvdReg(), id->idInsOpt(), false, size);
11044 emitDispAddrRRExt(id->idReg2(), id->idReg3(), id->idInsOpt(), id->idReg3Scaled(), size);
11048 case IF_LS_3B: // LS_3B X............... .aaaaannnnnddddd Rt Ra Rn
11049 assert(insOptsNone(id->idInsOpt()));
11050 assert(emitGetInsSC(id) == 0);
11051 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
11052 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
11053 emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
11056 case IF_LS_3C: // LS_3C X.........iiiiii iaaaaannnnnddddd Rt Ra Rn imm(im7,sh)
11057 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
11058 imm = emitGetInsSC(id);
11059 scale = NaturalScale_helper(emitInsLoadStoreSize(id));
11061 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
11062 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
11063 emitDispAddrRI(id->idReg3(), id->idInsOpt(), imm);
11066 case IF_LS_3D: // LS_3D .X.......X.mmmmm ......nnnnnttttt Wm Rt Rn
11067 assert(insOptsNone(id->idInsOpt()));
11068 emitDispReg(id->idReg1(), EA_4BYTE, true);
11069 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
11070 emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
11073 case IF_LS_3E: // LS_3E .X.........mmmmm ......nnnnnttttt Rm Rt Rn ARMv8.1 LSE Atomics
11074 assert(insOptsNone(id->idInsOpt()));
11075 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
11076 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
11077 emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
11080 case IF_DI_1A: // DI_1A X.......shiiiiii iiiiiinnnnn..... Rn imm(i12,sh)
11081 emitDispReg(id->idReg1(), size, true);
11082 emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
11085 case IF_DI_1B: // DI_1B X........hwiiiii iiiiiiiiiiiddddd Rd imm(i16,hw)
11086 emitDispReg(id->idReg1(), size, true);
11087 hwi.immHWVal = (unsigned)emitGetInsSC(id);
11088 if (ins == INS_mov)
11090 emitDispImm(emitDecodeHalfwordImm(hwi, size), false);
11092 else // movz, movn, movk
11094 emitDispImm(hwi.immVal, false);
11095 if (hwi.immHW != 0)
11097 emitDispShiftOpts(INS_OPTS_LSL);
11098 emitDispImm(hwi.immHW * 16, false);
11103 case IF_DI_1C: // DI_1C X........Nrrrrrr ssssssnnnnn..... Rn imm(N,r,s)
11104 emitDispReg(id->idReg1(), size, true);
11105 bmi.immNRS = (unsigned)emitGetInsSC(id);
11106 emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
11109 case IF_DI_1D: // DI_1D X........Nrrrrrr ssssss.....ddddd Rd imm(N,r,s)
11110 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11111 bmi.immNRS = (unsigned)emitGetInsSC(id);
11112 emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
11115 case IF_DI_2A: // DI_2A X.......shiiiiii iiiiiinnnnnddddd Rd Rn imm(i12,sh)
11116 if ((ins == INS_add) || (ins == INS_sub))
11118 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11119 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11123 emitDispReg(id->idReg1(), size, true);
11124 emitDispReg(id->idReg2(), size, true);
11126 emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
11129 case IF_DI_2B: // DI_2B X........X.nnnnn ssssssnnnnnddddd Rd Rn imm(0-63)
11130 emitDispReg(id->idReg1(), size, true);
11131 emitDispReg(id->idReg2(), size, true);
11132 emitDispImm(emitGetInsSC(id), false);
11135 case IF_DI_2C: // DI_2C X........Nrrrrrr ssssssnnnnnddddd Rd Rn imm(N,r,s)
11136 if (ins == INS_ands)
11138 emitDispReg(id->idReg1(), size, true);
11142 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11144 emitDispReg(id->idReg2(), size, true);
11145 bmi.immNRS = (unsigned)emitGetInsSC(id);
11146 emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
11149 case IF_DI_2D: // DI_2D X........Nrrrrrr ssssssnnnnnddddd Rd Rn imr, ims (N,r,s)
11150 emitDispReg(id->idReg1(), size, true);
11151 emitDispReg(id->idReg2(), size, true);
11153 imm = emitGetInsSC(id);
11154 bmi.immNRS = (unsigned)imm;
11161 emitDispImm(bmi.immR, true);
11162 emitDispImm(bmi.immS, false);
11168 emitDispImm(getBitWidth(size) - bmi.immR, true);
11169 emitDispImm(bmi.immS + 1, false);
11175 emitDispImm(bmi.immR, true);
11176 emitDispImm(bmi.immS - bmi.immR + 1, false);
11182 emitDispImm(imm, false);
11186 assert(!"Unexpected instruction in IF_DI_2D");
11191 case IF_DI_1F: // DI_1F X..........iiiii cccc..nnnnn.nzcv Rn imm5 nzcv cond
11192 emitDispReg(id->idReg1(), size, true);
11193 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11194 emitDispImm(cfi.imm5, true);
11195 emitDispFlags(cfi.flags);
11197 emitDispCond(cfi.cond);
11200 case IF_DR_1D: // DR_1D X............... cccc.......mmmmm Rd cond
11201 emitDispReg(id->idReg1(), size, true);
11202 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11203 emitDispCond(cfi.cond);
11206 case IF_DR_2A: // DR_2A X..........mmmmm ......nnnnn..... Rn Rm
11207 emitDispReg(id->idReg1(), size, true);
11208 emitDispReg(id->idReg2(), size, false);
11211 case IF_DR_2B: // DR_2B X.......sh.mmmmm ssssssnnnnn..... Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
11212 emitDispReg(id->idReg1(), size, true);
11213 emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
11216 case IF_DR_2C: // DR_2C X..........mmmmm ooosssnnnnn..... Rn Rm ext(Rm) LSL imm(0-4)
11217 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11218 imm = emitGetInsSC(id);
11219 emitDispExtendReg(id->idReg2(), id->idInsOpt(), imm);
11222 case IF_DR_2D: // DR_2D X..........nnnnn cccc..nnnnnddddd Rd Rn cond
11223 emitDispReg(id->idReg1(), size, true);
11224 emitDispReg(id->idReg2(), size, true);
11225 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11226 emitDispCond(cfi.cond);
11229 case IF_DR_2E: // DR_2E X..........mmmmm ...........ddddd Rd Rm
11230 case IF_DR_2J: // DR_2J ................ ......nnnnnddddd Sd Sn
11231 emitDispReg(id->idReg1(), size, true);
11232 emitDispReg(id->idReg2(), size, false);
11235 case IF_DR_2F: // DR_2F X.......sh.mmmmm ssssss.....ddddd Rd Rm {LSL,LSR,ASR} imm(0-63)
11236 emitDispReg(id->idReg1(), size, true);
11237 emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
11240 case IF_DR_2G: // DR_2G X............... ......nnnnnddddd Rd Rn
11241 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11242 emitDispReg(encodingZRtoSP(id->idReg2()), size, false);
11245 case IF_DR_2H: // DR_2H X........X...... ......nnnnnddddd Rd Rn
11246 emitDispReg(id->idReg1(), size, true);
11247 emitDispReg(id->idReg2(), size, false);
11250 case IF_DR_2I: // DR_2I X..........mmmmm cccc..nnnnn.nzcv Rn Rm nzcv cond
11251 emitDispReg(id->idReg1(), size, true);
11252 emitDispReg(id->idReg2(), size, true);
11253 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11254 emitDispFlags(cfi.flags);
11256 emitDispCond(cfi.cond);
11259 case IF_DR_3A: // DR_3A X..........mmmmm ......nnnnnmmmmm Rd Rn Rm
11260 if ((ins == INS_add) || (ins == INS_sub))
11262 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11263 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11265 else if ((ins == INS_smull) || (ins == INS_smulh))
11267 // Rd is always 8 bytes
11268 emitDispReg(id->idReg1(), EA_8BYTE, true);
11270 // Rn, Rm effective size depends on instruction type
11271 size = (ins == INS_smulh) ? EA_8BYTE : EA_4BYTE;
11272 emitDispReg(id->idReg2(), size, true);
11276 emitDispReg(id->idReg1(), size, true);
11277 emitDispReg(id->idReg2(), size, true);
11279 if (id->idIsLclVar())
11281 emitDispReg(codeGen->rsGetRsvdReg(), size, false);
11285 emitDispReg(id->idReg3(), size, false);
11290 case IF_DR_3B: // DR_3B X.......sh.mmmmm ssssssnnnnnddddd Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
11291 emitDispReg(id->idReg1(), size, true);
11292 emitDispReg(id->idReg2(), size, true);
11293 emitDispShiftedReg(id->idReg3(), id->idInsOpt(), emitGetInsSC(id), size);
11296 case IF_DR_3C: // DR_3C X..........mmmmm ooosssnnnnnddddd Rd Rn Rm ext(Rm) LSL imm(0-4)
11297 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11298 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11299 imm = emitGetInsSC(id);
11300 emitDispExtendReg(id->idReg3(), id->idInsOpt(), imm);
11303 case IF_DR_3D: // DR_3D X..........mmmmm cccc..nnnnnmmmmm Rd Rn Rm cond
11304 emitDispReg(id->idReg1(), size, true);
11305 emitDispReg(id->idReg2(), size, true);
11306 emitDispReg(id->idReg3(), size, true);
11307 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11308 emitDispCond(cfi.cond);
11311 case IF_DR_3E: // DR_3E X........X.mmmmm ssssssnnnnnddddd Rd Rn Rm imm(0-63)
11312 emitDispReg(id->idReg1(), size, true);
11313 emitDispReg(id->idReg2(), size, true);
11314 emitDispReg(id->idReg3(), size, true);
11315 emitDispImm(emitGetInsSC(id), false);
11318 case IF_DR_4A: // DR_4A X..........mmmmm .aaaaannnnnmmmmm Rd Rn Rm Ra
11319 emitDispReg(id->idReg1(), size, true);
11320 emitDispReg(id->idReg2(), size, true);
11321 emitDispReg(id->idReg3(), size, true);
11322 emitDispReg(id->idReg4(), size, false);
11325 case IF_DV_1A: // DV_1A .........X.iiiii iii........ddddd Vd imm8 (fmov - immediate scalar)
11326 elemsize = id->idOpSize();
11327 emitDispReg(id->idReg1(), elemsize, true);
11328 emitDispFloatImm(emitGetInsSC(id));
11331 case IF_DV_1B: // DV_1B .QX..........iii cmod..iiiiiddddd Vd imm8 (immediate vector)
11332 imm = emitGetInsSC(id) & 0x0ff;
11333 immShift = (emitGetInsSC(id) & 0x700) >> 8;
11334 hasShift = (immShift != 0);
11335 elemsize = optGetElemsize(id->idInsOpt());
11336 if (id->idInsOpt() == INS_OPTS_1D)
11338 assert(elemsize == size);
11339 emitDispReg(id->idReg1(), size, true);
11343 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11345 if (ins == INS_fmov)
11347 emitDispFloatImm(imm);
11348 assert(hasShift == false);
11352 if (elemsize == EA_8BYTE)
11354 assert(ins == INS_movi);
11356 const ssize_t mask8 = 0xFF;
11357 for (unsigned b = 0; b < 8; b++)
11359 if (imm & (1 << b))
11361 imm64 |= (mask8 << (b * 8));
11364 emitDispImm(imm64, hasShift, true);
11368 emitDispImm(imm, hasShift, true);
11372 insOpts opt = (immShift & 0x4) ? INS_OPTS_MSL : INS_OPTS_LSL;
11373 unsigned shift = (immShift & 0x3) * 8;
11374 emitDispShiftOpts(opt);
11375 emitDispImm(shift, false);
11380 case IF_DV_1C: // DV_1C .........X...... ......nnnnn..... Vn #0.0 (fcmp - with zero)
11381 elemsize = id->idOpSize();
11382 emitDispReg(id->idReg1(), elemsize, true);
11383 emitDispFloatZero();
11386 case IF_DV_2A: // DV_2A .Q.......X...... ......nnnnnddddd Vd Vn (fabs, fcvt - vector)
11387 case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
11388 case IF_DV_2P: // DV_2P ................ ......nnnnnddddd Vd Vn (aes*, sha1su1)
11389 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11390 emitDispVectorReg(id->idReg2(), id->idInsOpt(), false);
11393 case IF_DV_2N: // DV_2N .........iiiiiii ......nnnnnddddd Vd Vn imm (shift - scalar)
11394 elemsize = id->idOpSize();
11395 emitDispReg(id->idReg1(), elemsize, true);
11396 emitDispReg(id->idReg2(), elemsize, true);
11397 emitDispImm(emitGetInsSC(id), false);
11400 case IF_DV_2O: // DV_2O .Q.......iiiiiii ......nnnnnddddd Vd Vn imm (shift - vector)
11401 imm = emitGetInsSC(id);
11402 // Do we have a sxtl or uxtl instruction?
11403 isExtendAlias = ((ins == INS_sxtl) || (ins == INS_sxtl2) || (ins == INS_uxtl) || (ins == INS_uxtl2));
11404 code = emitInsCode(ins, fmt);
11405 if (code & 0x00008000) // widen/narrow opcodes
11407 if (code & 0x00002000) // SHL opcodes
11409 emitDispVectorReg(id->idReg1(), optWidenElemsize(id->idInsOpt()), true);
11410 emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11412 else // SHR opcodes
11414 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11415 emitDispVectorReg(id->idReg2(), optWidenElemsize(id->idInsOpt()), !isExtendAlias);
11420 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11421 emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11423 // Print the immediate unless we have a sxtl or uxtl instruction
11424 if (!isExtendAlias)
11426 emitDispImm(imm, false);
11430 case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov/smov - to general)
11431 srcsize = id->idOpSize();
11432 index = emitGetInsSC(id);
11433 if (ins == INS_smov)
11435 dstsize = EA_8BYTE;
11437 else // INS_umov or INS_mov
11439 dstsize = (srcsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE;
11441 emitDispReg(id->idReg1(), dstsize, true);
11442 emitDispVectorRegIndex(id->idReg2(), srcsize, index, false);
11445 case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
11446 if (ins == INS_dup)
11448 datasize = id->idOpSize();
11449 assert(isValidVectorDatasize(datasize));
11450 assert(isValidArrangement(datasize, id->idInsOpt()));
11451 elemsize = optGetElemsize(id->idInsOpt());
11452 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11456 elemsize = id->idOpSize();
11457 index = emitGetInsSC(id);
11458 assert(isValidVectorElemsize(elemsize));
11459 emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11461 emitDispReg(id->idReg2(), (elemsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE, false);
11464 case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
11465 datasize = id->idOpSize();
11466 assert(isValidVectorDatasize(datasize));
11467 assert(isValidArrangement(datasize, id->idInsOpt()));
11468 elemsize = optGetElemsize(id->idInsOpt());
11469 index = emitGetInsSC(id);
11470 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11471 emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11474 case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
11475 elemsize = id->idOpSize();
11476 index = emitGetInsSC(id);
11477 emitDispReg(id->idReg1(), elemsize, true);
11478 emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11481 case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
11482 imm = emitGetInsSC(id);
11483 index = (imm >> 4) & 0xf;
11484 index2 = imm & 0xf;
11485 elemsize = id->idOpSize();
11486 emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11487 emitDispVectorRegIndex(id->idReg2(), elemsize, index2, false);
11490 case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov, fcvtXX - register)
11491 case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
11492 case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
11493 elemsize = id->idOpSize();
11494 emitDispReg(id->idReg1(), elemsize, true);
11495 emitDispReg(id->idReg2(), elemsize, false);
11498 case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov, fcvtXX - to general)
11499 case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov, Xcvtf - from general)
11500 case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
11501 dstsize = optGetDstsize(id->idInsOpt());
11502 srcsize = optGetSrcsize(id->idInsOpt());
11504 emitDispReg(id->idReg1(), dstsize, true);
11505 emitDispReg(id->idReg2(), srcsize, false);
11508 case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11509 case IF_DV_3B: // DV_3B .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11510 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11511 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11512 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11515 case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11516 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11517 if (ins != INS_mov)
11519 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11521 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11524 case IF_DV_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
11525 case IF_DV_3BI: // DV_3BI .Q........Lmmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
11526 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11527 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11528 elemsize = optGetElemsize(id->idInsOpt());
11529 emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11532 case IF_DV_3D: // DV_3D .........X.mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
11533 case IF_DV_3E: // DV_3E ...........mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
11534 emitDispReg(id->idReg1(), size, true);
11535 emitDispReg(id->idReg2(), size, true);
11536 emitDispReg(id->idReg3(), size, false);
11539 case IF_DV_3F: // DV_3F ..........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11540 if ((ins == INS_sha1c) || (ins == INS_sha1m) || (ins == INS_sha1p))
11542 // Qd, Sn, Vm (vector)
11543 emitDispReg(id->idReg1(), size, true);
11544 emitDispReg(id->idReg2(), EA_4BYTE, true);
11545 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11547 else if ((ins == INS_sha256h) || (ins == INS_sha256h2))
11549 // Qd Qn Vm (vector)
11550 emitDispReg(id->idReg1(), size, true);
11551 emitDispReg(id->idReg2(), size, true);
11552 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11554 else // INS_sha1su0, INS_sha256su1
11556 // Vd, Vn, Vm (vector)
11557 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11558 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11559 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11563 case IF_DV_3DI: // DV_3DI .........XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (scalar by elem)
11564 emitDispReg(id->idReg1(), size, true);
11565 emitDispReg(id->idReg2(), size, true);
11567 emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11570 case IF_DV_4A: // DV_4A .........X.mmmmm .aaaaannnnnddddd Vd Va Vn Vm (scalar)
11571 emitDispReg(id->idReg1(), size, true);
11572 emitDispReg(id->idReg2(), size, true);
11573 emitDispReg(id->idReg3(), size, true);
11574 emitDispReg(id->idReg4(), size, false);
11577 case IF_SN_0A: // SN_0A ................ ................
11580 case IF_SI_0A: // SI_0A ...........iiiii iiiiiiiiiii..... imm16
11581 emitDispImm(emitGetInsSC(id), false);
11584 case IF_SI_0B: // SI_0B ................ ....bbbb........ imm4 - barrier
11585 emitDispBarrier((insBarrier)emitGetInsSC(id));
11589 printf("unexpected format %s", emitIfName(id->idInsFmt()));
11590 assert(!"unexpectedFormat");
11594 if (id->idDebugOnlyInfo()->idVarRefOffs)
11597 emitDispFrameRef(id->idAddr()->iiaLclVar.lvaVarNum(), id->idAddr()->iiaLclVar.lvaOffset(),
11598 id->idDebugOnlyInfo()->idVarRefOffs, asmfm);
11604 /*****************************************************************************
11606 * Display a stack frame reference.
11609 void emitter::emitDispFrameRef(int varx, int disp, int offs, bool asmfm)
11614 printf("TEMP_%02u", -varx);
11616 emitComp->gtDispLclVar(+varx, false);
11619 printf("-0x%02x", -disp);
11621 printf("+0x%02x", +disp);
11625 if (varx >= 0 && emitComp->opts.varNames)
11628 const char* varName;
11630 assert((unsigned)varx < emitComp->lvaCount);
11631 varDsc = emitComp->lvaTable + varx;
11632 varName = emitComp->compLocalVarName(varx, offs);
11636 printf("'%s", varName);
11639 printf("-%d", -disp);
11641 printf("+%d", +disp);
11650 // Generate code for a load or store operation with a potentially complex addressing mode
11651 // This method handles the case of a GT_IND with contained GT_LEA op1 of the x86 form [base + index*sccale + offset]
11652 // Since Arm64 does not directly support this complex of an addressing mode
11653 // we may generates up to three instructions for this for Arm64
11655 void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataReg, GenTreeIndir* indir)
11657 emitAttr ldstAttr = isVectorRegister(dataReg) ? attr : emitInsAdjustLoadStoreAttr(ins, attr);
11659 GenTree* addr = indir->Addr();
11661 if (addr->isContained())
11663 assert(addr->OperGet() == GT_LCL_VAR_ADDR || addr->OperGet() == GT_LEA);
11668 if (addr->OperGet() == GT_LEA)
11670 offset = addr->AsAddrMode()->Offset();
11671 if (addr->AsAddrMode()->gtScale > 0)
11673 assert(isPow2(addr->AsAddrMode()->gtScale));
11674 BitScanForward(&lsl, addr->AsAddrMode()->gtScale);
11678 GenTree* memBase = indir->Base();
11680 if (indir->HasIndex())
11682 GenTree* index = indir->Index();
11686 regNumber tmpReg = indir->GetSingleTempReg();
11688 emitAttr addType = varTypeIsGC(memBase) ? EA_BYREF : EA_PTRSIZE;
11690 if (emitIns_valid_imm_for_add(offset, EA_8BYTE))
11694 // Generate code to set tmpReg = base + index*scale
11695 emitIns_R_R_R_I(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum, lsl,
11700 // Generate code to set tmpReg = base + index
11701 emitIns_R_R_R(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum);
11704 noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11706 // Then load/store dataReg from/to [tmpReg + offset]
11707 emitIns_R_R_I(ins, ldstAttr, dataReg, tmpReg, offset);
11709 else // large offset
11711 // First load/store tmpReg with the large offset constant
11712 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11713 // Then add the base register
11715 emitIns_R_R_R(INS_add, addType, tmpReg, tmpReg, memBase->gtRegNum);
11717 noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11718 noway_assert(tmpReg != index->gtRegNum);
11720 // Then load/store dataReg from/to [tmpReg + index*scale]
11721 emitIns_R_R_R_I(ins, ldstAttr, dataReg, tmpReg, index->gtRegNum, lsl, INS_OPTS_LSL);
11724 else // (offset == 0)
11728 // Then load/store dataReg from/to [memBase + index*scale]
11729 emitIns_R_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum, lsl, INS_OPTS_LSL);
11733 // Then load/store dataReg from/to [memBase + index]
11734 emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum);
11738 else // no Index register
11740 if (emitIns_valid_imm_for_ldst_offset(offset, EA_SIZE(attr)))
11742 // Then load/store dataReg from/to [memBase + offset]
11743 emitIns_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, offset);
11747 // We require a tmpReg to hold the offset
11748 regNumber tmpReg = indir->GetSingleTempReg();
11750 // First load/store tmpReg with the large offset constant
11751 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11753 // Then load/store dataReg from/to [memBase + tmpReg]
11754 emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, tmpReg);
11758 else // addr is not contained, so we evaluate it into a register
11760 // Then load/store dataReg from/to [addrReg]
11761 emitIns_R_R(ins, ldstAttr, dataReg, addr->gtRegNum);
11765 // The callee must call genConsumeReg() for any non-contained srcs
11766 // and genProduceReg() for any non-contained dsts.
11768 regNumber emitter::emitInsBinary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src)
11770 regNumber result = REG_NA;
11772 // dst can only be a reg
11773 assert(!dst->isContained());
11775 // src can be immed or reg
11776 assert(!src->isContained() || src->isContainedIntOrIImmed());
11778 // find immed (if any) - it cannot be a dst
11779 GenTreeIntConCommon* intConst = nullptr;
11780 if (src->isContainedIntOrIImmed())
11782 intConst = src->AsIntConCommon();
11787 emitIns_R_I(ins, attr, dst->gtRegNum, intConst->IconValue());
11788 return dst->gtRegNum;
11792 emitIns_R_R(ins, attr, dst->gtRegNum, src->gtRegNum);
11793 return dst->gtRegNum;
11797 // The callee must call genConsumeReg() for any non-contained srcs
11798 // and genProduceReg() for any non-contained dsts.
11800 regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src1, GenTree* src2)
11802 regNumber result = REG_NA;
11804 // dst can only be a reg
11805 assert(!dst->isContained());
11807 // find immed (if any) - it cannot be a dst
11808 // Only one src can be an int.
11809 GenTreeIntConCommon* intConst = nullptr;
11810 GenTree* nonIntReg = nullptr;
11812 if (varTypeIsFloating(dst))
11814 // src1 can only be a reg
11815 assert(!src1->isContained());
11816 // src2 can only be a reg
11817 assert(!src2->isContained());
11819 else // not floating point
11821 // src2 can be immed or reg
11822 assert(!src2->isContained() || src2->isContainedIntOrIImmed());
11824 // Check src2 first as we can always allow it to be a contained immediate
11825 if (src2->isContainedIntOrIImmed())
11827 intConst = src2->AsIntConCommon();
11830 // Only for commutative operations do we check src1 and allow it to be a contained immediate
11831 else if (dst->OperIsCommutative())
11833 // src1 can be immed or reg
11834 assert(!src1->isContained() || src1->isContainedIntOrIImmed());
11836 // Check src1 and allow it to be a contained immediate
11837 if (src1->isContainedIntOrIImmed())
11839 assert(!src2->isContainedIntOrIImmed());
11840 intConst = src1->AsIntConCommon();
11846 // src1 can only be a reg
11847 assert(!src1->isContained());
11851 bool isMulOverflow = false;
11852 if (dst->gtOverflowEx())
11854 if ((ins == INS_add) || (ins == INS_adds))
11858 else if ((ins == INS_sub) || (ins == INS_subs))
11862 else if (ins == INS_mul)
11864 isMulOverflow = true;
11865 assert(intConst == nullptr); // overflow format doesn't support an int constant operand
11869 assert(!"Invalid ins for overflow check");
11872 if (intConst != nullptr)
11874 emitIns_R_R_I(ins, attr, dst->gtRegNum, nonIntReg->gtRegNum, intConst->IconValue());
11880 regNumber extraReg = dst->GetSingleTempReg();
11881 assert(extraReg != dst->gtRegNum);
11883 if ((dst->gtFlags & GTF_UNSIGNED) != 0)
11885 if (attr == EA_4BYTE)
11887 // Compute 8 byte results from 4 byte by 4 byte multiplication.
11888 emitIns_R_R_R(INS_umull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11890 // Get the high result by shifting dst.
11891 emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11895 assert(attr == EA_8BYTE);
11896 // Compute the high result.
11897 emitIns_R_R_R(INS_umulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11899 // Now multiply without skewing the high result.
11900 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11903 // zero-sign bit comparison to detect overflow.
11904 emitIns_R_I(INS_cmp, attr, extraReg, 0);
11909 if (attr == EA_4BYTE)
11911 // Compute 8 byte results from 4 byte by 4 byte multiplication.
11912 emitIns_R_R_R(INS_smull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11914 // Get the high result by shifting dst.
11915 emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11921 assert(attr == EA_8BYTE);
11922 // Save the high result in a temporary register.
11923 emitIns_R_R_R(INS_smulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11925 // Now multiply without skewing the high result.
11926 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11931 // Sign bit comparison to detect overflow.
11932 emitIns_R_R_I(INS_cmp, attr, extraReg, dst->gtRegNum, bitShift, INS_OPTS_ASR);
11937 // We can just multiply.
11938 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11942 if (dst->gtOverflowEx())
11944 assert(!varTypeIsFloating(dst));
11945 codeGen->genCheckOverflow(dst);
11948 return dst->gtRegNum;
11951 #endif // defined(_TARGET_ARM64_)