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;
8504 // Set default ins/fmt from id.
8505 instruction ins = id->idIns();
8506 insFormat fmt = id->idInsFmt();
8508 bool loadLabel = false;
8509 bool isJump = false;
8510 bool loadConstant = false;
8527 loadConstant = true;
8536 /* Figure out the distance to the target */
8538 srcOffs = emitCurCodeOffs(dst);
8539 srcAddr = emitOffsetToPtr(srcOffs);
8541 if (id->idAddr()->iiaIsJitDataOffset())
8543 assert(loadConstant || loadLabel);
8544 int doff = id->idAddr()->iiaGetJitDataOffset();
8546 ssize_t imm = emitGetInsSC(id);
8547 assert((imm >= 0) && (imm < 0x1000)); // 0x1000 is arbitrary, currently 'imm' is always 0
8549 unsigned dataOffs = (unsigned)(doff + imm);
8550 assert(dataOffs < emitDataSize());
8551 dstAddr = emitDataOffsetToPtr(dataOffs);
8553 regNumber dstReg = id->idReg1();
8554 regNumber addrReg = dstReg; // an integer register to compute long address.
8555 emitAttr opSize = id->idOpSize();
8561 // ldr x/v, [rel addr] -- load constant from current addr(ip) + rel addr.
8562 assert(ins == INS_ldr);
8563 assert(fmt == IF_LS_1A);
8564 distVal = (ssize_t)(dstAddr - srcAddr);
8565 dst = emitOutputShortConstant(dst, ins, fmt, distVal, dstReg, opSize);
8569 // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8570 assert(fmt == IF_LARGELDC);
8571 ssize_t relPageAddr =
8572 (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8573 if (isVectorRegister(dstReg))
8575 // Update addrReg with the reserved integer register
8576 // since we cannot use dstReg (vector) to load constant directly from memory.
8577 addrReg = id->idReg2();
8578 assert(isGeneralRegister(addrReg));
8582 dst = emitOutputShortAddress(dst, ins, fmt, relPageAddr, addrReg);
8584 // ldr x, [x, page offs] -- load constant from page address + page offset into integer register.
8585 ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8586 assert(isValidUimm12(imm12));
8589 dst = emitOutputShortConstant(dst, ins, fmt, imm12, addrReg, opSize);
8591 // fmov v, d -- copy constant in integer register to vector register.
8592 // This is needed only for vector constant.
8593 if (addrReg != dstReg)
8595 // fmov Vd,Rn DV_2I X00111100X100111 000000nnnnnddddd 1E27 0000 Vd,Rn
8596 // (scalar, from general)
8597 assert(isVectorRegister(dstReg) && isGeneralRegister(addrReg));
8600 code_t code = emitInsCode(ins, fmt);
8602 code |= insEncodeReg_Vd(dstReg); // ddddd
8603 code |= insEncodeReg_Rn(addrReg); // nnnnn
8604 if (id->idOpSize() == EA_8BYTE)
8606 code |= 0x80400000; // X ... X
8608 dst += emitOutput_Instr(dst, code);
8615 dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8621 assert(loadLabel || isJump);
8623 if (id->idAddr()->iiaHasInstrCount())
8626 int instrCount = id->idAddr()->iiaGetInstrCount();
8627 unsigned insNum = emitFindInsNum(ig, id);
8630 // Backward branches using instruction count must be within the same instruction group.
8631 assert(insNum + 1 >= (unsigned)(-instrCount));
8633 dstOffs = ig->igOffs + emitFindOffset(ig, (insNum + 1 + instrCount));
8634 dstAddr = emitOffsetToPtr(dstOffs);
8638 dstOffs = id->idAddr()->iiaIGlabel->igOffs;
8639 dstAddr = emitOffsetToPtr(dstOffs);
8642 distVal = (ssize_t)(dstAddr - srcAddr);
8644 if (dstOffs <= srcOffs)
8647 /* This is a backward jump - distance is known at this point */
8649 if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8651 size_t blkOffs = id->idjIG->igOffs;
8653 if (INTERESTING_JUMP_NUM == 0)
8654 printf("[3] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8655 printf("[3] Jump block is at %08X - %02X = %08X\n", blkOffs, emitOffsAdj, blkOffs - emitOffsAdj);
8656 printf("[3] Jump is at %08X - %02X = %08X\n", srcOffs, emitOffsAdj, srcOffs - emitOffsAdj);
8657 printf("[3] Label block is at %08X - %02X = %08X\n", dstOffs, emitOffsAdj, dstOffs - emitOffsAdj);
8663 /* This is a forward jump - distance will be an upper limit */
8665 emitFwdJumps = true;
8667 /* The target offset will be closer by at least 'emitOffsAdj', but only if this
8668 jump doesn't cross the hot-cold boundary. */
8670 if (!emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8672 dstOffs -= emitOffsAdj;
8673 distVal -= emitOffsAdj;
8676 /* Record the location of the jump for later patching */
8678 id->idjOffs = dstOffs;
8680 /* Are we overflowing the id->idjOffs bitfield? */
8681 if (id->idjOffs != dstOffs)
8682 IMPL_LIMITATION("Method is too large");
8685 if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8687 size_t blkOffs = id->idjIG->igOffs;
8689 if (INTERESTING_JUMP_NUM == 0)
8690 printf("[4] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8691 printf("[4] Jump block is at %08X\n", blkOffs);
8692 printf("[4] Jump is at %08X\n", srcOffs);
8693 printf("[4] Label block is at %08X - %02X = %08X\n", dstOffs + emitOffsAdj, emitOffsAdj, dstOffs);
8699 if (0 && emitComp->verbose)
8702 int distValSize = id->idjShort ? 4 : 8;
8703 printf("; %s jump [%08X/%03u] from %0*X to %0*X: dist = %08XH\n", (dstOffs <= srcOffs) ? "Fwd" : "Bwd",
8704 dspPtr(id), id->idDebugOnlyInfo()->idNum, distValSize, srcOffs + sz, distValSize, dstOffs, distVal);
8708 /* For forward jumps, record the address of the distance value */
8709 id->idjTemp.idjAddr = (distVal > 0) ? dst : NULL;
8711 if (emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8713 assert(!id->idjShort);
8714 NYI_ARM64("Relocation Support for long address");
8717 assert(insOptsNone(id->idInsOpt()));
8723 // Short conditional/unconditional jump
8724 assert(!id->idjKeepLong);
8725 assert(emitJumpCrossHotColdBoundary(srcOffs, dstOffs) == false);
8726 assert((fmt == IF_BI_0A) || (fmt == IF_BI_0B) || (fmt == IF_BI_1A) || (fmt == IF_BI_1B));
8730 // Long conditional jump
8731 assert(fmt == IF_LARGEJMP);
8732 // This is a pseudo-instruction format representing a large conditional branch, to allow
8733 // us to get a greater branch target range than we can get by using a straightforward conditional
8734 // branch. It is encoded as a short conditional branch that branches around a long unconditional
8737 // Conceptually, we have:
8741 // The code we emit is:
8743 // b<!cond> L_not // 4 bytes. Note that we reverse the condition.
8744 // b L_target // 4 bytes
8747 // Note that we don't actually insert any blocks: we simply encode "b <!cond> L_not" as a branch with
8748 // the correct offset. Note also that this works for both integer and floating-point conditions, because
8749 // the condition inversion takes ordered/unordered into account, preserving NaN behavior. For example,
8750 // "GT" (greater than) is inverted to "LE" (less than, equal, or unordered).
8752 instruction reverseIns;
8753 insFormat reverseFmt;
8758 reverseIns = INS_cbnz;
8759 reverseFmt = IF_BI_1A;
8762 reverseIns = INS_cbz;
8763 reverseFmt = IF_BI_1A;
8766 reverseIns = INS_tbnz;
8767 reverseFmt = IF_BI_1B;
8770 reverseIns = INS_tbz;
8771 reverseFmt = IF_BI_1B;
8774 reverseIns = emitJumpKindToIns(emitReverseJumpKind(emitInsToJumpKind(ins)));
8775 reverseFmt = IF_BI_0B;
8779 emitOutputShortBranch(dst,
8780 reverseIns, // reverse the conditional instruction
8782 8, /* 8 bytes from start of this large conditional pseudo-instruction to L_not. */
8785 // Now, pretend we've got a normal unconditional branch, and fall through to the code to emit that.
8789 // The distVal was computed based on the beginning of the pseudo-instruction,
8790 // So subtract the size of the conditional branch so that it is relative to the
8791 // unconditional branch.
8795 dst = emitOutputShortBranch(dst, ins, fmt, distVal, id);
8799 dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8805 /*****************************************************************************
8807 * Output a short branch instruction.
8809 BYTE* emitter::emitOutputShortBranch(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, instrDescJmp* id)
8811 code_t code = emitInsCode(ins, fmt);
8813 ssize_t loBits = (distVal & 3);
8814 noway_assert(loBits == 0);
8815 distVal >>= 2; // branch offset encodings are scaled by 4.
8817 if (fmt == IF_BI_0A)
8819 // INS_b or INS_bl_local
8820 noway_assert(isValidSimm26(distVal));
8821 distVal &= 0x3FFFFFFLL;
8824 else if (fmt == IF_BI_0B) // BI_0B 01010100iiiiiiii iiiiiiiiiiiXXXXX simm19:00
8826 // INS_beq, INS_bne, etc...
8827 noway_assert(isValidSimm19(distVal));
8828 distVal &= 0x7FFFFLL;
8829 code |= distVal << 5;
8831 else if (fmt == IF_BI_1A) // BI_1A X.......iiiiiiii iiiiiiiiiiittttt Rt simm19:00
8833 // INS_cbz or INS_cbnz
8834 assert(id != nullptr);
8835 code |= insEncodeDatasize(id->idOpSize()); // X
8836 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
8838 noway_assert(isValidSimm19(distVal));
8839 distVal &= 0x7FFFFLL; // 19 bits
8840 code |= distVal << 5;
8842 else if (fmt == IF_BI_1B) // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
8844 // INS_tbz or INS_tbnz
8845 assert(id != nullptr);
8846 ssize_t imm = emitGetInsSC(id);
8847 assert(isValidImmShift(imm, id->idOpSize()));
8849 if (imm & 0x20) // test bit 32-63 ?
8851 code |= 0x80000000; // B
8853 code |= ((imm & 0x1F) << 19); // bbbbb
8854 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
8856 noway_assert(isValidSimm14(distVal));
8857 distVal &= 0x3FFFLL; // 14 bits
8858 code |= distVal << 5;
8862 assert(!"Unknown fmt for emitOutputShortBranch");
8865 dst += emitOutput_Instr(dst, code);
8870 /*****************************************************************************
8872 * Output a short address instruction.
8874 BYTE* emitter::emitOutputShortAddress(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, regNumber reg)
8876 ssize_t loBits = (distVal & 3);
8879 code_t code = emitInsCode(ins, fmt);
8880 if (fmt == IF_DI_1E) // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
8882 // INS_adr or INS_adrp
8883 code |= insEncodeReg_Rd(reg); // ddddd
8885 noway_assert(isValidSimm19(distVal));
8886 distVal &= 0x7FFFFLL; // 19 bits
8887 code |= distVal << 5;
8888 code |= loBits << 29; // 2 bits
8892 assert(!"Unknown fmt for emitOutputShortAddress");
8895 dst += emitOutput_Instr(dst, code);
8900 /*****************************************************************************
8902 * Output a short constant instruction.
8904 BYTE* emitter::emitOutputShortConstant(
8905 BYTE* dst, instruction ins, insFormat fmt, ssize_t imm, regNumber reg, emitAttr opSize)
8907 code_t code = emitInsCode(ins, fmt);
8909 if (fmt == IF_LS_1A)
8911 // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt simm21
8912 // INS_ldr or INS_ldrsw (PC-Relative)
8914 ssize_t loBits = (imm & 3);
8915 noway_assert(loBits == 0);
8916 ssize_t distVal = imm >>= 2; // load offset encodings are scaled by 4.
8918 noway_assert(isValidSimm19(distVal));
8920 // Is the target a vector register?
8921 if (isVectorRegister(reg))
8923 code |= insEncodeDatasizeVLS(code, opSize); // XX V
8924 code |= insEncodeReg_Vt(reg); // ttttt
8928 assert(isGeneralRegister(reg));
8929 // insEncodeDatasizeLS is not quite right for this case.
8930 // So just specialize it.
8931 if ((ins == INS_ldr) && (opSize == EA_8BYTE))
8933 // set the operation size in bit 30
8937 code |= insEncodeReg_Rt(reg); // ttttt
8940 distVal &= 0x7FFFFLL; // 19 bits
8941 code |= distVal << 5;
8943 else if (fmt == IF_LS_2B)
8945 // ldr Rt,[Xn+pimm12] LS_2B 1X11100101iiiiii iiiiiinnnnnttttt B940 0000 imm(0-4095<<{2,3})
8946 // INS_ldr or INS_ldrsw (PC-Relative)
8947 noway_assert(isValidUimm12(imm));
8948 assert(isGeneralRegister(reg));
8950 if (opSize == EA_8BYTE)
8952 // insEncodeDatasizeLS is not quite right for this case.
8953 // So just specialize it.
8956 // set the operation size in bit 30
8959 // Low 3 bits should be 0 -- 8 byte JIT data should be aligned on 8 byte.
8960 assert((imm & 7) == 0);
8965 assert(opSize == EA_4BYTE);
8966 // Low 2 bits should be 0 -- 4 byte aligned data.
8967 assert((imm & 3) == 0);
8971 code |= insEncodeReg_Rt(reg); // ttttt
8972 code |= insEncodeReg_Rn(reg); // nnnnn
8977 assert(!"Unknown fmt for emitOutputShortConstant");
8980 dst += emitOutput_Instr(dst, code);
8984 /*****************************************************************************
8986 * Output a call instruction.
8989 unsigned emitter::emitOutputCall(insGroup* ig, BYTE* dst, instrDesc* id, code_t code)
8991 const unsigned char callInstrSize = sizeof(code_t); // 4 bytes
8992 regMaskTP gcrefRegs;
8993 regMaskTP byrefRegs;
8995 VARSET_TP GCvars(VarSetOps::UninitVal());
8997 // Is this a "fat" call descriptor?
8998 if (id->idIsLargeCall())
9000 instrDescCGCA* idCall = (instrDescCGCA*)id;
9001 gcrefRegs = idCall->idcGcrefRegs;
9002 byrefRegs = idCall->idcByrefRegs;
9003 VarSetOps::Assign(emitComp, GCvars, idCall->idcGCvars);
9007 assert(!id->idIsLargeDsp());
9008 assert(!id->idIsLargeCns());
9010 gcrefRegs = emitDecodeCallGCregs(id);
9012 VarSetOps::AssignNoCopy(emitComp, GCvars, VarSetOps::MakeEmpty(emitComp));
9015 /* We update the GC info before the call as the variables cannot be
9016 used by the call. Killing variables before the call helps with
9017 boundary conditions if the call is CORINFO_HELP_THROW - see bug 50029.
9018 If we ever track aliased variables (which could be used by the
9019 call), we would have to keep them alive past the call. */
9021 emitUpdateLiveGCvars(GCvars, dst);
9023 // Now output the call instruction and update the 'dst' pointer
9025 unsigned outputInstrSize = emitOutput_Instr(dst, code);
9026 dst += outputInstrSize;
9028 // All call instructions are 4-byte in size on ARM64
9030 assert(outputInstrSize == callInstrSize);
9032 // If the method returns a GC ref, mark INTRET (R0) appropriately.
9033 if (id->idGCref() == GCT_GCREF)
9035 gcrefRegs |= RBM_INTRET;
9037 else if (id->idGCref() == GCT_BYREF)
9039 byrefRegs |= RBM_INTRET;
9042 // If is a multi-register return method is called, mark INTRET_1 (X1) appropriately
9043 if (id->idIsLargeCall())
9045 instrDescCGCA* idCall = (instrDescCGCA*)id;
9046 if (idCall->idSecondGCref() == GCT_GCREF)
9048 gcrefRegs |= RBM_INTRET_1;
9050 else if (idCall->idSecondGCref() == GCT_BYREF)
9052 byrefRegs |= RBM_INTRET_1;
9056 // If the GC register set has changed, report the new set.
9057 if (gcrefRegs != emitThisGCrefRegs)
9059 emitUpdateLiveGCregs(GCT_GCREF, gcrefRegs, dst);
9061 // If the Byref register set has changed, report the new set.
9062 if (byrefRegs != emitThisByrefRegs)
9064 emitUpdateLiveGCregs(GCT_BYREF, byrefRegs, dst);
9067 // Some helper calls may be marked as not requiring GC info to be recorded.
9068 if ((!id->idIsNoGC()))
9070 // On ARM64, as on AMD64, we don't change the stack pointer to push/pop args.
9071 // So we're not really doing a "stack pop" here (note that "args" is 0), but we use this mechanism
9072 // to record the call for GC info purposes. (It might be best to use an alternate call,
9073 // and protect "emitStackPop" under the EMIT_TRACK_STACK_DEPTH preprocessor variable.)
9074 emitStackPop(dst, /*isCall*/ true, callInstrSize, /*args*/ 0);
9076 // Do we need to record a call location for GC purposes?
9078 if (!emitFullGCinfo)
9080 emitRecordGCcall(dst, callInstrSize);
9083 return callInstrSize;
9086 /*****************************************************************************
9088 * Emit a 32-bit Arm64 instruction
9091 /*static*/ unsigned emitter::emitOutput_Instr(BYTE* dst, code_t code)
9093 assert(sizeof(code_t) == 4);
9094 *((code_t*)dst) = code;
9096 return sizeof(code_t);
9099 /*****************************************************************************
9101 * Append the machine code corresponding to the given instruction descriptor
9102 * to the code block at '*dp'; the base of the code block is 'bp', and 'ig'
9103 * is the instruction group that contains the instruction. Updates '*dp' to
9104 * point past the generated code, and returns the size of the instruction
9105 * descriptor in bytes.
9108 size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
9113 size_t sz = emitGetInstrDescSize(id); // TODO-ARM64-Cleanup: on ARM, this is set in each case. why?
9114 instruction ins = id->idIns();
9115 insFormat fmt = id->idInsFmt();
9116 emitAttr size = id->idOpSize();
9117 unsigned char callInstrSize = 0;
9121 bool dspOffs = emitComp->opts.dspGCtbls;
9123 bool dspOffs = !emitComp->opts.disDiffable;
9127 assert(REG_NA == (int)REG_NA);
9129 VARSET_TP GCvars(VarSetOps::UninitVal());
9131 /* What instruction format have we got? */
9143 case IF_BI_0A: // BI_0A ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
9144 case IF_BI_0B: // BI_0B ......iiiiiiiiii iiiiiiiiiii..... simm19:00
9146 assert(id->idGCref() == GCT_NONE);
9147 assert(id->idIsBound());
9148 dst = emitOutputLJ(ig, dst, id);
9149 sz = sizeof(instrDescJmp);
9152 case IF_BI_0C: // BI_0C ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
9153 code = emitInsCode(ins, fmt);
9154 sz = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
9155 dst += emitOutputCall(ig, dst, id, code);
9156 // Always call RecordRelocation so that we wire in a JumpStub when we don't reach
9157 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_BRANCH26);
9160 case IF_BI_1A: // BI_1A ......iiiiiiiiii iiiiiiiiiiittttt Rt simm19:00
9161 assert(insOptsNone(id->idInsOpt()));
9162 assert(id->idIsBound());
9164 dst = emitOutputLJ(ig, dst, id);
9165 sz = sizeof(instrDescJmp);
9168 case IF_BI_1B: // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
9169 assert(insOptsNone(id->idInsOpt()));
9170 assert(id->idIsBound());
9172 dst = emitOutputLJ(ig, dst, id);
9173 sz = sizeof(instrDescJmp);
9176 case IF_BR_1A: // BR_1A ................ ......nnnnn..... Rn
9177 assert(insOptsNone(id->idInsOpt()));
9178 assert((ins == INS_ret) || (ins == INS_br));
9179 code = emitInsCode(ins, fmt);
9180 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9182 dst += emitOutput_Instr(dst, code);
9185 case IF_BR_1B: // BR_1B ................ ......nnnnn..... Rn
9186 assert(insOptsNone(id->idInsOpt()));
9187 assert((ins == INS_br_tail) || (ins == INS_blr));
9188 code = emitInsCode(ins, fmt);
9189 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9191 sz = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
9192 dst += emitOutputCall(ig, dst, id, code);
9195 case IF_LS_1A: // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB)
9197 assert(insOptsNone(id->idInsOpt()));
9198 assert(id->idIsBound());
9200 dst = emitOutputLJ(ig, dst, id);
9201 sz = sizeof(instrDescJmp);
9204 case IF_LS_2A: // LS_2A .X.......X...... ......nnnnnttttt Rt Rn
9205 assert(insOptsNone(id->idInsOpt()));
9206 code = emitInsCode(ins, fmt);
9207 // Is the target a vector register?
9208 if (isVectorRegister(id->idReg1()))
9210 code &= 0x3FFFFFFF; // clear the size bits
9211 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9212 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9216 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9217 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9219 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9220 dst += emitOutput_Instr(dst, code);
9223 case IF_LS_2B: // LS_2B .X.......Xiiiiii iiiiiinnnnnttttt Rt Rn imm(0-4095)
9224 assert(insOptsNone(id->idInsOpt()));
9225 imm = emitGetInsSC(id);
9226 assert(isValidUimm12(imm));
9227 code = emitInsCode(ins, fmt);
9228 // Is the target a vector register?
9229 if (isVectorRegister(id->idReg1()))
9231 code &= 0x3FFFFFFF; // clear the size bits
9232 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9233 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9237 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9238 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9240 code |= ((code_t)imm << 10); // iiiiiiiiiiii
9241 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9242 dst += emitOutput_Instr(dst, code);
9245 case IF_LS_2C: // LS_2C .X.......X.iiiii iiiiPPnnnnnttttt Rt Rn imm(-256..+255) no/pre/post inc
9246 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9247 imm = emitGetInsSC(id);
9248 assert((imm >= -256) && (imm <= 255)); // signed 9 bits
9249 imm &= 0x1ff; // force into unsigned 9 bit representation
9250 code = emitInsCode(ins, fmt);
9251 // Is the target a vector register?
9252 if (isVectorRegister(id->idReg1()))
9254 code &= 0x3FFFFFFF; // clear the size bits
9255 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9256 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9260 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9261 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9263 code |= insEncodeIndexedOpt(id->idInsOpt()); // PP
9264 code |= ((code_t)imm << 12); // iiiiiiiii
9265 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9266 dst += emitOutput_Instr(dst, code);
9269 case IF_LS_3A: // LS_3A .X.......X.mmmmm oooS..nnnnnttttt Rt Rn Rm ext(Rm) LSL {}
9270 assert(insOptsLSExtend(id->idInsOpt()));
9271 code = emitInsCode(ins, fmt);
9272 // Is the target a vector register?
9273 if (isVectorRegister(id->idReg1()))
9275 code &= 0x3FFFFFFF; // clear the size bits
9276 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9277 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9281 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9282 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9284 code |= insEncodeExtend(id->idInsOpt()); // ooo
9285 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9286 if (id->idIsLclVar())
9288 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9292 code |= insEncodeReg3Scale(id->idReg3Scaled()); // S
9293 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9295 dst += emitOutput_Instr(dst, code);
9298 case IF_LS_3B: // LS_3B X............... .aaaaannnnnddddd Rd Ra Rn
9299 assert(insOptsNone(id->idInsOpt()));
9300 code = emitInsCode(ins, fmt);
9301 // Is the target a vector register?
9302 if (isVectorRegister(id->idReg1()))
9304 code &= 0x3FFFFFFF; // clear the size bits
9305 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9306 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9307 code |= insEncodeReg_Va(id->idReg2()); // aaaaa
9311 code |= insEncodeDatasize(id->idOpSize()); // X
9312 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9313 code |= insEncodeReg_Ra(id->idReg2()); // aaaaa
9315 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9316 dst += emitOutput_Instr(dst, code);
9319 case IF_LS_3C: // LS_3C X......PP.iiiiii iaaaaannnnnddddd Rd Ra Rn imm(im7,sh)
9320 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9321 imm = emitGetInsSC(id);
9322 assert((imm >= -64) && (imm <= 63)); // signed 7 bits
9323 imm &= 0x7f; // force into unsigned 7 bit representation
9324 code = emitInsCode(ins, fmt);
9325 // Is the target a vector register?
9326 if (isVectorRegister(id->idReg1()))
9328 code &= 0x3FFFFFFF; // clear the size bits
9329 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9330 code |= insEncodeReg_Vt(id->idReg1()); // ttttt
9331 code |= insEncodeReg_Va(id->idReg2()); // aaaaa
9335 code |= insEncodeDatasize(id->idOpSize()); // X
9336 code |= insEncodeReg_Rt(id->idReg1()); // ttttt
9337 code |= insEncodeReg_Ra(id->idReg2()); // aaaaa
9339 code |= insEncodePairIndexedOpt(ins, id->idInsOpt()); // PP
9340 code |= ((code_t)imm << 15); // iiiiiiiii
9341 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9342 dst += emitOutput_Instr(dst, code);
9345 case IF_LS_3D: // LS_3D .X.......X.mmmmm ......nnnnnttttt Wm Rt Rn
9346 code = emitInsCode(ins, fmt);
9347 // Arm64 store exclusive unpredictable cases
9348 assert(id->idReg1() != id->idReg2());
9349 assert(id->idReg1() != id->idReg3());
9350 code |= insEncodeDatasizeLS(code, id->idOpSize()); // X
9351 code |= insEncodeReg_Rm(id->idReg1()); // mmmmm
9352 code |= insEncodeReg_Rt(id->idReg2()); // ttttt
9353 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9354 dst += emitOutput_Instr(dst, code);
9357 case IF_LS_3E: // LS_3E .X.........mmmmm ......nnnnnttttt Rm Rt Rn ARMv8.1 LSE Atomics
9358 code = emitInsCode(ins, fmt);
9359 code |= insEncodeDatasizeLS(code, id->idOpSize()); // X
9360 code |= insEncodeReg_Rm(id->idReg1()); // mmmmm
9361 code |= insEncodeReg_Rt(id->idReg2()); // ttttt
9362 code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9363 dst += emitOutput_Instr(dst, code);
9366 case IF_DI_1A: // DI_1A X.......shiiiiii iiiiiinnnnn..... Rn imm(i12,sh)
9367 assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9368 imm = emitGetInsSC(id);
9369 assert(isValidUimm12(imm));
9370 code = emitInsCode(ins, fmt);
9371 code |= insEncodeDatasize(id->idOpSize()); // X
9372 code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9373 code |= ((code_t)imm << 10); // iiiiiiiiiiii
9374 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9375 dst += emitOutput_Instr(dst, code);
9378 case IF_DI_1B: // DI_1B X........hwiiiii iiiiiiiiiiiddddd Rd imm(i16,hw)
9379 imm = emitGetInsSC(id);
9380 assert(isValidImmHWVal(imm, id->idOpSize()));
9381 code = emitInsCode(ins, fmt);
9382 code |= insEncodeDatasize(id->idOpSize()); // X
9383 code |= ((code_t)imm << 5); // hwiiiii iiiiiiiiiii
9384 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9385 dst += emitOutput_Instr(dst, code);
9388 case IF_DI_1C: // DI_1C X........Nrrrrrr ssssssnnnnn..... Rn imm(N,r,s)
9389 imm = emitGetInsSC(id);
9390 assert(isValidImmNRS(imm, id->idOpSize()));
9391 code = emitInsCode(ins, fmt);
9392 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9393 code |= insEncodeDatasize(id->idOpSize()); // X
9394 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9395 dst += emitOutput_Instr(dst, code);
9398 case IF_DI_1D: // DI_1D X........Nrrrrrr ssssss.....ddddd Rd imm(N,r,s)
9399 imm = emitGetInsSC(id);
9400 assert(isValidImmNRS(imm, id->idOpSize()));
9401 code = emitInsCode(ins, fmt);
9402 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9403 code |= insEncodeDatasize(id->idOpSize()); // X
9404 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9405 dst += emitOutput_Instr(dst, code);
9408 case IF_DI_1E: // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
9410 assert(insOptsNone(id->idInsOpt()));
9411 if (id->idIsReloc())
9413 code = emitInsCode(ins, fmt);
9414 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9415 dst += emitOutput_Instr(dst, code);
9416 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEBASE_REL21);
9420 // Local jmp/load case which does not need a relocation.
9421 assert(id->idIsBound());
9422 dst = emitOutputLJ(ig, dst, id);
9424 sz = sizeof(instrDescJmp);
9427 case IF_DI_1F: // DI_1F X..........iiiii cccc..nnnnn.nzcv Rn imm5 nzcv cond
9428 imm = emitGetInsSC(id);
9429 assert(isValidImmCondFlagsImm5(imm));
9432 cfi.immCFVal = (unsigned)imm;
9433 code = emitInsCode(ins, fmt);
9434 code |= insEncodeDatasize(id->idOpSize()); // X
9435 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9436 code |= ((code_t)cfi.imm5 << 16); // iiiii
9437 code |= insEncodeFlags(cfi.flags); // nzcv
9438 code |= insEncodeCond(cfi.cond); // cccc
9439 dst += emitOutput_Instr(dst, code);
9443 case IF_DI_2A: // DI_2A X.......shiiiiii iiiiiinnnnnddddd Rd Rn imm(i12,sh)
9444 assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9445 imm = emitGetInsSC(id);
9446 assert(isValidUimm12(imm));
9447 code = emitInsCode(ins, fmt);
9448 code |= insEncodeDatasize(id->idOpSize()); // X
9449 code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9450 code |= ((code_t)imm << 10); // iiiiiiiiiiii
9451 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9452 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9453 dst += emitOutput_Instr(dst, code);
9455 if (id->idIsReloc())
9457 assert(sz == sizeof(instrDesc));
9458 assert(id->idAddr()->iiaAddr != nullptr);
9459 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEOFFSET_12A);
9463 case IF_DI_2B: // DI_2B X.........Xnnnnn ssssssnnnnnddddd Rd Rn imm(0-63)
9464 code = emitInsCode(ins, fmt);
9465 imm = emitGetInsSC(id);
9466 assert(isValidImmShift(imm, id->idOpSize()));
9467 code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9468 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9469 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9470 code |= insEncodeReg_Rm(id->idReg2()); // Reg2 also in mmmmm
9471 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9472 dst += emitOutput_Instr(dst, code);
9475 case IF_DI_2C: // DI_2C X........Nrrrrrr ssssssnnnnnddddd Rd Rn imm(N,r,s)
9476 imm = emitGetInsSC(id);
9477 assert(isValidImmNRS(imm, id->idOpSize()));
9478 code = emitInsCode(ins, fmt);
9479 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9480 code |= insEncodeDatasize(id->idOpSize()); // X
9481 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9482 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9483 dst += emitOutput_Instr(dst, code);
9486 case IF_DI_2D: // DI_2D X........Nrrrrrr ssssssnnnnnddddd Rd Rn imr, imms (N,r,s)
9487 if (ins == INS_asr || ins == INS_lsl || ins == INS_lsr)
9489 imm = emitGetInsSC(id);
9490 assert(isValidImmShift(imm, id->idOpSize()));
9492 // Shift immediates are aliases of the SBFM/UBFM instructions
9493 // that actually take 2 registers and 2 constants,
9494 // Since we stored the shift immediate value
9495 // we need to calculate the N,R and S values here.
9500 bmi.immN = (size == EA_8BYTE) ? 1 : 0;
9502 bmi.immS = (size == EA_8BYTE) ? 0x3f : 0x1f;
9504 // immR and immS are now set correctly for INS_asr and INS_lsr
9505 // but for INS_lsl we have to adjust the values for immR and immS
9509 bmi.immR = -imm & bmi.immS;
9510 bmi.immS = bmi.immS - imm;
9513 // setup imm with the proper 13 bit value N:R:S
9519 // The other instructions have already have encoded N,R and S values
9520 imm = emitGetInsSC(id);
9522 assert(isValidImmNRS(imm, id->idOpSize()));
9524 code = emitInsCode(ins, fmt);
9525 code |= ((code_t)imm << 10); // Nrrrrrrssssss
9526 code |= insEncodeDatasize(id->idOpSize()); // X
9527 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9528 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9529 dst += emitOutput_Instr(dst, code);
9532 case IF_DR_1D: // DR_1D X............... cccc.......ddddd Rd cond
9533 imm = emitGetInsSC(id);
9534 assert(isValidImmCond(imm));
9537 cfi.immCFVal = (unsigned)imm;
9538 code = emitInsCode(ins, fmt);
9539 code |= insEncodeDatasize(id->idOpSize()); // X
9540 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9541 code |= insEncodeInvertedCond(cfi.cond); // cccc
9542 dst += emitOutput_Instr(dst, code);
9546 case IF_DR_2A: // DR_2A X..........mmmmm ......nnnnn..... Rn Rm
9547 assert(insOptsNone(id->idInsOpt()));
9548 code = emitInsCode(ins, fmt);
9549 code |= insEncodeDatasize(id->idOpSize()); // X
9550 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9551 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9552 dst += emitOutput_Instr(dst, code);
9555 case IF_DR_2B: // DR_2B X.......sh.mmmmm ssssssnnnnn..... Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
9556 code = emitInsCode(ins, fmt);
9557 imm = emitGetInsSC(id);
9558 assert(isValidImmShift(imm, id->idOpSize()));
9559 code |= insEncodeDatasize(id->idOpSize()); // X
9560 code |= insEncodeShiftType(id->idInsOpt()); // sh
9561 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9562 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9563 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9564 dst += emitOutput_Instr(dst, code);
9567 case IF_DR_2C: // DR_2C X..........mmmmm ooosssnnnnn..... Rn Rm ext(Rm) LSL imm(0-4)
9568 code = emitInsCode(ins, fmt);
9569 imm = emitGetInsSC(id);
9570 assert((imm >= 0) && (imm <= 4)); // imm [0..4]
9571 code |= insEncodeDatasize(id->idOpSize()); // X
9572 code |= insEncodeExtend(id->idInsOpt()); // ooo
9573 code |= insEncodeExtendScale(imm); // sss
9574 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9575 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9576 dst += emitOutput_Instr(dst, code);
9579 case IF_DR_2D: // DR_2D X..........nnnnn cccc..nnnnnddddd Rd Rn cond
9580 imm = emitGetInsSC(id);
9581 assert(isValidImmCond(imm));
9584 cfi.immCFVal = (unsigned)imm;
9585 code = emitInsCode(ins, fmt);
9586 code |= insEncodeDatasize(id->idOpSize()); // X
9587 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9588 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9589 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9590 code |= insEncodeInvertedCond(cfi.cond); // cccc
9591 dst += emitOutput_Instr(dst, code);
9595 case IF_DR_2E: // DR_2E X..........mmmmm ...........ddddd Rd Rm
9596 code = emitInsCode(ins, fmt);
9597 code |= insEncodeDatasize(id->idOpSize()); // X
9598 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9599 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9600 dst += emitOutput_Instr(dst, code);
9603 case IF_DR_2F: // DR_2F X.......sh.mmmmm ssssss.....ddddd Rd Rm {LSL,LSR,ASR} imm(0-63)
9604 code = emitInsCode(ins, fmt);
9605 imm = emitGetInsSC(id);
9606 assert(isValidImmShift(imm, id->idOpSize()));
9607 code |= insEncodeDatasize(id->idOpSize()); // X
9608 code |= insEncodeShiftType(id->idInsOpt()); // sh
9609 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9610 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9611 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9612 dst += emitOutput_Instr(dst, code);
9615 case IF_DR_2G: // DR_2G X............... .....xnnnnnddddd Rd Rn
9616 code = emitInsCode(ins, fmt);
9617 code |= insEncodeDatasize(id->idOpSize()); // X
9620 if (size == EA_8BYTE)
9622 code |= 0x00000400; // x - bit at location 10
9625 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9626 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9627 dst += emitOutput_Instr(dst, code);
9630 case IF_DR_2H: // DR_2H X........X...... ......nnnnnddddd Rd Rn
9631 code = emitInsCode(ins, fmt);
9632 code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9633 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9634 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9635 dst += emitOutput_Instr(dst, code);
9638 case IF_DR_2I: // DR_2I X..........mmmmm cccc..nnnnn.nzcv Rn Rm nzcv cond
9639 imm = emitGetInsSC(id);
9640 assert(isValidImmCondFlags(imm));
9643 cfi.immCFVal = (unsigned)imm;
9644 code = emitInsCode(ins, fmt);
9645 code |= insEncodeDatasize(id->idOpSize()); // X
9646 code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9647 code |= insEncodeReg_Rm(id->idReg2()); // mmmmm
9648 code |= insEncodeFlags(cfi.flags); // nzcv
9649 code |= insEncodeCond(cfi.cond); // cccc
9650 dst += emitOutput_Instr(dst, code);
9654 case IF_DR_2J: // DR_2J ................ ......nnnnnddddd Sd Sn (sha1h)
9655 code = emitInsCode(ins, fmt);
9656 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9657 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9658 dst += emitOutput_Instr(dst, code);
9661 case IF_DR_3A: // DR_3A X..........mmmmm ......nnnnnmmmmm Rd Rn Rm
9662 code = emitInsCode(ins, fmt);
9663 code |= insEncodeDatasize(id->idOpSize()); // X
9664 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9665 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9666 if (id->idIsLclVar())
9668 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9672 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9674 dst += emitOutput_Instr(dst, code);
9677 case IF_DR_3B: // DR_3B X.......sh.mmmmm ssssssnnnnnddddd Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
9678 code = emitInsCode(ins, fmt);
9679 imm = emitGetInsSC(id);
9680 assert(isValidImmShift(imm, id->idOpSize()));
9681 code |= insEncodeDatasize(id->idOpSize()); // X
9682 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9683 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9684 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9685 code |= insEncodeShiftType(id->idInsOpt()); // sh
9686 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9687 dst += emitOutput_Instr(dst, code);
9690 case IF_DR_3C: // DR_3C X..........mmmmm ooosssnnnnnddddd Rd Rn Rm ext(Rm) LSL imm(0-4)
9691 code = emitInsCode(ins, fmt);
9692 imm = emitGetInsSC(id);
9693 assert((imm >= 0) && (imm <= 4)); // imm [0..4]
9694 code |= insEncodeDatasize(id->idOpSize()); // X
9695 code |= insEncodeExtend(id->idInsOpt()); // ooo
9696 code |= insEncodeExtendScale(imm); // sss
9697 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9698 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9699 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9700 dst += emitOutput_Instr(dst, code);
9703 case IF_DR_3D: // DR_3D X..........mmmmm cccc..nnnnnddddd Rd Rn Rm cond
9704 imm = emitGetInsSC(id);
9705 assert(isValidImmCond(imm));
9708 cfi.immCFVal = (unsigned)imm;
9709 code = emitInsCode(ins, fmt);
9710 code |= insEncodeDatasize(id->idOpSize()); // X
9711 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9712 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9713 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9714 code |= insEncodeCond(cfi.cond); // cccc
9715 dst += emitOutput_Instr(dst, code);
9719 case IF_DR_3E: // DR_3E X........X.mmmmm ssssssnnnnnddddd Rd Rn Rm imm(0-63)
9720 code = emitInsCode(ins, fmt);
9721 imm = emitGetInsSC(id);
9722 assert(isValidImmShift(imm, id->idOpSize()));
9723 code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9724 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9725 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9726 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9727 code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9728 dst += emitOutput_Instr(dst, code);
9731 case IF_DR_4A: // DR_4A X..........mmmmm .aaaaannnnnmmmmm Rd Rn Rm Ra
9732 code = emitInsCode(ins, fmt);
9733 code |= insEncodeDatasize(id->idOpSize()); // X
9734 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9735 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9736 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9737 code |= insEncodeReg_Ra(id->idReg4()); // aaaaa
9738 dst += emitOutput_Instr(dst, code);
9741 case IF_DV_1A: // DV_1A .........X.iiiii iii........ddddd Vd imm8 (fmov - immediate scalar)
9742 imm = emitGetInsSC(id);
9743 elemsize = id->idOpSize();
9744 code = emitInsCode(ins, fmt);
9745 code |= insEncodeFloatElemsize(elemsize); // X
9746 code |= ((code_t)imm << 13); // iiiii iii
9747 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9748 dst += emitOutput_Instr(dst, code);
9751 case IF_DV_1B: // DV_1B .QX..........iii cmod..iiiiiddddd Vd imm8 (immediate vector)
9752 imm = emitGetInsSC(id) & 0x0ff;
9753 immShift = (emitGetInsSC(id) & 0x700) >> 8;
9754 elemsize = optGetElemsize(id->idInsOpt());
9759 cmode = 0xE; // 1110
9763 cmode |= (immShift << 1); // 10x0
9769 cmode |= (immShift << 1); // 0xx0
9779 cmode = 0xE; // 1110
9786 code = emitInsCode(ins, fmt);
9787 code |= insEncodeVectorsize(id->idOpSize()); // Q
9788 if ((ins == INS_fmov) || (ins == INS_movi))
9790 if (elemsize == EA_8BYTE)
9792 code |= 0x20000000; // X
9795 if (ins != INS_fmov)
9797 assert((cmode >= 0) && (cmode <= 0xF));
9798 code |= (cmode << 12); // cmod
9800 code |= (((code_t)imm >> 5) << 16); // iii
9801 code |= (((code_t)imm & 0x1f) << 5); // iiiii
9802 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9803 dst += emitOutput_Instr(dst, code);
9806 case IF_DV_1C: // DV_1C .........X...... ......nnnnn..... Vn #0.0 (fcmp - with zero)
9807 elemsize = id->idOpSize();
9808 code = emitInsCode(ins, fmt);
9809 code |= insEncodeFloatElemsize(elemsize); // X
9810 code |= insEncodeReg_Vn(id->idReg1()); // nnnnn
9811 dst += emitOutput_Instr(dst, code);
9814 case IF_DV_2A: // DV_2A .Q.......X...... ......nnnnnddddd Vd Vn (fabs, fcvt - vector)
9815 elemsize = optGetElemsize(id->idInsOpt());
9816 code = emitInsCode(ins, fmt);
9817 code |= insEncodeVectorsize(id->idOpSize()); // Q
9818 code |= insEncodeFloatElemsize(elemsize); // X
9819 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9820 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9821 dst += emitOutput_Instr(dst, code);
9824 case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov/smov - to general)
9825 elemsize = id->idOpSize();
9826 index = emitGetInsSC(id);
9827 datasize = (elemsize == EA_8BYTE) ? EA_16BYTE : EA_8BYTE;
9828 if (ins == INS_smov)
9830 datasize = EA_16BYTE;
9832 code = emitInsCode(ins, fmt);
9833 code |= insEncodeVectorsize(datasize); // Q
9834 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9835 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9836 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9837 dst += emitOutput_Instr(dst, code);
9840 case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
9843 datasize = id->idOpSize();
9844 elemsize = optGetElemsize(id->idInsOpt());
9849 datasize = EA_16BYTE;
9850 elemsize = id->idOpSize();
9851 index = emitGetInsSC(id);
9853 code = emitInsCode(ins, fmt);
9854 code |= insEncodeVectorsize(datasize); // Q
9855 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9856 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9857 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9858 dst += emitOutput_Instr(dst, code);
9861 case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
9862 index = emitGetInsSC(id);
9863 elemsize = optGetElemsize(id->idInsOpt());
9864 code = emitInsCode(ins, fmt);
9865 code |= insEncodeVectorsize(id->idOpSize()); // Q
9866 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9867 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9868 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9869 dst += emitOutput_Instr(dst, code);
9872 case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
9873 index = emitGetInsSC(id);
9874 elemsize = id->idOpSize();
9875 code = emitInsCode(ins, fmt);
9876 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9877 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9878 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9879 dst += emitOutput_Instr(dst, code);
9882 case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
9883 elemsize = id->idOpSize();
9884 imm = emitGetInsSC(id);
9885 index = (imm >> 4) & 0xf;
9887 code = emitInsCode(ins, fmt);
9888 code |= insEncodeVectorIndex(elemsize, index); // iiiii
9889 code |= insEncodeVectorIndex2(elemsize, index2); // jjjj
9890 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9891 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9892 dst += emitOutput_Instr(dst, code);
9895 case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov,fcvtXX - register)
9896 elemsize = id->idOpSize();
9897 code = emitInsCode(ins, fmt);
9898 code |= insEncodeFloatElemsize(elemsize); // X
9899 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9900 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9901 dst += emitOutput_Instr(dst, code);
9904 case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov - to general)
9905 elemsize = id->idOpSize();
9906 code = emitInsCode(ins, fmt);
9907 code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X X
9908 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9909 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9910 dst += emitOutput_Instr(dst, code);
9913 case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov - from general)
9914 elemsize = id->idOpSize();
9915 code = emitInsCode(ins, fmt);
9916 code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X X
9917 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9918 code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9919 dst += emitOutput_Instr(dst, code);
9922 case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
9923 code = emitInsCode(ins, fmt);
9924 code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // SS DD
9925 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9926 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9927 dst += emitOutput_Instr(dst, code);
9930 case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
9931 elemsize = id->idOpSize();
9932 code = emitInsCode(ins, fmt);
9933 code |= insEncodeFloatElemsize(elemsize); // X
9934 code |= insEncodeReg_Vn(id->idReg1()); // nnnnn
9935 code |= insEncodeReg_Vm(id->idReg2()); // mmmmm
9936 dst += emitOutput_Instr(dst, code);
9939 case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
9940 elemsize = id->idOpSize();
9941 code = emitInsCode(ins, fmt);
9942 code |= insEncodeElemsize(elemsize); // XX
9943 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9944 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9945 dst += emitOutput_Instr(dst, code);
9948 case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
9949 elemsize = optGetElemsize(id->idInsOpt());
9950 code = emitInsCode(ins, fmt);
9951 code |= insEncodeVectorsize(id->idOpSize()); // Q
9952 code |= insEncodeElemsize(elemsize); // XX
9953 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9954 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9955 dst += emitOutput_Instr(dst, code);
9958 case IF_DV_2N: // DV_2N .........iiiiiii ......nnnnnddddd Vd Vn imm (shift - scalar)
9959 imm = emitGetInsSC(id);
9960 code = emitInsCode(ins, fmt);
9961 code |= insEncodeVectorShift(EA_8BYTE, imm); // iiiiiii
9962 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9963 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9964 dst += emitOutput_Instr(dst, code);
9967 case IF_DV_2O: // DV_2O .Q.......iiiiiii ......nnnnnddddd Vd Vn imm (shift - vector)
9968 imm = emitGetInsSC(id);
9969 elemsize = optGetElemsize(id->idInsOpt());
9970 code = emitInsCode(ins, fmt);
9971 code |= insEncodeVectorsize(id->idOpSize()); // Q
9972 code |= insEncodeVectorShift(elemsize, imm); // iiiiiii
9973 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9974 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9975 dst += emitOutput_Instr(dst, code);
9978 case IF_DV_2P: // DV_2P ............... ......nnnnnddddd Vd Vn (aes*, sha1su1)
9979 elemsize = optGetElemsize(id->idInsOpt());
9980 code = emitInsCode(ins, fmt);
9981 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9982 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9983 dst += emitOutput_Instr(dst, code);
9986 case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
9987 code = emitInsCode(ins, fmt);
9988 elemsize = optGetElemsize(id->idInsOpt());
9989 code |= insEncodeVectorsize(id->idOpSize()); // Q
9990 code |= insEncodeElemsize(elemsize); // XX
9991 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9992 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9993 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9994 dst += emitOutput_Instr(dst, code);
9997 case IF_DV_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector)
9998 code = emitInsCode(ins, fmt);
9999 imm = emitGetInsSC(id);
10000 elemsize = optGetElemsize(id->idInsOpt());
10001 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
10002 code |= insEncodeVectorsize(id->idOpSize()); // Q
10003 code |= insEncodeElemsize(elemsize); // XX
10004 code |= insEncodeVectorIndexLMH(elemsize, imm); // LM H
10005 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
10006 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
10007 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
10008 dst += emitOutput_Instr(dst, code);
10011 case IF_DV_3B: // DV_3B .Q.......X.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
10012 code = emitInsCode(ins, fmt);
10013 elemsize = optGetElemsize(id->idInsOpt());
10014 code |= insEncodeVectorsize(id->idOpSize()); // Q
10015 code |= insEncodeFloatElemsize(elemsize); // X
10016 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
10017 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
10018 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
10019 dst += emitOutput_Instr(dst, code);
10022 case IF_DV_3BI: // DV_3BI .Q.......XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
10023 code = emitInsCode(ins, fmt);
10024 imm = emitGetInsSC(id);
10025 elemsize = optGetElemsize(id->idInsOpt());
10026 assert(isValidVectorIndex(id->idOpSize(), elemsize, imm));
10027 code |= insEncodeVectorsize(id->idOpSize()); // Q
10028 code |= insEncodeFloatElemsize(elemsize); // X
10029 code |= insEncodeFloatIndex(elemsize, imm); // L H
10030 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
10031 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
10032 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
10033 dst += emitOutput_Instr(dst, code);
10036 case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
10037 code = emitInsCode(ins, fmt);
10038 code |= insEncodeVectorsize(id->idOpSize()); // Q
10039 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
10040 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
10041 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
10042 dst += emitOutput_Instr(dst, code);
10045 case IF_DV_3D: // DV_3D .........X.mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
10046 code = emitInsCode(ins, fmt);
10047 code |= insEncodeFloatElemsize(id->idOpSize()); // X
10048 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
10049 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
10050 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
10051 dst += emitOutput_Instr(dst, code);
10054 case IF_DV_3DI: // DV_3DI .........XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (scalar by elem)
10055 code = emitInsCode(ins, fmt);
10056 imm = emitGetInsSC(id);
10057 elemsize = id->idOpSize();
10058 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
10059 code |= insEncodeFloatElemsize(elemsize); // X
10060 code |= insEncodeFloatIndex(elemsize, imm); // L H
10061 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
10062 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
10063 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
10064 dst += emitOutput_Instr(dst, code);
10067 case IF_DV_3E: // DV_3E ...........mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
10068 case IF_DV_3F: // DV_3F ...........mmmmm ......nnnnnddddd Vd Vn Vm (vector) - source dest regs overlap
10069 code = emitInsCode(ins, fmt);
10070 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
10071 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
10072 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
10073 dst += emitOutput_Instr(dst, code);
10076 case IF_DV_4A: // DV_4A .........X.mmmmm .aaaaannnnnddddd Vd Va Vn Vm (scalar)
10077 code = emitInsCode(ins, fmt);
10078 elemsize = id->idOpSize();
10079 code |= insEncodeFloatElemsize(elemsize); // X
10080 code |= insEncodeReg_Vd(id->idReg1()); // ddddd
10081 code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
10082 code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
10083 code |= insEncodeReg_Va(id->idReg4()); // aaaaa
10084 dst += emitOutput_Instr(dst, code);
10087 case IF_SN_0A: // SN_0A ................ ................
10088 code = emitInsCode(ins, fmt);
10089 dst += emitOutput_Instr(dst, code);
10092 case IF_SI_0A: // SI_0A ...........iiiii iiiiiiiiiii..... imm16
10093 imm = emitGetInsSC(id);
10094 assert(isValidUimm16(imm));
10095 code = emitInsCode(ins, fmt);
10096 code |= ((code_t)imm << 5); // iiiii iiiiiiiiiii
10097 dst += emitOutput_Instr(dst, code);
10100 case IF_SI_0B: // SI_0B ................ ....bbbb........ imm4 - barrier
10101 imm = emitGetInsSC(id);
10102 assert((imm >= 0) && (imm <= 15));
10103 code = emitInsCode(ins, fmt);
10104 code |= ((code_t)imm << 8); // bbbb
10105 dst += emitOutput_Instr(dst, code);
10109 assert(!"Unexpected format");
10113 // Determine if any registers now hold GC refs, or whether a register that was overwritten held a GC ref.
10114 // We assume here that "id->idGCref()" is not GC_NONE only if the instruction described by "id" writes a
10115 // GC ref to register "id->idReg1()". (It may, apparently, also not be GC_NONE in other cases, such as
10116 // for stores, but we ignore those cases here.)
10117 if (emitInsMayWriteToGCReg(id)) // True if "id->idIns()" writes to a register than can hold GC ref.
10119 // We assume that "idReg1" is the primary destination register for all instructions
10120 if (id->idGCref() != GCT_NONE)
10122 emitGCregLiveUpd(id->idGCref(), id->idReg1(), dst);
10126 emitGCregDeadUpd(id->idReg1(), dst);
10129 if (emitInsMayWriteMultipleRegs(id))
10132 // "idReg2" is the secondary destination register
10133 if (id->idGCrefReg2() != GCT_NONE)
10135 emitGCregLiveUpd(id->idGCrefReg2(), id->idReg2(), dst);
10139 emitGCregDeadUpd(id->idReg2(), dst);
10144 // Now we determine if the instruction has written to a (local variable) stack location, and either written a GC
10145 // ref or overwritten one.
10146 if (emitInsWritesToLclVarStackLoc(id) || emitInsWritesToLclVarStackLocPair(id))
10148 int varNum = id->idAddr()->iiaLclVar.lvaVarNum();
10149 unsigned ofs = AlignDown(id->idAddr()->iiaLclVar.lvaOffset(), TARGET_POINTER_SIZE);
10151 int adr = emitComp->lvaFrameAddress(varNum, &FPbased);
10152 if (id->idGCref() != GCT_NONE)
10154 emitGCvarLiveUpd(adr + ofs, varNum, id->idGCref(), dst);
10158 // If the type of the local is a gc ref type, update the liveness.
10162 // "Regular" (non-spill-temp) local.
10163 vt = var_types(emitComp->lvaTable[varNum].lvType);
10167 TempDsc* tmpDsc = emitComp->tmpFindNum(varNum);
10168 vt = tmpDsc->tdTempType();
10170 if (vt == TYP_REF || vt == TYP_BYREF)
10171 emitGCvarDeadUpd(adr + ofs, dst);
10173 if (emitInsWritesToLclVarStackLocPair(id))
10175 unsigned ofs2 = ofs + TARGET_POINTER_SIZE;
10176 if (id->idGCrefReg2() != GCT_NONE)
10178 emitGCvarLiveUpd(adr + ofs2, varNum, id->idGCrefReg2(), dst);
10182 // If the type of the local is a gc ref type, update the liveness.
10186 // "Regular" (non-spill-temp) local.
10187 vt = var_types(emitComp->lvaTable[varNum].lvType);
10191 TempDsc* tmpDsc = emitComp->tmpFindNum(varNum);
10192 vt = tmpDsc->tdTempType();
10194 if (vt == TYP_REF || vt == TYP_BYREF)
10195 emitGCvarDeadUpd(adr + ofs2, dst);
10201 /* Make sure we set the instruction descriptor size correctly */
10203 size_t expected = emitSizeOfInsDsc(id);
10204 assert(sz == expected);
10206 if (emitComp->opts.disAsm || emitComp->opts.dspEmit || emitComp->verbose)
10208 emitDispIns(id, false, dspOffs, true, emitCurCodeOffs(odst), *dp, (dst - *dp), ig);
10211 if (emitComp->compDebugBreak)
10213 // For example, set JitBreakEmitOutputInstr=a6 will break when this method is called for
10214 // emitting instruction a6, (i.e. IN00a6 in jitdump).
10215 if ((unsigned)JitConfig.JitBreakEmitOutputInstr() == id->idDebugOnlyInfo()->idNum)
10217 assert(!"JitBreakEmitOutputInstr reached");
10222 /* All instructions are expected to generate code */
10224 assert(*dp != dst);
10231 /*****************************************************************************/
10232 /*****************************************************************************/
10236 /*****************************************************************************
10238 * Display the instruction name
10240 void emitter::emitDispInst(instruction ins)
10242 const char* insstr = codeGen->genInsName(ins);
10243 size_t len = strlen(insstr);
10245 /* Display the instruction name */
10247 printf("%s", insstr);
10250 // Add at least one space after the instruction name
10251 // and add spaces until we have reach the normal size of 8
10259 /*****************************************************************************
10261 * Display an reloc value
10262 * If we are formatting for an assembly listing don't print the hex value
10263 * since it will prevent us from doing assembly diffs
10265 void emitter::emitDispReloc(int value, bool addComma)
10267 if (emitComp->opts.disAsm)
10273 printf("(reloc 0x%x)", dspPtr(value));
10280 /*****************************************************************************
10282 * Display an immediate value
10284 void emitter::emitDispImm(ssize_t imm, bool addComma, bool alwaysHex /* =false */)
10291 // Munge any pointers if we want diff-able disassembly.
10292 // Since some may be emitted as partial words, print as diffable anything that has
10293 // significant bits beyond the lowest 8-bits.
10294 if (emitComp->opts.disDiffable)
10296 ssize_t top56bits = (imm >> 8);
10297 if ((top56bits != 0) && (top56bits != -1))
10301 if (!alwaysHex && (imm > -1000) && (imm < 1000))
10307 if ((imm < 0) && ((imm & 0xFFFFFFFF00000000LL) == 0xFFFFFFFF00000000LL))
10313 if ((imm & 0xFFFFFFFF00000000LL) != 0)
10315 printf("0x%llx", imm);
10319 printf("0x%02x", imm);
10327 /*****************************************************************************
10329 * Display a float zero constant
10331 void emitter::emitDispFloatZero()
10340 /*****************************************************************************
10342 * Display an encoded float constant value
10344 void emitter::emitDispFloatImm(ssize_t imm8)
10346 assert((0 <= imm8) && (imm8 <= 0x0ff));
10353 fpImm.immFPIVal = (unsigned)imm8;
10354 double result = emitDecodeFloatImm8(fpImm);
10356 printf("%.4f", result);
10359 /*****************************************************************************
10361 * Display an immediate that is optionally LSL12.
10363 void emitter::emitDispImmOptsLSL12(ssize_t imm, insOpts opt)
10365 if (!strictArmAsm && insOptsLSL12(opt))
10369 emitDispImm(imm, false);
10370 if (strictArmAsm && insOptsLSL12(opt))
10372 printf(", LSL #12");
10376 /*****************************************************************************
10378 * Display an ARM64 condition code for the conditional instructions
10380 void emitter::emitDispCond(insCond cond)
10382 const static char* armCond[16] = {"eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc",
10383 "hi", "ls", "ge", "lt", "gt", "le", "AL", "NV"}; // The last two are invalid
10384 unsigned imm = (unsigned)cond;
10385 assert((0 <= imm) && (imm < ArrLen(armCond)));
10386 printf(armCond[imm]);
10389 /*****************************************************************************
10391 * Display an ARM64 flags for the conditional instructions
10393 void emitter::emitDispFlags(insCflags flags)
10395 const static char* armFlags[16] = {"0", "v", "c", "cv", "z", "zv", "zc", "zcv",
10396 "n", "nv", "nc", "ncv", "nz", "nzv", "nzc", "nzcv"};
10397 unsigned imm = (unsigned)flags;
10398 assert((0 <= imm) && (imm < ArrLen(armFlags)));
10399 printf(armFlags[imm]);
10402 /*****************************************************************************
10404 * Display an ARM64 'barrier' for the memory barrier instructions
10406 void emitter::emitDispBarrier(insBarrier barrier)
10408 const static char* armBarriers[16] = {"#0", "oshld", "oshst", "osh", "#4", "nshld", "nshst", "nsh",
10409 "#8", "ishld", "ishst", "ish", "#12", "ld", "st", "sy"};
10410 unsigned imm = (unsigned)barrier;
10411 assert((0 <= imm) && (imm < ArrLen(armBarriers)));
10412 printf(armBarriers[imm]);
10415 /*****************************************************************************
10417 * Prints the encoding for the Shift Type encoding
10420 void emitter::emitDispShiftOpts(insOpts opt)
10422 if (opt == INS_OPTS_LSL)
10424 else if (opt == INS_OPTS_LSR)
10426 else if (opt == INS_OPTS_ASR)
10428 else if (opt == INS_OPTS_ROR)
10430 else if (opt == INS_OPTS_MSL)
10433 assert(!"Bad value");
10436 /*****************************************************************************
10438 * Prints the encoding for the Extend Type encoding
10441 void emitter::emitDispExtendOpts(insOpts opt)
10443 if (opt == INS_OPTS_UXTB)
10445 else if (opt == INS_OPTS_UXTH)
10447 else if (opt == INS_OPTS_UXTW)
10449 else if (opt == INS_OPTS_UXTX)
10451 else if (opt == INS_OPTS_SXTB)
10453 else if (opt == INS_OPTS_SXTH)
10455 else if (opt == INS_OPTS_SXTW)
10457 else if (opt == INS_OPTS_SXTX)
10460 assert(!"Bad value");
10463 /*****************************************************************************
10465 * Prints the encoding for the Extend Type encoding in loads/stores
10468 void emitter::emitDispLSExtendOpts(insOpts opt)
10470 if (opt == INS_OPTS_LSL)
10472 else if (opt == INS_OPTS_UXTW)
10474 else if (opt == INS_OPTS_UXTX)
10476 else if (opt == INS_OPTS_SXTW)
10478 else if (opt == INS_OPTS_SXTX)
10481 assert(!"Bad value");
10484 /*****************************************************************************
10486 * Display a register
10488 void emitter::emitDispReg(regNumber reg, emitAttr attr, bool addComma)
10490 emitAttr size = EA_SIZE(attr);
10491 printf(emitRegName(reg, size));
10497 /*****************************************************************************
10499 * Display a vector register with an arrangement suffix
10501 void emitter::emitDispVectorReg(regNumber reg, insOpts opt, bool addComma)
10503 assert(isVectorRegister(reg));
10504 printf(emitVectorRegName(reg));
10505 emitDispArrangement(opt);
10511 /*****************************************************************************
10513 * Display an vector register index suffix
10515 void emitter::emitDispVectorRegIndex(regNumber reg, emitAttr elemsize, ssize_t index, bool addComma)
10517 assert(isVectorRegister(reg));
10518 printf(emitVectorRegName(reg));
10535 assert(!"invalid elemsize");
10539 printf("[%d]", index);
10545 /*****************************************************************************
10547 * Display an arrangement suffix
10549 void emitter::emitDispArrangement(insOpts opt)
10551 const char* str = "???";
10581 assert(!"Invalid insOpt for vector register");
10587 /*****************************************************************************
10589 * Display a register with an optional shift operation
10591 void emitter::emitDispShiftedReg(regNumber reg, insOpts opt, ssize_t imm, emitAttr attr)
10593 emitAttr size = EA_SIZE(attr);
10594 assert((imm & 0x003F) == imm);
10595 assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
10597 printf(emitRegName(reg, size));
10605 emitDispShiftOpts(opt);
10606 emitDispImm(imm, false);
10610 /*****************************************************************************
10612 * Display a register with an optional extend and scale operations
10614 void emitter::emitDispExtendReg(regNumber reg, insOpts opt, ssize_t imm)
10616 assert((imm >= 0) && (imm <= 4));
10617 assert(insOptsNone(opt) || insOptsAnyExtend(opt) || (opt == INS_OPTS_LSL));
10619 // size is based on the extend option, not the instr size.
10620 emitAttr size = insOpts32BitExtend(opt) ? EA_4BYTE : EA_8BYTE;
10624 if (insOptsNone(opt))
10626 emitDispReg(reg, size, false);
10630 emitDispReg(reg, size, true);
10631 if (opt == INS_OPTS_LSL)
10634 emitDispExtendOpts(opt);
10635 if ((imm > 0) || (opt == INS_OPTS_LSL))
10638 emitDispImm(imm, false);
10642 else // !strictArmAsm
10644 if (insOptsNone(opt))
10646 emitDispReg(reg, size, false);
10650 if (opt != INS_OPTS_LSL)
10652 emitDispExtendOpts(opt);
10654 emitDispReg(reg, size, false);
10661 emitDispImm(1 << imm, false);
10666 /*****************************************************************************
10668 * Display an addressing operand [reg + imm]
10670 void emitter::emitDispAddrRI(regNumber reg, insOpts opt, ssize_t imm)
10672 reg = encodingZRtoSP(reg); // ZR (R31) encodes the SP register
10678 emitDispReg(reg, EA_8BYTE, false);
10680 if (!insOptsPostIndex(opt) && (imm != 0))
10683 emitDispImm(imm, false);
10687 if (insOptsPreIndex(opt))
10691 else if (insOptsPostIndex(opt))
10694 emitDispImm(imm, false);
10697 else // !strictArmAsm
10701 const char* operStr = "++";
10708 if (insOptsPreIndex(opt))
10713 emitDispReg(reg, EA_8BYTE, false);
10715 if (insOptsPostIndex(opt))
10720 if (insOptsIndexed(opt))
10726 printf("%c", operStr[1]);
10728 emitDispImm(imm, false);
10733 /*****************************************************************************
10735 * Display an addressing operand [reg + extended reg]
10737 void emitter::emitDispAddrRRExt(regNumber reg1, regNumber reg2, insOpts opt, bool isScaled, emitAttr size)
10739 reg1 = encodingZRtoSP(reg1); // ZR (R31) encodes the SP register
10741 unsigned scale = 0;
10744 scale = NaturalScale_helper(size);
10751 emitDispReg(reg1, EA_8BYTE, true);
10752 emitDispExtendReg(reg2, opt, scale);
10754 else // !strictArmAsm
10756 emitDispReg(reg1, EA_8BYTE, false);
10758 emitDispExtendReg(reg2, opt, scale);
10764 /*****************************************************************************
10766 * Display (optionally) the instruction encoding in hex
10769 void emitter::emitDispInsHex(BYTE* code, size_t sz)
10771 // We do not display the instruction hex if we want diff-able disassembly
10772 if (!emitComp->opts.disDiffable)
10776 printf(" %08X ", (*((code_t*)code)));
10785 /****************************************************************************
10787 * Display the given instruction.
10790 void emitter::emitDispIns(
10791 instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* pCode, size_t sz, insGroup* ig)
10796 id->idDebugOnlyInfo()->idNum; // Do not remove this! It is needed for VisualStudio conditional breakpoints
10798 printf("IN%04x: ", idNum);
10804 if (!emitComp->opts.dspEmit && !isNew && !asmfm && sz)
10807 /* Display the instruction offset */
10809 emitDispInsOffs(offset, doffs);
10811 /* Display the instruction hex code */
10813 emitDispInsHex(pCode, sz);
10817 /* Get the instruction and format */
10819 instruction ins = id->idIns();
10820 insFormat fmt = id->idInsFmt();
10824 /* If this instruction has just been added, check its size */
10826 assert(isNew == false || (int)emitSizeOfInsDsc(id) == emitCurIGfreeNext - (BYTE*)id);
10828 /* Figure out the operand size */
10829 emitAttr size = id->idOpSize();
10830 emitAttr attr = size;
10831 if (id->idGCref() == GCT_GCREF)
10833 else if (id->idGCref() == GCT_BYREF)
10841 bool isExtendAlias;
10849 const char* methodName;
10857 case IF_BI_0A: // BI_0A ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
10858 case IF_BI_0B: // BI_0B ......iiiiiiiiii iiiiiiiiiii..... simm19:00
10861 if (fmt == IF_LARGEJMP)
10863 printf("(LARGEJMP)");
10865 if (id->idAddr()->iiaHasInstrCount())
10867 int instrCount = id->idAddr()->iiaGetInstrCount();
10871 printf("pc%s%d instructions", (instrCount >= 0) ? "+" : "", instrCount);
10875 unsigned insNum = emitFindInsNum(ig, id);
10876 UNATIVE_OFFSET srcOffs = ig->igOffs + emitFindOffset(ig, insNum + 1);
10877 UNATIVE_OFFSET dstOffs = ig->igOffs + emitFindOffset(ig, insNum + 1 + instrCount);
10878 ssize_t relOffs = (ssize_t)(emitOffsetToPtr(dstOffs) - emitOffsetToPtr(srcOffs));
10879 printf("pc%s%d (%d instructions)", (relOffs >= 0) ? "+" : "", relOffs, instrCount);
10882 else if (id->idIsBound())
10884 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10888 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10893 case IF_BI_0C: // BI_0C ......iiiiiiiiii iiiiiiiiiiiiiiii simm26:00
10894 if (id->idIsCallAddr())
10896 offs = (ssize_t)id->idAddr()->iiaAddr;
10902 methodName = emitComp->eeGetMethodFullName((CORINFO_METHOD_HANDLE)id->idDebugOnlyInfo()->idMemCookie);
10907 if (id->idIsDspReloc())
10909 printf("%08X", offs);
10913 printf("%s", methodName);
10917 case IF_BI_1A: // BI_1A ......iiiiiiiiii iiiiiiiiiiittttt Rt simm19:00
10918 assert(insOptsNone(id->idInsOpt()));
10919 emitDispReg(id->idReg1(), size, true);
10920 if (id->idIsBound())
10922 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10926 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10930 case IF_BI_1B: // BI_1B B.......bbbbbiii iiiiiiiiiiittttt Rt imm6, simm14:00
10931 assert(insOptsNone(id->idInsOpt()));
10932 emitDispReg(id->idReg1(), size, true);
10933 emitDispImm(emitGetInsSC(id), true);
10934 if (id->idIsBound())
10936 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10940 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10944 case IF_BR_1A: // BR_1A ................ ......nnnnn..... Rn
10945 assert(insOptsNone(id->idInsOpt()));
10946 emitDispReg(id->idReg1(), size, false);
10949 case IF_BR_1B: // BR_1B ................ ......nnnnn..... Rn
10950 assert(insOptsNone(id->idInsOpt()));
10951 emitDispReg(id->idReg3(), size, false);
10954 case IF_LS_1A: // LS_1A XX...V..iiiiiiii iiiiiiiiiiittttt Rt PC imm(1MB)
10955 case IF_DI_1E: // DI_1E .ii.....iiiiiiii iiiiiiiiiiiddddd Rd simm21
10958 assert(insOptsNone(id->idInsOpt()));
10959 emitDispReg(id->idReg1(), size, true);
10960 imm = emitGetInsSC(id);
10962 /* Is this actually a reference to a data section? */
10963 if (fmt == IF_LARGEADR)
10965 printf("(LARGEADR)");
10967 else if (fmt == IF_LARGELDC)
10969 printf("(LARGELDC)");
10973 if (id->idAddr()->iiaIsJitDataOffset())
10975 doffs = Compiler::eeGetJitDataOffs(id->idAddr()->iiaFieldHnd);
10976 /* Display a data section reference */
10979 printf("@CNS%02u", doffs - 1);
10981 printf("@RWD%02u", doffs);
10984 printf("%+Id", imm);
10989 if (id->idIsReloc())
10992 emitDispImm((ssize_t)id->idAddr()->iiaAddr, false);
10994 else if (id->idIsBound())
10996 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
11000 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
11006 case IF_LS_2A: // LS_2A .X.......X...... ......nnnnnttttt Rt Rn
11007 assert(insOptsNone(id->idInsOpt()));
11008 assert(emitGetInsSC(id) == 0);
11009 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
11010 emitDispAddrRI(id->idReg2(), id->idInsOpt(), 0);
11013 case IF_LS_2B: // LS_2B .X.......Xiiiiii iiiiiinnnnnttttt Rt Rn imm(0-4095)
11014 assert(insOptsNone(id->idInsOpt()));
11015 imm = emitGetInsSC(id);
11016 scale = NaturalScale_helper(emitInsLoadStoreSize(id));
11017 imm <<= scale; // The immediate is scaled by the size of the ld/st
11018 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
11019 emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
11022 case IF_LS_2C: // LS_2C .X.......X.iiiii iiiiPPnnnnnttttt Rt Rn imm(-256..+255) no/pre/post inc
11023 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
11024 imm = emitGetInsSC(id);
11025 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
11026 emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
11029 case IF_LS_3A: // LS_3A .X.......X.mmmmm oooS..nnnnnttttt Rt Rn Rm ext(Rm) LSL {}
11030 assert(insOptsLSExtend(id->idInsOpt()));
11031 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
11032 if (id->idIsLclVar())
11034 emitDispAddrRRExt(id->idReg2(), codeGen->rsGetRsvdReg(), id->idInsOpt(), false, size);
11038 emitDispAddrRRExt(id->idReg2(), id->idReg3(), id->idInsOpt(), id->idReg3Scaled(), size);
11042 case IF_LS_3B: // LS_3B X............... .aaaaannnnnddddd Rt Ra Rn
11043 assert(insOptsNone(id->idInsOpt()));
11044 assert(emitGetInsSC(id) == 0);
11045 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
11046 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
11047 emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
11050 case IF_LS_3C: // LS_3C X.........iiiiii iaaaaannnnnddddd Rt Ra Rn imm(im7,sh)
11051 assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
11052 imm = emitGetInsSC(id);
11053 scale = NaturalScale_helper(emitInsLoadStoreSize(id));
11055 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
11056 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
11057 emitDispAddrRI(id->idReg3(), id->idInsOpt(), imm);
11060 case IF_LS_3D: // LS_3D .X.......X.mmmmm ......nnnnnttttt Wm Rt Rn
11061 assert(insOptsNone(id->idInsOpt()));
11062 emitDispReg(id->idReg1(), EA_4BYTE, true);
11063 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
11064 emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
11067 case IF_LS_3E: // LS_3E .X.........mmmmm ......nnnnnttttt Rm Rt Rn ARMv8.1 LSE Atomics
11068 assert(insOptsNone(id->idInsOpt()));
11069 emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
11070 emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
11071 emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
11074 case IF_DI_1A: // DI_1A X.......shiiiiii iiiiiinnnnn..... Rn imm(i12,sh)
11075 emitDispReg(id->idReg1(), size, true);
11076 emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
11079 case IF_DI_1B: // DI_1B X........hwiiiii iiiiiiiiiiiddddd Rd imm(i16,hw)
11080 emitDispReg(id->idReg1(), size, true);
11081 hwi.immHWVal = (unsigned)emitGetInsSC(id);
11082 if (ins == INS_mov)
11084 emitDispImm(emitDecodeHalfwordImm(hwi, size), false);
11086 else // movz, movn, movk
11088 emitDispImm(hwi.immVal, false);
11089 if (hwi.immHW != 0)
11091 emitDispShiftOpts(INS_OPTS_LSL);
11092 emitDispImm(hwi.immHW * 16, false);
11097 case IF_DI_1C: // DI_1C X........Nrrrrrr ssssssnnnnn..... Rn imm(N,r,s)
11098 emitDispReg(id->idReg1(), size, true);
11099 bmi.immNRS = (unsigned)emitGetInsSC(id);
11100 emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
11103 case IF_DI_1D: // DI_1D X........Nrrrrrr ssssss.....ddddd Rd imm(N,r,s)
11104 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11105 bmi.immNRS = (unsigned)emitGetInsSC(id);
11106 emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
11109 case IF_DI_2A: // DI_2A X.......shiiiiii iiiiiinnnnnddddd Rd Rn imm(i12,sh)
11110 if ((ins == INS_add) || (ins == INS_sub))
11112 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11113 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11117 emitDispReg(id->idReg1(), size, true);
11118 emitDispReg(id->idReg2(), size, true);
11120 emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
11123 case IF_DI_2B: // DI_2B X........X.nnnnn ssssssnnnnnddddd Rd Rn imm(0-63)
11124 emitDispReg(id->idReg1(), size, true);
11125 emitDispReg(id->idReg2(), size, true);
11126 emitDispImm(emitGetInsSC(id), false);
11129 case IF_DI_2C: // DI_2C X........Nrrrrrr ssssssnnnnnddddd Rd Rn imm(N,r,s)
11130 if (ins == INS_ands)
11132 emitDispReg(id->idReg1(), size, true);
11136 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11138 emitDispReg(id->idReg2(), size, true);
11139 bmi.immNRS = (unsigned)emitGetInsSC(id);
11140 emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
11143 case IF_DI_2D: // DI_2D X........Nrrrrrr ssssssnnnnnddddd Rd Rn imr, ims (N,r,s)
11144 emitDispReg(id->idReg1(), size, true);
11145 emitDispReg(id->idReg2(), size, true);
11147 imm = emitGetInsSC(id);
11148 bmi.immNRS = (unsigned)imm;
11155 emitDispImm(bmi.immR, true);
11156 emitDispImm(bmi.immS, false);
11162 emitDispImm(getBitWidth(size) - bmi.immR, true);
11163 emitDispImm(bmi.immS + 1, false);
11169 emitDispImm(bmi.immR, true);
11170 emitDispImm(bmi.immS - bmi.immR + 1, false);
11176 emitDispImm(imm, false);
11180 assert(!"Unexpected instruction in IF_DI_2D");
11185 case IF_DI_1F: // DI_1F X..........iiiii cccc..nnnnn.nzcv Rn imm5 nzcv cond
11186 emitDispReg(id->idReg1(), size, true);
11187 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11188 emitDispImm(cfi.imm5, true);
11189 emitDispFlags(cfi.flags);
11191 emitDispCond(cfi.cond);
11194 case IF_DR_1D: // DR_1D X............... cccc.......mmmmm Rd cond
11195 emitDispReg(id->idReg1(), size, true);
11196 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11197 emitDispCond(cfi.cond);
11200 case IF_DR_2A: // DR_2A X..........mmmmm ......nnnnn..... Rn Rm
11201 emitDispReg(id->idReg1(), size, true);
11202 emitDispReg(id->idReg2(), size, false);
11205 case IF_DR_2B: // DR_2B X.......sh.mmmmm ssssssnnnnn..... Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
11206 emitDispReg(id->idReg1(), size, true);
11207 emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
11210 case IF_DR_2C: // DR_2C X..........mmmmm ooosssnnnnn..... Rn Rm ext(Rm) LSL imm(0-4)
11211 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11212 imm = emitGetInsSC(id);
11213 emitDispExtendReg(id->idReg2(), id->idInsOpt(), imm);
11216 case IF_DR_2D: // DR_2D X..........nnnnn cccc..nnnnnddddd Rd Rn cond
11217 emitDispReg(id->idReg1(), size, true);
11218 emitDispReg(id->idReg2(), size, true);
11219 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11220 emitDispCond(cfi.cond);
11223 case IF_DR_2E: // DR_2E X..........mmmmm ...........ddddd Rd Rm
11224 case IF_DR_2J: // DR_2J ................ ......nnnnnddddd Sd Sn
11225 emitDispReg(id->idReg1(), size, true);
11226 emitDispReg(id->idReg2(), size, false);
11229 case IF_DR_2F: // DR_2F X.......sh.mmmmm ssssss.....ddddd Rd Rm {LSL,LSR,ASR} imm(0-63)
11230 emitDispReg(id->idReg1(), size, true);
11231 emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
11234 case IF_DR_2G: // DR_2G X............... ......nnnnnddddd Rd Rn
11235 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11236 emitDispReg(encodingZRtoSP(id->idReg2()), size, false);
11239 case IF_DR_2H: // DR_2H X........X...... ......nnnnnddddd Rd Rn
11240 emitDispReg(id->idReg1(), size, true);
11241 emitDispReg(id->idReg2(), size, false);
11244 case IF_DR_2I: // DR_2I X..........mmmmm cccc..nnnnn.nzcv Rn Rm nzcv cond
11245 emitDispReg(id->idReg1(), size, true);
11246 emitDispReg(id->idReg2(), size, true);
11247 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11248 emitDispFlags(cfi.flags);
11250 emitDispCond(cfi.cond);
11253 case IF_DR_3A: // DR_3A X..........mmmmm ......nnnnnmmmmm Rd Rn Rm
11254 if ((ins == INS_add) || (ins == INS_sub))
11256 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11257 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11259 else if ((ins == INS_smull) || (ins == INS_smulh))
11261 // Rd is always 8 bytes
11262 emitDispReg(id->idReg1(), EA_8BYTE, true);
11264 // Rn, Rm effective size depends on instruction type
11265 size = (ins == INS_smulh) ? EA_8BYTE : EA_4BYTE;
11266 emitDispReg(id->idReg2(), size, true);
11270 emitDispReg(id->idReg1(), size, true);
11271 emitDispReg(id->idReg2(), size, true);
11273 if (id->idIsLclVar())
11275 emitDispReg(codeGen->rsGetRsvdReg(), size, false);
11279 emitDispReg(id->idReg3(), size, false);
11284 case IF_DR_3B: // DR_3B X.......sh.mmmmm ssssssnnnnnddddd Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
11285 emitDispReg(id->idReg1(), size, true);
11286 emitDispReg(id->idReg2(), size, true);
11287 emitDispShiftedReg(id->idReg3(), id->idInsOpt(), emitGetInsSC(id), size);
11290 case IF_DR_3C: // DR_3C X..........mmmmm ooosssnnnnnddddd Rd Rn Rm ext(Rm) LSL imm(0-4)
11291 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11292 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11293 imm = emitGetInsSC(id);
11294 emitDispExtendReg(id->idReg3(), id->idInsOpt(), imm);
11297 case IF_DR_3D: // DR_3D X..........mmmmm cccc..nnnnnmmmmm Rd Rn Rm cond
11298 emitDispReg(id->idReg1(), size, true);
11299 emitDispReg(id->idReg2(), size, true);
11300 emitDispReg(id->idReg3(), size, true);
11301 cfi.immCFVal = (unsigned)emitGetInsSC(id);
11302 emitDispCond(cfi.cond);
11305 case IF_DR_3E: // DR_3E X........X.mmmmm ssssssnnnnnddddd Rd Rn Rm imm(0-63)
11306 emitDispReg(id->idReg1(), size, true);
11307 emitDispReg(id->idReg2(), size, true);
11308 emitDispReg(id->idReg3(), size, true);
11309 emitDispImm(emitGetInsSC(id), false);
11312 case IF_DR_4A: // DR_4A X..........mmmmm .aaaaannnnnmmmmm Rd Rn Rm Ra
11313 emitDispReg(id->idReg1(), size, true);
11314 emitDispReg(id->idReg2(), size, true);
11315 emitDispReg(id->idReg3(), size, true);
11316 emitDispReg(id->idReg4(), size, false);
11319 case IF_DV_1A: // DV_1A .........X.iiiii iii........ddddd Vd imm8 (fmov - immediate scalar)
11320 elemsize = id->idOpSize();
11321 emitDispReg(id->idReg1(), elemsize, true);
11322 emitDispFloatImm(emitGetInsSC(id));
11325 case IF_DV_1B: // DV_1B .QX..........iii cmod..iiiiiddddd Vd imm8 (immediate vector)
11326 imm = emitGetInsSC(id) & 0x0ff;
11327 immShift = (emitGetInsSC(id) & 0x700) >> 8;
11328 hasShift = (immShift != 0);
11329 elemsize = optGetElemsize(id->idInsOpt());
11330 if (id->idInsOpt() == INS_OPTS_1D)
11332 assert(elemsize == size);
11333 emitDispReg(id->idReg1(), size, true);
11337 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11339 if (ins == INS_fmov)
11341 emitDispFloatImm(imm);
11342 assert(hasShift == false);
11346 if (elemsize == EA_8BYTE)
11348 assert(ins == INS_movi);
11350 const ssize_t mask8 = 0xFF;
11351 for (unsigned b = 0; b < 8; b++)
11353 if (imm & (1 << b))
11355 imm64 |= (mask8 << (b * 8));
11358 emitDispImm(imm64, hasShift, true);
11362 emitDispImm(imm, hasShift, true);
11366 insOpts opt = (immShift & 0x4) ? INS_OPTS_MSL : INS_OPTS_LSL;
11367 unsigned shift = (immShift & 0x3) * 8;
11368 emitDispShiftOpts(opt);
11369 emitDispImm(shift, false);
11374 case IF_DV_1C: // DV_1C .........X...... ......nnnnn..... Vn #0.0 (fcmp - with zero)
11375 elemsize = id->idOpSize();
11376 emitDispReg(id->idReg1(), elemsize, true);
11377 emitDispFloatZero();
11380 case IF_DV_2A: // DV_2A .Q.......X...... ......nnnnnddddd Vd Vn (fabs, fcvt - vector)
11381 case IF_DV_2M: // DV_2M .Q......XX...... ......nnnnnddddd Vd Vn (abs, neg - vector)
11382 case IF_DV_2P: // DV_2P ................ ......nnnnnddddd Vd Vn (aes*, sha1su1)
11383 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11384 emitDispVectorReg(id->idReg2(), id->idInsOpt(), false);
11387 case IF_DV_2N: // DV_2N .........iiiiiii ......nnnnnddddd Vd Vn imm (shift - scalar)
11388 elemsize = id->idOpSize();
11389 emitDispReg(id->idReg1(), elemsize, true);
11390 emitDispReg(id->idReg2(), elemsize, true);
11391 emitDispImm(emitGetInsSC(id), false);
11394 case IF_DV_2O: // DV_2O .Q.......iiiiiii ......nnnnnddddd Vd Vn imm (shift - vector)
11395 imm = emitGetInsSC(id);
11396 // Do we have a sxtl or uxtl instruction?
11397 isExtendAlias = ((ins == INS_sxtl) || (ins == INS_sxtl2) || (ins == INS_uxtl) || (ins == INS_uxtl2));
11398 code = emitInsCode(ins, fmt);
11399 if (code & 0x00008000) // widen/narrow opcodes
11401 if (code & 0x00002000) // SHL opcodes
11403 emitDispVectorReg(id->idReg1(), optWidenElemsize(id->idInsOpt()), true);
11404 emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11406 else // SHR opcodes
11408 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11409 emitDispVectorReg(id->idReg2(), optWidenElemsize(id->idInsOpt()), !isExtendAlias);
11414 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11415 emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11417 // Print the immediate unless we have a sxtl or uxtl instruction
11418 if (!isExtendAlias)
11420 emitDispImm(imm, false);
11424 case IF_DV_2B: // DV_2B .Q.........iiiii ......nnnnnddddd Rd Vn[] (umov/smov - to general)
11425 srcsize = id->idOpSize();
11426 index = emitGetInsSC(id);
11427 if (ins == INS_smov)
11429 dstsize = EA_8BYTE;
11431 else // INS_umov or INS_mov
11433 dstsize = (srcsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE;
11435 emitDispReg(id->idReg1(), dstsize, true);
11436 emitDispVectorRegIndex(id->idReg2(), srcsize, index, false);
11439 case IF_DV_2C: // DV_2C .Q.........iiiii ......nnnnnddddd Vd Rn (dup/ins - vector from general)
11440 if (ins == INS_dup)
11442 datasize = id->idOpSize();
11443 assert(isValidVectorDatasize(datasize));
11444 assert(isValidArrangement(datasize, id->idInsOpt()));
11445 elemsize = optGetElemsize(id->idInsOpt());
11446 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11450 elemsize = id->idOpSize();
11451 index = emitGetInsSC(id);
11452 assert(isValidVectorElemsize(elemsize));
11453 emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11455 emitDispReg(id->idReg2(), (elemsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE, false);
11458 case IF_DV_2D: // DV_2D .Q.........iiiii ......nnnnnddddd Vd Vn[] (dup - vector)
11459 datasize = id->idOpSize();
11460 assert(isValidVectorDatasize(datasize));
11461 assert(isValidArrangement(datasize, id->idInsOpt()));
11462 elemsize = optGetElemsize(id->idInsOpt());
11463 index = emitGetInsSC(id);
11464 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11465 emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11468 case IF_DV_2E: // DV_2E ...........iiiii ......nnnnnddddd Vd Vn[] (dup - scalar)
11469 elemsize = id->idOpSize();
11470 index = emitGetInsSC(id);
11471 emitDispReg(id->idReg1(), elemsize, true);
11472 emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11475 case IF_DV_2F: // DV_2F ...........iiiii .jjjj.nnnnnddddd Vd[] Vn[] (ins - element)
11476 imm = emitGetInsSC(id);
11477 index = (imm >> 4) & 0xf;
11478 index2 = imm & 0xf;
11479 elemsize = id->idOpSize();
11480 emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11481 emitDispVectorRegIndex(id->idReg2(), elemsize, index2, false);
11484 case IF_DV_2G: // DV_2G .........X...... ......nnnnnddddd Vd Vn (fmov, fcvtXX - register)
11485 case IF_DV_2K: // DV_2K .........X.mmmmm ......nnnnn..... Vn Vm (fcmp)
11486 case IF_DV_2L: // DV_2L ........XX...... ......nnnnnddddd Vd Vn (abs, neg - scalar)
11487 elemsize = id->idOpSize();
11488 emitDispReg(id->idReg1(), elemsize, true);
11489 emitDispReg(id->idReg2(), elemsize, false);
11492 case IF_DV_2H: // DV_2H X........X...... ......nnnnnddddd Rd Vn (fmov, fcvtXX - to general)
11493 case IF_DV_2I: // DV_2I X........X...... ......nnnnnddddd Vd Rn (fmov, Xcvtf - from general)
11494 case IF_DV_2J: // DV_2J ........SS.....D D.....nnnnnddddd Vd Vn (fcvt)
11495 dstsize = optGetDstsize(id->idInsOpt());
11496 srcsize = optGetSrcsize(id->idInsOpt());
11498 emitDispReg(id->idReg1(), dstsize, true);
11499 emitDispReg(id->idReg2(), srcsize, false);
11502 case IF_DV_3A: // DV_3A .Q......XX.mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11503 case IF_DV_3B: // DV_3B .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11504 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11505 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11506 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11509 case IF_DV_3C: // DV_3C .Q.........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11510 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11511 if (ins != INS_mov)
11513 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11515 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11518 case IF_DV_3AI: // DV_3AI .Q......XXLMmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
11519 case IF_DV_3BI: // DV_3BI .Q........Lmmmmm ....H.nnnnnddddd Vd Vn Vm[] (vector by elem)
11520 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11521 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11522 elemsize = optGetElemsize(id->idInsOpt());
11523 emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11526 case IF_DV_3D: // DV_3D .........X.mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
11527 case IF_DV_3E: // DV_3E ...........mmmmm ......nnnnnddddd Vd Vn Vm (scalar)
11528 emitDispReg(id->idReg1(), size, true);
11529 emitDispReg(id->idReg2(), size, true);
11530 emitDispReg(id->idReg3(), size, false);
11533 case IF_DV_3F: // DV_3F ..........mmmmm ......nnnnnddddd Vd Vn Vm (vector)
11534 if ((ins == INS_sha1c) || (ins == INS_sha1m) || (ins == INS_sha1p))
11536 // Qd, Sn, Vm (vector)
11537 emitDispReg(id->idReg1(), size, true);
11538 emitDispReg(id->idReg2(), EA_4BYTE, true);
11539 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11541 else if ((ins == INS_sha256h) || (ins == INS_sha256h2))
11543 // Qd Qn Vm (vector)
11544 emitDispReg(id->idReg1(), size, true);
11545 emitDispReg(id->idReg2(), size, true);
11546 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11548 else // INS_sha1su0, INS_sha256su1
11550 // Vd, Vn, Vm (vector)
11551 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11552 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11553 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11557 case IF_DV_3DI: // DV_3DI .........XLmmmmm ....H.nnnnnddddd Vd Vn Vm[] (scalar by elem)
11558 emitDispReg(id->idReg1(), size, true);
11559 emitDispReg(id->idReg2(), size, true);
11561 emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11564 case IF_DV_4A: // DV_4A .........X.mmmmm .aaaaannnnnddddd Vd Va Vn Vm (scalar)
11565 emitDispReg(id->idReg1(), size, true);
11566 emitDispReg(id->idReg2(), size, true);
11567 emitDispReg(id->idReg3(), size, true);
11568 emitDispReg(id->idReg4(), size, false);
11571 case IF_SN_0A: // SN_0A ................ ................
11574 case IF_SI_0A: // SI_0A ...........iiiii iiiiiiiiiii..... imm16
11575 emitDispImm(emitGetInsSC(id), false);
11578 case IF_SI_0B: // SI_0B ................ ....bbbb........ imm4 - barrier
11579 emitDispBarrier((insBarrier)emitGetInsSC(id));
11583 printf("unexpected format %s", emitIfName(id->idInsFmt()));
11584 assert(!"unexpectedFormat");
11588 if (id->idDebugOnlyInfo()->idVarRefOffs)
11591 emitDispFrameRef(id->idAddr()->iiaLclVar.lvaVarNum(), id->idAddr()->iiaLclVar.lvaOffset(),
11592 id->idDebugOnlyInfo()->idVarRefOffs, asmfm);
11598 /*****************************************************************************
11600 * Display a stack frame reference.
11603 void emitter::emitDispFrameRef(int varx, int disp, int offs, bool asmfm)
11608 printf("TEMP_%02u", -varx);
11610 emitComp->gtDispLclVar(+varx, false);
11613 printf("-0x%02x", -disp);
11615 printf("+0x%02x", +disp);
11619 if (varx >= 0 && emitComp->opts.varNames)
11622 const char* varName;
11624 assert((unsigned)varx < emitComp->lvaCount);
11625 varDsc = emitComp->lvaTable + varx;
11626 varName = emitComp->compLocalVarName(varx, offs);
11630 printf("'%s", varName);
11633 printf("-%d", -disp);
11635 printf("+%d", +disp);
11644 // Generate code for a load or store operation with a potentially complex addressing mode
11645 // This method handles the case of a GT_IND with contained GT_LEA op1 of the x86 form [base + index*sccale + offset]
11646 // Since Arm64 does not directly support this complex of an addressing mode
11647 // we may generates up to three instructions for this for Arm64
11649 void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataReg, GenTreeIndir* indir)
11651 emitAttr ldstAttr = isVectorRegister(dataReg) ? attr : emitInsAdjustLoadStoreAttr(ins, attr);
11653 GenTree* addr = indir->Addr();
11655 if (addr->isContained())
11657 assert(addr->OperGet() == GT_LCL_VAR_ADDR || addr->OperGet() == GT_LEA);
11662 if (addr->OperGet() == GT_LEA)
11664 offset = addr->AsAddrMode()->Offset();
11665 if (addr->AsAddrMode()->gtScale > 0)
11667 assert(isPow2(addr->AsAddrMode()->gtScale));
11668 BitScanForward(&lsl, addr->AsAddrMode()->gtScale);
11672 GenTree* memBase = indir->Base();
11674 if (indir->HasIndex())
11676 GenTree* index = indir->Index();
11680 regNumber tmpReg = indir->GetSingleTempReg();
11682 emitAttr addType = varTypeIsGC(memBase) ? EA_BYREF : EA_PTRSIZE;
11684 if (emitIns_valid_imm_for_add(offset, EA_8BYTE))
11688 // Generate code to set tmpReg = base + index*scale
11689 emitIns_R_R_R_I(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum, lsl,
11694 // Generate code to set tmpReg = base + index
11695 emitIns_R_R_R(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum);
11698 noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11700 // Then load/store dataReg from/to [tmpReg + offset]
11701 emitIns_R_R_I(ins, ldstAttr, dataReg, tmpReg, offset);
11703 else // large offset
11705 // First load/store tmpReg with the large offset constant
11706 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11707 // Then add the base register
11709 emitIns_R_R_R(INS_add, addType, tmpReg, tmpReg, memBase->gtRegNum);
11711 noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11712 noway_assert(tmpReg != index->gtRegNum);
11714 // Then load/store dataReg from/to [tmpReg + index*scale]
11715 emitIns_R_R_R_I(ins, ldstAttr, dataReg, tmpReg, index->gtRegNum, lsl, INS_OPTS_LSL);
11718 else // (offset == 0)
11722 // Then load/store dataReg from/to [memBase + index*scale]
11723 emitIns_R_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum, lsl, INS_OPTS_LSL);
11727 // Then load/store dataReg from/to [memBase + index]
11728 emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum);
11732 else // no Index register
11734 if (emitIns_valid_imm_for_ldst_offset(offset, EA_SIZE(attr)))
11736 // Then load/store dataReg from/to [memBase + offset]
11737 emitIns_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, offset);
11741 // We require a tmpReg to hold the offset
11742 regNumber tmpReg = indir->GetSingleTempReg();
11744 // First load/store tmpReg with the large offset constant
11745 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11747 // Then load/store dataReg from/to [memBase + tmpReg]
11748 emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, tmpReg);
11752 else // addr is not contained, so we evaluate it into a register
11754 // Then load/store dataReg from/to [addrReg]
11755 emitIns_R_R(ins, ldstAttr, dataReg, addr->gtRegNum);
11759 // The callee must call genConsumeReg() for any non-contained srcs
11760 // and genProduceReg() for any non-contained dsts.
11762 regNumber emitter::emitInsBinary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src)
11764 regNumber result = REG_NA;
11766 // dst can only be a reg
11767 assert(!dst->isContained());
11769 // src can be immed or reg
11770 assert(!src->isContained() || src->isContainedIntOrIImmed());
11772 // find immed (if any) - it cannot be a dst
11773 GenTreeIntConCommon* intConst = nullptr;
11774 if (src->isContainedIntOrIImmed())
11776 intConst = src->AsIntConCommon();
11781 emitIns_R_I(ins, attr, dst->gtRegNum, intConst->IconValue());
11782 return dst->gtRegNum;
11786 emitIns_R_R(ins, attr, dst->gtRegNum, src->gtRegNum);
11787 return dst->gtRegNum;
11791 // The callee must call genConsumeReg() for any non-contained srcs
11792 // and genProduceReg() for any non-contained dsts.
11794 regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src1, GenTree* src2)
11796 regNumber result = REG_NA;
11798 // dst can only be a reg
11799 assert(!dst->isContained());
11801 // find immed (if any) - it cannot be a dst
11802 // Only one src can be an int.
11803 GenTreeIntConCommon* intConst = nullptr;
11804 GenTree* nonIntReg = nullptr;
11806 if (varTypeIsFloating(dst))
11808 // src1 can only be a reg
11809 assert(!src1->isContained());
11810 // src2 can only be a reg
11811 assert(!src2->isContained());
11813 else // not floating point
11815 // src2 can be immed or reg
11816 assert(!src2->isContained() || src2->isContainedIntOrIImmed());
11818 // Check src2 first as we can always allow it to be a contained immediate
11819 if (src2->isContainedIntOrIImmed())
11821 intConst = src2->AsIntConCommon();
11824 // Only for commutative operations do we check src1 and allow it to be a contained immediate
11825 else if (dst->OperIsCommutative())
11827 // src1 can be immed or reg
11828 assert(!src1->isContained() || src1->isContainedIntOrIImmed());
11830 // Check src1 and allow it to be a contained immediate
11831 if (src1->isContainedIntOrIImmed())
11833 assert(!src2->isContainedIntOrIImmed());
11834 intConst = src1->AsIntConCommon();
11840 // src1 can only be a reg
11841 assert(!src1->isContained());
11845 bool isMulOverflow = false;
11846 if (dst->gtOverflowEx())
11848 if ((ins == INS_add) || (ins == INS_adds))
11852 else if ((ins == INS_sub) || (ins == INS_subs))
11856 else if (ins == INS_mul)
11858 isMulOverflow = true;
11859 assert(intConst == nullptr); // overflow format doesn't support an int constant operand
11863 assert(!"Invalid ins for overflow check");
11866 if (intConst != nullptr)
11868 emitIns_R_R_I(ins, attr, dst->gtRegNum, nonIntReg->gtRegNum, intConst->IconValue());
11874 regNumber extraReg = dst->GetSingleTempReg();
11875 assert(extraReg != dst->gtRegNum);
11877 if ((dst->gtFlags & GTF_UNSIGNED) != 0)
11879 if (attr == EA_4BYTE)
11881 // Compute 8 byte results from 4 byte by 4 byte multiplication.
11882 emitIns_R_R_R(INS_umull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11884 // Get the high result by shifting dst.
11885 emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11889 assert(attr == EA_8BYTE);
11890 // Compute the high result.
11891 emitIns_R_R_R(INS_umulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11893 // Now multiply without skewing the high result.
11894 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11897 // zero-sign bit comparison to detect overflow.
11898 emitIns_R_I(INS_cmp, attr, extraReg, 0);
11903 if (attr == EA_4BYTE)
11905 // Compute 8 byte results from 4 byte by 4 byte multiplication.
11906 emitIns_R_R_R(INS_smull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11908 // Get the high result by shifting dst.
11909 emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11915 assert(attr == EA_8BYTE);
11916 // Save the high result in a temporary register.
11917 emitIns_R_R_R(INS_smulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11919 // Now multiply without skewing the high result.
11920 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11925 // Sign bit comparison to detect overflow.
11926 emitIns_R_R_I(INS_cmp, attr, extraReg, dst->gtRegNum, bitShift, INS_OPTS_ASR);
11931 // We can just multiply.
11932 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11936 if (dst->gtOverflowEx())
11938 assert(!varTypeIsFloating(dst));
11939 codeGen->genCheckOverflow(dst);
11942 return dst->gtRegNum;
11945 #endif // defined(_TARGET_ARM64_)