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
18 #if defined(_TARGET_ARM_)
20 /*****************************************************************************/
21 /*****************************************************************************/
27 /*****************************************************************************/
29 const instruction emitJumpKindInstructions[] = {
32 #define JMP_SMALL(en, rev, ins) INS_##ins,
36 const emitJumpKind emitReverseJumpKinds[] = {
39 #define JMP_SMALL(en, rev, ins) EJ_##rev,
43 /*****************************************************************************
44 * Look up the instruction for a jump kind
47 /*static*/ instruction emitter::emitJumpKindToIns(emitJumpKind jumpKind)
49 assert((unsigned)jumpKind < ArrLen(emitJumpKindInstructions));
50 return emitJumpKindInstructions[jumpKind];
53 /*****************************************************************************
54 * Look up the jump kind for an instruction. It better be a conditional
55 * branch instruction with a jump kind!
58 /*static*/ emitJumpKind emitter::emitInsToJumpKind(instruction ins)
60 for (unsigned i = 0; i < ArrLen(emitJumpKindInstructions); i++)
62 if (ins == emitJumpKindInstructions[i])
64 emitJumpKind ret = (emitJumpKind)i;
65 assert(EJ_NONE < ret && ret < EJ_COUNT);
72 /*****************************************************************************
73 * Reverse the conditional jump
76 /*static*/ emitJumpKind emitter::emitReverseJumpKind(emitJumpKind jumpKind)
78 assert(jumpKind < EJ_COUNT);
79 return emitReverseJumpKinds[jumpKind];
82 /*****************************************************************************
84 * Return the allocated size (in bytes) of the given instruction descriptor.
87 size_t emitter::emitSizeOfInsDsc(instrDesc* id)
89 if (emitIsScnsInsDsc(id))
90 return SMALL_IDSC_SIZE;
92 assert((unsigned)id->idInsFmt() < emitFmtCount);
94 ID_OPS idOp = (ID_OPS)emitFmtToOps[id->idInsFmt()];
95 bool isCallIns = (id->idIns() == INS_bl) || (id->idIns() == INS_blx);
96 bool maybeCallIns = (id->idIns() == INS_b) || (id->idIns() == INS_bx);
98 // An INS_call instruction may use a "fat" direct/indirect call descriptor
99 // except for a local call to a label (i.e. call to a finally).
100 // Only ID_OP_CALL and ID_OP_SPEC check for this, so we enforce that the
101 // INS_call instruction always uses one of these idOps.
103 assert(!isCallIns || // either not a call or
104 idOp == ID_OP_CALL || // is a direct call
105 idOp == ID_OP_SPEC || // is an indirect call
106 idOp == ID_OP_JMP); // is a local call to finally clause
114 return sizeof(instrDescJmp);
117 return sizeof(instrDescLbl);
121 assert(isCallIns || maybeCallIns);
122 if (id->idIsLargeCall())
124 /* Must be a "fat" indirect call descriptor */
125 return sizeof(instrDescCGCA);
129 assert(!id->idIsLargeDsp());
130 assert(!id->idIsLargeCns());
131 return sizeof(instrDesc);
136 NO_WAY("unexpected instruction descriptor format");
140 if (id->idInsFmt() == IF_T2_N3)
142 assert((id->idIns() == INS_movw) || (id->idIns() == INS_movt));
143 return sizeof(instrDescReloc);
146 if (id->idIsLargeCns())
148 if (id->idIsLargeDsp())
149 return sizeof(instrDescCnsDsp);
151 return sizeof(instrDescCns);
155 if (id->idIsLargeDsp())
156 return sizeof(instrDescDsp);
158 return sizeof(instrDesc);
162 bool offsetFitsInVectorMem(int disp)
164 unsigned imm = unsigned_abs(disp);
165 return ((imm & 0x03fc) == imm);
169 /*****************************************************************************
171 * The following called for each recorded instruction -- use for debugging.
173 void emitter::emitInsSanityCheck(instrDesc* id)
175 /* What instruction format have we got? */
177 switch (id->idInsFmt())
179 case IF_T1_A: // T1_A ................
180 case IF_T2_A: // T2_A ................ ................
183 case IF_T1_B: // T1_B ........cccc.... cond
184 case IF_T2_B: // T2_B ................ ............iiii imm4
185 assert(emitGetInsSC(id) < 0x10);
188 case IF_T1_C: // T1_C .....iiiiinnnddd R1 R2 imm5
189 assert(isLowRegister(id->idReg1()));
190 assert(isLowRegister(id->idReg2()));
191 if (emitInsIsLoadOrStore(id->idIns()))
193 emitAttr size = id->idOpSize();
194 int imm = emitGetInsSC(id);
196 imm = insUnscaleImm(imm, size);
201 assert(id->idSmallCns() < 0x20);
205 case IF_T1_D0: // T1_D0 ........Dmmmmddd R1* R2*
206 assert(isGeneralRegister(id->idReg1()));
207 assert(isGeneralRegister(id->idReg2()));
210 case IF_T1_D1: // T1_D1 .........mmmm... R1*
211 assert(isGeneralRegister(id->idReg1()));
214 case IF_T1_D2: // T1_D2 .........mmmm... R3*
215 assert(isGeneralRegister(id->idReg3()));
218 case IF_T1_E: // T1_E ..........nnnddd R1 R2
219 assert(isLowRegister(id->idReg1()));
220 assert(isLowRegister(id->idReg2()));
221 assert(id->idSmallCns() < 0x20);
224 case IF_T1_F: // T1_F .........iiiiiii SP imm7
225 assert(id->idReg1() == REG_SP);
226 assert(id->idOpSize() == EA_4BYTE);
227 assert((emitGetInsSC(id) & ~0x1FC) == 0);
230 case IF_T1_G: // T1_G .......iiinnnddd R1 R2 imm3
231 assert(isLowRegister(id->idReg1()));
232 assert(isLowRegister(id->idReg2()));
233 assert(id->idSmallCns() < 0x8);
236 case IF_T1_H: // T1_H .......mmmnnnddd R1 R2 R3
237 assert(isLowRegister(id->idReg1()));
238 assert(isLowRegister(id->idReg2()));
239 assert(isLowRegister(id->idReg3()));
242 case IF_T1_I: // T1_I ......i.iiiiiddd R1 imm6
243 assert(isLowRegister(id->idReg1()));
246 case IF_T1_J0: // T1_J0 .....dddiiiiiiii R1 imm8
247 assert(isLowRegister(id->idReg1()));
248 assert(emitGetInsSC(id) < 0x100);
251 case IF_T1_J1: // T1_J1 .....dddiiiiiiii R1 <regmask8>
252 assert(isLowRegister(id->idReg1()));
253 assert(emitGetInsSC(id) < 0x100);
256 case IF_T1_J2: // T1_J2 .....dddiiiiiiii R1 SP imm8
257 assert(isLowRegister(id->idReg1()));
258 assert(id->idReg2() == REG_SP);
259 assert(id->idOpSize() == EA_4BYTE);
260 assert((emitGetInsSC(id) & ~0x3FC) == 0);
263 case IF_T1_L0: // T1_L0 ........iiiiiiii imm8
264 assert(emitGetInsSC(id) < 0x100);
267 case IF_T1_L1: // T1_L1 .......Rrrrrrrrr <regmask8+2>
268 assert(emitGetInsSC(id) < 0x400);
271 case IF_T2_C0: // T2_C0 ...........Snnnn .iiiddddiishmmmm R1 R2 R3 S, imm5, sh
272 assert(isGeneralRegister(id->idReg1()));
273 assert(isGeneralRegister(id->idReg2()));
274 assert(isGeneralRegister(id->idReg3()));
275 assert(emitGetInsSC(id) < 0x20);
278 case IF_T2_C4: // T2_C4 ...........Snnnn ....dddd....mmmm R1 R2 R3 S
279 case IF_T2_C5: // T2_C5 ............nnnn ....dddd....mmmm R1 R2 R3
280 case IF_T2_G1: // T2_G1 ............nnnn ttttTTTT........ R1 R2 R3
281 assert(isGeneralRegister(id->idReg1()));
282 assert(isGeneralRegister(id->idReg2()));
283 assert(isGeneralRegister(id->idReg3()));
286 case IF_T2_C1: // T2_C1 ...........S.... .iiiddddiishmmmm R1 R2 S, imm5, sh
287 case IF_T2_C2: // T2_C2 ...........S.... .iiiddddii..mmmm R1 R2 S, imm5
288 case IF_T2_C8: // T2_C8 ............nnnn .iii....iishmmmm R1 R2 imm5, sh
289 assert(isGeneralRegister(id->idReg1()));
290 assert(isGeneralRegister(id->idReg2()));
291 assert(emitGetInsSC(id) < 0x20);
294 case IF_T2_C6: // T2_C6 ................ ....dddd..iimmmm R1 R2 imm2
295 case IF_T2_C7: // T2_C7 ............nnnn ..........shmmmm R1 R2 imm2
296 assert(isGeneralRegister(id->idReg1()));
297 assert(isGeneralRegister(id->idReg2()));
298 assert(emitGetInsSC(id) < 0x4);
301 case IF_T2_C3: // T2_C3 ...........S.... ....dddd....mmmm R1 R2 S
302 case IF_T2_C9: // T2_C9 ............nnnn ............mmmm R1 R2
303 case IF_T2_C10: // T2_C10 ............mmmm ....dddd....mmmm R1 R2
304 assert(isGeneralRegister(id->idReg1()));
305 assert(isGeneralRegister(id->idReg2()));
308 case IF_T2_D0: // T2_D0 ............nnnn .iiiddddii.wwwww R1 R2 imm5, imm5
309 assert(isGeneralRegister(id->idReg1()));
310 assert(isGeneralRegister(id->idReg2()));
311 assert(emitGetInsSC(id) < 0x400);
314 case IF_T2_D1: // T2_D1 ................ .iiiddddii.wwwww R1 imm5, imm5
315 assert(isGeneralRegister(id->idReg1()));
316 assert(emitGetInsSC(id) < 0x400);
319 case IF_T2_E0: // T2_E0 ............nnnn tttt......shmmmm R1 R2 R3 imm2
320 assert(isGeneralRegister(id->idReg1()));
321 assert(isGeneralRegister(id->idReg2()));
322 if (id->idIsLclVar())
324 assert(isGeneralRegister(codeGen->rsGetRsvdReg()));
328 assert(isGeneralRegister(id->idReg3()));
329 assert(emitGetInsSC(id) < 0x4);
333 case IF_T2_E1: // T2_E1 ............nnnn tttt............ R1 R2
334 assert(isGeneralRegister(id->idReg1()));
335 assert(isGeneralRegister(id->idReg2()));
338 case IF_T2_E2: // T2_E2 ................ tttt............ R1
339 assert(isGeneralRegister(id->idReg1()));
342 case IF_T2_F1: // T2_F1 ............nnnn ttttdddd....mmmm R1 R2 R3 R4
343 case IF_T2_F2: // T2_F2 ............nnnn aaaadddd....mmmm R1 R2 R3 R4
344 assert(isGeneralRegister(id->idReg1()));
345 assert(isGeneralRegister(id->idReg2()));
346 assert(isGeneralRegister(id->idReg3()));
347 assert(isGeneralRegister(id->idReg4()));
350 case IF_T2_G0: // T2_G0 .......PU.W.nnnn ttttTTTTiiiiiiii R1 R2 R3 imm8, PUW
351 assert(isGeneralRegister(id->idReg1()));
352 assert(isGeneralRegister(id->idReg2()));
353 assert(isGeneralRegister(id->idReg3()));
354 assert(unsigned_abs(emitGetInsSC(id)) < 0x100);
357 case IF_T2_H0: // T2_H0 ............nnnn tttt.PUWiiiiiiii R1 R2 imm8, PUW
358 assert(isGeneralRegister(id->idReg1()));
359 assert(isGeneralRegister(id->idReg2()));
360 assert(unsigned_abs(emitGetInsSC(id)) < 0x100);
363 case IF_T2_H1: // T2_H1 ............nnnn tttt....iiiiiiii R1 R2 imm8
364 assert(isGeneralRegister(id->idReg1()));
365 assert(isGeneralRegister(id->idReg2()));
366 assert(emitGetInsSC(id) < 0x100);
369 case IF_T2_H2: // T2_H2 ............nnnn ........iiiiiiii R1 imm8
370 assert(isGeneralRegister(id->idReg1()));
371 assert(emitGetInsSC(id) < 0x100);
374 case IF_T2_I0: // T2_I0 ..........W.nnnn rrrrrrrrrrrrrrrr R1 W, imm16
375 assert(isGeneralRegister(id->idReg1()));
376 assert(emitGetInsSC(id) < 0x10000);
379 case IF_T2_N: // T2_N .....i......iiii .iiiddddiiiiiiii R1 imm16
380 assert(isGeneralRegister(id->idReg1()));
381 assert(!id->idIsReloc());
384 case IF_T2_N2: // T2_N2 .....i......iiii .iiiddddiiiiiiii R1 imm16
385 assert(isGeneralRegister(id->idReg1()));
386 assert((size_t)emitGetInsSC(id) < emitDataSize());
389 case IF_T2_N3: // T2_N3 .....i......iiii .iiiddddiiiiiiii R1 imm16
390 assert(isGeneralRegister(id->idReg1()));
391 assert(id->idIsReloc());
394 case IF_T2_I1: // T2_I1 ................ rrrrrrrrrrrrrrrr imm16
395 assert(emitGetInsSC(id) < 0x10000);
398 case IF_T2_K1: // T2_K1 ............nnnn ttttiiiiiiiiiiii R1 R2 imm12
399 case IF_T2_M0: // T2_M0 .....i......nnnn .iiiddddiiiiiiii R1 R2 imm12
400 assert(isGeneralRegister(id->idReg1()));
401 assert(isGeneralRegister(id->idReg2()));
402 assert(emitGetInsSC(id) < 0x1000);
405 case IF_T2_L0: // T2_L0 .....i.....Snnnn .iiiddddiiiiiiii R1 R2 S, imm8<<imm4
406 assert(isGeneralRegister(id->idReg1()));
407 assert(isGeneralRegister(id->idReg2()));
408 assert(isModImmConst(emitGetInsSC(id)));
411 case IF_T2_K4: // T2_K4 ........U....... ttttiiiiiiiiiiii R1 PC U, imm12
412 case IF_T2_M1: // T2_M1 .....i.......... .iiiddddiiiiiiii R1 PC imm12
413 assert(isGeneralRegister(id->idReg1()));
414 assert(id->idReg2() == REG_PC);
415 assert(emitGetInsSC(id) < 0x1000);
418 case IF_T2_K3: // T2_K3 ........U....... ....iiiiiiiiiiii PC U, imm12
419 assert(id->idReg1() == REG_PC);
420 assert(emitGetInsSC(id) < 0x1000);
423 case IF_T2_K2: // T2_K2 ............nnnn ....iiiiiiiiiiii R1 imm12
424 assert(isGeneralRegister(id->idReg1()));
425 assert(emitGetInsSC(id) < 0x1000);
428 case IF_T2_L1: // T2_L1 .....i.....S.... .iiiddddiiiiiiii R1 S, imm8<<imm4
429 case IF_T2_L2: // T2_L2 .....i......nnnn .iii....iiiiiiii R1 imm8<<imm4
430 assert(isGeneralRegister(id->idReg1()));
431 assert(isModImmConst(emitGetInsSC(id)));
434 case IF_T1_J3: // T1_J3 .....dddiiiiiiii R1 PC imm8
435 assert(isGeneralRegister(id->idReg1()));
436 assert(id->idReg2() == REG_PC);
437 assert(emitGetInsSC(id) < 0x100);
440 case IF_T1_K: // T1_K ....cccciiiiiiii Branch imm8, cond4
441 case IF_T1_M: // T1_M .....iiiiiiiiiii Branch imm11
442 case IF_T2_J1: // T2_J1 .....Scccciiiiii ..j.jiiiiiiiiiii Branch imm20, cond4
443 case IF_T2_J2: // T2_J2 .....Siiiiiiiiii ..j.jiiiiiiiiii. Branch imm24
444 case IF_T2_N1: // T2_N .....i......iiii .iiiddddiiiiiiii R1 imm16
445 case IF_T2_J3: // T2_J3 .....Siiiiiiiiii ..j.jiiiiiiiiii. Call imm24
450 if (id->idOpSize() == EA_8BYTE)
452 assert(isDoubleReg(id->idReg1()));
453 assert(isDoubleReg(id->idReg2()));
454 assert(isDoubleReg(id->idReg3()));
458 assert(id->idOpSize() == EA_4BYTE);
459 assert(isFloatReg(id->idReg1()));
460 assert(isFloatReg(id->idReg2()));
461 assert(isFloatReg(id->idReg3()));
466 assert(isFloatReg(id->idReg1()));
467 assert(isFloatReg(id->idReg2()));
471 if (id->idOpSize() == EA_8BYTE)
472 assert(isDoubleReg(id->idReg1()));
474 assert(isFloatReg(id->idReg1()));
475 assert(isGeneralRegister(id->idReg2()));
476 assert(offsetFitsInVectorMem(emitGetInsSC(id)));
480 assert(id->idOpSize() == EA_8BYTE);
481 if (id->idIns() == INS_vmov_d2i)
483 assert(isGeneralRegister(id->idReg1()));
484 assert(isGeneralRegister(id->idReg2()));
485 assert(isDoubleReg(id->idReg3()));
489 assert(id->idIns() == INS_vmov_i2d);
490 assert(isDoubleReg(id->idReg1()));
491 assert(isGeneralRegister(id->idReg2()));
492 assert(isGeneralRegister(id->idReg3()));
497 assert(id->idOpSize() == EA_4BYTE);
498 if (id->idIns() == INS_vmov_i2f)
500 assert(isFloatReg(id->idReg1()));
501 assert(isGeneralRegister(id->idReg2()));
505 assert(id->idIns() == INS_vmov_f2i);
506 assert(isGeneralRegister(id->idReg1()));
507 assert(isFloatReg(id->idReg2()));
512 printf("unexpected format %s\n", emitIfName(id->idInsFmt()));
513 assert(!"Unexpected format");
519 bool emitter::emitInsMayWriteToGCReg(instrDesc* id)
521 instruction ins = id->idIns();
522 insFormat fmt = id->idInsFmt();
527 // These are the formats with "destination" or "target" registers:
569 // Some formats with "destination" or "target" registers are actually used for store instructions, for the
570 // "source" value written to memory.
571 // Similarly, PUSH has a target register, indicating the start of the set of registers to push. POP
572 // *does* write to at least one register, so we do not make that a special case.
573 // Various compare/test instructions do not write (except to the flags). Technically "teq" does not need to
575 // be in this list because it has no forms matched above, but I'm putting it here for completeness.
596 // VMOV.i2f reads from the integer register. Conversely VMOV.f2i writes to GC pointer-sized
597 // integer register that might have previously held GC pointers, so they need to be included.
598 assert(id->idGCref() == GCT_NONE);
599 return (ins == INS_vmov_f2i);
602 // VMOV.i2d reads from the integer registers. Conversely VMOV.d2i writes to GC pointer-sized
603 // integer registers that might have previously held GC pointers, so they need to be included.
604 assert(id->idGCref() == GCT_NONE);
605 return (ins == INS_vmov_d2i);
612 bool emitter::emitInsWritesToLclVarStackLoc(instrDesc* id)
614 if (!id->idIsLclVar())
617 instruction ins = id->idIns();
619 // This list is related to the list of instructions used to store local vars in emitIns_S_R().
620 // We don't accept writing to float local vars.
633 bool emitter::emitInsMayWriteMultipleRegs(instrDesc* id)
635 instruction ins = id->idIns();
653 /*****************************************************************************/
655 /*****************************************************************************
657 * Return a string that represents the given register.
660 const char* emitter::emitRegName(regNumber reg, emitAttr attr, bool varName)
662 assert(reg < REG_COUNT);
664 const char* rn = emitComp->compRegVarName(reg, varName, false);
666 assert(strlen(rn) >= 1);
671 const char* emitter::emitFloatRegName(regNumber reg, emitAttr attr, bool varName)
673 assert(reg < REG_COUNT);
675 const char* rn = emitComp->compRegVarName(reg, varName, true);
677 assert(strlen(rn) >= 1);
683 /*****************************************************************************
685 * Returns the base encoding of the given CPU instruction.
688 emitter::insFormat emitter::emitInsFormat(instruction ins)
691 const static insFormat insFormats[] =
693 #define INST1(id, nm, fp, ldst, fmt, e1 ) fmt,
694 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) fmt,
695 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) fmt,
696 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) fmt,
697 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) fmt,
698 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) fmt,
699 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) fmt,
700 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) fmt,
705 assert(ins < ArrLen(insFormats));
706 assert((insFormats[ins] != IF_NONE));
708 return insFormats[ins];
717 /*static*/ const BYTE CodeGenInterface::instInfo[] =
719 #define INST1(id, nm, fp, ldst, fmt, e1 ) ldst | INST_FP*fp,
720 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) ldst | INST_FP*fp,
721 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) ldst | INST_FP*fp,
722 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) ldst | INST_FP*fp,
723 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) ldst | INST_FP*fp,
724 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) ldst | INST_FP*fp,
725 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) ldst | INST_FP*fp,
726 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) ldst | INST_FP*fp,
731 /*****************************************************************************
733 * Returns true if the instruction is some kind of load instruction
736 bool emitter::emitInsIsLoad(instruction ins)
738 // We have pseudo ins like lea which are not included in emitInsLdStTab.
739 if (ins < ArrLen(CodeGenInterface::instInfo))
740 return (CodeGenInterface::instInfo[ins] & LD) ? true : false;
745 /*****************************************************************************
747 * Returns true if the instruction is some kind of compare or test instruction
750 bool emitter::emitInsIsCompare(instruction ins)
752 // We have pseudo ins like lea which are not included in emitInsLdStTab.
753 if (ins < ArrLen(CodeGenInterface::instInfo))
754 return (CodeGenInterface::instInfo[ins] & CMP) ? true : false;
759 /*****************************************************************************
761 * Returns true if the instruction is some kind of store instruction
764 bool emitter::emitInsIsStore(instruction ins)
766 // We have pseudo ins like lea which are not included in emitInsLdStTab.
767 if (ins < ArrLen(CodeGenInterface::instInfo))
768 return (CodeGenInterface::instInfo[ins] & ST) ? true : false;
773 /*****************************************************************************
775 * Returns true if the instruction is some kind of load/store instruction
778 bool emitter::emitInsIsLoadOrStore(instruction ins)
780 // We have pseudo ins like lea which are not included in emitInsLdStTab.
781 if (ins < ArrLen(CodeGenInterface::instInfo))
782 return (CodeGenInterface::instInfo[ins] & (LD | ST)) ? true : false;
791 /*****************************************************************************
793 * Returns the specific encoding of the given CPU instruction and format
796 emitter::code_t emitter::emitInsCode(instruction ins, insFormat fmt)
799 const static code_t insCodes1[] =
801 #define INST1(id, nm, fp, ldst, fmt, e1 ) e1,
802 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) e1,
803 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) e1,
804 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e1,
805 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e1,
806 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e1,
807 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) e1,
808 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e1,
811 const static code_t insCodes2[] =
813 #define INST1(id, nm, fp, ldst, fmt, e1 )
814 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) e2,
815 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) e2,
816 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e2,
817 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e2,
818 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e2,
819 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) e2,
820 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e2,
823 const static code_t insCodes3[] =
825 #define INST1(id, nm, fp, ldst, fmt, e1 )
826 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
827 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) e3,
828 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e3,
829 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e3,
830 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e3,
831 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) e3,
832 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e3,
835 const static code_t insCodes4[] =
837 #define INST1(id, nm, fp, ldst, fmt, e1 )
838 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
839 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
840 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e4,
841 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e4,
842 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e4,
843 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) e4,
844 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e4,
847 const static code_t insCodes5[] =
849 #define INST1(id, nm, fp, ldst, fmt, e1 )
850 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
851 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
852 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
853 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e5,
854 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e5,
855 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) e5,
856 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e5,
859 const static code_t insCodes6[] =
861 #define INST1(id, nm, fp, ldst, fmt, e1 )
862 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
863 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
864 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
865 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
866 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e6,
867 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) e6,
868 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e6,
871 const static code_t insCodes7[] =
873 #define INST1(id, nm, fp, ldst, fmt, e1 )
874 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
875 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
876 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
877 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
878 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 )
879 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) e7,
880 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e7,
883 const static code_t insCodes8[] =
885 #define INST1(id, nm, fp, ldst, fmt, e1 )
886 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
887 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
888 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
889 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
890 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 )
891 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) e8,
892 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e8,
895 const static code_t insCodes9[] =
897 #define INST1(id, nm, fp, ldst, fmt, e1 )
898 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
899 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
900 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
901 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
902 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 )
903 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 )
904 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e9,
907 const static insFormat formatEncode9[9] = { IF_T1_D0, IF_T1_H, IF_T1_J0, IF_T1_G, IF_T2_L0, IF_T2_C0, IF_T1_F, IF_T1_J2, IF_T1_J3 };
908 const static insFormat formatEncode8[8] = { IF_T1_H, IF_T1_C, IF_T2_E0, IF_T2_H0, IF_T2_K1, IF_T2_K4, IF_T1_J2, IF_T1_J3 };
909 const static insFormat formatEncode6A[6] = { IF_T1_H, IF_T1_C, IF_T2_E0, IF_T2_H0, IF_T2_K1, IF_T2_K4};
910 const static insFormat formatEncode6B[6] = { IF_T1_H, IF_T1_C, IF_T2_E0, IF_T2_H0, IF_T2_K1, IF_T1_J2 };
911 const static insFormat formatEncode5A[5] = { IF_T1_E, IF_T1_D0, IF_T1_J0, IF_T2_L1, IF_T2_C3 };
912 const static insFormat formatEncode5B[5] = { IF_T1_E, IF_T1_D0, IF_T1_J0, IF_T2_L2, IF_T2_C8 };
913 const static insFormat formatEncode4A[4] = { IF_T1_E, IF_T1_C, IF_T2_C4, IF_T2_C2 };
914 const static insFormat formatEncode4B[4] = { IF_T2_K2, IF_T2_H2, IF_T2_C7, IF_T2_K3 };
915 const static insFormat formatEncode4C[4] = { IF_T2_N, IF_T2_N1, IF_T2_N2, IF_T2_N3 };
916 const static insFormat formatEncode3A[3] = { IF_T1_E, IF_T2_C0, IF_T2_L0 };
917 const static insFormat formatEncode3B[3] = { IF_T1_E, IF_T2_C8, IF_T2_L2 };
918 const static insFormat formatEncode3C[3] = { IF_T1_E, IF_T2_C1, IF_T2_L1 };
919 const static insFormat formatEncode3D[3] = { IF_T1_L1, IF_T2_E2, IF_T2_I1 };
920 const static insFormat formatEncode3E[3] = { IF_T1_M, IF_T2_J2, IF_T2_J3 };
921 const static insFormat formatEncode2A[2] = { IF_T1_K, IF_T2_J1 };
922 const static insFormat formatEncode2B[2] = { IF_T1_D1, IF_T1_D2 };
923 const static insFormat formatEncode2C[2] = { IF_T1_D2, IF_T2_J3 };
924 const static insFormat formatEncode2D[2] = { IF_T1_J1, IF_T2_I0 };
925 const static insFormat formatEncode2E[2] = { IF_T1_E, IF_T2_C6 };
926 const static insFormat formatEncode2F[2] = { IF_T1_E, IF_T2_C5 };
927 const static insFormat formatEncode2G[2] = { IF_T1_J3, IF_T2_M1 };
930 code_t code = BAD_CODE;
931 insFormat insFmt = emitInsFormat(ins);
938 for (index = 0; index < 9; index++)
940 if (fmt == formatEncode9[index])
949 for (index = 0; index < 8; index++)
951 if (fmt == formatEncode8[index])
960 for (index = 0; index < 6; index++)
962 if (fmt == formatEncode6A[index])
971 for (index = 0; index < 6; index++)
973 if (fmt == formatEncode6B[index])
982 for (index = 0; index < 5; index++)
984 if (fmt == formatEncode5A[index])
993 for (index = 0; index < 5; index++)
995 if (fmt == formatEncode5B[index])
1004 for (index = 0; index < 4; index++)
1006 if (fmt == formatEncode4A[index])
1015 for (index = 0; index < 4; index++)
1017 if (fmt == formatEncode4B[index])
1026 for (index = 0; index < 4; index++)
1028 if (fmt == formatEncode4C[index])
1037 for (index = 0; index < 3; index++)
1039 if (fmt == formatEncode3A[index])
1048 for (index = 0; index < 3; index++)
1050 if (fmt == formatEncode3B[index])
1058 for (index = 0; index < 3; index++)
1060 if (fmt == formatEncode3C[index])
1068 for (index = 0; index < 3; index++)
1070 if (fmt == formatEncode3D[index])
1078 for (index = 0; index < 3; index++)
1080 if (fmt == formatEncode3E[index])
1089 for (index = 0; index < 2; index++)
1091 if (fmt == formatEncode2A[index])
1099 for (index = 0; index < 2; index++)
1101 if (fmt == formatEncode2B[index])
1109 for (index = 0; index < 2; index++)
1111 if (fmt == formatEncode2C[index])
1119 for (index = 0; index < 2; index++)
1121 if (fmt == formatEncode2D[index])
1129 for (index = 0; index < 2; index++)
1131 if (fmt == formatEncode2E[index])
1139 for (index = 0; index < 2; index++)
1141 if (fmt == formatEncode2F[index])
1150 for (index = 0; index < 2; index++)
1152 if (fmt == formatEncode2G[index])
1171 assert(ins < ArrLen(insCodes1));
1172 code = insCodes1[ins];
1175 assert(ins < ArrLen(insCodes2));
1176 code = insCodes2[ins];
1179 assert(ins < ArrLen(insCodes3));
1180 code = insCodes3[ins];
1183 assert(ins < ArrLen(insCodes4));
1184 code = insCodes4[ins];
1187 assert(ins < ArrLen(insCodes5));
1188 code = insCodes5[ins];
1191 assert(ins < ArrLen(insCodes6));
1192 code = insCodes6[ins];
1195 assert(ins < ArrLen(insCodes7));
1196 code = insCodes7[ins];
1199 assert(ins < ArrLen(insCodes8));
1200 code = insCodes8[ins];
1203 assert(ins < ArrLen(insCodes9));
1204 code = insCodes9[ins];
1208 assert((code != BAD_CODE));
1213 /*****************************************************************************
1215 * Return the code size of the given instruction format. The 'insSize' return type enum
1216 * indicates a 16 bit, 32 bit, or 48 bit instruction.
1219 emitter::insSize emitter::emitInsSize(insFormat insFmt)
1221 if ((insFmt >= IF_T1_A) && (insFmt < IF_T2_A))
1224 if ((insFmt >= IF_T2_A) && (insFmt < IF_INVALID))
1227 if (insFmt == IF_LARGEJMP)
1230 assert(!"Invalid insFormat");
1234 /*****************************************************************************
1236 * isModImmConst() returns true when immediate 'val32' can be encoded
1237 * using the special modified immediate constant available in Thumb
1240 /*static*/ bool emitter::isModImmConst(int val32)
1242 unsigned uval32 = (unsigned)val32;
1243 unsigned imm8 = uval32 & 0xff;
1245 /* encode = 0000x */
1249 unsigned imm32a = (imm8 << 16) | imm8;
1250 /* encode = 0001x */
1251 if (imm32a == uval32)
1254 unsigned imm32b = (imm32a << 8);
1255 /* encode = 0010x */
1256 if (imm32b == uval32)
1259 unsigned imm32c = (imm32a | imm32b);
1260 /* encode = 0011x */
1261 if (imm32c == uval32)
1264 unsigned mask32 = 0x00000ff;
1266 unsigned encode = 31; /* 11111 */
1272 temp = uval32 & ~mask32;
1276 } while (encode >= 8);
1281 /*****************************************************************************
1283 * encodeModImmConst() returns the special ARM 12-bit immediate encoding.
1284 * that is used to encode the immediate. (4-bits, 8-bits)
1285 * If the imm can not be encoded then 0x0BADC0DE is returned.
1288 /*static*/ int emitter::encodeModImmConst(int val32)
1290 unsigned uval32 = (unsigned)val32;
1291 unsigned imm8 = uval32 & 0xff;
1292 unsigned encode = imm8 >> 7;
1299 /* encode = 0000x */
1305 imm32a = (imm8 << 16) | imm8;
1306 /* encode = 0001x */
1307 if (imm32a == uval32)
1313 imm32b = (imm32a << 8);
1314 /* encode = 0010x */
1315 if (imm32b == uval32)
1321 imm32c = (imm32a | imm32b);
1322 /* encode = 0011x */
1323 if (imm32c == uval32)
1331 encode = 31; /* 11111 */
1335 temp = uval32 & ~mask32;
1338 imm8 = (uval32 & mask32) >> (32 - encode);
1339 assert((imm8 & 0x80) != 0);
1343 } while (encode >= 8);
1345 assert(!"encodeModImmConst failed!");
1349 unsigned result = (encode << 7) | (imm8 & 0x7f);
1350 assert(result <= 0x0fff);
1351 assert(result >= 0);
1355 /*****************************************************************************
1357 * emitIns_valid_imm_for_alu() returns true when the immediate 'imm'
1358 * can be encoded using the 12-bit funky Arm immediate encoding
1360 /*static*/ bool emitter::emitIns_valid_imm_for_alu(int imm)
1362 if (isModImmConst(imm))
1367 /*****************************************************************************
1369 * emitIns_valid_imm_for_mov() returns true when the immediate 'imm'
1370 * can be encoded using a single mov or mvn instruction.
1372 /*static*/ bool emitter::emitIns_valid_imm_for_mov(int imm)
1374 if ((imm & 0x0000ffff) == imm) // 16-bit immediate
1376 if (isModImmConst(imm)) // funky arm immediate
1378 if (isModImmConst(~imm)) // funky arm immediate via mvn
1383 /*****************************************************************************
1385 * emitIns_valid_imm_for_small_mov() returns true when the immediate 'imm'
1386 * can be encoded using a single 2-byte mov instruction.
1388 /*static*/ bool emitter::emitIns_valid_imm_for_small_mov(regNumber reg, int imm, insFlags flags)
1390 return isLowRegister(reg) && insSetsFlags(flags) && ((imm & 0x00ff) == imm);
1393 /*****************************************************************************
1395 * emitins_valid_imm_for_add() returns true when the immediate 'imm'
1396 * can be encoded using a single add or sub instruction.
1398 /*static*/ bool emitter::emitIns_valid_imm_for_add(int imm, insFlags flags)
1400 if ((unsigned_abs(imm) <= 0x00000fff) && (flags != INS_FLAGS_SET)) // 12-bit immediate via add/sub
1402 if (isModImmConst(imm)) // funky arm immediate
1404 if (isModImmConst(-imm)) // funky arm immediate via sub
1409 /*****************************************************************************
1411 * emitins_valid_imm_for_cmp() returns true if this 'imm'
1412 * can be encoded as a input operand to an cmp instruction.
1414 /*static*/ bool emitter::emitIns_valid_imm_for_cmp(int imm, insFlags flags)
1416 if (isModImmConst(imm)) // funky arm immediate
1418 if (isModImmConst(-imm)) // funky arm immediate via sub
1423 /*****************************************************************************
1425 * emitIns_valid_imm_for_add_sp() returns true when the immediate 'imm'
1426 * can be encoded in "add Rd,SP,i10".
1428 /*static*/ bool emitter::emitIns_valid_imm_for_add_sp(int imm)
1430 if ((imm & 0x03fc) == imm)
1435 /*****************************************************************************
1437 * emitIns_valid_imm_for_ldst_offset() returns true when the immediate 'imm'
1438 * can be encoded as the offset in a ldr/str instruction.
1440 /*static*/ bool emitter::emitIns_valid_imm_for_ldst_offset(int imm, emitAttr size)
1442 if ((imm & 0x0fff) == imm)
1443 return true; // encodable using IF_T2_K1
1444 if (unsigned_abs(imm) <= 0x0ff)
1445 return true; // encodable using IF_T2_H0
1449 /*****************************************************************************
1451 * emitIns_valid_imm_for_vldst_offset() returns true when the immediate 'imm'
1452 * can be encoded as the offset in a vldr/vstr instruction, i.e. when it is
1453 * a non-negative multiple of 4 that is less than 1024.
1455 /*static*/ bool emitter::emitIns_valid_imm_for_vldst_offset(int imm)
1457 if ((imm & 0x3fc) == imm)
1462 /*****************************************************************************
1464 * Add an instruction with no operands.
1467 void emitter::emitIns(instruction ins)
1469 instrDesc* id = emitNewInstrSmall(EA_4BYTE);
1470 insFormat fmt = emitInsFormat(ins);
1471 insSize isz = emitInsSize(fmt);
1473 assert((fmt == IF_T1_A) || (fmt == IF_T2_A));
1483 /*****************************************************************************
1485 * Add an instruction with a single immediate value.
1488 void emitter::emitIns_I(instruction ins, emitAttr attr, target_ssize_t imm)
1490 insFormat fmt = IF_NONE;
1494 bool onlyT1 = false;
1496 /* Figure out the encoding format of the instruction */
1499 #ifdef FEATURE_ITINSTRUCTION
1515 assert((imm & 0x0F) == imm);
1519 #endif // FEATURE_ITINSTRUCTION
1522 assert((imm & 0xA000) == 0); // Cannot push PC or SP
1524 if (imm & 0x4000) // Is the LR being pushed?
1527 goto COMMON_PUSH_POP;
1530 assert((imm & 0x2000) == 0); // Cannot pop SP
1531 assert((imm & 0xC000) != 0xC000); // Cannot pop both PC and LR
1533 if (imm & 0x8000) // Is the PC being popped?
1535 if (imm & 0x4000) // Is the LR being popped?
1543 if (((imm - 1) & imm) == 0) // Is only one or zero bits set in imm?
1545 if (((imm == 0) && !hasLR) || // imm has no bits set, but hasLR is set
1546 (!hasPC && !hasLR)) // imm has one bit set, and neither of hasPC/hasLR are set
1548 onlyT1 = true; // if only one bit is set we must use the T1 encoding
1552 imm &= ~0xE000; // ensure that PC, LR and SP bits are removed from imm
1554 if (((imm & 0x00ff) == imm) && !useT2)
1564 // We have to use the Thumb-2 push single register encoding
1565 regNumber reg = genRegNumFromMask(imm);
1566 emitIns_R(ins, attr, reg);
1571 // Encode the PC and LR bits as the lowest two bits
1584 // TODO-ARM-Cleanup: Enable or delete.
1585 case INS_bkpt: // Windows uses a different encoding
1586 if ((imm & 0x0000ffff) == imm)
1592 assert(!"Instruction cannot be encoded");
1599 if ((imm & 0x000f) == imm)
1606 assert(!"Instruction cannot be encoded");
1613 assert((fmt == IF_T1_B) || (fmt == IF_T1_L0) || (fmt == IF_T1_L1) || (fmt == IF_T2_I1) || (fmt == IF_T2_B));
1615 instrDesc* id = emitNewInstrSC(attr, imm);
1616 insSize isz = emitInsSize(fmt);
1626 /*****************************************************************************
1628 * Add an instruction referencing a single register.
1631 void emitter::emitIns_R(instruction ins, emitAttr attr, regNumber reg)
1633 emitAttr size = EA_SIZE(attr);
1634 insFormat fmt = IF_NONE;
1636 /* Figure out the encoding format of the instruction */
1641 if (isLowRegister(reg))
1643 int regmask = 1 << ((int)reg);
1644 emitIns_I(ins, attr, regmask);
1647 assert(size == EA_PTRSIZE);
1652 assert(size == EA_PTRSIZE);
1657 assert(size == EA_PTRSIZE);
1662 emitIns_R_R_I(ins, attr, reg, reg, 0);
1668 assert((fmt == IF_T1_D1) || (fmt == IF_T2_E2));
1670 instrDesc* id = emitNewInstrSmall(attr);
1671 insSize isz = emitInsSize(fmt);
1682 /*****************************************************************************
1684 * Add an instruction referencing a register and a constant.
1687 void emitter::emitIns_R_I(
1688 instruction ins, emitAttr attr, regNumber reg, target_ssize_t imm, insFlags flags /* = INS_FLAGS_DONT_CARE */)
1691 insFormat fmt = IF_NONE;
1692 insFlags sf = INS_FLAGS_DONT_CARE;
1694 /* Figure out the encoding format of the instruction */
1699 if ((reg == REG_SP) && insDoesNotSetFlags(flags) && ((imm & 0x01fc) == imm))
1702 sf = INS_FLAGS_NOT_SET;
1704 else if (isLowRegister(reg) && insSetsFlags(flags) && (unsigned_abs(imm) <= 0x00ff))
1708 assert((ins == INS_add) || (ins == INS_sub));
1711 else // ins == INS_sub
1720 // otherwise we have to use a Thumb-2 encoding
1721 emitIns_R_R_I(ins, attr, reg, reg, imm, flags);
1727 emitIns_R_R_I(ins, attr, reg, reg, imm, flags);
1733 if (attr == EA_8BYTE)
1735 assert(isDoubleReg(reg));
1741 assert(attr == EA_4BYTE);
1742 assert(isFloatReg(reg));
1745 assert(((reg - REG_F0) + imm) <= 32);
1748 if (ins == INS_vpush)
1751 sf = INS_FLAGS_NOT_SET;
1757 sf = INS_FLAGS_NOT_SET;
1762 bool onlyT1 = false;
1764 assert((imm & 0x2000) == 0); // Cannot pop SP
1765 assert((imm & 0xC000) != 0xC000); // Cannot pop both PC and LR
1766 assert((imm & 0xFFFF0000) == 0); // Can only contain lower 16 bits
1768 if (imm & 0x8000) // Is the PC being popped?
1771 if (imm & 0x4000) // Is the LR being pushed?
1777 if (!isLowRegister(reg))
1780 if (((imm - 1) & imm) == 0) // Is only one or zero bits set in imm?
1782 if (((imm == 0) && !hasLR) || // imm has no bits set, but hasLR is set
1783 (!hasPC && !hasLR)) // imm has one bit set, and neither of hasPC/hasLR are set
1785 onlyT1 = true; // if only one bit is set we must use the T1 encoding
1789 imm &= ~0xE000; // ensure that PC, LR and SP bits are removed from imm
1791 if (((imm & 0x00ff) == imm) && !useT2)
1801 assert(!"Instruction cannot be encoded");
1802 // We have to use the Thumb-2 str single register encoding
1803 // reg = genRegNumFromMask(imm);
1804 // emitIns_R(ins, attr, reg);
1809 // Encode the PC and LR bits as the lowest two bits
1811 if (fmt == IF_T2_I0)
1835 // use the Reg, Reg, Imm encoding
1836 emitIns_R_R_I(ins, attr, reg, reg, imm, flags);
1840 assert(!EA_IS_CNS_RELOC(attr));
1842 if (isLowRegister(reg) && insSetsFlags(flags) && ((imm & 0x00ff) == imm))
1847 else if (isModImmConst(imm))
1850 sf = insMustSetFlags(flags);
1852 else if (isModImmConst(~imm)) // See if we can use move negated instruction instead
1857 sf = insMustSetFlags(flags);
1859 else if (insDoesNotSetFlags(flags) && ((imm & 0x0000ffff) == imm))
1861 // mov => movw instruction
1864 sf = INS_FLAGS_NOT_SET;
1868 assert(!"Instruction cannot be encoded");
1874 assert(!EA_IS_RELOC(attr));
1875 assert(insDoesNotSetFlags(flags));
1877 if ((imm & 0x0000ffff) == imm)
1880 sf = INS_FLAGS_NOT_SET;
1884 assert(!"Instruction cannot be encoded");
1889 if (isModImmConst(imm))
1892 sf = insMustSetFlags(flags);
1896 assert(!"Instruction cannot be encoded");
1901 assert(!EA_IS_CNS_RELOC(attr));
1902 assert(insSetsFlags(flags));
1904 if (isLowRegister(reg) && ((imm & 0x0ff) == imm))
1908 else if (isModImmConst(imm))
1912 else if (isModImmConst(-imm))
1920 assert(!"emitIns_R_I: immediate doesn't fit into the instruction");
1928 assert(insSetsFlags(flags));
1930 if (isModImmConst(imm))
1936 assert(!"Instruction cannot be encoded");
1940 #ifdef FEATURE_PLI_INSTRUCTION
1942 assert(insDoesNotSetFlags(flags));
1943 if ((reg == REG_SP) && (unsigned_abs(imm) <= 0x0fff))
1946 sf = INS_FLAGS_NOT_SET;
1949 #endif // FEATURE_PLI_INSTRUCTION
1953 assert(insDoesNotSetFlags(flags));
1954 sf = INS_FLAGS_NOT_SET;
1955 if ((imm >= 0) && (imm <= 0x0fff))
1959 else if ((imm < 0) && (-imm <= 0x00ff))
1966 assert(!"Instruction cannot be encoded");
1973 assert((fmt == IF_T1_F) || (fmt == IF_T1_J0) || (fmt == IF_T1_J1) || (fmt == IF_T2_H2) || (fmt == IF_T2_I0) ||
1974 (fmt == IF_T2_K2) || (fmt == IF_T2_K3) || (fmt == IF_T2_L1) || (fmt == IF_T2_L2) || (fmt == IF_T2_M1) ||
1975 (fmt == IF_T2_N) || (fmt == IF_T2_VLDST));
1977 assert(sf != INS_FLAGS_DONT_CARE);
1979 instrDesc* id = emitNewInstrSC(attr, imm);
1980 insSize isz = emitInsSize(fmt);
1992 void emitter::emitIns_MovRelocatableImmediate(instruction ins, emitAttr attr, regNumber reg, BYTE* addr)
1994 assert(EA_IS_RELOC(attr));
1995 assert((ins == INS_movw) || (ins == INS_movt));
1997 insFormat fmt = IF_T2_N3;
1998 insFlags sf = INS_FLAGS_NOT_SET;
2000 instrDesc* id = emitNewInstrReloc(attr, addr);
2001 insSize isz = emitInsSize(fmt);
2013 /*****************************************************************************
2015 * Add an instruction referencing two registers
2018 void emitter::emitIns_R_R(
2019 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insFlags flags /* = INS_FLAGS_DONT_CARE */)
2022 emitAttr size = EA_SIZE(attr);
2023 insFormat fmt = IF_NONE;
2024 insFlags sf = INS_FLAGS_DONT_CARE;
2026 /* Figure out the encoding format of the instruction */
2030 if (insDoesNotSetFlags(flags))
2033 sf = INS_FLAGS_NOT_SET;
2039 // Use the Thumb-1 reg,reg,reg encoding
2040 emitIns_R_R_R(ins, attr, reg1, reg1, reg2, flags);
2044 if (insDoesNotSetFlags(flags))
2046 assert(reg1 != reg2);
2048 sf = INS_FLAGS_NOT_SET;
2050 else // insSetsFlags(flags)
2053 if (isLowRegister(reg1) && isLowRegister(reg2))
2065 assert(insSetsFlags(flags));
2067 if (isLowRegister(reg1) && isLowRegister(reg2))
2069 fmt = IF_T1_E; // both are low registers
2073 fmt = IF_T1_D0; // one or both are high registers
2078 assert(isGeneralRegister(reg1));
2079 assert(isFloatReg(reg2));
2081 sf = INS_FLAGS_NOT_SET;
2085 assert(isFloatReg(reg1));
2086 assert(isGeneralRegister(reg2));
2088 sf = INS_FLAGS_NOT_SET;
2094 assert(isFloatReg(reg1));
2095 assert(isDoubleReg(reg2));
2101 assert(isDoubleReg(reg1));
2102 assert(isFloatReg(reg2));
2109 assert(size == EA_4BYTE);
2110 assert(isFloatReg(reg1));
2111 assert(isFloatReg(reg2));
2115 assert(reg1 != reg2);
2122 if (size == EA_8BYTE)
2124 assert(isDoubleReg(reg1));
2125 assert(isDoubleReg(reg2));
2129 assert(isFloatReg(reg1));
2130 assert(isFloatReg(reg2));
2136 sf = INS_FLAGS_NOT_SET;
2143 emitIns_R_R_R(ins, attr, reg1, reg1, reg2);
2157 emitIns_R_R_I(ins, attr, reg1, reg2, 0);
2166 if (insSetsFlags(flags) && isLowRegister(reg1) && isLowRegister(reg2))
2175 // assert below fired for bug 281892 where the two operands of an OR were
2176 // the same static field load which got cse'd.
2177 // there's no reason why this assert would be true in general
2178 // assert(reg1 != reg2);
2179 // Use the Thumb-2 three register encoding
2180 emitIns_R_R_R_I(ins, attr, reg1, reg1, reg2, 0, flags);
2187 // assert below fired for bug 296394 where the two operands of an
2188 // arithmetic right shift were the same local variable
2189 // there's no reason why this assert would be true in general
2190 // assert(reg1 != reg2);
2191 if (insSetsFlags(flags) && isLowRegister(reg1) && isLowRegister(reg2))
2198 // Use the Thumb-2 three register encoding
2199 emitIns_R_R_R(ins, attr, reg1, reg1, reg2, flags);
2205 // We will prefer the T2 encoding, unless (flags == INS_FLAGS_SET)
2206 // The thumb-1 instruction executes much slower as it must always set the flags
2208 if (insMustSetFlags(flags) && isLowRegister(reg1) && isLowRegister(reg2))
2215 // Use the Thumb-2 three register encoding
2216 emitIns_R_R_R(ins, attr, reg1, reg2, reg1, flags);
2224 if (insSetsFlags(flags) && isLowRegister(reg1) && isLowRegister(reg2))
2231 // Use the Thumb-2 register with shift encoding
2232 emitIns_R_R_I(ins, attr, reg1, reg2, 0, flags);
2239 assert(size == EA_4BYTE);
2244 assert(size == EA_4BYTE);
2246 assert(insDoesNotSetFlags(flags));
2247 if (isLowRegister(reg1) && isLowRegister(reg2))
2250 sf = INS_FLAGS_NOT_SET;
2254 // Use the Thumb-2 reg,reg with rotation encoding
2255 emitIns_R_R_I(ins, attr, reg1, reg2, 0, INS_FLAGS_NOT_SET);
2261 assert(size == EA_1BYTE);
2262 assert(insDoesNotSetFlags(flags));
2264 sf = INS_FLAGS_NOT_SET;
2268 assert(size == EA_2BYTE);
2269 assert(insDoesNotSetFlags(flags));
2271 sf = INS_FLAGS_NOT_SET;
2275 assert(insDoesNotSetFlags(flags));
2277 sf = INS_FLAGS_NOT_SET;
2282 assert(size == EA_1BYTE);
2283 assert(insDoesNotSetFlags(flags));
2285 sf = INS_FLAGS_NOT_SET;
2290 assert(size == EA_2BYTE);
2291 assert(insDoesNotSetFlags(flags));
2293 sf = INS_FLAGS_NOT_SET;
2297 printf("did not expect instruction %s\n", codeGen->genInsName(ins));
2302 assert((fmt == IF_T1_D0) || (fmt == IF_T1_E) || (fmt == IF_T2_C3) || (fmt == IF_T2_C9) || (fmt == IF_T2_C10) ||
2303 (fmt == IF_T2_VFP2) || (fmt == IF_T2_VMOVD) || (fmt == IF_T2_VMOVS) || (fmt == IF_T2_E1));
2305 assert(sf != INS_FLAGS_DONT_CARE);
2307 instrDesc* id = emitNewInstrSmall(attr);
2308 insSize isz = emitInsSize(fmt);
2321 /*****************************************************************************
2323 * Add an instruction referencing a register and two constants.
2326 void emitter::emitIns_R_I_I(
2327 instruction ins, emitAttr attr, regNumber reg, int imm1, int imm2, insFlags flags /* = INS_FLAGS_DONT_CARE */)
2330 insFormat fmt = IF_NONE;
2331 insFlags sf = INS_FLAGS_DONT_CARE;
2332 int imm = 0; // combined immediates
2334 /* Figure out the encoding format of the instruction */
2340 int msb = lsb + imm2 - 1;
2342 assert((lsb >= 0) && (lsb <= 31)); // required for encoding of INS_bfc
2343 assert((msb >= 0) && (msb <= 31)); // required for encoding of INS_bfc
2344 assert(msb >= lsb); // required for encoding of INS_bfc
2346 imm = (lsb << 5) | msb;
2348 assert(insDoesNotSetFlags(flags));
2350 sf = INS_FLAGS_NOT_SET;
2357 assert(fmt == IF_T2_D1);
2358 assert(sf != INS_FLAGS_DONT_CARE);
2360 instrDesc* id = emitNewInstrSC(attr, imm);
2361 insSize isz = emitInsSize(fmt);
2373 /*****************************************************************************
2375 * Add an instruction referencing two registers and a constant.
2378 void emitter::emitIns_R_R_I(instruction ins,
2383 insFlags flags /* = INS_FLAGS_DONT_CARE */,
2384 insOpts opt /* = INS_OPTS_NONE */)
2386 emitAttr size = EA_SIZE(attr);
2387 insFormat fmt = IF_NONE;
2388 insFlags sf = INS_FLAGS_DONT_CARE;
2395 /* Figure out the encoding format of the instruction */
2399 assert(insOptsNone(opt));
2401 // Can we possibly encode the immediate 'imm' using a Thumb-1 encoding?
2402 if ((reg2 == REG_SP) && insDoesNotSetFlags(flags) && ((imm & 0x03fc) == imm))
2404 if ((reg1 == REG_SP) && ((imm & 0x01fc) == imm))
2406 // Use Thumb-1 encoding
2407 emitIns_R_I(ins, attr, reg1, imm, flags);
2410 else if (isLowRegister(reg1))
2413 sf = INS_FLAGS_NOT_SET;
2420 assert(insOptsNone(opt));
2422 // Is it just a mov?
2423 if ((imm == 0) && insDoesNotSetFlags(flags))
2425 // Is the mov even necessary?
2426 // Fix 383915 ARM ILGEN
2429 emitIns_R_R(INS_mov, attr, reg1, reg2, flags);
2433 // Can we encode the immediate 'imm' using a Thumb-1 encoding?
2434 else if (isLowRegister(reg1) && isLowRegister(reg2) && insSetsFlags(flags) && (unsigned_abs(imm) <= 0x0007))
2438 assert((ins == INS_add) || (ins == INS_sub));
2448 else if ((reg1 == reg2) && isLowRegister(reg1) && insSetsFlags(flags) && (unsigned_abs(imm) <= 0x00ff))
2452 assert((ins == INS_add) || (ins == INS_sub));
2459 // Use Thumb-1 encoding
2460 emitIns_R_I(ins, attr, reg1, imm, flags);
2463 else if (isModImmConst(imm))
2466 sf = insMustSetFlags(flags);
2468 else if (isModImmConst(-imm))
2470 assert((ins == INS_add) || (ins == INS_sub));
2471 ins = (ins == INS_add) ? INS_sub : INS_add;
2474 sf = insMustSetFlags(flags);
2476 else if (insDoesNotSetFlags(flags) && (unsigned_abs(imm) <= 0x0fff))
2480 assert((ins == INS_add) || (ins == INS_sub));
2481 ins = (ins == INS_add) ? INS_sub : INS_add;
2484 // add/sub => addw/subw instruction
2485 // Note that even when using the w prefix the immediate is still only 12 bits?
2486 ins = (ins == INS_add) ? INS_addw : INS_subw;
2488 sf = INS_FLAGS_NOT_SET;
2490 else if (insDoesNotSetFlags(flags) && (reg1 != REG_SP) && (reg1 != REG_PC))
2492 // movw,movt reg1, imm
2493 codeGen->instGen_Set_Reg_To_Imm(attr, reg1, (ins == INS_sub ? -1 : 1) * imm);
2496 emitIns_R_R(INS_add, attr, reg1, reg2);
2502 assert(!"Instruction cannot be encoded");
2510 assert(insOptsNone(opt));
2511 if (isModImmConst(imm))
2514 sf = insMustSetFlags(flags);
2516 else if (isModImmConst(~imm))
2519 sf = insMustSetFlags(flags);
2524 else if (ins == INS_bic)
2526 else if (ins == INS_orr)
2528 else if (ins == INS_orn)
2531 assert(!"Instruction cannot be encoded");
2535 assert(!"Instruction cannot be encoded");
2540 assert(insOptsNone(opt));
2541 if (imm == 0 && isLowRegister(reg1) && isLowRegister(reg2) && insSetsFlags(flags))
2552 assert(insOptsNone(opt));
2553 if (isModImmConst(imm))
2556 sf = insMustSetFlags(flags);
2560 assert(!"Instruction cannot be encoded");
2565 assert(insOptsNone(opt));
2566 assert(insDoesNotSetFlags(flags));
2567 assert(reg2 == REG_PC);
2568 sf = INS_FLAGS_NOT_SET;
2570 if (isLowRegister(reg1) && ((imm & 0x00ff) == imm))
2574 else if ((imm & 0x0fff) == imm)
2580 assert(!"Instruction cannot be encoded");
2585 assert((imm >= 0) && (imm <= 31)); // required for encoding
2586 assert(!insOptAnyInc(opt));
2589 assert(insOptsNone(opt));
2590 if (isLowRegister(reg1) && isLowRegister(reg2) && insSetsFlags(flags))
2592 // Use the Thumb-1 reg,reg encoding
2593 emitIns_R_R(ins, attr, reg1, reg2, flags);
2597 else // imm > 0 && imm <= 31
2599 assert(insOptAnyShift(opt));
2602 sf = insMustSetFlags(flags);
2609 assert(insSetsFlags(flags));
2610 assert((imm >= 0) && (imm <= 31)); // required for encoding
2611 assert(!insOptAnyInc(opt));
2614 assert(insOptsNone(opt));
2617 // Use the Thumb-1 reg,reg encoding
2618 emitIns_R_R(ins, attr, reg1, reg2, flags);
2621 if (((ins == INS_cmn) || (ins == INS_tst)) && isLowRegister(reg1) && isLowRegister(reg2))
2623 // Use the Thumb-1 reg,reg encoding
2624 emitIns_R_R(ins, attr, reg1, reg2, flags);
2628 else // imm > 0 && imm <= 31)
2630 assert(insOptAnyShift(opt));
2631 if (insOptsRRX(opt))
2643 assert(insOptsNone(opt));
2645 // On ARM, the immediate shift count of LSL and ROR must be between 1 and 31. For LSR and ASR, it is between
2646 // 1 and 32, though we don't ever use 32. Although x86 allows an immediate shift count of 8-bits in
2647 // instruction encoding, the CPU looks at only the lower 5 bits. As per ECMA, specifying a shift count to
2648 // the IL SHR, SHL, or SHL.UN instruction that is greater than or equal to the width of the type will yield
2649 // an undefined value. We choose that undefined value in this case to match x86 behavior, by only using the
2650 // lower 5 bits of the constant shift count.
2655 // Additional Fix 383915 ARM ILGEN
2656 if ((reg1 != reg2) || insMustSetFlags(flags))
2658 // Use MOV/MOVS instriction
2659 emitIns_R_R(INS_mov, attr, reg1, reg2, flags);
2664 if (insSetsFlags(flags) && (ins != INS_ror) && isLowRegister(reg1) && isLowRegister(reg2))
2672 sf = insMustSetFlags(flags);
2678 assert(size == EA_4BYTE);
2683 assert(size == EA_4BYTE);
2685 assert(insOptsNone(opt));
2686 assert(insDoesNotSetFlags(flags));
2687 assert((imm & 0x018) == imm); // required for encoding
2689 if ((imm == 0) && isLowRegister(reg1) && isLowRegister(reg2))
2691 // Use Thumb-1 encoding
2692 emitIns_R_R(ins, attr, reg1, reg2, INS_FLAGS_NOT_SET);
2697 sf = INS_FLAGS_NOT_SET;
2702 #ifdef FEATURE_PLI_INSTRUCTION
2704 #endif // FEATURE_PLI_INSTRUCTION
2705 assert(insOptsNone(opt));
2706 assert(insDoesNotSetFlags(flags));
2707 assert((imm & 0x003) == imm); // required for encoding
2710 sf = INS_FLAGS_NOT_SET;
2715 assert(size == EA_1BYTE);
2716 assert(insDoesNotSetFlags(flags));
2718 if (isLowRegister(reg1) && isLowRegister(reg2) && insOptsNone(opt) && ((imm & 0x001f) == imm))
2721 sf = INS_FLAGS_NOT_SET;
2724 goto COMMON_THUMB2_LDST;
2727 assert(size == EA_1BYTE);
2728 goto COMMON_THUMB2_LDST;
2732 assert(size == EA_2BYTE);
2733 assert(insDoesNotSetFlags(flags));
2735 if (isLowRegister(reg1) && isLowRegister(reg2) && insOptsNone(opt) && ((imm & 0x003e) == imm))
2738 sf = INS_FLAGS_NOT_SET;
2741 goto COMMON_THUMB2_LDST;
2744 assert(size == EA_2BYTE);
2745 goto COMMON_THUMB2_LDST;
2751 assert(fmt == IF_NONE);
2752 assert(insDoesNotSetFlags(flags));
2753 assert(offsetFitsInVectorMem(imm)); // required for encoding
2754 if (insOptAnyInc(opt))
2756 if (insOptsPostInc(opt))
2760 else // insOptsPreDec(opt)
2767 assert(insOptsNone(opt));
2770 sf = INS_FLAGS_NOT_SET;
2776 assert(size == EA_4BYTE);
2777 assert(insDoesNotSetFlags(flags));
2779 // Can we possibly encode the immediate 'imm' using a Thumb-1 encoding?
2780 if (isLowRegister(reg1) && insOptsNone(opt) && ((imm & 0x03fc) == imm))
2785 sf = INS_FLAGS_NOT_SET;
2788 else if (reg2 == REG_PC)
2793 sf = INS_FLAGS_NOT_SET;
2797 else if (isLowRegister(reg2))
2799 // Only the smaller range 'imm' can be encoded
2800 if ((imm & 0x07c) == imm)
2803 sf = INS_FLAGS_NOT_SET;
2809 // If we did not find a thumb-1 encoding above
2814 assert(fmt == IF_NONE);
2815 assert(insDoesNotSetFlags(flags));
2816 sf = INS_FLAGS_NOT_SET;
2818 if (insOptAnyInc(opt))
2820 if (insOptsPostInc(opt))
2822 else // insOptsPreDec(opt)
2825 if (unsigned_abs(imm) <= 0x00ff)
2831 assert(!"Instruction cannot be encoded");
2836 assert(insOptsNone(opt));
2837 if ((reg2 == REG_PC) && (unsigned_abs(imm) <= 0x0fff))
2841 else if ((imm & 0x0fff) == imm)
2845 else if (unsigned_abs(imm) <= 0x0ff)
2851 // Load imm into a register
2852 regNumber rsvdReg = codeGen->rsGetRsvdReg();
2853 codeGen->instGen_Set_Reg_To_Imm(EA_4BYTE, rsvdReg, (ssize_t)imm);
2854 emitIns_R_R_R(ins, attr, reg1, reg2, rsvdReg);
2862 assert(insOptsNone(opt));
2863 assert(insDoesNotSetFlags(flags));
2864 sf = INS_FLAGS_NOT_SET;
2866 if ((imm & 0x03fc) == imm)
2872 assert(!"Instruction cannot be encoded");
2877 assert(!"Unexpected instruction");
2879 assert((fmt == IF_T1_C) || (fmt == IF_T1_E) || (fmt == IF_T1_G) || (fmt == IF_T1_J2) || (fmt == IF_T1_J3) ||
2880 (fmt == IF_T2_C1) || (fmt == IF_T2_C2) || (fmt == IF_T2_C6) || (fmt == IF_T2_C7) || (fmt == IF_T2_C8) ||
2881 (fmt == IF_T2_H0) || (fmt == IF_T2_H1) || (fmt == IF_T2_K1) || (fmt == IF_T2_K4) || (fmt == IF_T2_L0) ||
2882 (fmt == IF_T2_M0) || (fmt == IF_T2_VLDST) || (fmt == IF_T2_M1));
2883 assert(sf != INS_FLAGS_DONT_CARE);
2885 instrDesc* id = emitNewInstrSC(attr, imm);
2886 insSize isz = emitInsSize(fmt);
2900 /*****************************************************************************
2902 * Add an instruction referencing three registers.
2905 void emitter::emitIns_R_R_R(instruction ins,
2910 insFlags flags /* = INS_FLAGS_DONT_CARE */)
2912 emitAttr size = EA_SIZE(attr);
2913 insFormat fmt = IF_NONE;
2914 insFlags sf = INS_FLAGS_DONT_CARE;
2916 /* Figure out the encoding format of the instruction */
2920 // Encodings do not support SP in the reg3 slot
2923 // Swap reg2 and reg3
2930 assert(reg3 != REG_SP);
2932 if (isLowRegister(reg1) && isLowRegister(reg2) && isLowRegister(reg3) && insSetsFlags(flags))
2939 if ((ins == INS_add) && insDoesNotSetFlags(flags))
2943 // Use the Thumb-1 regdest,reg encoding
2944 emitIns_R_R(ins, attr, reg1, reg3, flags);
2949 // Use the Thumb-1 regdest,reg encoding
2950 emitIns_R_R(ins, attr, reg1, reg2, flags);
2955 // Use the Thumb-2 reg,reg,reg with shift encoding
2956 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, flags);
2967 // Try to encode as a Thumb-1 instruction
2968 emitIns_R_R(ins, attr, reg1, reg3, flags);
2974 // Use the Thumb-2 three register encoding, with imm=0
2975 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, flags);
2981 if (reg1 == reg2 && insSetsFlags(flags) && isLowRegister(reg1) && isLowRegister(reg3))
2983 // Use the Thumb-1 regdest,reg encoding
2984 emitIns_R_R(ins, attr, reg1, reg3, flags);
2991 sf = insMustSetFlags(flags);
2995 if (insMustSetFlags(flags))
2997 if ((reg1 == reg2) && isLowRegister(reg1))
2999 // Use the Thumb-1 regdest,reg encoding
3000 emitIns_R_R(ins, attr, reg1, reg3, flags);
3003 if ((reg1 == reg3) && isLowRegister(reg1))
3005 // Use the Thumb-1 regdest,reg encoding
3006 emitIns_R_R(ins, attr, reg1, reg2, flags);
3011 assert(!"Instruction cannot be encoded");
3016 #if !defined(USE_HELPERS_FOR_INT_DIV)
3019 #endif // !USE_HELPERS_FOR_INT_DIV
3021 assert(insDoesNotSetFlags(flags));
3023 sf = INS_FLAGS_NOT_SET;
3029 assert(size == EA_1BYTE);
3030 goto COMMON_THUMB1_LDST;
3035 assert(size == EA_2BYTE);
3036 goto COMMON_THUMB1_LDST;
3040 assert(size == EA_4BYTE);
3043 assert(insDoesNotSetFlags(flags));
3045 if (isLowRegister(reg1) && isLowRegister(reg2) && isLowRegister(reg3))
3048 sf = INS_FLAGS_NOT_SET;
3052 // Use the Thumb-2 reg,reg,reg with shift encoding
3053 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, flags);
3062 if (size == EA_8BYTE)
3064 assert(isDoubleReg(reg1));
3065 assert(isDoubleReg(reg2));
3066 assert(isDoubleReg(reg3));
3070 assert(isFloatReg(reg1));
3071 assert(isFloatReg(reg2));
3072 assert(isFloatReg(reg3));
3075 sf = INS_FLAGS_NOT_SET;
3079 assert(isDoubleReg(reg1));
3080 assert(isGeneralRegister(reg2));
3081 assert(isGeneralRegister(reg3));
3083 sf = INS_FLAGS_NOT_SET;
3087 assert(isGeneralRegister(reg1));
3088 assert(isGeneralRegister(reg2));
3089 assert(isDoubleReg(reg3));
3091 sf = INS_FLAGS_NOT_SET;
3096 assert(insDoesNotSetFlags(flags));
3098 sf = INS_FLAGS_NOT_SET;
3104 assert((fmt == IF_T1_H) || (fmt == IF_T2_C4) || (fmt == IF_T2_C5) || (fmt == IF_T2_VFP3) || (fmt == IF_T2_VMOVD) ||
3106 assert(sf != INS_FLAGS_DONT_CARE);
3108 instrDesc* id = emitNewInstr(attr);
3109 insSize isz = emitInsSize(fmt);
3123 /*****************************************************************************
3125 * Add an instruction referencing two registers and two constants.
3128 void emitter::emitIns_R_R_I_I(instruction ins,
3134 insFlags flags /* = INS_FLAGS_DONT_CARE */)
3136 insFormat fmt = IF_NONE;
3137 insFlags sf = INS_FLAGS_DONT_CARE;
3141 int msb = lsb + width - 1;
3142 int imm = 0; /* combined immediate */
3144 assert((lsb >= 0) && (lsb <= 31)); // required for encodings
3145 assert((width > 0) && (width <= 32)); // required for encodings
3146 assert((msb >= 0) && (msb <= 31)); // required for encodings
3147 assert(msb >= lsb); // required for encodings
3149 /* Figure out the encoding format of the instruction */
3153 assert(insDoesNotSetFlags(flags));
3154 imm = (lsb << 5) | msb;
3157 sf = INS_FLAGS_NOT_SET;
3162 assert(insDoesNotSetFlags(flags));
3163 imm = (lsb << 5) | (width - 1);
3166 sf = INS_FLAGS_NOT_SET;
3172 assert((fmt == IF_T2_D0));
3173 assert(sf != INS_FLAGS_DONT_CARE);
3175 instrDesc* id = emitNewInstrSC(attr, imm);
3176 insSize isz = emitInsSize(fmt);
3189 /*****************************************************************************
3191 * Add an instruction referencing three registers and a constant.
3194 void emitter::emitIns_R_R_R_I(instruction ins,
3200 insFlags flags /* = INS_FLAGS_DONT_CARE */,
3201 insOpts opt /* = INS_OPTS_NONE */)
3203 emitAttr size = EA_SIZE(attr);
3204 insFormat fmt = IF_NONE;
3205 insFlags sf = INS_FLAGS_DONT_CARE;
3207 /* Figure out the encoding format of the instruction */
3215 if (isLowRegister(reg1) && isLowRegister(reg2) && isLowRegister(reg3) && insSetsFlags(flags))
3217 // Use the Thumb-1 reg,reg,reg encoding
3218 emitIns_R_R_R(ins, attr, reg1, reg2, reg3, flags);
3221 if ((ins == INS_add) && insDoesNotSetFlags(flags))
3225 // Use the Thumb-1 regdest,reg encoding
3226 emitIns_R_R(ins, attr, reg1, reg3, flags);
3231 // Use the Thumb-1 regdest,reg encoding
3232 emitIns_R_R(ins, attr, reg1, reg2, flags);
3246 assert((imm >= 0) && (imm <= 31)); // required for encoding
3247 assert(!insOptAnyInc(opt));
3250 if (opt == INS_OPTS_LSL) // left shift of zero
3251 opt = INS_OPTS_NONE; // is a nop
3253 assert(insOptsNone(opt));
3254 if (isLowRegister(reg1) && isLowRegister(reg2) && isLowRegister(reg3) && insSetsFlags(flags))
3258 // Use the Thumb-1 regdest,reg encoding
3259 emitIns_R_R(ins, attr, reg1, reg3, flags);
3262 if ((reg1 == reg3) && (ins != INS_bic) && (ins != INS_orn) && (ins != INS_sbc))
3264 // Use the Thumb-1 regdest,reg encoding
3265 emitIns_R_R(ins, attr, reg1, reg2, flags);
3270 else // imm > 0 && imm <= 31)
3272 assert(insOptAnyShift(opt));
3273 if (insOptsRRX(opt))
3277 sf = insMustSetFlags(flags);
3283 assert(size == EA_1BYTE);
3284 goto COMMON_THUMB2_LDST;
3289 assert(size == EA_2BYTE);
3290 goto COMMON_THUMB2_LDST;
3294 assert(size == EA_4BYTE);
3297 assert(insDoesNotSetFlags(flags));
3298 assert((imm & 0x0003) == imm); // required for encoding
3300 if ((imm == 0) && insOptsNone(opt) && isLowRegister(reg1) && isLowRegister(reg2) && isLowRegister(reg3))
3302 // Use the Thumb-1 reg,reg,reg encoding
3303 emitIns_R_R_R(ins, attr, reg1, reg2, reg3, flags);
3306 assert(insOptsNone(opt) || insOptsLSL(opt));
3308 sf = INS_FLAGS_NOT_SET;
3313 assert(insDoesNotSetFlags(flags));
3314 assert((imm & 0x03) == 0);
3315 sf = INS_FLAGS_NOT_SET;
3317 if (insOptAnyInc(opt))
3319 if (insOptsPostInc(opt))
3321 else // insOptsPreDec(opt)
3326 assert(insOptsNone(opt));
3329 if (unsigned_abs(imm) <= 0x03fc)
3336 assert(!"Instruction cannot be encoded");
3343 assert((fmt == IF_T2_C0) || (fmt == IF_T2_E0) || (fmt == IF_T2_G0));
3344 assert(sf != INS_FLAGS_DONT_CARE);
3346 // 3-reg ops can't use the small instrdesc
3347 instrDescCns* id = emitAllocInstrCns(attr);
3348 id->idSetIsLargeCns();
3349 id->idcCnsVal = imm;
3353 id->idInsSize(emitInsSize(fmt));
3365 /*****************************************************************************
3367 * Add an instruction referencing four registers.
3370 void emitter::emitIns_R_R_R_R(
3371 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, regNumber reg4)
3373 insFormat fmt = IF_NONE;
3374 insFlags sf = INS_FLAGS_NOT_SET;
3376 /* Figure out the encoding format of the instruction */
3384 assert(reg1 != reg2); // Illegal encoding
3394 assert((fmt == IF_T2_F1) || (fmt == IF_T2_F2));
3396 instrDesc* id = emitNewInstr(attr);
3397 insSize isz = emitInsSize(fmt);
3412 /*****************************************************************************
3414 * Add an instruction with a static data member operand. If 'size' is 0, the
3415 * instruction operates on the address of the static member instead of its
3416 * value (e.g. "push offset clsvar", rather than "push dword ptr [clsvar]").
3419 void emitter::emitIns_C(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, int offs)
3424 /*****************************************************************************
3426 * Add an instruction referencing stack-based local variable.
3429 void emitter::emitIns_S(instruction ins, emitAttr attr, int varx, int offs)
3434 /*****************************************************************************
3436 * Add an instruction referencing a register and a stack-based local variable.
3438 void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
3442 assert(!"Please use ins_Load() to select the correct instruction");
3468 insFormat fmt = IF_NONE;
3469 insFlags sf = INS_FLAGS_NOT_SET;
3472 /* Figure out the variable's frame position */
3477 base = emitComp->lvaFrameAddress(varx, emitComp->funCurrentFunc()->funKind != FUNC_ROOT, ®2, offs);
3480 undisp = unsigned_abs(disp);
3482 if (CodeGen::instIsFP(ins))
3484 // all fp mem ops take 8 bit immediate, multiplied by 4, plus sign
3486 // Note if undisp is not a multiple of four we will fail later on
3487 // when we try to encode this instruction
3488 // Its better to fail later with a better error message than
3489 // to fail here when the RBM_OPT_RSVD is not available
3491 if (undisp <= 0x03fc)
3497 regNumber rsvdReg = codeGen->rsGetRsvdReg();
3498 emitIns_genStackOffset(rsvdReg, varx, offs);
3499 emitIns_R_R(INS_add, EA_4BYTE, rsvdReg, reg2);
3500 emitIns_R_R_I(ins, attr, reg1, rsvdReg, 0);
3504 else if (emitInsIsLoadOrStore(ins))
3506 if (isLowRegister(reg1) && (reg2 == REG_SP) && (ins == INS_ldr) && ((disp & 0x03fc) == disp))
3510 else if (disp >= 0 && disp <= 0x0fff)
3514 else if (undisp <= 0x0ff)
3520 // Load disp into a register
3521 regNumber rsvdReg = codeGen->rsGetRsvdReg();
3522 emitIns_genStackOffset(rsvdReg, varx, offs);
3526 else if (ins == INS_add)
3528 if (isLowRegister(reg1) && (reg2 == REG_SP) && ((disp & 0x03fc) == disp))
3532 else if (undisp <= 0x0fff)
3539 // add/sub => addw/subw instruction
3540 // Note that even when using the w prefix the immediate is still only 12 bits?
3541 ins = (ins == INS_add) ? INS_addw : INS_subw;
3546 // Load disp into a register
3547 regNumber rsvdReg = codeGen->rsGetRsvdReg();
3548 emitIns_genStackOffset(rsvdReg, varx, offs);
3549 emitIns_R_R_R(ins, attr, reg1, reg2, rsvdReg);
3553 else if (ins == INS_movw || ins == INS_movt)
3558 assert((fmt == IF_T1_J2) || (fmt == IF_T2_E0) || (fmt == IF_T2_H0) || (fmt == IF_T2_K1) || (fmt == IF_T2_L0) ||
3559 (fmt == IF_T2_N) || (fmt == IF_T2_VLDST) || (fmt == IF_T2_M0));
3560 assert(sf != INS_FLAGS_DONT_CARE);
3562 instrDesc* id = emitNewInstrCns(attr, disp);
3563 insSize isz = emitInsSize(fmt);
3569 id->idInsOpt(INS_OPTS_NONE);
3572 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
3573 id->idSetIsLclVar();
3575 id->idSetIsLclFPBase();
3578 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
3585 // generate the offset of &varx + offs into a register
3586 void emitter::emitIns_genStackOffset(regNumber r, int varx, int offs)
3592 base = emitComp->lvaFrameAddress(varx, emitComp->funCurrentFunc()->funKind != FUNC_ROOT, ®Base, offs);
3595 emitIns_R_S(INS_movw, EA_4BYTE, r, varx, offs);
3597 if ((disp & 0xffff) != disp)
3599 emitIns_R_S(INS_movt, EA_4BYTE, r, varx, offs);
3603 /*****************************************************************************
3605 * Add an instruction referencing a stack-based local variable and a register
3607 void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
3611 assert(!"Please use ins_Store() to select the correct instruction");
3627 insFormat fmt = IF_NONE;
3628 insFlags sf = INS_FLAGS_NOT_SET;
3631 /* Figure out the variable's frame position */
3636 base = emitComp->lvaFrameAddress(varx, emitComp->funCurrentFunc()->funKind != FUNC_ROOT, ®2, offs);
3639 undisp = unsigned_abs(disp);
3641 if (CodeGen::instIsFP(ins))
3643 // all fp mem ops take 8 bit immediate, multiplied by 4, plus sign
3645 // Note if undisp is not a multiple of four we will fail later on
3646 // when we try to encode this instruction
3647 // Its better to fail later with a better error message than
3648 // to fail here when the RBM_OPT_RSVD is not available
3650 if (undisp <= 0x03fc)
3656 regNumber rsvdReg = codeGen->rsGetRsvdReg();
3657 emitIns_genStackOffset(rsvdReg, varx, offs);
3658 emitIns_R_R(INS_add, EA_4BYTE, rsvdReg, reg2);
3659 emitIns_R_R_I(ins, attr, reg1, rsvdReg, 0);
3663 else if (isLowRegister(reg1) && (reg2 == REG_SP) && (ins == INS_str) && ((disp & 0x03fc) == disp))
3667 else if (disp >= 0 && disp <= 0x0fff)
3671 else if (undisp <= 0x0ff)
3677 // Load disp into a register
3678 regNumber rsvdReg = codeGen->rsGetRsvdReg();
3679 emitIns_genStackOffset(rsvdReg, varx, offs);
3682 assert((fmt == IF_T1_J2) || (fmt == IF_T2_E0) || (fmt == IF_T2_H0) || (fmt == IF_T2_VLDST) || (fmt == IF_T2_K1));
3683 assert(sf != INS_FLAGS_DONT_CARE);
3685 instrDesc* id = emitNewInstrCns(attr, disp);
3686 insSize isz = emitInsSize(fmt);
3692 id->idInsOpt(INS_OPTS_NONE);
3695 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
3696 id->idSetIsLclVar();
3698 id->idSetIsLclFPBase();
3700 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
3707 /*****************************************************************************
3709 * Add an instruction referencing stack-based local variable and an immediate
3711 void emitter::emitIns_S_I(instruction ins, emitAttr attr, int varx, int offs, int val)
3716 /*****************************************************************************
3718 * Add an instruction with a register + static member operands.
3720 void emitter::emitIns_R_C(instruction ins, emitAttr attr, regNumber reg, CORINFO_FIELD_HANDLE fldHnd, int offs)
3724 assert(!"Please use ins_Load() to select the correct instruction");
3726 assert(emitInsIsLoad(ins) || (ins == INS_lea));
3732 int doff = Compiler::eeGetJitDataOffs(fldHnd);
3733 ssize_t addr = NULL;
3737 NYI_ARM("JitDataOffset static fields");
3739 else if (fldHnd == FLD_GLOBAL_FS)
3741 NYI_ARM("Thread-Local-Storage static fields");
3743 else if (fldHnd == FLD_GLOBAL_DS)
3745 addr = (ssize_t)offs;
3750 assert(!jitStaticFldIsGlobAddr(fldHnd));
3751 addr = (ssize_t)emitComp->info.compCompHnd->getFieldAddress(fldHnd, NULL);
3753 NO_WAY("could not obtain address of static field");
3756 // We can use reg to load the constant address,
3757 // as long as it is not a floating point register
3758 regNumber regTmp = reg;
3760 if (isFloatReg(regTmp))
3762 assert(!"emitIns_R_C() cannot be called with floating point target");
3766 // Load address of CLS_VAR into a register
3767 codeGen->instGen_Set_Reg_To_Imm(EA_HANDLE_CNS_RELOC, regTmp, addr);
3769 if ((ins != INS_add) || (offs != 0) || (reg != regTmp))
3771 emitIns_R_R_I(ins, attr, reg, regTmp, offs);
3775 /*****************************************************************************
3777 * Add an instruction with a static member + register operands.
3780 void emitter::emitIns_C_R(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, regNumber reg, int offs)
3782 assert(!"emitIns_C_R not supported");
3785 /*****************************************************************************
3787 * Add an instruction with a static member + constant.
3790 void emitter::emitIns_C_I(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, int offs, ssize_t val)
3795 /*****************************************************************************
3797 * The following adds instructions referencing address modes.
3800 void emitter::emitIns_I_AR(instruction ins, emitAttr attr, int val, regNumber reg, int offs)
3802 NYI("emitIns_I_AR");
3805 void emitter::emitIns_R_AR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
3809 assert(!"Please use ins_Load() to select the correct instruction");
3814 if (emitter::emitIns_valid_imm_for_add(offs, INS_FLAGS_DONT_CARE))
3816 emitIns_R_R_I(INS_add, attr, ireg, reg, offs);
3820 assert(!"emitIns_R_AR: immediate doesn't fit in the instruction");
3824 else if (emitInsIsLoad(ins))
3826 emitIns_R_R_I(ins, attr, ireg, reg, offs);
3829 else if ((ins == INS_mov) || (ins == INS_ldr))
3831 if (EA_SIZE(attr) == EA_4BYTE)
3833 emitIns_R_R_I(INS_ldr, attr, ireg, reg, offs);
3837 else if (ins == INS_vldr)
3839 emitIns_R_R_I(ins, attr, ireg, reg, offs);
3841 NYI("emitIns_R_AR");
3844 void emitter::emitIns_R_AI(instruction ins, emitAttr attr, regNumber ireg, ssize_t disp)
3846 if (emitInsIsLoad(ins))
3848 // We can use ireg to load the constant address,
3849 // as long as it is not a floating point register
3850 regNumber regTmp = ireg;
3852 if (isFloatReg(regTmp))
3854 assert(!"emitIns_R_AI with floating point reg");
3858 codeGen->instGen_Set_Reg_To_Imm(EA_IS_RELOC(attr) ? EA_HANDLE_CNS_RELOC : EA_PTRSIZE, regTmp, disp);
3859 emitIns_R_R_I(ins, EA_TYPE(attr), ireg, regTmp, 0);
3862 NYI("emitIns_R_AI");
3865 void emitter::emitIns_AR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
3869 assert(!"Please use ins_Store() to select the correct instruction");
3871 emitIns_R_R_I(ins, attr, ireg, reg, offs);
3874 void emitter::emitIns_R_ARR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
3878 assert(!"Please use ins_Load() to select the correct instruction");
3883 emitIns_R_R_R(INS_add, attr, ireg, reg, rg2);
3886 emitIns_R_R_I(INS_add, attr, ireg, ireg, disp);
3890 else if (emitInsIsLoad(ins))
3894 emitIns_R_R_R_I(ins, attr, ireg, reg, rg2, 0, INS_FLAGS_DONT_CARE, INS_OPTS_NONE);
3898 assert(!"emitIns_R_ARR: Unexpected instruction");
3901 void emitter::emitIns_ARR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
3905 assert(!"Please use ins_Store() to select the correct instruction");
3907 if (emitInsIsStore(ins))
3911 emitIns_R_R_R(ins, attr, ireg, reg, rg2);
3915 emitIns_R_R_R(INS_add, attr, ireg, reg, rg2);
3916 emitIns_R_R_I(ins, attr, ireg, ireg, disp);
3920 assert(!"emitIns_ARR_R: Unexpected instruction");
3923 void emitter::emitIns_R_ARX(
3924 instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, unsigned mul, int disp)
3928 assert(!"Please use ins_Load() to select the correct instruction");
3931 unsigned shift = genLog2((unsigned)mul);
3933 if ((ins == INS_lea) || emitInsIsLoad(ins))
3941 emitIns_R_R_R_I(ins, attr, ireg, reg, rg2, (int)shift, INS_FLAGS_DONT_CARE, INS_OPTS_LSL);
3946 bool useForm2 = false;
3947 bool mustUseForm1 = ((disp % mul) != 0) || (reg == ireg);
3950 // If all of the below things are true we can generate a Thumb-1 add instruction
3951 // followed by a Thumb-2 add instruction
3952 // We also useForm1 when reg is a low register since the second instruction
3953 // can then always be generated using a Thumb-1 add
3955 if ((reg >= REG_R8) && (ireg < REG_R8) && (rg2 < REG_R8) && ((disp >> shift) <= 7))
3964 // Thumb-1 instruction add Rd, Rx, disp>>shift
3965 // Thumb-2 instructions ldr Rd, Rb, Rd LSL shift
3967 emitIns_R_R_I(INS_add, EA_4BYTE, ireg, rg2, disp >> shift);
3968 emitIns_R_R_R_I(ins, attr, ireg, reg, ireg, shift, INS_FLAGS_NOT_SET, INS_OPTS_LSL);
3973 // Thumb-2 instruction add Rd, Rb, Rx LSL shift
3974 // Thumb-1/2 instructions ldr Rd, Rd, disp
3976 emitIns_R_R_R_I(INS_add, attr, ireg, reg, rg2, shift, INS_FLAGS_NOT_SET, INS_OPTS_LSL);
3977 emitIns_R_R_I(ins, attr, ireg, ireg, disp);
3983 assert(!"emitIns_R_ARX: Unexpected instruction");
3986 /*****************************************************************************
3988 * Record that a jump instruction uses the short encoding
3991 void emitter::emitSetShortJump(instrDescJmp* id)
3993 if (id->idjKeepLong)
3996 if (emitIsCondJump(id))
3998 id->idInsFmt(IF_T1_K);
4000 else if (emitIsCmpJump(id))
4002 // These are always only ever short!
4003 assert(id->idjShort);
4006 else if (emitIsUncondJump(id))
4008 id->idInsFmt(IF_T1_M);
4010 else if (emitIsLoadLabel(id))
4012 return; // Keep long - we don't know the alignment of the target
4016 assert(!"Unknown instruction in emitSetShortJump()");
4019 id->idjShort = true;
4022 if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
4024 printf("[8] Converting jump %u to short\n", id->idDebugOnlyInfo()->idNum);
4026 #endif // DEBUG_EMIT
4028 insSize isz = emitInsSize(id->idInsFmt());
4032 /*****************************************************************************
4034 * Record that a jump instruction uses the medium encoding
4037 void emitter::emitSetMediumJump(instrDescJmp* id)
4039 if (id->idjKeepLong)
4043 if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
4045 printf("[9] Converting jump %u to medium\n", id->idDebugOnlyInfo()->idNum);
4047 #endif // DEBUG_EMIT
4049 assert(emitIsCondJump(id));
4050 id->idInsFmt(IF_T2_J1);
4051 id->idjShort = false;
4053 insSize isz = emitInsSize(id->idInsFmt());
4057 /*****************************************************************************
4059 * Add a jmp instruction.
4060 * When dst is NULL, instrCount specifies number of instructions
4061 * to jump: positive is forward, negative is backward.
4062 * Unconditional branches have two sizes: short and long.
4063 * Conditional branches have three sizes: short, medium, and long. A long
4064 * branch is a pseudo-instruction that represents two instructions:
4065 * a short conditional branch to branch around a large unconditional
4066 * branch. Thus, we can handle branch offsets of imm24 instead of just imm20.
4069 void emitter::emitIns_J(instruction ins, BasicBlock* dst, int instrCount /* = 0 */)
4071 insFormat fmt = IF_NONE;
4075 assert(dst->bbFlags & BBF_JMP_TARGET);
4079 assert(instrCount != 0);
4082 /* Figure out the encoding format of the instruction */
4086 fmt = IF_T2_J2; /* Assume the jump will be long */
4103 fmt = IF_LARGEJMP; /* Assume the jump will be long */
4109 assert((fmt == IF_LARGEJMP) || (fmt == IF_T2_J2));
4111 instrDescJmp* id = emitNewInstrJmp();
4112 insSize isz = emitInsSize(fmt);
4119 // Mark the finally call
4120 if (ins == INS_b && emitComp->compCurBB->bbJumpKind == BBJ_CALLFINALLY)
4122 id->idDebugOnlyInfo()->idFinallyCall = true;
4126 /* Assume the jump will be long */
4131 id->idAddr()->iiaBBlabel = dst;
4132 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
4135 if (emitComp->opts.compLongAddress) // Force long branches
4136 id->idjKeepLong = 1;
4141 id->idAddr()->iiaSetInstrCount(instrCount);
4142 id->idjKeepLong = false;
4143 /* This jump must be short */
4144 emitSetShortJump(id);
4148 /* Record the jump's IG and offset within it */
4150 id->idjIG = emitCurIG;
4151 id->idjOffs = emitCurIGsize;
4153 /* Append this jump to this IG's jump list */
4155 id->idjNext = emitCurIGjmpList;
4156 emitCurIGjmpList = id;
4162 /* Figure out the max. size of the jump/call instruction */
4164 if (!id->idjKeepLong)
4166 insGroup* tgt = NULL;
4168 /* Can we guess at the jump distance? */
4172 tgt = (insGroup*)emitCodeGetCookie(dst);
4177 UNATIVE_OFFSET srcOffs;
4180 assert(JMP_SIZE_SMALL == JCC_SIZE_SMALL);
4182 /* This is a backward jump - figure out the distance */
4184 srcOffs = emitCurCodeOffset + emitCurIGsize;
4186 /* Compute the distance estimate */
4188 jmpDist = srcOffs - tgt->igOffs;
4189 assert(jmpDist >= 0);
4190 jmpDist += 4; // Adjustment for ARM PC
4195 if (JMP_DIST_SMALL_MAX_NEG <= -jmpDist)
4197 /* This jump surely will be short */
4198 emitSetShortJump(id);
4203 if (JCC_DIST_SMALL_MAX_NEG <= -jmpDist)
4205 /* This jump surely will be short */
4206 emitSetShortJump(id);
4208 else if (JCC_DIST_MEDIUM_MAX_NEG <= -jmpDist)
4210 /* This jump surely will be medium */
4211 emitSetMediumJump(id);
4226 /*****************************************************************************
4228 * Add a label instruction.
4231 void emitter::emitIns_R_L(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
4233 assert(dst->bbFlags & BBF_JMP_TARGET);
4235 insFormat fmt = IF_NONE;
4238 /* Figure out the encoding format of the instruction */
4242 id = emitNewInstrLbl();
4247 id = emitNewInstrJmp();
4253 assert((fmt == IF_T2_M1) || (fmt == IF_T2_N1));
4255 insSize isz = emitInsSize(fmt);
4263 // Mark the catch return
4264 if (emitComp->compCurBB->bbJumpKind == BBJ_EHCATCHRET)
4266 id->idDebugOnlyInfo()->idCatchRet = true;
4270 id->idAddr()->iiaBBlabel = dst;
4271 id->idjShort = false;
4276 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
4280 id->idjKeepLong = true;
4283 /* Record the jump's IG and offset within it */
4285 id->idjIG = emitCurIG;
4286 id->idjOffs = emitCurIGsize;
4288 /* Append this jump to this IG's jump list */
4290 id->idjNext = emitCurIGjmpList;
4291 emitCurIGjmpList = id;
4293 // Set the relocation flags - these give hint to zap to perform
4294 // relocation of the specified 32bit address.
4295 id->idSetRelocFlags(attr);
4305 /*****************************************************************************
4307 * Add a data label instruction.
4310 void emitter::emitIns_R_D(instruction ins, emitAttr attr, unsigned offs, regNumber reg)
4312 noway_assert((ins == INS_movw) || (ins == INS_movt));
4314 insFormat fmt = IF_T2_N2;
4315 instrDesc* id = emitNewInstrSC(attr, offs);
4316 insSize isz = emitInsSize(fmt);
4323 if (emitComp->opts.compReloc)
4325 // Set the relocation flags - these give hint to zap to perform
4326 // relocation of the specified 32bit address.
4327 id->idSetRelocFlags(attr);
4334 void emitter::emitIns_J_R(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
4336 assert(dst->bbFlags & BBF_JMP_TARGET);
4338 insFormat fmt = IF_NONE;
4348 assert(fmt == IF_T1_I);
4350 assert(isLowRegister(reg));
4352 instrDescJmp* id = emitNewInstrJmp();
4354 id->idInsFmt(IF_T1_I);
4355 id->idInsSize(emitInsSize(IF_T1_I));
4358 /* This jump better be short or-else! */
4359 id->idjShort = true;
4360 id->idAddr()->iiaBBlabel = dst;
4361 id->idjKeepLong = false;
4363 /* Record the jump's IG and offset within it */
4365 id->idjIG = emitCurIG;
4366 id->idjOffs = emitCurIGsize;
4368 /* Append this jump to this IG's jump list */
4370 id->idjNext = emitCurIGjmpList;
4371 emitCurIGjmpList = id;
4381 /*****************************************************************************
4383 * Add a call instruction (direct or indirect).
4384 * argSize<0 means that the caller will pop the arguments
4386 * The other arguments are interpreted depending on callType as shown:
4387 * Unless otherwise specified, ireg,xreg,xmul,disp should have default values.
4389 * EC_FUNC_TOKEN : addr is the method address
4390 * EC_FUNC_ADDR : addr is the absolute address of the function
4391 * if addr is NULL, it is a recursive call
4393 * If callType is one of these emitCallTypes, addr has to be NULL.
4394 * EC_INDIR_R : "call ireg".
4396 * For ARM xreg, xmul and disp are never used and should always be 0/REG_NA.
4398 * Please consult the "debugger team notification" comment in genFnProlog().
4401 void emitter::emitIns_Call(EmitCallType callType,
4402 CORINFO_METHOD_HANDLE methHnd, // used for pretty printing
4403 INDEBUG_LDISASM_COMMA(CORINFO_SIG_INFO* sigInfo) // used to report call sites to the EE
4407 VARSET_VALARG_TP ptrVars,
4408 regMaskTP gcrefRegs,
4409 regMaskTP byrefRegs,
4410 IL_OFFSETX ilOffset /* = BAD_IL_OFFSET */,
4411 regNumber ireg /* = REG_NA */,
4412 regNumber xreg /* = REG_NA */,
4413 unsigned xmul /* = 0 */,
4415 bool isJump /* = false */,
4416 bool isNoGC /* = false */,
4417 bool isProfLeaveCB /* = false */)
4419 /* Sanity check the arguments depending on callType */
4421 assert(callType < EC_COUNT);
4422 assert((callType != EC_FUNC_TOKEN && callType != EC_FUNC_ADDR) ||
4423 (ireg == REG_NA && xreg == REG_NA && xmul == 0 && disp == 0));
4424 assert(callType < EC_INDIR_R || addr == NULL);
4425 assert(callType != EC_INDIR_R || (ireg < REG_COUNT && xreg == REG_NA && xmul == 0 && disp == 0));
4427 // ARM never uses these
4428 assert(xreg == REG_NA && xmul == 0 && disp == 0);
4430 // Our stack level should be always greater than the bytes of arguments we push. Just
4432 assert((unsigned)abs(argSize) <= codeGen->genStackLevel);
4437 /* This is the saved set of registers after a normal call */
4438 regMaskTP savedSet = RBM_CALLEE_SAVED;
4440 /* some special helper calls have a different saved set registers */
4444 assert(emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
4446 // Get the set of registers that this call kills and remove it from the saved set.
4447 savedSet = RBM_ALLINT & ~emitComp->compNoGCHelperCallKillSet(Compiler::eeGetHelperNum(methHnd));
4449 // In case of Leave profiler callback, we need to preserve liveness of REG_PROFILER_RET_SCRATCH
4452 savedSet |= RBM_PROFILER_RET_SCRATCH;
4456 if (emitComp->verbose)
4458 printf("NOGC Call: savedSet=");
4459 printRegMaskInt(savedSet);
4460 emitDispRegSet(savedSet);
4467 assert(!emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
4470 /* Trim out any callee-trashed registers from the live set */
4472 gcrefRegs &= savedSet;
4473 byrefRegs &= savedSet;
4476 if (EMIT_GC_VERBOSE)
4478 printf("Call: GCvars=%s ", VarSetOps::ToString(emitComp, ptrVars));
4479 dumpConvertedVarSet(emitComp, ptrVars);
4480 printf(", gcrefRegs=");
4481 printRegMaskInt(gcrefRegs);
4482 emitDispRegSet(gcrefRegs);
4483 printf(", byrefRegs=");
4484 printRegMaskInt(byrefRegs);
4485 emitDispRegSet(byrefRegs);
4490 assert(argSize % (int)REGSIZE_BYTES == 0);
4491 argCnt = argSize / (int)REGSIZE_BYTES;
4493 /* Managed RetVal: emit sequence point for the call */
4494 if (emitComp->opts.compDbgInfo && ilOffset != BAD_IL_OFFSET)
4496 codeGen->genIPmappingAdd(ilOffset, false);
4500 We need to allocate the appropriate instruction descriptor based
4501 on whether this is a direct/indirect call, and whether we need to
4502 record an updated set of live GC variables.
4504 The stats for a ton of classes is as follows:
4506 Direct call w/o GC vars 220,216
4507 Indir. call w/o GC vars 144,781
4509 Direct call with GC vars 9,440
4510 Indir. call with GC vars 5,768
4513 if (callType >= EC_INDIR_R)
4515 /* Indirect call, virtual calls */
4517 assert(callType == EC_INDIR_R);
4519 id = emitNewInstrCallInd(argCnt, disp, ptrVars, gcrefRegs, byrefRegs, retSize);
4523 /* Helper/static/nonvirtual/function calls (direct or through handle),
4524 and calls to an absolute addr. */
4526 assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
4528 id = emitNewInstrCallDir(argCnt, ptrVars, gcrefRegs, byrefRegs, retSize);
4531 /* Update the emitter's live GC ref sets */
4533 VarSetOps::Assign(emitComp, emitThisGCrefVars, ptrVars);
4534 emitThisGCrefRegs = gcrefRegs;
4535 emitThisByrefRegs = byrefRegs;
4537 /* Set the instruction - special case jumping a function */
4539 insFormat fmt = IF_NONE;
4541 id->idSetIsNoGC(isNoGC);
4543 /* Record the address: method, indirection, or funcptr */
4545 if (callType > EC_FUNC_ADDR)
4547 /* This is an indirect call (either a virtual call or func ptr call) */
4551 case EC_INDIR_R: // the address is in a register
4553 id->idSetIsCallRegPtr();
4557 ins = INS_bx; // INS_bx Reg
4561 ins = INS_blx; // INS_blx Reg
4567 id->idInsSize(emitInsSize(fmt));
4569 assert(xreg == REG_NA);
4573 NO_WAY("unexpected instruction");
4579 /* This is a simple direct call: "call helper/method/addr" */
4581 assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
4583 // if addr is nullptr then this call is treated as a recursive call.
4584 assert(addr == nullptr || codeGen->arm_Valid_Imm_For_BL((ssize_t)addr));
4588 ins = INS_b; // INS_b imm24
4592 ins = INS_bl; // INS_bl imm24
4599 id->idInsSize(emitInsSize(fmt));
4601 id->idAddr()->iiaAddr = (BYTE*)addr;
4603 if (callType == EC_FUNC_ADDR)
4605 id->idSetIsCallAddr();
4608 if (emitComp->opts.compReloc)
4610 // Since this is an indirect call through a pointer and we don't
4611 // currently pass in emitAttr into this function we have decided
4612 // to always mark the displacement as being relocatable.
4614 id->idSetIsDspReloc();
4619 if (EMIT_GC_VERBOSE)
4621 if (id->idIsLargeCall())
4623 printf("[%02u] Rec call GC vars = %s\n", id->idDebugOnlyInfo()->idNum,
4624 VarSetOps::ToString(emitComp, ((instrDescCGCA*)id)->idcGCvars));
4628 id->idDebugOnlyInfo()->idMemCookie = (size_t)methHnd; // method token
4629 id->idDebugOnlyInfo()->idCallSig = sigInfo;
4633 if (addr != nullptr)
4635 codeGen->getDisAssembler().disSetMethod((size_t)addr, methHnd);
4637 #endif // LATE_DISASM
4643 /*****************************************************************************
4645 * Returns an encoding for the specified register (any-reg) to be used in
4646 * a Thumb-1 encoding in the M4 position
4649 inline unsigned insEncodeRegT1_M4(regNumber reg)
4651 assert(reg < REG_STK);
4656 /*****************************************************************************
4658 * Returns an encoding for the specified register (any-reg) to be used in
4659 * a Thumb-1 encoding in the D4 position
4662 inline unsigned insEncodeRegT1_D4(regNumber reg)
4664 assert(reg < REG_STK);
4666 return (reg & 0x7) | ((reg & 0x8) << 4);
4669 /*****************************************************************************
4671 * Returns an encoding for the specified register (low-only) to be used in
4672 * a Thumb-1 encoding in the M3 position
4675 inline unsigned insEncodeRegT1_M3(regNumber reg)
4677 assert(reg < REG_R8);
4682 /*****************************************************************************
4684 * Returns an encoding for the specified register (low-only) to be used in
4685 * a Thumb-1 encoding in the N3 position
4688 inline unsigned insEncodeRegT1_N3(regNumber reg)
4690 assert(reg < REG_R8);
4695 /*****************************************************************************
4697 * Returns an encoding for the specified register (low-only) to be used in
4698 * a Thumb-1 encoding in the D3 position
4701 inline unsigned insEncodeRegT1_D3(regNumber reg)
4703 assert(reg < REG_R8);
4707 /*****************************************************************************
4709 * Returns an encoding for the specified register (low-only) to be used in
4710 * a Thumb-1 encoding in the DI position
4713 inline unsigned insEncodeRegT1_DI(regNumber reg)
4715 assert(reg < REG_R8);
4720 /*****************************************************************************
4722 * Returns an encoding for the specified register to be used in
4723 * a Thumb-2 encoding in the N position
4726 inline unsigned insEncodeRegT2_N(regNumber reg)
4728 assert(reg < REG_STK);
4733 inline unsigned floatRegIndex(regNumber reg, int size)
4735 // theoretically this could support quad floats as well but for now...
4736 assert(size == EA_8BYTE || size == EA_4BYTE);
4738 if (size == EA_8BYTE)
4739 assert(emitter::isDoubleReg(reg));
4741 assert(emitter::isFloatReg(reg));
4743 unsigned result = reg - REG_F0;
4745 // the assumption here is that the register F8 also refers to D4
4746 if (size == EA_8BYTE)
4754 // variant: SOME arm VFP instructions use the convention that
4755 // for doubles, the split bit holds the msb of the register index
4756 // for singles it holds the lsb
4757 // excerpt : d = if dp_operation then UInt(D:Vd)
4758 // if single UInt(Vd:D);
4760 inline unsigned floatRegEncoding(unsigned index, int size, bool variant = false)
4762 if (!variant || size == EA_8BYTE)
4766 return ((index & 1) << 4) | (index >> 1);
4770 // thumb2 VFP M register encoding
4771 inline unsigned insEncodeRegT2_VectorM(regNumber reg, int size, bool variant)
4773 unsigned enc = floatRegIndex(reg, size);
4774 enc = floatRegEncoding(enc, size, variant);
4775 return ((enc & 0xf) << 0) | ((enc & 0x10) << 1);
4778 // thumb2 VFP N register encoding
4779 inline unsigned insEncodeRegT2_VectorN(regNumber reg, int size, bool variant)
4781 unsigned enc = floatRegIndex(reg, size);
4782 enc = floatRegEncoding(enc, size, variant);
4783 return ((enc & 0xf) << 16) | ((enc & 0x10) << 3);
4786 // thumb2 VFP D register encoding
4787 inline unsigned insEncodeRegT2_VectorD(regNumber reg, int size, bool variant)
4789 unsigned enc = floatRegIndex(reg, size);
4790 enc = floatRegEncoding(enc, size, variant);
4791 return ((enc & 0xf) << 12) | ((enc & 0x10) << 18);
4794 /*****************************************************************************
4796 * Returns an encoding for the specified register to be used in
4797 * a Thumb-2 encoding in the T position
4800 inline unsigned insEncodeRegT2_T(regNumber reg)
4802 assert(reg < REG_STK);
4807 /*****************************************************************************
4809 * Returns an encoding for the specified register to be used in
4810 * a Thumb-2 encoding in the D position
4813 inline unsigned insEncodeRegT2_D(regNumber reg)
4815 assert(reg < REG_STK);
4820 /*****************************************************************************
4822 * Returns an encoding for the specified register to be used in
4823 * a Thumb-2 encoding in the M position
4826 inline unsigned insEncodeRegT2_M(regNumber reg)
4828 assert(reg < REG_STK);
4833 /*****************************************************************************
4835 * Returns the encoding for the Set Flags bit to be used in a Thumb-2 encoding
4838 unsigned emitter::insEncodeSetFlags(insFlags sf)
4840 if (sf == INS_FLAGS_SET)
4846 /*****************************************************************************
4848 * Returns the encoding for the Shift Type bits to be used in a Thumb-2 encoding
4851 unsigned emitter::insEncodeShiftOpts(insOpts opt)
4853 if (opt == INS_OPTS_NONE)
4855 else if (opt == INS_OPTS_LSL)
4857 else if (opt == INS_OPTS_LSR)
4859 else if (opt == INS_OPTS_ASR)
4861 else if (opt == INS_OPTS_ROR)
4863 else if (opt == INS_OPTS_RRX)
4866 assert(!"Invalid insOpts");
4870 /*****************************************************************************
4872 * Returns the encoding for the PUW bits to be used in a T2_G0 Thumb-2 encoding
4875 unsigned emitter::insEncodePUW_G0(insOpts opt, int imm)
4877 unsigned result = 0;
4879 if (opt != INS_OPTS_LDST_POST_INC)
4880 result |= (1 << 24); // The P bit
4883 result |= (1 << 23); // The U bit
4885 if (opt != INS_OPTS_NONE)
4886 result |= (1 << 21); // The W bits
4890 /*****************************************************************************
4892 * Returns the encoding for the PUW bits to be used in a T2_H0 Thumb-2 encoding
4895 unsigned emitter::insEncodePUW_H0(insOpts opt, int imm)
4897 unsigned result = 0;
4899 if (opt != INS_OPTS_LDST_POST_INC)
4900 result |= (1 << 10); // The P bit
4903 result |= (1 << 9); // The U bit
4905 if (opt != INS_OPTS_NONE)
4906 result |= (1 << 8); // The W bits
4911 /*****************************************************************************
4913 * Returns the encoding for the Shift Count bits to be used in a Thumb-2 encoding
4916 inline unsigned insEncodeShiftCount(int imm)
4920 assert((imm & 0x001F) == imm);
4921 result = (imm & 0x03) << 6;
4922 result |= (imm & 0x1C) << 10;
4927 /*****************************************************************************
4929 * Returns the encoding for the immediate use by BFI/BFC Thumb-2 encodings
4932 inline unsigned insEncodeBitFieldImm(int imm)
4936 assert((imm & 0x03FF) == imm);
4937 result = (imm & 0x001f);
4938 result |= (imm & 0x0060) << 1;
4939 result |= (imm & 0x0380) << 5;
4944 /*****************************************************************************
4946 * Returns an encoding for the immediate use by MOV/MOVW Thumb-2 encodings
4949 inline unsigned insEncodeImmT2_Mov(int imm)
4953 assert((imm & 0x0000ffff) == imm);
4954 result = (imm & 0x00ff);
4955 result |= ((imm & 0x0700) << 4);
4956 result |= ((imm & 0x0800) << 15);
4957 result |= ((imm & 0xf000) << 4);
4962 /*****************************************************************************
4964 * Unscales the immediate based on the operand size in 'size'
4966 /*static*/ int emitter::insUnscaleImm(int imm, emitAttr size)
4972 assert((imm & 0x0003) == 0);
4977 assert((imm & 0x0001) == 0);
4986 assert(!"Invalid value in size");
4992 /*****************************************************************************
4994 * Emit a Thumb-1 instruction (a 16-bit integer as code)
4997 /*static*/ unsigned emitter::emitOutput_Thumb1Instr(BYTE* dst, code_t code)
4999 unsigned short word1 = code & 0xffff;
5000 assert(word1 == code);
5003 unsigned short top5bits = (word1 & 0xf800) >> 11;
5004 assert(top5bits < 29);
5007 MISALIGNED_WR_I2(dst, word1);
5009 return sizeof(short);
5011 /*****************************************************************************
5013 * Emit a Thumb-2 instruction (two 16-bit integers as code)
5016 /*static*/ unsigned emitter::emitOutput_Thumb2Instr(BYTE* dst, code_t code)
5018 unsigned short word1 = (code >> 16) & 0xffff;
5019 unsigned short word2 = (code)&0xffff;
5020 assert((code_t)((word1 << 16) | word2) == code);
5023 unsigned short top5bits = (word1 & 0xf800) >> 11;
5024 assert(top5bits >= 29);
5027 MISALIGNED_WR_I2(dst, word1);
5029 MISALIGNED_WR_I2(dst, word2);
5031 return sizeof(short) * 2;
5034 /*****************************************************************************
5036 * Output a local jump instruction.
5037 * Note that this may be invoked to overwrite an existing jump instruction at 'dst'
5038 * to handle forward branch patching.
5041 BYTE* emitter::emitOutputLJ(insGroup* ig, BYTE* dst, instrDesc* i)
5047 instrDescJmp* id = (instrDescJmp*)i;
5048 instruction ins = id->idIns();
5051 bool loadLabel = false;
5052 bool isJump = false;
5053 bool relAddr = true; // does the instruction use relative-addressing?
5060 sdistneg = JCC_DIST_SMALL_MAX_NEG;
5066 // One size fits all!
5072 sdistneg = LBL_DIST_SMALL_MAX_NEG;
5078 sdistneg = LBL_DIST_SMALL_MAX_NEG;
5084 /* Figure out the distance to the target */
5086 srcOffs = emitCurCodeOffs(dst);
5087 if (id->idAddr()->iiaHasInstrCount())
5090 int instrCount = id->idAddr()->iiaGetInstrCount();
5091 unsigned insNum = emitFindInsNum(ig, id);
5094 // Backward branches using instruction count must be within the same instruction group.
5095 assert(insNum + 1 >= (unsigned)(-instrCount));
5097 dstOffs = ig->igOffs + emitFindOffset(ig, (insNum + 1 + instrCount));
5101 dstOffs = id->idAddr()->iiaIGlabel->igOffs;
5108 // for adr, the distance is calculated from 4-byte aligned srcOffs.
5109 distVal = (ssize_t)((emitOffsetToPtr(dstOffs) - (BYTE*)(((size_t)emitOffsetToPtr(srcOffs)) & ~3)) + 1);
5113 distVal = (ssize_t)(emitOffsetToPtr(dstOffs) - emitOffsetToPtr(srcOffs));
5118 assert(ins == INS_movw || ins == INS_movt);
5119 distVal = (ssize_t)emitOffsetToPtr(dstOffs) + 1; // Or in thumb bit
5122 if (dstOffs <= srcOffs)
5124 /* This is a backward jump - distance is known at this point */
5127 if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
5129 size_t blkOffs = id->idjIG->igOffs;
5131 if (INTERESTING_JUMP_NUM == 0)
5132 printf("[3] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
5133 printf("[3] Jump block is at %08X - %02X = %08X\n", blkOffs, emitOffsAdj, blkOffs - emitOffsAdj);
5134 printf("[3] Jump is at %08X - %02X = %08X\n", srcOffs, emitOffsAdj, srcOffs - emitOffsAdj);
5135 printf("[3] Label block is at %08X - %02X = %08X\n", dstOffs, emitOffsAdj, dstOffs - emitOffsAdj);
5139 // This format only supports forward branches
5140 noway_assert(id->idInsFmt() != IF_T1_I);
5142 /* Can we use a short jump? */
5144 if (isJump && ((unsigned)(distVal - 4) >= (unsigned)sdistneg))
5146 emitSetShortJump(id);
5151 /* This is a forward jump - distance will be an upper limit */
5153 emitFwdJumps = true;
5155 /* The target offset will be closer by at least 'emitOffsAdj', but only if this
5156 jump doesn't cross the hot-cold boundary. */
5158 if (!emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
5160 dstOffs -= emitOffsAdj;
5161 distVal -= emitOffsAdj;
5164 /* Record the location of the jump for later patching */
5166 id->idjOffs = dstOffs;
5168 /* Are we overflowing the id->idjOffs bitfield? */
5169 if (id->idjOffs != dstOffs)
5170 IMPL_LIMITATION("Method is too large");
5173 if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
5175 size_t blkOffs = id->idjIG->igOffs;
5177 if (INTERESTING_JUMP_NUM == 0)
5178 printf("[4] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
5179 printf("[4] Jump block is at %08X\n", blkOffs);
5180 printf("[4] Jump is at %08X\n", srcOffs);
5181 printf("[4] Label block is at %08X - %02X = %08X\n", dstOffs + emitOffsAdj, emitOffsAdj, dstOffs);
5186 /* Adjust the offset to emit relative to the end of the instruction */
5192 if (0 && emitComp->verbose)
5194 size_t sz = 4; // Thumb-2 pretends all instructions are 4-bytes long for computing jump offsets?
5195 int distValSize = id->idjShort ? 4 : 8;
5196 printf("; %s jump [%08X/%03u] from %0*X to %0*X: dist = %08XH\n", (dstOffs <= srcOffs) ? "Fwd" : "Bwd",
5197 dspPtr(id), id->idDebugOnlyInfo()->idNum, distValSize, srcOffs + sz, distValSize, dstOffs, distVal);
5201 insFormat fmt = id->idInsFmt();
5205 /* What size jump should we use? */
5211 assert(!id->idjKeepLong);
5212 assert(emitJumpCrossHotColdBoundary(srcOffs, dstOffs) == false);
5214 assert(JMP_SIZE_SMALL == JCC_SIZE_SMALL);
5215 assert(JMP_SIZE_SMALL == 2);
5217 /* For forward jumps, record the address of the distance value */
5218 id->idjTemp.idjAddr = (distVal > 0) ? dst : NULL;
5220 dst = emitOutputShortBranch(dst, ins, fmt, distVal, id);
5226 /* For forward jumps, record the address of the distance value */
5227 id->idjTemp.idjAddr = (dstOffs > srcOffs) ? dst : NULL;
5229 if (fmt == IF_LARGEJMP)
5231 // This is a pseudo-instruction format representing a large conditional branch, to allow
5232 // us to get a greater branch target range than we can get by using a straightforward conditional
5233 // branch. It is encoded as a short conditional branch that branches around a long unconditional
5236 // Conceptually, we have:
5240 // The code we emit is:
5242 // b<!cond> L_not // 2 bytes. Note that we reverse the condition.
5243 // b L_target // 4 bytes
5246 // Note that we don't actually insert any blocks: we simply encode "b <!cond> L_not" as a branch with
5247 // the correct offset. Note also that this works for both integer and floating-point conditions, because
5248 // the condition inversion takes ordered/unordered into account, preserving NaN behavior. For example,
5249 // "GT" (greater than) is inverted to "LE" (less than, equal, or unordered).
5251 // History: previously, we generated:
5254 // but the "it" instruction was deprecated, so we can't use it.
5256 dst = emitOutputShortBranch(dst,
5257 emitJumpKindToIns(emitReverseJumpKind(
5258 emitInsToJumpKind(ins))), // reverse the conditional instruction
5260 6 - 4, /* 6 bytes from start of this large conditional pseudo-instruction to
5261 L_not. Jumps are encoded as offset from instr address + 4. */
5262 NULL /* only used for cbz/cbnz */);
5264 // Now, pretend we've got a normal unconditional branch, and fall through to the code to emit that.
5268 // The distVal was computed based on the beginning of the pseudo-instruction, which is
5269 // the IT. So subtract the size of the IT from the offset, so it is relative to the
5270 // unconditional branch.
5274 code = emitInsCode(ins, fmt);
5276 if (fmt == IF_T2_J1)
5278 // Can't use this form for jumps between the hot and cold regions
5279 assert(!id->idjKeepLong);
5280 assert(emitJumpCrossHotColdBoundary(srcOffs, dstOffs) == false);
5282 assert((distVal & 1) == 0);
5283 assert(distVal >= -1048576);
5284 assert(distVal <= 1048574);
5288 code |= ((distVal >> 1) & 0x0007ff);
5289 code |= (((distVal >> 1) & 0x01f800) << 5);
5290 code |= (((distVal >> 1) & 0x020000) >> 4);
5291 code |= (((distVal >> 1) & 0x040000) >> 7);
5293 else if (fmt == IF_T2_J2)
5295 assert((distVal & 1) == 0);
5296 if (emitComp->opts.compReloc && emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
5298 // dst isn't an actual final target location, just some intermediate
5299 // location. Thus we cannot make any guarantees about distVal (not
5300 // even the direction/sign). Instead we don't encode any offset and
5301 // rely on the relocation to do all the work
5305 assert(distVal >= CALL_DIST_MAX_NEG);
5306 assert(distVal <= CALL_DIST_MAX_POS);
5310 code |= ((distVal >> 1) & 0x0007ff);
5311 code |= (((distVal >> 1) & 0x1ff800) << 5);
5313 bool S = (distVal < 0);
5314 bool I1 = ((distVal & 0x00800000) == 0);
5315 bool I2 = ((distVal & 0x00400000) == 0);
5318 code |= (1 << 13); // J1 bit
5320 code |= (1 << 11); // J2 bit
5325 assert(!"Unknown fmt");
5328 unsigned instrSize = emitOutput_Thumb2Instr(dst, code);
5330 if (emitComp->opts.compReloc)
5332 if (emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
5334 assert(id->idjKeepLong);
5335 if (emitComp->info.compMatchedVM)
5337 void* target = emitOffsetToPtr(dstOffs);
5338 emitRecordRelocation((void*)dst, target, IMAGE_REL_BASED_THUMB_BRANCH24);
5348 /* For forward jumps, record the address of the distance value */
5349 id->idjTemp.idjAddr = (distVal > 0) ? dst : NULL;
5351 code = emitInsCode(ins, fmt);
5353 if (fmt == IF_T1_J3)
5355 assert((dstOffs & 3) == 0); // The target label must be 4-byte aligned
5356 assert(distVal >= 0);
5357 assert(distVal <= 1022);
5358 code |= ((distVal >> 2) & 0xff);
5360 dst += emitOutput_Thumb1Instr(dst, code);
5362 else if (fmt == IF_T2_M1)
5364 assert(distVal >= -4095);
5365 assert(distVal <= +4095);
5368 code |= 0x00A0 << 16;
5371 assert((distVal & 0x0fff) == distVal);
5372 code |= (distVal & 0x00ff);
5373 code |= ((distVal & 0x0700) << 4);
5375 code |= ((distVal & 0x0800) << 15);
5376 code |= id->idReg1() << 8;
5378 dst += emitOutput_Thumb2Instr(dst, code);
5380 else if (fmt == IF_T2_N1)
5382 code |= insEncodeRegT2_D(id->idReg1());
5383 unsigned imm = distVal;
5384 if (ins == INS_movw)
5390 imm = (imm >> 16) & 0xffff;
5392 ((instrDescJmp*)id)->idjTemp.idjAddr = (dstOffs > srcOffs) ? dst : NULL;
5394 code |= insEncodeImmT2_Mov(imm);
5395 dst += emitOutput_Thumb2Instr(dst, code);
5397 if (id->idIsCnsReloc() || id->idIsDspReloc())
5399 assert(ins == INS_movt || ins == INS_movw);
5400 if ((ins == INS_movt) && emitComp->info.compMatchedVM)
5401 emitHandlePCRelativeMov32((void*)(dst - 8), (void*)distVal);
5406 assert(!"Unknown fmt");
5413 /*****************************************************************************
5415 * Output a short branch instruction.
5418 BYTE* emitter::emitOutputShortBranch(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, instrDescJmp* id)
5422 code = emitInsCode(ins, fmt);
5426 assert((distVal & 1) == 0);
5427 assert(distVal >= -256);
5428 assert(distVal <= 254);
5432 code |= ((distVal >> 1) & 0x7f);
5434 else if (fmt == IF_T1_M)
5436 assert((distVal & 1) == 0);
5437 assert(distVal >= -2048);
5438 assert(distVal <= 2046);
5442 code |= ((distVal >> 1) & 0x3ff);
5444 else if (fmt == IF_T1_I)
5447 assert(ins == INS_cbz || INS_cbnz);
5448 assert((distVal & 1) == 0);
5449 assert(distVal >= 0);
5450 assert(distVal <= 126);
5452 code |= ((distVal << 3) & 0x0200);
5453 code |= ((distVal << 2) & 0x00F8);
5454 code |= (id->idReg1() & 0x0007);
5458 assert(!"Unknown fmt");
5461 dst += emitOutput_Thumb1Instr(dst, code);
5466 #ifdef FEATURE_ITINSTRUCTION
5468 /*****************************************************************************
5469 * The "IT" instruction is deprecated (with a very few exceptions). Don't generate it!
5470 * Don't delete this code, though, in case we ever want to bring it back.
5471 *****************************************************************************/
5473 /*****************************************************************************
5475 * Output an IT instruction.
5478 BYTE* emitter::emitOutputIT(BYTE* dst, instruction ins, insFormat fmt, code_t condcode)
5481 code_t code, mask, bit;
5483 code = emitInsCode(ins, fmt);
5484 code |= (condcode << 4); // encode firstcond
5485 imm0 = condcode & 1; // this is firstcond[0]
5486 mask = code & 0x0f; // initialize mask encoded in opcode
5487 bit = 0x08; // where in mask we are encoding
5488 while ((mask & (bit - 1)) != 0) // are the remaining bits all zeros?
5489 { // then we are done
5490 // otherwise determine the setting of bit
5491 if ((imm0 == 1) ^ ((bit & mask) != 0))
5493 code |= bit; // set the current bit
5497 code &= ~bit; // clear the current bit
5501 dst += emitOutput_Thumb1Instr(dst, code);
5506 #endif // FEATURE_ITINSTRUCTION
5508 /*****************************************************************************
5510 * Append the machine code corresponding to the given instruction descriptor
5511 * to the code block at '*dp'; the base of the code block is 'bp', and 'ig'
5512 * is the instruction group that contains the instruction. Updates '*dp' to
5513 * point past the generated code, and returns the size of the instruction
5514 * descriptor in bytes.
5517 size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
5523 instruction ins = id->idIns();
5524 insFormat fmt = id->idInsFmt();
5525 emitAttr size = id->idOpSize();
5526 unsigned char callInstrSize = 0;
5529 bool dspOffs = emitComp->opts.dspGCtbls || !emitComp->opts.disDiffable;
5532 assert(REG_NA == (int)REG_NA);
5534 VARSET_TP GCvars(VarSetOps::UninitVal());
5536 /* What instruction format have we got? */
5542 regMaskTP gcrefRegs;
5543 regMaskTP byrefRegs;
5545 case IF_T1_A: // T1_A ................
5546 sz = SMALL_IDSC_SIZE;
5547 code = emitInsCode(ins, fmt);
5548 dst += emitOutput_Thumb1Instr(dst, code);
5551 #ifdef FEATURE_ITINSTRUCTION
5552 case IF_T1_B: // T1_B ........cccc.... cond
5554 assert(id->idGCref() == GCT_NONE);
5555 target_ssize_t condcode = emitGetInsSC(id);
5556 dst = emitOutputIT(dst, ins, fmt, condcode);
5557 sz = SMALL_IDSC_SIZE;
5560 #endif // FEATURE_ITINSTRUCTION
5562 case IF_T1_C: // T1_C .....iiiiinnnddd R1 R2 imm5
5563 sz = SMALL_IDSC_SIZE;
5564 imm = emitGetInsSC(id);
5565 code = emitInsCode(ins, fmt);
5566 code |= insEncodeRegT1_D3(id->idReg1());
5567 code |= insEncodeRegT1_N3(id->idReg2());
5568 if (emitInsIsLoadOrStore(ins))
5570 imm = insUnscaleImm(imm, size);
5572 assert((imm & 0x001f) == imm);
5574 dst += emitOutput_Thumb1Instr(dst, code);
5577 case IF_T1_D0: // T1_D0 ........Dmmmmddd R1* R2*
5578 sz = SMALL_IDSC_SIZE;
5579 code = emitInsCode(ins, fmt);
5580 code |= insEncodeRegT1_D4(id->idReg1());
5581 code |= insEncodeRegT1_M4(id->idReg2());
5582 dst += emitOutput_Thumb1Instr(dst, code);
5585 case IF_T1_E: // T1_E ..........nnnddd R1 R2
5586 sz = SMALL_IDSC_SIZE;
5587 code = emitInsCode(ins, fmt);
5588 code |= insEncodeRegT1_D3(id->idReg1());
5589 code |= insEncodeRegT1_N3(id->idReg2());
5590 dst += emitOutput_Thumb1Instr(dst, code);
5593 case IF_T1_F: // T1_F .........iiiiiii SP imm7
5594 sz = emitGetInstrDescSize(id);
5595 imm = emitGetInsSC(id);
5596 code = emitInsCode(ins, fmt);
5597 imm = insUnscaleImm(imm, size);
5598 assert((imm & 0x007F) == imm);
5600 dst += emitOutput_Thumb1Instr(dst, code);
5603 case IF_T1_G: // T1_G .......iiinnnddd R1 R2 imm3
5604 sz = SMALL_IDSC_SIZE;
5605 imm = emitGetInsSC(id);
5606 code = emitInsCode(ins, fmt);
5607 code |= insEncodeRegT1_D3(id->idReg1());
5608 code |= insEncodeRegT1_N3(id->idReg2());
5609 assert((imm & 0x0007) == imm);
5611 dst += emitOutput_Thumb1Instr(dst, code);
5614 case IF_T1_H: // T1_H .......mmmnnnddd R1 R2 R3
5615 sz = emitGetInstrDescSize(id);
5616 code = emitInsCode(ins, fmt);
5617 code |= insEncodeRegT1_D3(id->idReg1());
5618 code |= insEncodeRegT1_N3(id->idReg2());
5619 code |= insEncodeRegT1_M3(id->idReg3());
5620 dst += emitOutput_Thumb1Instr(dst, code);
5623 case IF_T1_I: // T1_I ......i.iiiiiddd R1 imm6
5624 assert(id->idIsBound());
5626 dst = emitOutputLJ(ig, dst, id);
5627 sz = sizeof(instrDescJmp);
5630 case IF_T1_J0: // T1_J0 .....dddiiiiiiii R1 imm8
5631 case IF_T1_J1: // T1_J1 .....dddiiiiiiii R1 <regmask8>
5632 case IF_T1_J2: // T1_J2 .....dddiiiiiiii R1 SP imm8
5633 sz = emitGetInstrDescSize(id);
5634 imm = emitGetInsSC(id);
5635 code = emitInsCode(ins, fmt);
5636 code |= insEncodeRegT1_DI(id->idReg1());
5637 if (fmt == IF_T1_J2)
5639 imm = insUnscaleImm(imm, size);
5641 assert((imm & 0x00ff) == imm);
5643 dst += emitOutput_Thumb1Instr(dst, code);
5646 case IF_T1_L0: // T1_L0 ........iiiiiiii imm8
5647 case IF_T1_L1: // T1_L1 .......Rrrrrrrrr <regmask8>
5648 sz = emitGetInstrDescSize(id);
5649 imm = emitGetInsSC(id);
5650 code = emitInsCode(ins, fmt);
5651 if (fmt == IF_T1_L1)
5653 assert((imm & 0x3) != 0x3);
5655 code |= 0x0100; // R bit
5658 assert((imm & 0x00ff) == imm);
5660 dst += emitOutput_Thumb1Instr(dst, code);
5663 case IF_T2_A: // T2_A ................ ................
5664 sz = SMALL_IDSC_SIZE;
5665 code = emitInsCode(ins, fmt);
5666 dst += emitOutput_Thumb2Instr(dst, code);
5669 case IF_T2_B: // T2_B ................ ............iiii imm4
5670 sz = SMALL_IDSC_SIZE;
5671 imm = emitGetInsSC(id);
5672 code = emitInsCode(ins, fmt);
5673 assert((imm & 0x000F) == imm);
5675 dst += emitOutput_Thumb2Instr(dst, code);
5678 case IF_T2_C0: // T2_C0 ...........Snnnn .iiiddddiishmmmm R1 R2 R3 S, imm5, sh
5679 case IF_T2_C4: // T2_C4 ...........Snnnn ....dddd....mmmm R1 R2 R3 S
5680 case IF_T2_C5: // T2_C5 ............nnnn ....dddd....mmmm R1 R2 R3
5681 sz = emitGetInstrDescSize(id);
5682 code = emitInsCode(ins, fmt);
5683 code |= insEncodeRegT2_D(id->idReg1());
5684 code |= insEncodeRegT2_N(id->idReg2());
5685 code |= insEncodeRegT2_M(id->idReg3());
5686 if (fmt != IF_T2_C5)
5687 code |= insEncodeSetFlags(id->idInsFlags());
5688 if (fmt == IF_T2_C0)
5690 imm = emitGetInsSC(id);
5691 code |= insEncodeShiftCount(imm);
5692 code |= insEncodeShiftOpts(id->idInsOpt());
5694 dst += emitOutput_Thumb2Instr(dst, code);
5697 case IF_T2_C1: // T2_C1 ...........S.... .iiiddddiishmmmm R1 R2 S, imm5, sh
5698 case IF_T2_C2: // T2_C2 ...........S.... .iiiddddii..mmmm R1 R2 S, imm5
5699 case IF_T2_C6: // T2_C6 ................ ....dddd..iimmmm R1 R2 imm2
5700 sz = SMALL_IDSC_SIZE;
5701 imm = emitGetInsSC(id);
5702 code = emitInsCode(ins, fmt);
5703 code |= insEncodeRegT2_D(id->idReg1());
5704 code |= insEncodeRegT2_M(id->idReg2());
5705 if (fmt == IF_T2_C6)
5707 assert((imm & 0x0018) == imm);
5712 code |= insEncodeSetFlags(id->idInsFlags());
5713 code |= insEncodeShiftCount(imm);
5714 if (fmt == IF_T2_C1)
5715 code |= insEncodeShiftOpts(id->idInsOpt());
5717 dst += emitOutput_Thumb2Instr(dst, code);
5720 case IF_T2_C3: // T2_C3 ...........S.... ....dddd....mmmm R1 R2 S
5721 sz = SMALL_IDSC_SIZE;
5722 code = emitInsCode(ins, fmt);
5723 code |= insEncodeRegT2_D(id->idReg1());
5724 code |= insEncodeRegT2_M(id->idReg2());
5725 code |= insEncodeSetFlags(id->idInsFlags());
5726 dst += emitOutput_Thumb2Instr(dst, code);
5729 case IF_T2_C7: // T2_C7 ............nnnn ..........shmmmm R1 R2 imm2
5730 case IF_T2_C8: // T2_C8 ............nnnn .iii....iishmmmm R1 R2 imm5, sh
5731 sz = SMALL_IDSC_SIZE;
5732 imm = emitGetInsSC(id);
5733 code = emitInsCode(ins, fmt);
5734 code |= insEncodeRegT2_N(id->idReg1());
5735 code |= insEncodeRegT2_M(id->idReg2());
5736 if (fmt == IF_T2_C7)
5738 assert((imm & 0x0003) == imm);
5741 else if (fmt == IF_T2_C8)
5743 code |= insEncodeShiftCount(imm);
5744 code |= insEncodeShiftOpts(id->idInsOpt());
5746 dst += emitOutput_Thumb2Instr(dst, code);
5749 case IF_T2_C9: // T2_C9 ............nnnn ............mmmm R1 R2
5750 sz = SMALL_IDSC_SIZE;
5751 code = emitInsCode(ins, fmt);
5752 code |= insEncodeRegT2_N(id->idReg1());
5753 code |= insEncodeRegT2_M(id->idReg2());
5754 dst += emitOutput_Thumb2Instr(dst, code);
5757 case IF_T2_C10: // T2_C10 ............mmmm ....dddd....mmmm R1 R2
5758 sz = SMALL_IDSC_SIZE;
5759 code = emitInsCode(ins, fmt);
5760 code |= insEncodeRegT2_D(id->idReg1());
5761 code |= insEncodeRegT2_M(id->idReg2());
5762 code |= insEncodeRegT2_N(id->idReg2());
5763 dst += emitOutput_Thumb2Instr(dst, code);
5766 case IF_T2_D0: // T2_D0 ............nnnn .iiiddddii.wwwww R1 R2 imm5, imm5
5767 case IF_T2_D1: // T2_D1 ................ .iiiddddii.wwwww R1 imm5, imm5
5768 sz = SMALL_IDSC_SIZE;
5769 imm = emitGetInsSC(id);
5770 code = emitInsCode(ins, fmt);
5771 code |= insEncodeRegT2_D(id->idReg1());
5772 if (fmt == IF_T2_D0)
5773 code |= insEncodeRegT2_N(id->idReg2());
5774 code |= insEncodeBitFieldImm(imm);
5775 dst += emitOutput_Thumb2Instr(dst, code);
5778 case IF_T2_E0: // T2_E0 ............nnnn tttt......shmmmm R1 R2 R3 imm2
5779 case IF_T2_E1: // T2_E1 ............nnnn tttt............ R1 R2
5780 case IF_T2_E2: // T2_E2 ................ tttt............ R1
5781 code = emitInsCode(ins, fmt);
5782 code |= insEncodeRegT2_T(id->idReg1());
5783 if (fmt == IF_T2_E0)
5785 sz = emitGetInstrDescSize(id);
5786 code |= insEncodeRegT2_N(id->idReg2());
5787 if (id->idIsLclVar())
5789 code |= insEncodeRegT2_M(codeGen->rsGetRsvdReg());
5794 code |= insEncodeRegT2_M(id->idReg3());
5795 imm = emitGetInsSC(id);
5796 assert((imm & 0x0003) == imm);
5802 sz = SMALL_IDSC_SIZE;
5803 if (fmt != IF_T2_E2)
5805 code |= insEncodeRegT2_N(id->idReg2());
5808 dst += emitOutput_Thumb2Instr(dst, code);
5811 case IF_T2_F1: // T2_F1 ............nnnn ttttdddd....mmmm R1 R2 R3 R4
5812 sz = emitGetInstrDescSize(id);
5814 code = emitInsCode(ins, fmt);
5815 code |= insEncodeRegT2_T(id->idReg1());
5816 code |= insEncodeRegT2_D(id->idReg2());
5817 code |= insEncodeRegT2_N(id->idReg3());
5818 code |= insEncodeRegT2_M(id->idReg4());
5819 dst += emitOutput_Thumb2Instr(dst, code);
5822 case IF_T2_F2: // T2_F2 ............nnnn aaaadddd....mmmm R1 R2 R3 R4
5823 sz = emitGetInstrDescSize(id);
5824 code = emitInsCode(ins, fmt);
5825 code |= insEncodeRegT2_D(id->idReg1());
5826 code |= insEncodeRegT2_N(id->idReg2());
5827 code |= insEncodeRegT2_M(id->idReg3());
5828 code |= insEncodeRegT2_T(id->idReg4());
5829 dst += emitOutput_Thumb2Instr(dst, code);
5832 case IF_T2_G0: // T2_G0 .......PU.W.nnnn ttttTTTTiiiiiiii R1 R2 R3 imm8, PUW
5833 case IF_T2_G1: // T2_G1 ............nnnn ttttTTTT........ R1 R2 R3
5834 code = emitInsCode(ins, fmt);
5835 code |= insEncodeRegT2_T(id->idReg1());
5836 code |= insEncodeRegT2_D(id->idReg2());
5837 code |= insEncodeRegT2_N(id->idReg3());
5838 if (fmt == IF_T2_G0)
5840 sz = emitGetInstrDescSizeSC(id);
5841 imm = emitGetInsSC(id);
5842 assert(unsigned_abs(imm) <= 0x00ff);
5844 code |= insEncodePUW_G0(id->idInsOpt(), imm);
5848 sz = emitGetInstrDescSize(id);
5850 dst += emitOutput_Thumb2Instr(dst, code);
5853 case IF_T2_H0: // T2_H0 ............nnnn tttt.PUWiiiiiiii R1 R2 imm8, PUW
5854 case IF_T2_H1: // T2_H1 ............nnnn tttt....iiiiiiii R1 R2 imm8
5855 case IF_T2_H2: // T2_H2 ............nnnn ........iiiiiiii R1 imm8
5856 sz = emitGetInstrDescSizeSC(id);
5857 imm = emitGetInsSC(id);
5858 code = emitInsCode(ins, fmt);
5859 code |= insEncodeRegT2_T(id->idReg1());
5861 if (fmt != IF_T2_H2)
5862 code |= insEncodeRegT2_N(id->idReg2());
5864 if (fmt == IF_T2_H0)
5866 assert(unsigned_abs(imm) <= 0x00ff);
5867 code |= insEncodePUW_H0(id->idInsOpt(), imm);
5868 code |= unsigned_abs(imm);
5872 assert((imm & 0x00ff) == imm);
5875 dst += emitOutput_Thumb2Instr(dst, code);
5878 case IF_T2_I0: // T2_I0 ..........W.nnnn rrrrrrrrrrrrrrrr R1 W, imm16
5879 case IF_T2_I1: // T2_I1 ................ rrrrrrrrrrrrrrrr imm16
5880 sz = emitGetInstrDescSizeSC(id);
5881 code = emitInsCode(ins, fmt);
5882 if (fmt == IF_T2_I0)
5884 code |= insEncodeRegT2_N(id->idReg1());
5885 code |= (1 << 21); // W bit
5887 imm = emitGetInsSC(id);
5888 assert((imm & 0x3) != 0x3);
5890 code |= 0x8000; // PC bit
5892 code |= 0x4000; // LR bit
5894 assert(imm <= 0x1fff); // 13 bits
5896 dst += emitOutput_Thumb2Instr(dst, code);
5899 case IF_T2_K1: // T2_K1 ............nnnn ttttiiiiiiiiiiii R1 R2 imm12
5900 case IF_T2_K4: // T2_K4 ........U....... ttttiiiiiiiiiiii R1 PC U, imm12
5901 case IF_T2_K3: // T2_K3 ........U....... ....iiiiiiiiiiii PC U, imm12
5902 sz = emitGetInstrDescSize(id);
5903 imm = emitGetInsSC(id);
5904 code = emitInsCode(ins, fmt);
5905 if (fmt != IF_T2_K3)
5907 code |= insEncodeRegT2_T(id->idReg1());
5909 if (fmt == IF_T2_K1)
5911 code |= insEncodeRegT2_N(id->idReg2());
5912 assert(imm <= 0xfff); // 12 bits
5917 assert(unsigned_abs(imm) <= 0xfff); // 12 bits (signed)
5920 code |= (1 << 23); // U bit
5922 dst += emitOutput_Thumb2Instr(dst, code);
5925 case IF_T2_K2: // T2_K2 ............nnnn ....iiiiiiiiiiii R1 imm12
5926 sz = emitGetInstrDescSizeSC(id);
5927 imm = emitGetInsSC(id);
5928 code = emitInsCode(ins, fmt);
5929 code |= insEncodeRegT2_N(id->idReg1());
5930 assert(imm <= 0xfff); // 12 bits
5932 dst += emitOutput_Thumb2Instr(dst, code);
5935 case IF_T2_L0: // T2_L0 .....i.....Snnnn .iiiddddiiiiiiii R1 R2 S, imm8<<imm4
5936 case IF_T2_L1: // T2_L1 .....i.....S.... .iiiddddiiiiiiii R1 S, imm8<<imm4
5937 case IF_T2_L2: // T2_L2 .....i......nnnn .iii....iiiiiiii R1 imm8<<imm4
5938 sz = emitGetInstrDescSize(id);
5939 imm = emitGetInsSC(id);
5940 code = emitInsCode(ins, fmt);
5942 if (fmt == IF_T2_L2)
5943 code |= insEncodeRegT2_N(id->idReg1());
5946 code |= insEncodeSetFlags(id->idInsFlags());
5947 code |= insEncodeRegT2_D(id->idReg1());
5948 if (fmt == IF_T2_L0)
5949 code |= insEncodeRegT2_N(id->idReg2());
5951 assert(isModImmConst(imm)); // Funky ARM imm encoding
5952 imm = encodeModImmConst(imm);
5953 assert(imm <= 0xfff); // 12 bits
5954 code |= (imm & 0x00ff);
5955 code |= (imm & 0x0700) << 4;
5956 code |= (imm & 0x0800) << 15;
5957 dst += emitOutput_Thumb2Instr(dst, code);
5960 case IF_T2_M0: // T2_M0 .....i......nnnn .iiiddddiiiiiiii R1 R2 imm12
5961 sz = emitGetInstrDescSizeSC(id);
5962 imm = emitGetInsSC(id);
5963 code = emitInsCode(ins, fmt);
5964 code |= insEncodeRegT2_D(id->idReg1());
5965 if (fmt == IF_T2_M0)
5966 code |= insEncodeRegT2_N(id->idReg2());
5967 imm = emitGetInsSC(id);
5968 assert(imm <= 0xfff); // 12 bits
5969 code |= (imm & 0x00ff);
5970 code |= (imm & 0x0700) << 4;
5971 code |= (imm & 0x0800) << 15;
5972 dst += emitOutput_Thumb2Instr(dst, code);
5975 case IF_T2_N: // T2_N .....i......iiii .iiiddddiiiiiiii R1 imm16
5976 sz = emitGetInstrDescSizeSC(id);
5977 code = emitInsCode(ins, fmt);
5978 code |= insEncodeRegT2_D(id->idReg1());
5979 imm = emitGetInsSC(id);
5980 if (id->idIsLclVar())
5982 if (ins == INS_movw)
5988 assert(ins == INS_movt);
5989 imm = (imm >> 16) & 0xffff;
5993 assert(!id->idIsReloc());
5994 code |= insEncodeImmT2_Mov(imm);
5995 dst += emitOutput_Thumb2Instr(dst, code);
5998 case IF_T2_N2: // T2_N2 .....i......iiii .iiiddddiiiiiiii R1 imm16
5999 sz = emitGetInstrDescSizeSC(id);
6000 code = emitInsCode(ins, fmt);
6001 code |= insEncodeRegT2_D(id->idReg1());
6002 imm = emitGetInsSC(id);
6003 addr = emitConsBlock + imm;
6004 if (!id->idIsReloc())
6006 assert(sizeof(size_t) == sizeof(target_size_t));
6007 imm = (target_size_t)addr;
6008 if (ins == INS_movw)
6014 assert(ins == INS_movt);
6015 imm = (imm >> 16) & 0xffff;
6017 code |= insEncodeImmT2_Mov(imm);
6018 dst += emitOutput_Thumb2Instr(dst, code);
6022 assert((ins == INS_movt) || (ins == INS_movw));
6023 dst += emitOutput_Thumb2Instr(dst, code);
6024 if ((ins == INS_movt) && emitComp->info.compMatchedVM)
6025 emitHandlePCRelativeMov32((void*)(dst - 8), addr);
6029 case IF_T2_N3: // T2_N3 .....i......iiii .iiiddddiiiiiiii R1 imm16
6030 sz = sizeof(instrDescReloc);
6031 code = emitInsCode(ins, fmt);
6032 code |= insEncodeRegT2_D(id->idReg1());
6034 assert((ins == INS_movt) || (ins == INS_movw));
6035 assert(id->idIsReloc());
6037 addr = emitGetInsRelocValue(id);
6038 dst += emitOutput_Thumb2Instr(dst, code);
6039 if ((ins == INS_movt) && emitComp->info.compMatchedVM)
6040 emitHandlePCRelativeMov32((void*)(dst - 8), addr);
6044 // these are the binary operators
6046 sz = emitGetInstrDescSize(id);
6047 code = emitInsCode(ins, fmt);
6048 code |= insEncodeRegT2_VectorN(id->idReg2(), size, true);
6049 code |= insEncodeRegT2_VectorM(id->idReg3(), size, true);
6050 code |= insEncodeRegT2_VectorD(id->idReg1(), size, true);
6051 if (size == EA_8BYTE)
6053 dst += emitOutput_Thumb2Instr(dst, code);
6083 if (id->idOpSize() == EA_8BYTE)
6088 srcSize = dstSize = id->idOpSize();
6092 sz = emitGetInstrDescSize(id);
6093 code = emitInsCode(ins, fmt);
6095 code |= insEncodeRegT2_VectorD(id->idReg1(), dstSize, true);
6096 code |= insEncodeRegT2_VectorM(id->idReg2(), srcSize, true);
6098 dst += emitOutput_Thumb2Instr(dst, code);
6103 sz = emitGetInstrDescSizeSC(id);
6104 code = emitInsCode(ins, fmt);
6105 code |= insEncodeRegT2_N(id->idReg2());
6106 code |= insEncodeRegT2_VectorD(id->idReg1(), size, true);
6108 imm = emitGetInsSC(id);
6110 imm = -imm; // bit 23 at 0 means negate
6112 code |= 1 << 23; // set the positive bit
6114 // offset is +/- 1020
6116 assert(imm >> 10 == 0);
6118 // bit 8 is set for doubles
6119 if (id->idOpSize() == EA_8BYTE)
6121 dst += emitOutput_Thumb2Instr(dst, code);
6125 // 3op assemble a double from two int regs (or back)
6126 sz = emitGetInstrDescSize(id);
6127 code = emitInsCode(ins, fmt);
6128 if (ins == INS_vmov_i2d)
6130 code |= insEncodeRegT2_VectorM(id->idReg1(), size, true);
6131 code |= id->idReg2() << 12;
6132 code |= id->idReg3() << 16;
6136 assert(ins == INS_vmov_d2i);
6137 code |= id->idReg1() << 12;
6138 code |= id->idReg2() << 16;
6139 code |= insEncodeRegT2_VectorM(id->idReg3(), size, true);
6141 dst += emitOutput_Thumb2Instr(dst, code);
6145 // 2op assemble a float from one int reg (or back)
6146 sz = emitGetInstrDescSize(id);
6147 code = emitInsCode(ins, fmt);
6148 if (ins == INS_vmov_f2i)
6150 code |= insEncodeRegT2_VectorN(id->idReg2(), EA_4BYTE, true);
6151 code |= id->idReg1() << 12;
6155 assert(ins == INS_vmov_i2f);
6156 code |= insEncodeRegT2_VectorN(id->idReg1(), EA_4BYTE, true);
6157 code |= id->idReg2() << 12;
6160 dst += emitOutput_Thumb2Instr(dst, code);
6163 case IF_T1_J3: // T1_J3 .....dddiiiiiiii R1 PC imm8
6164 case IF_T2_M1: // T2_M1 .....i.......... .iiiddddiiiiiiii R1 PC imm12
6165 assert(id->idGCref() == GCT_NONE);
6166 assert(id->idIsBound());
6168 dst = emitOutputLJ(ig, dst, id);
6169 sz = sizeof(instrDescLbl);
6172 case IF_T1_K: // T1_K ....cccciiiiiiii Branch imm8, cond4
6173 case IF_T1_M: // T1_M .....iiiiiiiiiii Branch imm11
6174 case IF_T2_J1: // T2_J1 .....Scccciiiiii ..j.jiiiiiiiiiii Branch imm20, cond4
6175 case IF_T2_J2: // T2_J2 .....Siiiiiiiiii ..j.jiiiiiiiiii. Branch imm24
6176 case IF_T2_N1: // T2_N .....i......iiii .iiiddddiiiiiiii R1 imm16
6178 assert(id->idGCref() == GCT_NONE);
6179 assert(id->idIsBound());
6181 dst = emitOutputLJ(ig, dst, id);
6182 sz = sizeof(instrDescJmp);
6185 case IF_T1_D1: // T1_D1 .........mmmm... R1*
6187 code = emitInsCode(ins, fmt);
6188 code |= insEncodeRegT1_M4(id->idReg1());
6189 dst += emitOutput_Thumb1Instr(dst, code);
6190 sz = SMALL_IDSC_SIZE;
6193 case IF_T1_D2: // T1_D2 .........mmmm... R3*
6195 /* Is this a "fat" call descriptor? */
6197 if (id->idIsLargeCall())
6199 instrDescCGCA* idCall = (instrDescCGCA*)id;
6200 gcrefRegs = idCall->idcGcrefRegs;
6201 byrefRegs = idCall->idcByrefRegs;
6202 VarSetOps::Assign(emitComp, GCvars, idCall->idcGCvars);
6203 sz = sizeof(instrDescCGCA);
6207 assert(!id->idIsLargeDsp());
6208 assert(!id->idIsLargeCns());
6210 gcrefRegs = emitDecodeCallGCregs(id);
6212 VarSetOps::AssignNoCopy(emitComp, GCvars, VarSetOps::MakeEmpty(emitComp));
6213 sz = sizeof(instrDesc);
6216 code = emitInsCode(ins, fmt);
6217 code |= insEncodeRegT1_M4(id->idReg3());
6218 callInstrSize = SafeCvtAssert<unsigned char>(emitOutput_Thumb1Instr(dst, code));
6219 dst += callInstrSize;
6222 case IF_T2_J3: // T2_J3 .....Siiiiiiiiii ..j.jiiiiiiiiii. Call imm24
6224 /* Is this a "fat" call descriptor? */
6226 if (id->idIsLargeCall())
6228 instrDescCGCA* idCall = (instrDescCGCA*)id;
6229 gcrefRegs = idCall->idcGcrefRegs;
6230 byrefRegs = idCall->idcByrefRegs;
6231 VarSetOps::Assign(emitComp, GCvars, idCall->idcGCvars);
6232 sz = sizeof(instrDescCGCA);
6236 assert(!id->idIsLargeDsp());
6237 assert(!id->idIsLargeCns());
6239 gcrefRegs = emitDecodeCallGCregs(id);
6241 VarSetOps::AssignNoCopy(emitComp, GCvars, VarSetOps::MakeEmpty(emitComp));
6242 sz = sizeof(instrDesc);
6245 if (id->idAddr()->iiaAddr == NULL) /* a recursive call */
6247 addr = emitCodeBlock;
6251 addr = id->idAddr()->iiaAddr;
6253 code = emitInsCode(ins, fmt);
6255 if (id->idIsDspReloc())
6257 callInstrSize = SafeCvtAssert<unsigned char>(emitOutput_Thumb2Instr(dst, code));
6258 dst += callInstrSize;
6259 if (emitComp->info.compMatchedVM)
6260 emitRecordRelocation((void*)(dst - 4), addr, IMAGE_REL_BASED_THUMB_BRANCH24);
6264 addr = (BYTE*)((size_t)addr & ~1); // Clear the lowest bit from target address
6266 /* Calculate PC relative displacement */
6267 int disp = addr - (dst + 4);
6268 bool S = (disp < 0);
6269 bool I1 = ((disp & 0x00800000) == 0);
6270 bool I2 = ((disp & 0x00400000) == 0);
6273 code |= (1 << 26); // S bit
6275 code |= (1 << 13); // J1 bit
6277 code |= (1 << 11); // J2 bit
6279 int immLo = (disp & 0x00000ffe) >> 1;
6280 int immHi = (disp & 0x003ff000) >> 12;
6282 code |= (immHi << 16);
6286 assert((disp & 0x00fffffe) == disp);
6288 callInstrSize = SafeCvtAssert<unsigned char>(emitOutput_Thumb2Instr(dst, code));
6289 dst += callInstrSize;
6294 /* We update the GC info before the call as the variables cannot be
6295 used by the call. Killing variables before the call helps with
6296 boundary conditions if the call is CORINFO_HELP_THROW - see bug 50029.
6297 If we ever track aliased variables (which could be used by the
6298 call), we would have to keep them alive past the call. */
6300 emitUpdateLiveGCvars(GCvars, *dp);
6302 // If the method returns a GC ref, mark R0 appropriately.
6303 if (id->idGCref() == GCT_GCREF)
6304 gcrefRegs |= RBM_R0;
6305 else if (id->idGCref() == GCT_BYREF)
6306 byrefRegs |= RBM_R0;
6308 // If the GC register set has changed, report the new set.
6309 if (gcrefRegs != emitThisGCrefRegs)
6310 emitUpdateLiveGCregs(GCT_GCREF, gcrefRegs, dst);
6312 if (byrefRegs != emitThisByrefRegs)
6313 emitUpdateLiveGCregs(GCT_BYREF, byrefRegs, dst);
6315 // Some helper calls may be marked as not requiring GC info to be recorded.
6316 if ((!id->idIsNoGC()))
6318 // On ARM, as on AMD64, we don't change the stack pointer to push/pop args.
6319 // So we're not really doing a "stack pop" here (note that "args" is 0), but we use this mechanism
6320 // to record the call for GC info purposes. (It might be best to use an alternate call,
6321 // and protect "emitStackPop" under the EMIT_TRACK_STACK_DEPTH preprocessor variable.)
6322 emitStackPop(dst, /*isCall*/ true, callInstrSize, /*args*/ 0);
6324 /* Do we need to record a call location for GC purposes? */
6326 if (!emitFullGCinfo)
6328 emitRecordGCcall(dst, callInstrSize);
6334 /********************************************************************/
6336 /********************************************************************/
6341 printf("unexpected format %s\n", emitIfName(id->idInsFmt()));
6342 assert(!"don't know how to encode this instruction");
6347 // Determine if any registers now hold GC refs, or whether a register that was overwritten held a GC ref.
6348 // We assume here that "id->idGCref()" is not GC_NONE only if the instruction described by "id" writes a
6349 // GC ref to register "id->idReg1()". (It may, apparently, also not be GC_NONE in other cases, such as
6350 // for stores, but we ignore those cases here.)
6351 if (emitInsMayWriteToGCReg(id)) // True if "id->idIns()" writes to a register than can hold GC ref.
6353 // If we ever generate instructions that write to multiple registers (LDM, or POP),
6354 // then we'd need to more work here to ensure that changes in the status of GC refs are
6355 // tracked properly.
6356 if (emitInsMayWriteMultipleRegs(id))
6358 // We explicitly list the multiple-destination-target instruction that we expect to
6359 // be emitted outside of the prolog and epilog here.
6367 // For each of these, idReg1() and idReg2() are the destination registers.
6368 emitGCregDeadUpd(id->idReg1(), dst);
6369 emitGCregDeadUpd(id->idReg2(), dst);
6372 assert(false); // We need to recognize this multi-target instruction...
6377 if (id->idGCref() != GCT_NONE)
6379 emitGCregLiveUpd(id->idGCref(), id->idReg1(), dst);
6383 // I also assume that "idReg1" is the destination register of all instructions that write to registers.
6384 emitGCregDeadUpd(id->idReg1(), dst);
6389 // Now we determine if the instruction has written to a (local variable) stack location, and either written a GC
6390 // ref or overwritten one.
6391 if (emitInsWritesToLclVarStackLoc(id))
6393 int varNum = id->idAddr()->iiaLclVar.lvaVarNum();
6394 unsigned ofs = AlignDown(id->idAddr()->iiaLclVar.lvaOffset(), TARGET_POINTER_SIZE);
6396 int adr = emitComp->lvaFrameAddress(varNum, true, ®Base, ofs);
6397 if (id->idGCref() != GCT_NONE)
6399 emitGCvarLiveUpd(adr + ofs, varNum, id->idGCref(), dst);
6403 // If the type of the local is a gc ref type, update the liveness.
6407 // "Regular" (non-spill-temp) local.
6408 vt = var_types(emitComp->lvaTable[varNum].lvType);
6412 TempDsc* tmpDsc = codeGen->regSet.tmpFindNum(varNum);
6413 vt = tmpDsc->tdTempType();
6415 if (vt == TYP_REF || vt == TYP_BYREF)
6416 emitGCvarDeadUpd(adr + ofs, dst);
6421 /* Make sure we set the instruction descriptor size correctly */
6423 size_t expected = emitSizeOfInsDsc(id);
6424 assert(sz == expected);
6426 if (emitComp->opts.disAsm || emitComp->opts.dspEmit || emitComp->verbose)
6428 emitDispIns(id, false, dspOffs, true, emitCurCodeOffs(odst), *dp, (dst - *dp), ig);
6431 if (emitComp->compDebugBreak)
6433 // set JitEmitPrintRefRegs=1 will print out emitThisGCrefRegs and emitThisByrefRegs
6434 // at the beginning of this method.
6435 if (JitConfig.JitEmitPrintRefRegs() != 0)
6437 printf("Before emitOutputInstr for id->idDebugOnlyInfo()->idNum=0x%02x\n", id->idDebugOnlyInfo()->idNum);
6438 printf(" emitThisGCrefRegs(0x%p)=", dspPtr(&emitThisGCrefRegs));
6439 printRegMaskInt(emitThisGCrefRegs);
6440 emitDispRegSet(emitThisGCrefRegs);
6442 printf(" emitThisByrefRegs(0x%p)=", dspPtr(&emitThisByrefRegs));
6443 printRegMaskInt(emitThisByrefRegs);
6444 emitDispRegSet(emitThisByrefRegs);
6448 // For example, set JitBreakEmitOutputInstr=a6 will break when this method is called for
6449 // emitting instruction a6, (i.e. IN00a6 in jitdump).
6450 if ((unsigned)JitConfig.JitBreakEmitOutputInstr() == id->idDebugOnlyInfo()->idNum)
6452 assert(!"JitBreakEmitOutputInstr reached");
6457 /* All instructions are expected to generate code */
6466 /*****************************************************************************/
6467 /*****************************************************************************/
6471 static bool insAlwaysSetFlags(instruction ins)
6473 bool result = false;
6489 /*****************************************************************************
6491 * Display the instruction name, optionally the instruction
6492 * can add the "s" suffix if it must set the flags.
6494 void emitter::emitDispInst(instruction ins, insFlags flags)
6496 const char* insstr = codeGen->genInsName(ins);
6497 int len = strlen(insstr);
6499 /* Display the instruction name */
6501 printf("%s", insstr);
6502 if (insSetsFlags(flags) && !insAlwaysSetFlags(ins))
6509 // Add at least one space after the instruction name
6510 // and add spaces until we have reach the normal size of 8
6518 #define STRICT_ARM_ASM 0
6520 /*****************************************************************************
6522 * Display an immediate value
6524 void emitter::emitDispImm(int imm, bool addComma, bool alwaysHex /* =false */)
6526 if (!alwaysHex && (imm > -1000) && (imm < 1000))
6528 else if ((imm > 0) ||
6529 (imm == -imm) || // -0x80000000 == 0x80000000. So we don't want to add an extra "-" at the beginning.
6530 (emitComp->opts.disDiffable && (imm == 0xD1FFAB1E))) // Don't display this as negative
6531 printf("0x%02x", imm);
6532 else // val <= -1000
6533 printf("-0x%02x", -imm);
6539 /*****************************************************************************
6541 * Display a relocatable immediate value
6543 void emitter::emitDispReloc(BYTE* addr)
6545 printf("0x%p", dspPtr(addr));
6548 /*****************************************************************************
6550 * Display an arm condition for the IT instructions
6552 void emitter::emitDispCond(int cond)
6554 const static char* armCond[16] = {"eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc",
6555 "hi", "ls", "ge", "lt", "gt", "le", "AL", "NV"}; // The last two are invalid
6556 assert(0 <= cond && (unsigned)cond < ArrLen(armCond));
6557 printf(armCond[cond]);
6560 /*****************************************************************************
6562 * Display a register range in a range format
6564 void emitter::emitDispRegRange(regNumber reg, int len, emitAttr attr)
6567 emitDispReg(reg, attr, false);
6571 emitDispReg((regNumber)(reg + len - 1), attr, false);
6576 /*****************************************************************************
6578 * Display an register mask in a list format
6580 void emitter::emitDispRegmask(int imm, bool encodedPC_LR)
6582 bool printedOne = false;
6588 hasPC = (imm & 2) != 0;
6589 hasLR = (imm & 1) != 0;
6594 hasPC = (imm & RBM_PC) != 0;
6595 hasLR = (imm & RBM_LR) != 0;
6596 imm &= ~(RBM_PC | RBM_LR);
6599 regNumber reg = REG_R0;
6609 printf("%s", emitRegName(reg));
6614 reg = regNumber(reg + 1);
6622 printf("%s", emitRegName(REG_LR));
6630 printf("%s", emitRegName(REG_PC));
6636 /*****************************************************************************
6638 * Returns the encoding for the Shift Type bits to be used in a Thumb-2 encoding
6641 void emitter::emitDispShiftOpts(insOpts opt)
6643 if (opt == INS_OPTS_LSL)
6645 else if (opt == INS_OPTS_LSR)
6647 else if (opt == INS_OPTS_ASR)
6649 else if (opt == INS_OPTS_ROR)
6651 else if (opt == INS_OPTS_RRX)
6655 /*****************************************************************************
6657 * Display a register
6659 void emitter::emitDispReg(regNumber reg, emitAttr attr, bool addComma)
6661 if (isFloatReg(reg))
6663 const char* size = attr == EA_8BYTE ? "d" : "s";
6664 printf("%s%s", size, emitFloatRegName(reg, attr) + 1);
6668 printf("%s", emitRegName(reg, attr));
6675 /*****************************************************************************
6677 * Display an addressing operand [reg]
6679 void emitter::emitDispAddrR(regNumber reg, emitAttr attr)
6682 emitDispReg(reg, attr, false);
6687 /*****************************************************************************
6689 * Display an addressing operand [reg + imm]
6691 void emitter::emitDispAddrRI(regNumber reg, int imm, emitAttr attr)
6693 bool regIsSPorFP = (reg == REG_SP) || (reg == REG_FP);
6696 emitDispReg(reg, attr, false);
6707 emitDispImm(imm, false, regIsSPorFP);
6713 /*****************************************************************************
6715 * Display an addressing operand [reg + reg]
6717 void emitter::emitDispAddrRR(regNumber reg1, regNumber reg2, emitAttr attr)
6720 emitDispReg(reg1, attr, false);
6726 emitDispReg(reg2, attr, false);
6731 /*****************************************************************************
6733 * Display an addressing operand [reg + reg * imm]
6735 void emitter::emitDispAddrRRI(regNumber reg1, regNumber reg2, int imm, emitAttr attr)
6738 emitDispReg(reg1, attr, false);
6741 emitDispReg(reg2, attr, false);
6745 emitDispImm(1 << imm, false);
6751 emitDispImm(1 << imm, false);
6754 emitDispReg(reg2, attr, false);
6760 /*****************************************************************************
6762 * Display an addressing operand [reg + imm]
6764 void emitter::emitDispAddrPUW(regNumber reg, int imm, insOpts opt, emitAttr attr)
6766 bool regIsSPorFP = (reg == REG_SP) || (reg == REG_FP);
6769 emitDispReg(reg, attr, false);
6770 if (insOptAnyInc(opt))
6783 emitDispImm(imm, false, regIsSPorFP);
6790 /*****************************************************************************
6792 * Display the gc-ness of the operand
6794 void emitter::emitDispGC(emitAttr attr)
6797 // TODO-ARM-Cleanup: Fix or delete.
6798 if (attr == EA_GCREF)
6800 else if (attr == EA_BYREF)
6805 /*****************************************************************************
6807 * Display (optionally) the instruction encoding in hex
6810 void emitter::emitDispInsHex(BYTE* code, size_t sz)
6812 // We do not display the instruction hex if we want diff-able disassembly
6813 if (!emitComp->opts.disDiffable)
6817 printf(" %04X ", (*((unsigned short*)code)));
6821 printf(" %04X %04X", (*((unsigned short*)(code + 0))), (*((unsigned short*)(code + 2))));
6826 /****************************************************************************
6828 * Display the given instruction.
6831 void emitter::emitDispInsHelp(
6832 instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* code, size_t sz, insGroup* ig)
6836 unsigned idNum = id->idDebugOnlyInfo()->idNum; // Do not remove this! It is needed for VisualStudio
6837 // conditional breakpoints
6839 printf("IN%04x: ", idNum);
6845 if (!emitComp->opts.dspEmit && !isNew && !asmfm && sz)
6848 /* Display the instruction offset */
6850 emitDispInsOffs(offset, doffs);
6852 /* Display the instruction hex code */
6854 emitDispInsHex(code, sz);
6858 /* Get the instruction and format */
6860 instruction ins = id->idIns();
6861 insFormat fmt = id->idInsFmt();
6863 emitDispInst(ins, id->idInsFlags());
6865 /* If this instruction has just been added, check its size */
6867 assert(isNew == false || (int)emitSizeOfInsDsc(id) == emitCurIGfreeNext - (BYTE*)id);
6869 /* Figure out the operand size */
6871 if (id->idGCref() == GCT_GCREF)
6873 else if (id->idGCref() == GCT_BYREF)
6876 attr = id->idOpSize();
6882 const char* methodName;
6884 case IF_T1_A: // None
6888 case IF_T1_L0: // Imm
6890 emitDispImm(emitGetInsSC(id), false);
6893 case IF_T1_B: // <cond>
6894 emitDispCond(emitGetInsSC(id));
6897 case IF_T1_L1: // <regmask8>
6898 case IF_T2_I1: // <regmask16>
6899 emitDispRegmask(emitGetInsSC(id), true);
6902 case IF_T2_E2: // Reg
6903 if (id->idIns() == INS_vmrs)
6905 if (id->idReg1() != REG_R15)
6907 emitDispReg(id->idReg1(), attr, true);
6912 printf("APSR, FPSCR");
6917 emitDispReg(id->idReg1(), attr, false);
6922 emitDispReg(id->idReg1(), attr, false);
6926 emitDispReg(id->idReg3(), attr, false);
6928 CORINFO_METHOD_HANDLE handle = (CORINFO_METHOD_HANDLE)id->idDebugOnlyInfo()->idMemCookie;
6931 methodName = emitComp->eeGetMethodFullName(handle);
6932 printf("\t\t// %s", methodName);
6937 case IF_T1_F: // SP, Imm
6938 emitDispReg(REG_SP, attr, true);
6939 emitDispImm(emitGetInsSC(id), false);
6942 case IF_T1_J0: // Reg, Imm
6945 emitDispReg(id->idReg1(), attr, true);
6946 imm = emitGetInsSC(id);
6947 emitDispImm(imm, false, false);
6951 emitDispReg(id->idReg1(), attr, true);
6952 imm = emitGetInsSC(id);
6953 if (emitComp->opts.disDiffable)
6955 emitDispImm(imm, false, true);
6959 emitDispReg(id->idReg1(), attr, true);
6960 printf("%s RELOC ", (id->idIns() == INS_movw) ? "LOW" : "HIGH");
6961 emitDispReloc(emitGetInsRelocValue(id));
6965 emitDispReg(id->idReg1(), attr, true);
6966 imm = emitGetInsSC(id);
6968 dataSection* jdsc = 0;
6969 NATIVE_OFFSET offs = 0;
6971 /* Find the appropriate entry in the data section list */
6973 for (jdsc = emitConsDsc.dsdList; jdsc; jdsc = jdsc->dsNext)
6975 UNATIVE_OFFSET size = jdsc->dsSize;
6977 /* Is this a label table? */
6979 if (jdsc->dsType == dataSection::blockAbsoluteAddr)
6988 assert(jdsc != NULL);
6990 if (id->idIsDspReloc())
6994 printf("%s ADDRESS J_M%03u_DS%02u", (id->idIns() == INS_movw) ? "LOW" : "HIGH",
6995 Compiler::s_compMethodsCount, imm);
6997 // After the MOVT, dump the table
6998 if (id->idIns() == INS_movt)
7000 unsigned cnt = jdsc->dsSize / TARGET_POINTER_SIZE;
7001 BasicBlock** bbp = (BasicBlock**)jdsc->dsCont;
7003 bool isBound = (emitCodeGetCookie(*bbp) != NULL);
7007 printf("\n\n J_M%03u_DS%02u LABEL DWORD", Compiler::s_compMethodsCount, imm);
7009 /* Display the label table (it's stored as "BasicBlock*" values) */
7015 /* Convert the BasicBlock* value to an IG address */
7017 lab = (insGroup*)emitCodeGetCookie(*bbp++);
7020 printf("\n DD G_M%03u_IG%02u", Compiler::s_compMethodsCount, lab->igNum);
7027 case IF_T2_H2: // [Reg+imm]
7029 emitDispAddrRI(id->idReg1(), emitGetInsSC(id), attr);
7032 case IF_T2_K3: // [PC+imm]
7033 emitDispAddrRI(REG_PC, emitGetInsSC(id), attr);
7036 case IF_T1_J1: // reg, <regmask8>
7037 case IF_T2_I0: // reg, <regmask16>
7038 emitDispReg(id->idReg1(), attr, false);
7040 emitDispRegmask(emitGetInsSC(id), false);
7043 case IF_T1_D0: // Reg, Reg
7048 emitDispReg(id->idReg1(), attr, true);
7049 emitDispReg(id->idReg2(), attr, false);
7050 if (fmt == IF_T1_E && id->idIns() == INS_rsb)
7056 case IF_T2_E1: // Reg, [Reg]
7057 emitDispReg(id->idReg1(), attr, true);
7058 emitDispAddrR(id->idReg2(), attr);
7061 case IF_T2_D1: // Reg, Imm, Imm
7062 emitDispReg(id->idReg1(), attr, true);
7063 imm = emitGetInsSC(id);
7065 int lsb = (imm >> 5) & 0x1f;
7066 int msb = imm & 0x1f;
7068 int imm2 = msb + 1 - lsb;
7069 emitDispImm(imm1, true);
7070 emitDispImm(imm2, false);
7074 case IF_T1_C: // Reg, Reg, Imm
7081 emitDispReg(id->idReg1(), attr, true);
7082 imm = emitGetInsSC(id);
7083 if (emitInsIsLoadOrStore(ins))
7085 emitDispAddrRI(id->idReg2(), imm, attr);
7089 emitDispReg(id->idReg2(), attr, true);
7090 emitDispImm(imm, false);
7095 emitDispReg(id->idReg1(), attr, true);
7096 imm = emitGetInsSC(id);
7097 if (emitInsIsLoadOrStore(ins))
7099 emitDispAddrRI(REG_SP, imm, attr);
7103 emitDispReg(REG_SP, attr, true);
7104 emitDispImm(imm, false);
7109 emitDispReg(id->idReg1(), attr, true);
7110 emitDispAddrRI(REG_PC, emitGetInsSC(id), attr);
7115 emitDispReg(id->idReg1(), attr, true);
7116 emitDispReg(id->idReg2(), attr, false);
7117 imm = emitGetInsSC(id);
7118 if (id->idInsOpt() == INS_OPTS_RRX)
7120 emitDispShiftOpts(id->idInsOpt());
7125 emitDispShiftOpts(id->idInsOpt());
7126 emitDispImm(imm, false);
7131 imm = emitGetInsSC(id);
7132 emitDispReg(id->idReg1(), attr, true);
7133 emitDispReg(id->idReg2(), attr, (imm != 0));
7136 emitDispImm(imm, false);
7141 emitDispAddrRRI(id->idReg1(), id->idReg2(), emitGetInsSC(id), attr);
7145 emitDispReg(id->idReg1(), attr, true);
7146 emitDispAddrPUW(id->idReg2(), emitGetInsSC(id), id->idInsOpt(), attr);
7149 case IF_T1_H: // Reg, Reg, Reg
7150 emitDispReg(id->idReg1(), attr, true);
7151 if (emitInsIsLoadOrStore(ins))
7153 emitDispAddrRR(id->idReg2(), id->idReg3(), attr);
7157 emitDispReg(id->idReg2(), attr, true);
7158 emitDispReg(id->idReg3(), attr, false);
7164 emitDispReg(id->idReg1(), attr, true);
7165 emitDispReg(id->idReg2(), attr, true);
7166 emitDispReg(id->idReg3(), attr, false);
7170 emitDispReg(id->idReg1(), attr, true);
7171 emitDispReg(id->idReg2(), attr, true);
7172 emitDispReg(id->idReg3(), attr, false);
7176 switch (id->idIns())
7181 emitDispReg(id->idReg1(), EA_4BYTE, true);
7182 emitDispReg(id->idReg2(), EA_8BYTE, false);
7188 emitDispReg(id->idReg1(), EA_8BYTE, true);
7189 emitDispReg(id->idReg2(), EA_4BYTE, false);
7192 // we just use the type on the instruction
7193 // unless it is an asymmetrical one like the converts
7195 emitDispReg(id->idReg1(), attr, true);
7196 emitDispReg(id->idReg2(), attr, false);
7202 imm = emitGetInsSC(id);
7203 switch (id->idIns())
7207 emitDispReg(id->idReg1(), attr, true);
7208 emitDispAddrPUW(id->idReg2(), imm, id->idInsOpt(), attr);
7213 emitDispReg(id->idReg2(), attr, false);
7214 if (insOptAnyInc(id->idInsOpt()))
7217 emitDispRegRange(id->idReg1(), abs(imm) >> 2, attr);
7222 emitDispRegRange(id->idReg1(), abs(imm) >> 2, attr);
7231 switch (id->idIns())
7234 emitDispReg(id->idReg1(), attr, true); // EA_8BYTE
7235 emitDispReg(id->idReg2(), EA_4BYTE, true);
7236 emitDispReg(id->idReg3(), EA_4BYTE, false);
7239 emitDispReg(id->idReg1(), EA_4BYTE, true);
7240 emitDispReg(id->idReg2(), EA_4BYTE, true);
7241 emitDispReg(id->idReg3(), attr, false); // EA_8BYTE
7249 emitDispReg(id->idReg1(), attr, true);
7250 emitDispReg(id->idReg2(), attr, false);
7254 emitDispReg(id->idReg1(), attr, true);
7255 emitDispAddrRR(id->idReg2(), id->idReg3(), attr);
7258 case IF_T2_D0: // Reg, Reg, Imm, Imm
7259 emitDispReg(id->idReg1(), attr, true);
7260 emitDispReg(id->idReg2(), attr, true);
7261 imm = emitGetInsSC(id);
7264 int lsb = (imm >> 5) & 0x1f;
7265 int msb = imm & 0x1f;
7267 int imm2 = msb + 1 - lsb;
7268 emitDispImm(imm1, true);
7269 emitDispImm(imm2, false);
7273 int lsb = (imm >> 5) & 0x1f;
7274 int widthm1 = imm & 0x1f;
7276 int imm2 = widthm1 + 1;
7277 emitDispImm(imm1, true);
7278 emitDispImm(imm2, false);
7282 case IF_T2_C0: // Reg, Reg, Reg, Imm
7283 emitDispReg(id->idReg1(), attr, true);
7284 emitDispReg(id->idReg2(), attr, true);
7285 emitDispReg(id->idReg3(), attr, false);
7286 imm = emitGetInsSC(id);
7287 if (id->idInsOpt() == INS_OPTS_RRX)
7289 emitDispShiftOpts(id->idInsOpt());
7294 emitDispShiftOpts(id->idInsOpt());
7295 emitDispImm(imm, false);
7300 emitDispReg(id->idReg1(), attr, true);
7301 if (id->idIsLclVar())
7303 emitDispAddrRRI(id->idReg2(), codeGen->rsGetRsvdReg(), 0, attr);
7307 emitDispAddrRRI(id->idReg2(), id->idReg3(), emitGetInsSC(id), attr);
7312 emitDispReg(id->idReg1(), attr, true);
7313 emitDispReg(id->idReg2(), attr, true);
7314 emitDispAddrPUW(id->idReg3(), emitGetInsSC(id), id->idInsOpt(), attr);
7317 case IF_T2_F1: // Reg, Reg, Reg, Reg
7319 emitDispReg(id->idReg1(), attr, true);
7320 emitDispReg(id->idReg2(), attr, true);
7321 emitDispReg(id->idReg3(), attr, true);
7322 emitDispReg(id->idReg4(), attr, false);
7326 case IF_T2_M1: // Load Label
7327 emitDispReg(id->idReg1(), attr, true);
7328 if (id->idIsBound())
7329 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
7331 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
7334 case IF_T1_I: // Special Compare-and-branch
7335 emitDispReg(id->idReg1(), attr, true);
7338 case IF_T1_K: // Special Branch, conditional
7340 assert(((instrDescJmp*)id)->idjShort);
7345 if (fmt == IF_T2_N1)
7347 emitDispReg(id->idReg1(), attr, true);
7348 printf("%s ADDRESS ", (id->idIns() == INS_movw) ? "LOW" : "HIGH");
7356 if (id->idAddr()->iiaHasInstrCount())
7358 int instrCount = id->idAddr()->iiaGetInstrCount();
7362 printf("pc%s%d instructions", (instrCount >= 0) ? "+" : "", instrCount);
7366 unsigned insNum = emitFindInsNum(ig, id);
7367 UNATIVE_OFFSET srcOffs = ig->igOffs + emitFindOffset(ig, insNum + 1);
7368 UNATIVE_OFFSET dstOffs = ig->igOffs + emitFindOffset(ig, insNum + 1 + instrCount);
7369 ssize_t relOffs = (ssize_t)(emitOffsetToPtr(dstOffs) - emitOffsetToPtr(srcOffs));
7370 printf("pc%s%d (%d instructions)", (relOffs >= 0) ? "+" : "", relOffs, instrCount);
7373 else if (id->idIsBound())
7374 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
7376 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
7381 if (id->idIsCallAddr())
7383 offs = (ssize_t)id->idAddr()->iiaAddr;
7389 methodName = emitComp->eeGetMethodFullName((CORINFO_METHOD_HANDLE)id->idDebugOnlyInfo()->idMemCookie);
7394 if (id->idIsDspReloc())
7396 printf("%08X", offs);
7400 printf("%s", methodName);
7406 printf("unexpected format %s", emitIfName(id->idInsFmt()));
7407 assert(!"unexpectedFormat");
7411 if (id->idDebugOnlyInfo()->idVarRefOffs)
7414 emitDispFrameRef(id->idAddr()->iiaLclVar.lvaVarNum(), id->idAddr()->iiaLclVar.lvaOffset(),
7415 id->idDebugOnlyInfo()->idVarRefOffs, asmfm);
7421 void emitter::emitDispIns(
7422 instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* code, size_t sz, insGroup* ig)
7424 insFormat fmt = id->idInsFmt();
7426 /* Special-case IF_LARGEJMP */
7428 if ((fmt == IF_LARGEJMP) && id->idIsBound())
7430 // This is a pseudo-instruction format representing a large conditional branch. See the comment
7431 // in emitter::emitOutputLJ() for the full description.
7433 // For this pseudo-instruction, we will actually generate:
7435 // b<!cond> L_not // 2 bytes. Note that we reverse the condition.
7436 // b L_target // 4 bytes
7439 // These instructions don't exist in the actual instruction stream, so we need to fake them
7440 // up to display them.
7442 // Note: don't touch the actual instrDesc. If we accidentally messed it up, it would create a very
7443 // difficult to find bug.
7446 instrDescJmp* pidJmp = &idJmp;
7448 memset(&idJmp, 0, sizeof(idJmp));
7450 pidJmp->idIns(emitJumpKindToIns(emitReverseJumpKind(emitInsToJumpKind(id->idIns())))); // reverse the
7453 pidJmp->idInsFmt(IF_T1_K);
7454 pidJmp->idInsSize(emitInsSize(IF_T1_K));
7455 pidJmp->idjShort = 1;
7456 pidJmp->idAddr()->iiaSetInstrCount(1);
7457 pidJmp->idDebugOnlyInfo(id->idDebugOnlyInfo()); // share the idDebugOnlyInfo() field
7459 size_t bcondSizeOrZero = (code == NULL) ? 0 : 2; // branch is 2 bytes
7460 emitDispInsHelp(pidJmp, false, doffs, asmfm, offset, code, bcondSizeOrZero,
7461 NULL /* force display of pc-relative branch */);
7463 code += bcondSizeOrZero;
7466 // Next, display the unconditional branch
7468 // Reset the local instrDesc
7469 memset(&idJmp, 0, sizeof(idJmp));
7471 pidJmp->idIns(INS_b);
7472 pidJmp->idInsFmt(IF_T2_J2);
7473 pidJmp->idInsSize(emitInsSize(IF_T2_J2));
7474 pidJmp->idjShort = 0;
7475 if (id->idIsBound())
7477 pidJmp->idSetIsBound();
7478 pidJmp->idAddr()->iiaIGlabel = id->idAddr()->iiaIGlabel;
7482 pidJmp->idAddr()->iiaBBlabel = id->idAddr()->iiaBBlabel;
7484 pidJmp->idDebugOnlyInfo(id->idDebugOnlyInfo()); // share the idDebugOnlyInfo() field
7486 size_t brSizeOrZero = (code == NULL) ? 0 : 4; // unconditional branch is 4 bytes
7487 emitDispInsHelp(pidJmp, isNew, doffs, asmfm, offset, code, brSizeOrZero, ig);
7491 emitDispInsHelp(id, isNew, doffs, asmfm, offset, code, sz, ig);
7495 /*****************************************************************************
7497 * Display a stack frame reference.
7500 void emitter::emitDispFrameRef(int varx, int disp, int offs, bool asmfm)
7505 printf("TEMP_%02u", -varx);
7507 emitComp->gtDispLclVar(+varx, false);
7510 printf("-0x%02x", -disp);
7512 printf("+0x%02x", +disp);
7516 if (varx >= 0 && emitComp->opts.varNames)
7519 const char* varName;
7521 assert((unsigned)varx < emitComp->lvaCount);
7522 varDsc = emitComp->lvaTable + varx;
7523 varName = emitComp->compLocalVarName(varx, offs);
7527 printf("'%s", varName);
7530 printf("-%d", -disp);
7532 printf("+%d", +disp);
7541 void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataReg, GenTreeIndir* indir)
7543 // Handle unaligned floating point loads/stores
7544 if ((indir->gtFlags & GTF_IND_UNALIGNED))
7546 if (indir->OperGet() == GT_STOREIND)
7548 var_types type = indir->AsStoreInd()->Data()->TypeGet();
7549 if (type == TYP_FLOAT)
7551 regNumber tmpReg = indir->GetSingleTempReg();
7552 emitIns_R_R(INS_vmov_f2i, EA_4BYTE, tmpReg, dataReg);
7553 emitInsLoadStoreOp(INS_str, EA_4BYTE, tmpReg, indir, 0);
7556 else if (type == TYP_DOUBLE)
7558 regNumber tmpReg1 = indir->ExtractTempReg();
7559 regNumber tmpReg2 = indir->GetSingleTempReg();
7560 emitIns_R_R_R(INS_vmov_d2i, EA_8BYTE, tmpReg1, tmpReg2, dataReg);
7561 emitInsLoadStoreOp(INS_str, EA_4BYTE, tmpReg1, indir, 0);
7562 emitInsLoadStoreOp(INS_str, EA_4BYTE, tmpReg2, indir, 4);
7566 else if (indir->OperGet() == GT_IND)
7568 var_types type = indir->TypeGet();
7569 if (type == TYP_FLOAT)
7571 regNumber tmpReg = indir->GetSingleTempReg();
7572 emitInsLoadStoreOp(INS_ldr, EA_4BYTE, tmpReg, indir, 0);
7573 emitIns_R_R(INS_vmov_i2f, EA_4BYTE, dataReg, tmpReg);
7576 else if (type == TYP_DOUBLE)
7578 regNumber tmpReg1 = indir->ExtractTempReg();
7579 regNumber tmpReg2 = indir->GetSingleTempReg();
7580 emitInsLoadStoreOp(INS_ldr, EA_4BYTE, tmpReg1, indir, 0);
7581 emitInsLoadStoreOp(INS_ldr, EA_4BYTE, tmpReg2, indir, 4);
7582 emitIns_R_R_R(INS_vmov_i2d, EA_8BYTE, dataReg, tmpReg1, tmpReg2);
7588 // Proceed with ordinary loads/stores
7589 emitInsLoadStoreOp(ins, attr, dataReg, indir, 0);
7592 void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataReg, GenTreeIndir* indir, int offset)
7594 GenTree* addr = indir->Addr();
7596 if (addr->isContained())
7598 assert(addr->OperGet() == GT_LCL_VAR_ADDR || addr->OperGet() == GT_LEA);
7602 if (addr->OperGet() == GT_LEA)
7604 offset += addr->AsAddrMode()->Offset();
7605 if (addr->AsAddrMode()->gtScale > 0)
7607 assert(isPow2(addr->AsAddrMode()->gtScale));
7608 BitScanForward(&lsl, addr->AsAddrMode()->gtScale);
7612 GenTree* memBase = indir->Base();
7614 if (indir->HasIndex())
7616 assert(addr->OperGet() == GT_LEA);
7618 GenTree* index = indir->Index();
7622 regNumber tmpReg = indir->GetSingleTempReg();
7624 // If the LEA produces a GCREF or BYREF, we need to be careful to mark any temp register
7625 // computed with the base register as a BYREF.
7626 GenTreeAddrMode* lea = addr->AsAddrMode();
7627 emitAttr leaAttr = emitTypeSize(lea);
7628 emitAttr leaBasePartialAddrAttr = EA_IS_GCREF_OR_BYREF(leaAttr) ? EA_BYREF : EA_PTRSIZE;
7630 if (emitIns_valid_imm_for_add(offset, INS_FLAGS_DONT_CARE))
7634 // Generate code to set tmpReg = base + index*scale
7635 emitIns_R_R_R_I(INS_add, leaBasePartialAddrAttr, tmpReg, memBase->gtRegNum, index->gtRegNum,
7636 lsl, INS_FLAGS_DONT_CARE, INS_OPTS_LSL);
7640 // Generate code to set tmpReg = base + index
7641 emitIns_R_R_R(INS_add, leaBasePartialAddrAttr, tmpReg, memBase->gtRegNum, index->gtRegNum);
7644 noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
7646 // Then load/store dataReg from/to [tmpReg + offset]
7647 emitIns_R_R_I(ins, attr, dataReg, tmpReg, offset);
7649 else // large offset
7651 // First load/store tmpReg with the large offset constant
7652 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
7653 // Then add the base register
7655 emitIns_R_R_R(INS_add, leaBasePartialAddrAttr, tmpReg, tmpReg, memBase->gtRegNum);
7657 noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
7658 noway_assert(tmpReg != index->gtRegNum);
7660 // Then load/store dataReg from/to [tmpReg + index*scale]
7661 emitIns_R_R_R_I(ins, attr, dataReg, tmpReg, index->gtRegNum, lsl, INS_FLAGS_DONT_CARE,
7665 else // (offset == 0)
7669 // Then load/store dataReg from/to [memBase + index*scale]
7670 emitIns_R_R_R_I(ins, attr, dataReg, memBase->gtRegNum, index->gtRegNum, lsl, INS_FLAGS_DONT_CARE,
7675 // Then load/store dataReg from/to [memBase + index]
7676 emitIns_R_R_R(ins, attr, dataReg, memBase->gtRegNum, index->gtRegNum);
7682 if (emitIns_valid_imm_for_ldst_offset(offset, attr))
7684 // Then load/store dataReg from/to [memBase + offset]
7685 emitIns_R_R_I(ins, attr, dataReg, memBase->gtRegNum, offset);
7689 // We require a tmpReg to hold the offset
7690 regNumber tmpReg = indir->GetSingleTempReg();
7692 // First load/store tmpReg with the large offset constant
7693 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
7695 // Then load/store dataReg from/to [memBase + tmpReg]
7696 emitIns_R_R_R(ins, attr, dataReg, memBase->gtRegNum, tmpReg);
7704 assert(emitIns_valid_imm_for_add(offset, INS_FLAGS_DONT_CARE));
7705 emitIns_R_R_I(ins, attr, dataReg, addr->gtRegNum, offset);
7709 emitIns_R_R(ins, attr, dataReg, addr->gtRegNum);
7714 // The callee must call genConsumeReg() for any non-contained srcs
7715 // and genProduceReg() for any non-contained dsts.
7717 regNumber emitter::emitInsBinary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src)
7719 regNumber result = REG_NA;
7721 // dst can only be a reg
7722 assert(!dst->isContained());
7724 // src can be immed or reg
7725 assert(!src->isContained() || src->isContainedIntOrIImmed());
7727 // find immed (if any) - it cannot be a dst
7728 GenTreeIntConCommon* intConst = nullptr;
7729 if (src->isContainedIntOrIImmed())
7731 intConst = src->AsIntConCommon();
7736 emitIns_R_I(ins, attr, dst->gtRegNum, (target_ssize_t)intConst->IconValue());
7737 return dst->gtRegNum;
7741 emitIns_R_R(ins, attr, dst->gtRegNum, src->gtRegNum);
7742 return dst->gtRegNum;
7746 regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src1, GenTree* src2)
7748 // dst can only be a reg
7749 assert(!dst->isContained());
7751 // find immed (if any) - it cannot be a dst
7752 // Only one src can be an int.
7753 GenTreeIntConCommon* intConst = nullptr;
7754 GenTree* nonIntReg = nullptr;
7756 if (varTypeIsFloating(dst))
7758 // src1 can only be a reg
7759 assert(!src1->isContained());
7760 // src2 can only be a reg
7761 assert(!src2->isContained());
7763 else // not floating point
7765 // src2 can be immed or reg
7766 assert(!src2->isContained() || src2->isContainedIntOrIImmed());
7768 // Check src2 first as we can always allow it to be a contained immediate
7769 if (src2->isContainedIntOrIImmed())
7771 intConst = src2->AsIntConCommon();
7774 // Only for commutative operations do we check src1 and allow it to be a contained immediate
7775 else if (dst->OperIsCommutative())
7777 // src1 can be immed or reg
7778 assert(!src1->isContained() || src1->isContainedIntOrIImmed());
7780 // Check src1 and allow it to be a contained immediate
7781 if (src1->isContainedIntOrIImmed())
7783 assert(!src2->isContainedIntOrIImmed());
7784 intConst = src1->AsIntConCommon();
7790 // src1 can only be a reg
7791 assert(!src1->isContained());
7795 insFlags flags = INS_FLAGS_DONT_CARE;
7796 bool isMulOverflow = false;
7797 if (dst->gtOverflowEx())
7799 if ((ins == INS_add) || (ins == INS_adc) || (ins == INS_sub) || (ins == INS_sbc))
7801 flags = INS_FLAGS_SET;
7803 else if (ins == INS_mul)
7805 isMulOverflow = true;
7806 assert(intConst == nullptr); // overflow format doesn't support an int constant operand
7810 assert(!"Invalid ins for overflow check");
7814 if (dst->gtSetFlags())
7816 assert((ins == INS_add) || (ins == INS_adc) || (ins == INS_sub) || (ins == INS_sbc) || (ins == INS_and) ||
7817 (ins == INS_orr) || (ins == INS_eor) || (ins == INS_orn));
7818 flags = INS_FLAGS_SET;
7821 if (intConst != nullptr)
7823 emitIns_R_R_I(ins, attr, dst->gtRegNum, nonIntReg->gtRegNum, (target_ssize_t)intConst->IconValue(), flags);
7829 regNumber extraReg = dst->GetSingleTempReg();
7830 assert(extraReg != dst->gtRegNum);
7832 if ((dst->gtFlags & GTF_UNSIGNED) != 0)
7834 // Compute 8 byte result from 4 byte by 4 byte multiplication.
7835 emitIns_R_R_R_R(INS_umull, EA_4BYTE, dst->gtRegNum, extraReg, src1->gtRegNum, src2->gtRegNum);
7837 // Overflow exists if the result's high word is non-zero.
7838 emitIns_R_I(INS_cmp, attr, extraReg, 0);
7842 // Compute 8 byte result from 4 byte by 4 byte multiplication.
7843 emitIns_R_R_R_R(INS_smull, EA_4BYTE, dst->gtRegNum, extraReg, src1->gtRegNum, src2->gtRegNum);
7845 // Overflow exists if the result's high word is not merely a sign bit.
7846 emitIns_R_R_I(INS_cmp, attr, extraReg, dst->gtRegNum, 31, INS_FLAGS_DONT_CARE, INS_OPTS_ASR);
7851 // We can just do the arithmetic, setting the flags if needed.
7852 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum, flags);
7856 if (dst->gtOverflowEx())
7858 assert(!varTypeIsFloating(dst));
7860 emitJumpKind jumpKind;
7862 if (dst->OperGet() == GT_MUL)
7868 bool isUnsignedOverflow = ((dst->gtFlags & GTF_UNSIGNED) != 0);
7869 jumpKind = isUnsignedOverflow ? EJ_lo : EJ_vs;
7870 if (jumpKind == EJ_lo)
7872 if ((dst->OperGet() != GT_SUB) && (dst->OperGet() != GT_SUB_HI))
7879 // Jump to the block which will throw the exception.
7880 codeGen->genJumpToThrowHlpBlk(jumpKind, SCK_OVERFLOW);
7883 return dst->gtRegNum;
7886 #endif // defined(_TARGET_ARM_)