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 assert(!emitIsTinyInsDsc(id));
91 if (emitIsScnsInsDsc(id))
92 return SMALL_IDSC_SIZE;
94 assert((unsigned)id->idInsFmt() < emitFmtCount);
96 ID_OPS idOp = (ID_OPS)emitFmtToOps[id->idInsFmt()];
97 bool isCallIns = (id->idIns() == INS_bl) || (id->idIns() == INS_blx);
98 bool maybeCallIns = (id->idIns() == INS_b) || (id->idIns() == INS_bx);
100 // An INS_call instruction may use a "fat" direct/indirect call descriptor
101 // except for a local call to a label (i.e. call to a finally).
102 // Only ID_OP_CALL and ID_OP_SPEC check for this, so we enforce that the
103 // INS_call instruction always uses one of these idOps.
105 assert(!isCallIns || // either not a call or
106 idOp == ID_OP_CALL || // is a direct call
107 idOp == ID_OP_SPEC || // is an indirect call
108 idOp == ID_OP_JMP); // is a local call to finally clause
116 return sizeof(instrDescJmp);
119 return sizeof(instrDescLbl);
123 assert(isCallIns || maybeCallIns);
124 if (id->idIsLargeCall())
126 /* Must be a "fat" indirect call descriptor */
127 return sizeof(instrDescCGCA);
131 assert(!id->idIsLargeDsp());
132 assert(!id->idIsLargeCns());
133 return sizeof(instrDesc);
138 NO_WAY("unexpected instruction descriptor format");
142 if (id->idIsLargeCns())
144 if (id->idIsLargeDsp())
145 return sizeof(instrDescCnsDsp);
147 return sizeof(instrDescCns);
151 if (id->idIsLargeDsp())
152 return sizeof(instrDescDsp);
154 return sizeof(instrDesc);
158 bool offsetFitsInVectorMem(int disp)
160 unsigned imm = unsigned_abs(disp);
161 return ((imm & 0x03fc) == imm);
165 /*****************************************************************************
167 * The following called for each recorded instruction -- use for debugging.
169 void emitter::emitInsSanityCheck(instrDesc* id)
171 /* What instruction format have we got? */
173 switch (id->idInsFmt())
175 case IF_T1_A: // T1_A ................
176 case IF_T2_A: // T2_A ................ ................
179 case IF_T1_B: // T1_B ........cccc.... cond
180 case IF_T2_B: // T2_B ................ ............iiii imm4
181 assert(emitGetInsSC(id) < 0x10);
184 case IF_T1_C: // T1_C .....iiiiinnnddd R1 R2 imm5
185 assert(isLowRegister(id->idReg1()));
186 assert(isLowRegister(id->idReg2()));
187 if (emitInsIsLoadOrStore(id->idIns()))
189 emitAttr size = id->idOpSize();
190 int imm = emitGetInsSC(id);
192 imm = insUnscaleImm(imm, size);
197 assert(id->idSmallCns() < 0x20);
201 case IF_T1_D0: // T1_D0 ........Dmmmmddd R1* R2*
202 assert(isGeneralRegister(id->idReg1()));
203 assert(isGeneralRegister(id->idReg2()));
206 case IF_T1_D1: // T1_D1 .........mmmm... R1*
207 assert(isGeneralRegister(id->idReg1()));
210 case IF_T1_D2: // T1_D2 .........mmmm... R3*
211 assert(isGeneralRegister(id->idReg3()));
214 case IF_T1_E: // T1_E ..........nnnddd R1 R2
215 assert(isLowRegister(id->idReg1()));
216 assert(isLowRegister(id->idReg2()));
217 assert(id->idSmallCns() < 0x20);
220 case IF_T1_F: // T1_F .........iiiiiii SP imm7
221 assert(id->idReg1() == REG_SP);
222 assert(id->idOpSize() == EA_4BYTE);
223 assert((emitGetInsSC(id) & ~0x1FC) == 0);
226 case IF_T1_G: // T1_G .......iiinnnddd R1 R2 imm3
227 assert(isLowRegister(id->idReg1()));
228 assert(isLowRegister(id->idReg2()));
229 assert(id->idSmallCns() < 0x8);
232 case IF_T1_H: // T1_H .......mmmnnnddd R1 R2 R3
233 assert(isLowRegister(id->idReg1()));
234 assert(isLowRegister(id->idReg2()));
235 assert(isLowRegister(id->idReg3()));
238 case IF_T1_I: // T1_I ......i.iiiiiddd R1 imm6
239 assert(isLowRegister(id->idReg1()));
242 case IF_T1_J0: // T1_J0 .....dddiiiiiiii R1 imm8
243 assert(isLowRegister(id->idReg1()));
244 assert(emitGetInsSC(id) < 0x100);
247 case IF_T1_J1: // T1_J1 .....dddiiiiiiii R1 <regmask8>
248 assert(isLowRegister(id->idReg1()));
249 assert(emitGetInsSC(id) < 0x100);
252 case IF_T1_J2: // T1_J2 .....dddiiiiiiii R1 SP imm8
253 assert(isLowRegister(id->idReg1()));
254 assert(id->idReg2() == REG_SP);
255 assert(id->idOpSize() == EA_4BYTE);
256 assert((emitGetInsSC(id) & ~0x3FC) == 0);
259 case IF_T1_L0: // T1_L0 ........iiiiiiii imm8
260 assert(emitGetInsSC(id) < 0x100);
263 case IF_T1_L1: // T1_L1 .......Rrrrrrrrr <regmask8+2>
264 assert(emitGetInsSC(id) < 0x400);
267 case IF_T2_C0: // T2_C0 ...........Snnnn .iiiddddiishmmmm R1 R2 R3 S, imm5, sh
268 assert(isGeneralRegister(id->idReg1()));
269 assert(isGeneralRegister(id->idReg2()));
270 assert(isGeneralRegister(id->idReg3()));
271 assert(emitGetInsSC(id) < 0x20);
274 case IF_T2_C4: // T2_C4 ...........Snnnn ....dddd....mmmm R1 R2 R3 S
275 case IF_T2_C5: // T2_C5 ............nnnn ....dddd....mmmm R1 R2 R3
276 case IF_T2_G1: // T2_G1 ............nnnn ttttTTTT........ R1 R2 R3
277 assert(isGeneralRegister(id->idReg1()));
278 assert(isGeneralRegister(id->idReg2()));
279 assert(isGeneralRegister(id->idReg3()));
282 case IF_T2_C1: // T2_C1 ...........S.... .iiiddddiishmmmm R1 R2 S, imm5, sh
283 case IF_T2_C2: // T2_C2 ...........S.... .iiiddddii..mmmm R1 R2 S, imm5
284 case IF_T2_C8: // T2_C8 ............nnnn .iii....iishmmmm R1 R2 imm5, sh
285 assert(isGeneralRegister(id->idReg1()));
286 assert(isGeneralRegister(id->idReg2()));
287 assert(emitGetInsSC(id) < 0x20);
290 case IF_T2_C6: // T2_C6 ................ ....dddd..iimmmm R1 R2 imm2
291 case IF_T2_C7: // T2_C7 ............nnnn ..........shmmmm R1 R2 imm2
292 assert(isGeneralRegister(id->idReg1()));
293 assert(isGeneralRegister(id->idReg2()));
294 assert(emitGetInsSC(id) < 0x4);
297 case IF_T2_C3: // T2_C3 ...........S.... ....dddd....mmmm R1 R2 S
298 case IF_T2_C9: // T2_C9 ............nnnn ............mmmm R1 R2
299 case IF_T2_C10: // T2_C10 ............mmmm ....dddd....mmmm R1 R2
300 assert(isGeneralRegister(id->idReg1()));
301 assert(isGeneralRegister(id->idReg2()));
304 case IF_T2_D0: // T2_D0 ............nnnn .iiiddddii.wwwww R1 R2 imm5, imm5
305 assert(isGeneralRegister(id->idReg1()));
306 assert(isGeneralRegister(id->idReg2()));
307 assert(emitGetInsSC(id) < 0x400);
310 case IF_T2_D1: // T2_D1 ................ .iiiddddii.wwwww R1 imm5, imm5
311 assert(isGeneralRegister(id->idReg1()));
312 assert(emitGetInsSC(id) < 0x400);
315 case IF_T2_E0: // T2_E0 ............nnnn tttt......shmmmm R1 R2 R3 imm2
316 assert(isGeneralRegister(id->idReg1()));
317 assert(isGeneralRegister(id->idReg2()));
318 if (id->idIsLclVar())
320 assert(isGeneralRegister(codeGen->rsGetRsvdReg()));
324 assert(isGeneralRegister(id->idReg3()));
325 assert(emitGetInsSC(id) < 0x4);
329 case IF_T2_E1: // T2_E1 ............nnnn tttt............ R1 R2
330 assert(isGeneralRegister(id->idReg1()));
331 assert(isGeneralRegister(id->idReg2()));
334 case IF_T2_E2: // T2_E2 ................ tttt............ R1
335 assert(isGeneralRegister(id->idReg1()));
338 case IF_T2_F1: // T2_F1 ............nnnn ttttdddd....mmmm R1 R2 R3 R4
339 case IF_T2_F2: // T2_F2 ............nnnn aaaadddd....mmmm R1 R2 R3 R4
340 assert(isGeneralRegister(id->idReg1()));
341 assert(isGeneralRegister(id->idReg2()));
342 assert(isGeneralRegister(id->idReg3()));
343 assert(isGeneralRegister(id->idReg4()));
346 case IF_T2_G0: // T2_G0 .......PU.W.nnnn ttttTTTTiiiiiiii R1 R2 R3 imm8, PUW
347 assert(isGeneralRegister(id->idReg1()));
348 assert(isGeneralRegister(id->idReg2()));
349 assert(isGeneralRegister(id->idReg3()));
350 assert(unsigned_abs(emitGetInsSC(id)) < 0x100);
353 case IF_T2_H0: // T2_H0 ............nnnn tttt.PUWiiiiiiii R1 R2 imm8, PUW
354 assert(isGeneralRegister(id->idReg1()));
355 assert(isGeneralRegister(id->idReg2()));
356 assert(unsigned_abs(emitGetInsSC(id)) < 0x100);
359 case IF_T2_H1: // T2_H1 ............nnnn tttt....iiiiiiii R1 R2 imm8
360 assert(isGeneralRegister(id->idReg1()));
361 assert(isGeneralRegister(id->idReg2()));
362 assert(emitGetInsSC(id) < 0x100);
365 case IF_T2_H2: // T2_H2 ............nnnn ........iiiiiiii R1 imm8
366 assert(isGeneralRegister(id->idReg1()));
367 assert(emitGetInsSC(id) < 0x100);
370 case IF_T2_I0: // T2_I0 ..........W.nnnn rrrrrrrrrrrrrrrr R1 W, imm16
371 assert(isGeneralRegister(id->idReg1()));
372 assert(emitGetInsSC(id) < 0x10000);
375 case IF_T2_N: // T2_N .....i......iiii .iiiddddiiiiiiii R1 imm16
376 assert(isGeneralRegister(id->idReg1()));
379 case IF_T2_N2: // T2_N2 .....i......iiii .iiiddddiiiiiiii R1 imm16
380 assert(isGeneralRegister(id->idReg1()));
381 assert((size_t)emitGetInsSC(id) < emitDataSize());
384 case IF_T2_I1: // T2_I1 ................ rrrrrrrrrrrrrrrr imm16
385 assert(emitGetInsSC(id) < 0x10000);
388 case IF_T2_K1: // T2_K1 ............nnnn ttttiiiiiiiiiiii R1 R2 imm12
389 case IF_T2_M0: // T2_M0 .....i......nnnn .iiiddddiiiiiiii R1 R2 imm12
390 assert(isGeneralRegister(id->idReg1()));
391 assert(isGeneralRegister(id->idReg2()));
392 assert(emitGetInsSC(id) < 0x1000);
395 case IF_T2_L0: // T2_L0 .....i.....Snnnn .iiiddddiiiiiiii R1 R2 S, imm8<<imm4
396 assert(isGeneralRegister(id->idReg1()));
397 assert(isGeneralRegister(id->idReg2()));
398 assert(isModImmConst(emitGetInsSC(id)));
401 case IF_T2_K4: // T2_K4 ........U....... ttttiiiiiiiiiiii R1 PC U, imm12
402 case IF_T2_M1: // T2_M1 .....i.......... .iiiddddiiiiiiii R1 PC imm12
403 assert(isGeneralRegister(id->idReg1()));
404 assert(id->idReg2() == REG_PC);
405 assert(emitGetInsSC(id) < 0x1000);
408 case IF_T2_K3: // T2_K3 ........U....... ....iiiiiiiiiiii PC U, imm12
409 assert(id->idReg1() == REG_PC);
410 assert(emitGetInsSC(id) < 0x1000);
413 case IF_T2_K2: // T2_K2 ............nnnn ....iiiiiiiiiiii R1 imm12
414 assert(isGeneralRegister(id->idReg1()));
415 assert(emitGetInsSC(id) < 0x1000);
418 case IF_T2_L1: // T2_L1 .....i.....S.... .iiiddddiiiiiiii R1 S, imm8<<imm4
419 case IF_T2_L2: // T2_L2 .....i......nnnn .iii....iiiiiiii R1 imm8<<imm4
420 assert(isGeneralRegister(id->idReg1()));
421 assert(isModImmConst(emitGetInsSC(id)));
424 case IF_T1_J3: // T1_J3 .....dddiiiiiiii R1 PC imm8
425 assert(isGeneralRegister(id->idReg1()));
426 assert(id->idReg2() == REG_PC);
427 assert(emitGetInsSC(id) < 0x100);
430 case IF_T1_K: // T1_K ....cccciiiiiiii Branch imm8, cond4
431 case IF_T1_M: // T1_M .....iiiiiiiiiii Branch imm11
432 case IF_T2_J1: // T2_J1 .....Scccciiiiii ..j.jiiiiiiiiiii Branch imm20, cond4
433 case IF_T2_J2: // T2_J2 .....Siiiiiiiiii ..j.jiiiiiiiiii. Branch imm24
434 case IF_T2_N1: // T2_N .....i......iiii .iiiddddiiiiiiii R1 imm16
435 case IF_T2_J3: // T2_J3 .....Siiiiiiiiii ..j.jiiiiiiiiii. Call imm24
440 if (id->idOpSize() == EA_8BYTE)
442 assert(isDoubleReg(id->idReg1()));
443 assert(isDoubleReg(id->idReg2()));
444 assert(isDoubleReg(id->idReg3()));
448 assert(id->idOpSize() == EA_4BYTE);
449 assert(isFloatReg(id->idReg1()));
450 assert(isFloatReg(id->idReg2()));
451 assert(isFloatReg(id->idReg3()));
456 assert(isFloatReg(id->idReg1()));
457 assert(isFloatReg(id->idReg2()));
461 if (id->idOpSize() == EA_8BYTE)
462 assert(isDoubleReg(id->idReg1()));
464 assert(isFloatReg(id->idReg1()));
465 assert(isGeneralRegister(id->idReg2()));
466 assert(offsetFitsInVectorMem(emitGetInsSC(id)));
470 assert(id->idOpSize() == EA_8BYTE);
471 if (id->idIns() == INS_vmov_d2i)
473 assert(isGeneralRegister(id->idReg1()));
474 assert(isGeneralRegister(id->idReg2()));
475 assert(isDoubleReg(id->idReg3()));
479 assert(id->idIns() == INS_vmov_i2d);
480 assert(isDoubleReg(id->idReg1()));
481 assert(isGeneralRegister(id->idReg2()));
482 assert(isGeneralRegister(id->idReg3()));
487 assert(id->idOpSize() == EA_4BYTE);
488 if (id->idIns() == INS_vmov_i2f)
490 assert(isFloatReg(id->idReg1()));
491 assert(isGeneralRegister(id->idReg2()));
495 assert(id->idIns() == INS_vmov_f2i);
496 assert(isGeneralRegister(id->idReg1()));
497 assert(isFloatReg(id->idReg2()));
502 printf("unexpected format %s\n", emitIfName(id->idInsFmt()));
503 assert(!"Unexpected format");
509 bool emitter::emitInsMayWriteToGCReg(instrDesc* id)
511 instruction ins = id->idIns();
512 insFormat fmt = id->idInsFmt();
517 // These are the formats with "destination" or "target" registers:
558 // Some formats with "destination" or "target" registers are actually used for store instructions, for the
559 // "source" value written to memory.
560 // Similarly, PUSH has a target register, indicating the start of the set of registers to push. POP
561 // *does* write to at least one register, so we do not make that a special case.
562 // Various compare/test instructions do not write (except to the flags). Technically "teq" does not need to
564 // be in this list because it has no forms matched above, but I'm putting it here for completeness.
585 // VMOV.i2f reads from the integer register. Conversely VMOV.f2i writes to GC pointer-sized
586 // integer register that might have previously held GC pointers, so they need to be included.
587 assert(id->idGCref() == GCT_NONE);
588 return (ins == INS_vmov_f2i);
591 // VMOV.i2d reads from the integer registers. Conversely VMOV.d2i writes to GC pointer-sized
592 // integer registers that might have previously held GC pointers, so they need to be included.
593 assert(id->idGCref() == GCT_NONE);
594 return (ins == INS_vmov_d2i);
601 bool emitter::emitInsWritesToLclVarStackLoc(instrDesc* id)
603 if (!id->idIsLclVar())
606 instruction ins = id->idIns();
608 // This list is related to the list of instructions used to store local vars in emitIns_S_R().
609 // We don't accept writing to float local vars.
622 bool emitter::emitInsMayWriteMultipleRegs(instrDesc* id)
624 instruction ins = id->idIns();
642 /*****************************************************************************/
644 /*****************************************************************************
646 * Return a string that represents the given register.
649 const char* emitter::emitRegName(regNumber reg, emitAttr attr, bool varName)
651 assert(reg < REG_COUNT);
653 const char* rn = emitComp->compRegVarName(reg, varName, false);
655 assert(strlen(rn) >= 1);
660 const char* emitter::emitFloatRegName(regNumber reg, emitAttr attr, bool varName)
662 assert(reg < REG_COUNT);
664 const char* rn = emitComp->compRegVarName(reg, varName, true);
666 assert(strlen(rn) >= 1);
672 /*****************************************************************************
674 * Returns the base encoding of the given CPU instruction.
677 emitter::insFormat emitter::emitInsFormat(instruction ins)
680 const static insFormat insFormats[] =
682 #define INST1(id, nm, fp, ldst, fmt, e1 ) fmt,
683 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) fmt,
684 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) fmt,
685 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) fmt,
686 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) fmt,
687 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) fmt,
688 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) fmt,
689 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) fmt,
694 assert(ins < ArrLen(insFormats));
695 assert((insFormats[ins] != IF_NONE));
697 return insFormats[ins];
706 /*static*/ const BYTE CodeGenInterface::instInfo[] =
708 #define INST1(id, nm, fp, ldst, fmt, e1 ) ldst | INST_FP*fp,
709 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) ldst | INST_FP*fp,
710 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) ldst | INST_FP*fp,
711 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) ldst | INST_FP*fp,
712 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) ldst | INST_FP*fp,
713 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) ldst | INST_FP*fp,
714 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) ldst | INST_FP*fp,
715 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) ldst | INST_FP*fp,
720 /*****************************************************************************
722 * Returns true if the instruction is some kind of load instruction
725 bool emitter::emitInsIsLoad(instruction ins)
727 // We have pseudo ins like lea which are not included in emitInsLdStTab.
728 if (ins < ArrLen(CodeGenInterface::instInfo))
729 return (CodeGenInterface::instInfo[ins] & LD) ? true : false;
734 /*****************************************************************************
736 * Returns true if the instruction is some kind of compare or test instruction
739 bool emitter::emitInsIsCompare(instruction ins)
741 // We have pseudo ins like lea which are not included in emitInsLdStTab.
742 if (ins < ArrLen(CodeGenInterface::instInfo))
743 return (CodeGenInterface::instInfo[ins] & CMP) ? true : false;
748 /*****************************************************************************
750 * Returns true if the instruction is some kind of store instruction
753 bool emitter::emitInsIsStore(instruction ins)
755 // We have pseudo ins like lea which are not included in emitInsLdStTab.
756 if (ins < ArrLen(CodeGenInterface::instInfo))
757 return (CodeGenInterface::instInfo[ins] & ST) ? true : false;
762 /*****************************************************************************
764 * Returns true if the instruction is some kind of load/store instruction
767 bool emitter::emitInsIsLoadOrStore(instruction ins)
769 // We have pseudo ins like lea which are not included in emitInsLdStTab.
770 if (ins < ArrLen(CodeGenInterface::instInfo))
771 return (CodeGenInterface::instInfo[ins] & (LD | ST)) ? true : false;
780 /*****************************************************************************
782 * Returns the specific encoding of the given CPU instruction and format
785 emitter::code_t emitter::emitInsCode(instruction ins, insFormat fmt)
788 const static code_t insCodes1[] =
790 #define INST1(id, nm, fp, ldst, fmt, e1 ) e1,
791 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) e1,
792 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) e1,
793 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e1,
794 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e1,
795 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e1,
796 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) e1,
797 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e1,
800 const static code_t insCodes2[] =
802 #define INST1(id, nm, fp, ldst, fmt, e1 )
803 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) e2,
804 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) e2,
805 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e2,
806 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e2,
807 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e2,
808 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) e2,
809 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e2,
812 const static code_t insCodes3[] =
814 #define INST1(id, nm, fp, ldst, fmt, e1 )
815 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
816 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) e3,
817 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e3,
818 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e3,
819 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e3,
820 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) e3,
821 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e3,
824 const static code_t insCodes4[] =
826 #define INST1(id, nm, fp, ldst, fmt, e1 )
827 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
828 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
829 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e4,
830 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e4,
831 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e4,
832 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) e4,
833 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e4,
836 const static code_t insCodes5[] =
838 #define INST1(id, nm, fp, ldst, fmt, e1 )
839 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
840 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
841 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
842 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e5,
843 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e5,
844 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) e5,
845 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e5,
848 const static code_t insCodes6[] =
850 #define INST1(id, nm, fp, ldst, fmt, e1 )
851 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
852 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
853 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
854 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
855 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e6,
856 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) e6,
857 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e6,
860 const static code_t insCodes7[] =
862 #define INST1(id, nm, fp, ldst, fmt, e1 )
863 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
864 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
865 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
866 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
867 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 )
868 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) e7,
869 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e7,
872 const static code_t insCodes8[] =
874 #define INST1(id, nm, fp, ldst, fmt, e1 )
875 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
876 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
877 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
878 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
879 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 )
880 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) e8,
881 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e8,
884 const static code_t insCodes9[] =
886 #define INST1(id, nm, fp, ldst, fmt, e1 )
887 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
888 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
889 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
890 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
891 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 )
892 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 )
893 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e9,
896 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 };
897 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 };
898 const static insFormat formatEncode6A[6] = { IF_T1_H, IF_T1_C, IF_T2_E0, IF_T2_H0, IF_T2_K1, IF_T2_K4};
899 const static insFormat formatEncode6B[6] = { IF_T1_H, IF_T1_C, IF_T2_E0, IF_T2_H0, IF_T2_K1, IF_T1_J2 };
900 const static insFormat formatEncode5A[5] = { IF_T1_E, IF_T1_D0, IF_T1_J0, IF_T2_L1, IF_T2_C3 };
901 const static insFormat formatEncode5B[5] = { IF_T1_E, IF_T1_D0, IF_T1_J0, IF_T2_L2, IF_T2_C8 };
902 const static insFormat formatEncode4A[4] = { IF_T1_E, IF_T1_C, IF_T2_C4, IF_T2_C2 };
903 const static insFormat formatEncode4B[4] = { IF_T2_K2, IF_T2_H2, IF_T2_C7, IF_T2_K3 };
904 const static insFormat formatEncode3A[3] = { IF_T1_E, IF_T2_C0, IF_T2_L0 };
905 const static insFormat formatEncode3B[3] = { IF_T1_E, IF_T2_C8, IF_T2_L2 };
906 const static insFormat formatEncode3C[3] = { IF_T1_E, IF_T2_C1, IF_T2_L1 };
907 const static insFormat formatEncode3D[3] = { IF_T1_L1, IF_T2_E2, IF_T2_I1 };
908 const static insFormat formatEncode3E[3] = { IF_T2_N, IF_T2_N1, IF_T2_N2 };
909 const static insFormat formatEncode3F[3] = { IF_T1_M, IF_T2_J2, IF_T2_J3 };
910 const static insFormat formatEncode2A[2] = { IF_T1_K, IF_T2_J1 };
911 const static insFormat formatEncode2B[2] = { IF_T1_D1, IF_T1_D2 };
912 const static insFormat formatEncode2C[2] = { IF_T1_D2, IF_T2_J3 };
913 const static insFormat formatEncode2D[2] = { IF_T1_J1, IF_T2_I0 };
914 const static insFormat formatEncode2E[2] = { IF_T1_E, IF_T2_C6 };
915 const static insFormat formatEncode2F[2] = { IF_T1_E, IF_T2_C5 };
916 const static insFormat formatEncode2G[2] = { IF_T1_J3, IF_T2_M1 };
919 code_t code = BAD_CODE;
920 insFormat insFmt = emitInsFormat(ins);
927 for (index = 0; index < 9; index++)
929 if (fmt == formatEncode9[index])
938 for (index = 0; index < 8; index++)
940 if (fmt == formatEncode8[index])
949 for (index = 0; index < 6; index++)
951 if (fmt == formatEncode6A[index])
960 for (index = 0; index < 6; index++)
962 if (fmt == formatEncode6B[index])
971 for (index = 0; index < 5; index++)
973 if (fmt == formatEncode5A[index])
982 for (index = 0; index < 5; index++)
984 if (fmt == formatEncode5B[index])
993 for (index = 0; index < 4; index++)
995 if (fmt == formatEncode4A[index])
1004 for (index = 0; index < 4; index++)
1006 if (fmt == formatEncode4B[index])
1015 for (index = 0; index < 3; index++)
1017 if (fmt == formatEncode3A[index])
1026 for (index = 0; index < 3; index++)
1028 if (fmt == formatEncode3B[index])
1036 for (index = 0; index < 3; index++)
1038 if (fmt == formatEncode3C[index])
1046 for (index = 0; index < 3; index++)
1048 if (fmt == formatEncode3D[index])
1056 for (index = 0; index < 3; index++)
1058 if (fmt == formatEncode3E[index])
1066 for (index = 0; index < 3; index++)
1068 if (fmt == formatEncode3F[index])
1077 for (index = 0; index < 2; index++)
1079 if (fmt == formatEncode2A[index])
1087 for (index = 0; index < 2; index++)
1089 if (fmt == formatEncode2B[index])
1097 for (index = 0; index < 2; index++)
1099 if (fmt == formatEncode2C[index])
1107 for (index = 0; index < 2; index++)
1109 if (fmt == formatEncode2D[index])
1117 for (index = 0; index < 2; index++)
1119 if (fmt == formatEncode2E[index])
1127 for (index = 0; index < 2; index++)
1129 if (fmt == formatEncode2F[index])
1138 for (index = 0; index < 2; index++)
1140 if (fmt == formatEncode2G[index])
1159 assert(ins < ArrLen(insCodes1));
1160 code = insCodes1[ins];
1163 assert(ins < ArrLen(insCodes2));
1164 code = insCodes2[ins];
1167 assert(ins < ArrLen(insCodes3));
1168 code = insCodes3[ins];
1171 assert(ins < ArrLen(insCodes4));
1172 code = insCodes4[ins];
1175 assert(ins < ArrLen(insCodes5));
1176 code = insCodes5[ins];
1179 assert(ins < ArrLen(insCodes6));
1180 code = insCodes6[ins];
1183 assert(ins < ArrLen(insCodes7));
1184 code = insCodes7[ins];
1187 assert(ins < ArrLen(insCodes8));
1188 code = insCodes8[ins];
1191 assert(ins < ArrLen(insCodes9));
1192 code = insCodes9[ins];
1196 assert((code != BAD_CODE));
1201 /*****************************************************************************
1203 * Return the code size of the given instruction format. The 'insSize' return type enum
1204 * indicates a 16 bit, 32 bit, or 48 bit instruction.
1207 emitter::insSize emitter::emitInsSize(insFormat insFmt)
1209 if ((insFmt >= IF_T1_A) && (insFmt < IF_T2_A))
1212 if ((insFmt >= IF_T2_A) && (insFmt < IF_INVALID))
1215 if (insFmt == IF_LARGEJMP)
1218 assert(!"Invalid insFormat");
1222 /*****************************************************************************
1224 * isModImmConst() returns true when immediate 'val32' can be encoded
1225 * using the special modified immediate constant available in Thumb
1228 /*static*/ bool emitter::isModImmConst(int val32)
1230 unsigned uval32 = (unsigned)val32;
1231 unsigned imm8 = uval32 & 0xff;
1233 /* encode = 0000x */
1237 unsigned imm32a = (imm8 << 16) | imm8;
1238 /* encode = 0001x */
1239 if (imm32a == uval32)
1242 unsigned imm32b = (imm32a << 8);
1243 /* encode = 0010x */
1244 if (imm32b == uval32)
1247 unsigned imm32c = (imm32a | imm32b);
1248 /* encode = 0011x */
1249 if (imm32c == uval32)
1252 unsigned mask32 = 0x00000ff;
1254 unsigned encode = 31; /* 11111 */
1260 temp = uval32 & ~mask32;
1264 } while (encode >= 8);
1269 /*****************************************************************************
1271 * encodeModImmConst() returns the special ARM 12-bit immediate encoding.
1272 * that is used to encode the immediate. (4-bits, 8-bits)
1273 * If the imm can not be encoded then 0x0BADC0DE is returned.
1276 /*static*/ int emitter::encodeModImmConst(int val32)
1278 unsigned uval32 = (unsigned)val32;
1279 unsigned imm8 = uval32 & 0xff;
1280 unsigned encode = imm8 >> 7;
1287 /* encode = 0000x */
1293 imm32a = (imm8 << 16) | imm8;
1294 /* encode = 0001x */
1295 if (imm32a == uval32)
1301 imm32b = (imm32a << 8);
1302 /* encode = 0010x */
1303 if (imm32b == uval32)
1309 imm32c = (imm32a | imm32b);
1310 /* encode = 0011x */
1311 if (imm32c == uval32)
1319 encode = 31; /* 11111 */
1323 temp = uval32 & ~mask32;
1326 imm8 = (uval32 & mask32) >> (32 - encode);
1327 assert((imm8 & 0x80) != 0);
1331 } while (encode >= 8);
1333 assert(!"encodeModImmConst failed!");
1337 unsigned result = (encode << 7) | (imm8 & 0x7f);
1338 assert(result <= 0x0fff);
1339 assert(result >= 0);
1343 /*****************************************************************************
1345 * emitIns_valid_imm_for_alu() returns true when the immediate 'imm'
1346 * can be encoded using the 12-bit funky Arm immediate encoding
1348 /*static*/ bool emitter::emitIns_valid_imm_for_alu(int imm)
1350 if (isModImmConst(imm))
1355 /*****************************************************************************
1357 * emitIns_valid_imm_for_mov() returns true when the immediate 'imm'
1358 * can be encoded using a single mov or mvn instruction.
1360 /*static*/ bool emitter::emitIns_valid_imm_for_mov(int imm)
1362 if ((imm & 0x0000ffff) == imm) // 16-bit immediate
1364 if (isModImmConst(imm)) // funky arm immediate
1366 if (isModImmConst(~imm)) // funky arm immediate via mvn
1371 /*****************************************************************************
1373 * emitIns_valid_imm_for_small_mov() returns true when the immediate 'imm'
1374 * can be encoded using a single 2-byte mov instruction.
1376 /*static*/ bool emitter::emitIns_valid_imm_for_small_mov(regNumber reg, int imm, insFlags flags)
1378 return isLowRegister(reg) && insSetsFlags(flags) && ((imm & 0x00ff) == imm);
1381 /*****************************************************************************
1383 * emitins_valid_imm_for_add() returns true when the immediate 'imm'
1384 * can be encoded using a single add or sub instruction.
1386 /*static*/ bool emitter::emitIns_valid_imm_for_add(int imm, insFlags flags)
1388 if ((unsigned_abs(imm) <= 0x00000fff) && (flags != INS_FLAGS_SET)) // 12-bit immediate via add/sub
1390 if (isModImmConst(imm)) // funky arm immediate
1392 if (isModImmConst(-imm)) // funky arm immediate via sub
1397 /*****************************************************************************
1399 * emitins_valid_imm_for_cmp() returns true if this 'imm'
1400 * can be encoded as a input operand to an cmp instruction.
1402 /*static*/ bool emitter::emitIns_valid_imm_for_cmp(int imm, insFlags flags)
1404 if (isModImmConst(imm)) // funky arm immediate
1406 if (isModImmConst(-imm)) // funky arm immediate via sub
1411 /*****************************************************************************
1413 * emitIns_valid_imm_for_add_sp() returns true when the immediate 'imm'
1414 * can be encoded in "add Rd,SP,i10".
1416 /*static*/ bool emitter::emitIns_valid_imm_for_add_sp(int imm)
1418 if ((imm & 0x03fc) == imm)
1423 /*****************************************************************************
1425 * emitIns_valid_imm_for_ldst_offset() returns true when the immediate 'imm'
1426 * can be encoded as the offset in a ldr/str instruction.
1428 /*static*/ bool emitter::emitIns_valid_imm_for_ldst_offset(int imm, emitAttr size)
1430 if ((imm & 0x0fff) == imm)
1431 return true; // encodable using IF_T2_K1
1432 if (unsigned_abs(imm) <= 0x0ff)
1433 return true; // encodable using IF_T2_H0
1437 /*****************************************************************************
1439 * emitIns_valid_imm_for_vldst_offset() returns true when the immediate 'imm'
1440 * can be encoded as the offset in a vldr/vstr instruction, i.e. when it is
1441 * a non-negative multiple of 4 that is less than 1024.
1443 /*static*/ bool emitter::emitIns_valid_imm_for_vldst_offset(int imm)
1445 if ((imm & 0x3fc) == imm)
1450 /*****************************************************************************
1452 * Add an instruction with no operands.
1455 void emitter::emitIns(instruction ins)
1457 instrDesc* id = emitNewInstrSmall(EA_4BYTE);
1458 insFormat fmt = emitInsFormat(ins);
1459 insSize isz = emitInsSize(fmt);
1461 assert((fmt == IF_T1_A) || (fmt == IF_T2_A));
1471 /*****************************************************************************
1473 * Add an instruction with a single immediate value.
1476 void emitter::emitIns_I(instruction ins, emitAttr attr, ssize_t imm)
1478 insFormat fmt = IF_NONE;
1482 bool onlyT1 = false;
1484 /* Figure out the encoding format of the instruction */
1487 #ifdef FEATURE_ITINSTRUCTION
1503 assert((imm & 0x0F) == imm);
1507 #endif // FEATURE_ITINSTRUCTION
1510 assert((imm & 0xA000) == 0); // Cannot push PC or SP
1512 if (imm & 0x4000) // Is the LR being pushed?
1515 goto COMMON_PUSH_POP;
1518 assert((imm & 0x2000) == 0); // Cannot pop SP
1519 assert((imm & 0xC000) != 0xC000); // Cannot pop both PC and LR
1521 if (imm & 0x8000) // Is the PC being popped?
1523 if (imm & 0x4000) // Is the LR being popped?
1531 if (((imm - 1) & imm) == 0) // Is only one or zero bits set in imm?
1533 if (((imm == 0) && !hasLR) || // imm has no bits set, but hasLR is set
1534 (!hasPC && !hasLR)) // imm has one bit set, and neither of hasPC/hasLR are set
1536 onlyT1 = true; // if only one bit is set we must use the T1 encoding
1540 imm &= ~0xE000; // ensure that PC, LR and SP bits are removed from imm
1542 if (((imm & 0x00ff) == imm) && !useT2)
1552 // We have to use the Thumb-2 push single register encoding
1553 regNumber reg = genRegNumFromMask(imm);
1554 emitIns_R(ins, attr, reg);
1559 // Encode the PC and LR bits as the lowest two bits
1572 // TODO-ARM-Cleanup: Enable or delete.
1573 case INS_bkpt: // Windows uses a different encoding
1574 if ((imm & 0x0000ffff) == imm)
1580 assert(!"Instruction cannot be encoded");
1587 if ((imm & 0x000f) == imm)
1594 assert(!"Instruction cannot be encoded");
1601 assert((fmt == IF_T1_B) || (fmt == IF_T1_L0) || (fmt == IF_T1_L1) || (fmt == IF_T2_I1) || (fmt == IF_T2_B));
1603 instrDesc* id = emitNewInstrSC(attr, imm);
1604 insSize isz = emitInsSize(fmt);
1614 /*****************************************************************************
1616 * Add an instruction referencing a single register.
1619 void emitter::emitIns_R(instruction ins, emitAttr attr, regNumber reg)
1621 emitAttr size = EA_SIZE(attr);
1622 insFormat fmt = IF_NONE;
1624 /* Figure out the encoding format of the instruction */
1629 if (isLowRegister(reg))
1631 int regmask = 1 << ((int)reg);
1632 emitIns_I(ins, attr, regmask);
1635 assert(size == EA_PTRSIZE);
1640 assert(size == EA_PTRSIZE);
1645 assert(size == EA_PTRSIZE);
1650 emitIns_R_R_I(ins, attr, reg, reg, 0);
1656 assert((fmt == IF_T1_D1) || (fmt == IF_T2_E2));
1658 instrDesc* id = emitNewInstrSmall(attr);
1659 insSize isz = emitInsSize(fmt);
1670 /*****************************************************************************
1672 * Add an instruction referencing a register and a constant.
1675 void emitter::emitIns_R_I(
1676 instruction ins, emitAttr attr, regNumber reg, ssize_t imm, insFlags flags /* = INS_FLAGS_DONT_CARE */)
1679 insFormat fmt = IF_NONE;
1680 insFlags sf = INS_FLAGS_DONT_CARE;
1682 /* Figure out the encoding format of the instruction */
1687 if ((reg == REG_SP) && insDoesNotSetFlags(flags) && ((imm & 0x01fc) == imm))
1690 sf = INS_FLAGS_NOT_SET;
1692 else if (isLowRegister(reg) && insSetsFlags(flags) && (unsigned_abs(imm) <= 0x00ff))
1696 assert((ins == INS_add) || (ins == INS_sub));
1699 else // ins == INS_sub
1708 // otherwise we have to use a Thumb-2 encoding
1709 emitIns_R_R_I(ins, attr, reg, reg, imm, flags);
1715 emitIns_R_R_I(ins, attr, reg, reg, imm, flags);
1721 if (attr == EA_8BYTE)
1723 assert(isDoubleReg(reg));
1729 assert(attr == EA_4BYTE);
1730 assert(isFloatReg(reg));
1733 assert(((reg - REG_F0) + imm) <= 32);
1736 if (ins == INS_vpush)
1739 sf = INS_FLAGS_NOT_SET;
1745 sf = INS_FLAGS_NOT_SET;
1750 bool onlyT1 = false;
1752 assert((imm & 0x2000) == 0); // Cannot pop SP
1753 assert((imm & 0xC000) != 0xC000); // Cannot pop both PC and LR
1754 assert((imm & 0xFFFF0000) == 0); // Can only contain lower 16 bits
1756 if (imm & 0x8000) // Is the PC being popped?
1759 if (imm & 0x4000) // Is the LR being pushed?
1765 if (!isLowRegister(reg))
1768 if (((imm - 1) & imm) == 0) // Is only one or zero bits set in imm?
1770 if (((imm == 0) && !hasLR) || // imm has no bits set, but hasLR is set
1771 (!hasPC && !hasLR)) // imm has one bit set, and neither of hasPC/hasLR are set
1773 onlyT1 = true; // if only one bit is set we must use the T1 encoding
1777 imm &= ~0xE000; // ensure that PC, LR and SP bits are removed from imm
1779 if (((imm & 0x00ff) == imm) && !useT2)
1789 assert(!"Instruction cannot be encoded");
1790 // We have to use the Thumb-2 str single register encoding
1791 // reg = genRegNumFromMask(imm);
1792 // emitIns_R(ins, attr, reg);
1797 // Encode the PC and LR bits as the lowest two bits
1799 if (fmt == IF_T2_I0)
1823 // use the Reg, Reg, Imm encoding
1824 emitIns_R_R_I(ins, attr, reg, reg, imm, flags);
1828 assert(!EA_IS_CNS_RELOC(attr));
1830 if (isLowRegister(reg) && insSetsFlags(flags) && ((imm & 0x00ff) == imm))
1835 else if (isModImmConst(imm))
1838 sf = insMustSetFlags(flags);
1840 else if (isModImmConst(~imm)) // See if we can use move negated instruction instead
1845 sf = insMustSetFlags(flags);
1847 else if (insDoesNotSetFlags(flags) && ((imm & 0x0000ffff) == imm))
1849 // mov => movw instruction
1852 sf = INS_FLAGS_NOT_SET;
1856 assert(!"Instruction cannot be encoded");
1862 assert(insDoesNotSetFlags(flags));
1863 sf = INS_FLAGS_NOT_SET;
1864 if ((imm & 0x0000ffff) == imm || EA_IS_RELOC(attr))
1870 assert(!"Instruction cannot be encoded");
1875 if (isModImmConst(imm))
1878 sf = insMustSetFlags(flags);
1882 assert(!"Instruction cannot be encoded");
1887 assert(!EA_IS_CNS_RELOC(attr));
1888 assert(insSetsFlags(flags));
1890 if (isLowRegister(reg) && ((imm & 0x0ff) == imm))
1894 else if (isModImmConst(imm))
1898 else if (isModImmConst(-imm))
1906 #ifndef LEGACY_BACKEND
1907 assert(!"emitIns_R_I: immediate doesn't fit into the instruction");
1908 #else // LEGACY_BACKEND
1909 // Load val into a register
1910 regNumber valReg = codeGen->regSet.rsGrabReg(RBM_ALLINT & ~genRegMask(reg));
1911 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, valReg, (ssize_t)imm);
1912 emitIns_R_R(ins, attr, reg, valReg, flags);
1913 #endif // LEGACY_BACKEND
1921 assert(insSetsFlags(flags));
1923 if (isModImmConst(imm))
1929 assert(!"Instruction cannot be encoded");
1933 #ifdef FEATURE_PLI_INSTRUCTION
1935 assert(insDoesNotSetFlags(flags));
1936 if ((reg == REG_SP) && (unsigned_abs(imm) <= 0x0fff))
1939 sf = INS_FLAGS_NOT_SET;
1942 #endif // FEATURE_PLI_INSTRUCTION
1946 assert(insDoesNotSetFlags(flags));
1947 sf = INS_FLAGS_NOT_SET;
1948 if ((imm >= 0) && (imm <= 0x0fff))
1952 else if ((imm < 0) && (-imm <= 0x00ff))
1959 assert(!"Instruction cannot be encoded");
1966 assert((fmt == IF_T1_F) || (fmt == IF_T1_J0) || (fmt == IF_T1_J1) || (fmt == IF_T2_H2) || (fmt == IF_T2_I0) ||
1967 (fmt == IF_T2_K2) || (fmt == IF_T2_K3) || (fmt == IF_T2_L1) || (fmt == IF_T2_L2) || (fmt == IF_T2_M1) ||
1968 (fmt == IF_T2_N) || (fmt == IF_T2_VLDST));
1970 assert(sf != INS_FLAGS_DONT_CARE);
1972 instrDesc* id = emitNewInstrSC(attr, imm);
1973 insSize isz = emitInsSize(fmt);
1985 /*****************************************************************************
1987 * Add an instruction referencing two registers
1990 void emitter::emitIns_R_R(
1991 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insFlags flags /* = INS_FLAGS_DONT_CARE */)
1994 emitAttr size = EA_SIZE(attr);
1995 insFormat fmt = IF_NONE;
1996 insFlags sf = INS_FLAGS_DONT_CARE;
1998 /* Figure out the encoding format of the instruction */
2002 if (insDoesNotSetFlags(flags))
2005 sf = INS_FLAGS_NOT_SET;
2011 // Use the Thumb-1 reg,reg,reg encoding
2012 emitIns_R_R_R(ins, attr, reg1, reg1, reg2, flags);
2016 if (insDoesNotSetFlags(flags))
2018 assert(reg1 != reg2);
2020 sf = INS_FLAGS_NOT_SET;
2022 else // insSetsFlags(flags)
2025 if (isLowRegister(reg1) && isLowRegister(reg2))
2037 assert(insSetsFlags(flags));
2039 if (isLowRegister(reg1) && isLowRegister(reg2))
2041 fmt = IF_T1_E; // both are low registers
2045 fmt = IF_T1_D0; // one or both are high registers
2050 assert(isGeneralRegister(reg1));
2051 assert(isFloatReg(reg2));
2053 sf = INS_FLAGS_NOT_SET;
2057 assert(isFloatReg(reg1));
2058 assert(isGeneralRegister(reg2));
2060 sf = INS_FLAGS_NOT_SET;
2066 assert(isFloatReg(reg1));
2067 assert(isDoubleReg(reg2));
2073 assert(isDoubleReg(reg1));
2074 assert(isFloatReg(reg2));
2081 assert(size == EA_4BYTE);
2082 assert(isFloatReg(reg1));
2083 assert(isFloatReg(reg2));
2087 assert(reg1 != reg2);
2094 if (size == EA_8BYTE)
2096 assert(isDoubleReg(reg1));
2097 assert(isDoubleReg(reg2));
2101 assert(isFloatReg(reg1));
2102 assert(isFloatReg(reg2));
2108 sf = INS_FLAGS_NOT_SET;
2115 emitIns_R_R_R(ins, attr, reg1, reg1, reg2);
2129 emitIns_R_R_I(ins, attr, reg1, reg2, 0);
2138 if (insSetsFlags(flags) && isLowRegister(reg1) && isLowRegister(reg2))
2147 // assert below fired for bug 281892 where the two operands of an OR were
2148 // the same static field load which got cse'd.
2149 // there's no reason why this assert would be true in general
2150 // assert(reg1 != reg2);
2151 // Use the Thumb-2 three register encoding
2152 emitIns_R_R_R_I(ins, attr, reg1, reg1, reg2, 0, flags);
2159 // assert below fired for bug 296394 where the two operands of an
2160 // arithmetic right shift were the same local variable
2161 // there's no reason why this assert would be true in general
2162 // assert(reg1 != reg2);
2163 if (insSetsFlags(flags) && isLowRegister(reg1) && isLowRegister(reg2))
2170 // Use the Thumb-2 three register encoding
2171 emitIns_R_R_R(ins, attr, reg1, reg1, reg2, flags);
2177 // We will prefer the T2 encoding, unless (flags == INS_FLAGS_SET)
2178 // The thumb-1 instruction executes much slower as it must always set the flags
2180 if (insMustSetFlags(flags) && isLowRegister(reg1) && isLowRegister(reg2))
2187 // Use the Thumb-2 three register encoding
2188 emitIns_R_R_R(ins, attr, reg1, reg2, reg1, flags);
2196 if (insSetsFlags(flags) && isLowRegister(reg1) && isLowRegister(reg2))
2203 // Use the Thumb-2 register with shift encoding
2204 emitIns_R_R_I(ins, attr, reg1, reg2, 0, flags);
2211 assert(size == EA_1BYTE);
2216 assert(size == EA_2BYTE);
2218 assert(insDoesNotSetFlags(flags));
2219 if (isLowRegister(reg1) && isLowRegister(reg2))
2222 sf = INS_FLAGS_NOT_SET;
2226 // Use the Thumb-2 reg,reg with rotation encoding
2227 emitIns_R_R_I(ins, attr, reg1, reg2, 0, INS_FLAGS_NOT_SET);
2233 assert(size == EA_1BYTE);
2234 assert(insDoesNotSetFlags(flags));
2236 sf = INS_FLAGS_NOT_SET;
2240 assert(size == EA_2BYTE);
2241 assert(insDoesNotSetFlags(flags));
2243 sf = INS_FLAGS_NOT_SET;
2247 assert(insDoesNotSetFlags(flags));
2249 sf = INS_FLAGS_NOT_SET;
2254 assert(size == EA_1BYTE);
2255 assert(insDoesNotSetFlags(flags));
2257 sf = INS_FLAGS_NOT_SET;
2262 assert(size == EA_2BYTE);
2263 assert(insDoesNotSetFlags(flags));
2265 sf = INS_FLAGS_NOT_SET;
2269 printf("did not expect instruction %s\n", codeGen->genInsName(ins));
2274 assert((fmt == IF_T1_D0) || (fmt == IF_T1_E) || (fmt == IF_T2_C3) || (fmt == IF_T2_C9) || (fmt == IF_T2_C10) ||
2275 (fmt == IF_T2_VFP2) || (fmt == IF_T2_VMOVD) || (fmt == IF_T2_VMOVS) || (fmt == IF_T2_E1));
2277 assert(sf != INS_FLAGS_DONT_CARE);
2279 instrDesc* id = emitNewInstrSmall(attr);
2280 insSize isz = emitInsSize(fmt);
2293 /*****************************************************************************
2295 * Add an instruction referencing a register and two constants.
2298 void emitter::emitIns_R_I_I(
2299 instruction ins, emitAttr attr, regNumber reg, int imm1, int imm2, insFlags flags /* = INS_FLAGS_DONT_CARE */)
2302 insFormat fmt = IF_NONE;
2303 insFlags sf = INS_FLAGS_DONT_CARE;
2304 int imm = 0; // combined immediates
2306 /* Figure out the encoding format of the instruction */
2312 int msb = lsb + imm2 - 1;
2314 assert((lsb >= 0) && (lsb <= 31)); // required for encoding of INS_bfc
2315 assert((msb >= 0) && (msb <= 31)); // required for encoding of INS_bfc
2316 assert(msb >= lsb); // required for encoding of INS_bfc
2318 imm = (lsb << 5) | msb;
2320 assert(insDoesNotSetFlags(flags));
2322 sf = INS_FLAGS_NOT_SET;
2329 assert(fmt == IF_T2_D1);
2330 assert(sf != INS_FLAGS_DONT_CARE);
2332 instrDesc* id = emitNewInstrSC(attr, imm);
2333 insSize isz = emitInsSize(fmt);
2345 /*****************************************************************************
2347 * Add an instruction referencing two registers and a constant.
2350 void emitter::emitIns_R_R_I(instruction ins,
2355 insFlags flags /* = INS_FLAGS_DONT_CARE */,
2356 insOpts opt /* = INS_OPTS_NONE */)
2358 emitAttr size = EA_SIZE(attr);
2359 insFormat fmt = IF_NONE;
2360 insFlags sf = INS_FLAGS_DONT_CARE;
2367 /* Figure out the encoding format of the instruction */
2371 assert(insOptsNone(opt));
2373 // Can we possibly encode the immediate 'imm' using a Thumb-1 encoding?
2374 if ((reg2 == REG_SP) && insDoesNotSetFlags(flags) && ((imm & 0x03fc) == imm))
2376 if ((reg1 == REG_SP) && ((imm & 0x01fc) == imm))
2378 // Use Thumb-1 encoding
2379 emitIns_R_I(ins, attr, reg1, imm, flags);
2382 else if (isLowRegister(reg1))
2385 sf = INS_FLAGS_NOT_SET;
2392 assert(insOptsNone(opt));
2394 // Is it just a mov?
2395 if ((imm == 0) && insDoesNotSetFlags(flags))
2397 // Is the mov even necessary?
2398 // Fix 383915 ARM ILGEN
2401 emitIns_R_R(INS_mov, attr, reg1, reg2, flags);
2405 // Can we encode the immediate 'imm' using a Thumb-1 encoding?
2406 else if (isLowRegister(reg1) && isLowRegister(reg2) && insSetsFlags(flags) && (unsigned_abs(imm) <= 0x0007))
2410 assert((ins == INS_add) || (ins == INS_sub));
2420 else if ((reg1 == reg2) && isLowRegister(reg1) && insSetsFlags(flags) && (unsigned_abs(imm) <= 0x00ff))
2424 assert((ins == INS_add) || (ins == INS_sub));
2431 // Use Thumb-1 encoding
2432 emitIns_R_I(ins, attr, reg1, imm, flags);
2435 else if (isModImmConst(imm))
2438 sf = insMustSetFlags(flags);
2440 else if (isModImmConst(-imm))
2442 assert((ins == INS_add) || (ins == INS_sub));
2443 ins = (ins == INS_add) ? INS_sub : INS_add;
2446 sf = insMustSetFlags(flags);
2448 else if (insDoesNotSetFlags(flags) && (unsigned_abs(imm) <= 0x0fff))
2452 assert((ins == INS_add) || (ins == INS_sub));
2453 ins = (ins == INS_add) ? INS_sub : INS_add;
2456 // add/sub => addw/subw instruction
2457 // Note that even when using the w prefix the immediate is still only 12 bits?
2458 ins = (ins == INS_add) ? INS_addw : INS_subw;
2460 sf = INS_FLAGS_NOT_SET;
2462 else if (insDoesNotSetFlags(flags) && (reg1 != REG_SP) && (reg1 != REG_PC))
2464 // movw,movt reg1, imm
2465 codeGen->instGen_Set_Reg_To_Imm(attr, reg1, (ins == INS_sub ? -1 : 1) * imm);
2468 emitIns_R_R(INS_add, attr, reg1, reg2);
2474 assert(!"Instruction cannot be encoded");
2482 assert(insOptsNone(opt));
2483 if (isModImmConst(imm))
2486 sf = insMustSetFlags(flags);
2488 else if (isModImmConst(~imm))
2491 sf = insMustSetFlags(flags);
2496 else if (ins == INS_bic)
2498 else if (ins == INS_orr)
2500 else if (ins == INS_orn)
2503 assert(!"Instruction cannot be encoded");
2507 assert(!"Instruction cannot be encoded");
2512 assert(insOptsNone(opt));
2513 if (imm == 0 && isLowRegister(reg1) && isLowRegister(reg2) && insSetsFlags(flags))
2524 assert(insOptsNone(opt));
2525 if (isModImmConst(imm))
2528 sf = insMustSetFlags(flags);
2532 assert(!"Instruction cannot be encoded");
2537 assert(insOptsNone(opt));
2538 assert(insDoesNotSetFlags(flags));
2539 assert(reg2 == REG_PC);
2540 sf = INS_FLAGS_NOT_SET;
2542 if (isLowRegister(reg1) && ((imm & 0x00ff) == imm))
2546 else if ((imm & 0x0fff) == imm)
2552 assert(!"Instruction cannot be encoded");
2557 assert((imm >= 0) && (imm <= 31)); // required for encoding
2558 assert(!insOptAnyInc(opt));
2561 assert(insOptsNone(opt));
2562 if (isLowRegister(reg1) && isLowRegister(reg2) && insSetsFlags(flags))
2564 // Use the Thumb-1 reg,reg encoding
2565 emitIns_R_R(ins, attr, reg1, reg2, flags);
2569 else // imm > 0 && imm <= 31
2571 assert(insOptAnyShift(opt));
2574 sf = insMustSetFlags(flags);
2581 assert(insSetsFlags(flags));
2582 assert((imm >= 0) && (imm <= 31)); // required for encoding
2583 assert(!insOptAnyInc(opt));
2586 assert(insOptsNone(opt));
2589 // Use the Thumb-1 reg,reg encoding
2590 emitIns_R_R(ins, attr, reg1, reg2, flags);
2593 if (((ins == INS_cmn) || (ins == INS_tst)) && isLowRegister(reg1) && isLowRegister(reg2))
2595 // Use the Thumb-1 reg,reg encoding
2596 emitIns_R_R(ins, attr, reg1, reg2, flags);
2600 else // imm > 0 && imm <= 31)
2602 assert(insOptAnyShift(opt));
2603 if (insOptsRRX(opt))
2615 assert(insOptsNone(opt));
2617 // On ARM, the immediate shift count of LSL and ROR must be between 1 and 31. For LSR and ASR, it is between
2618 // 1 and 32, though we don't ever use 32. Although x86 allows an immediate shift count of 8-bits in
2619 // instruction encoding, the CPU looks at only the lower 5 bits. As per ECMA, specifying a shift count to
2620 // the IL SHR, SHL, or SHL.UN instruction that is greater than or equal to the width of the type will yield
2621 // an undefined value. We choose that undefined value in this case to match x86 behavior, by only using the
2622 // lower 5 bits of the constant shift count.
2627 // Additional Fix 383915 ARM ILGEN
2628 if ((reg1 != reg2) || insMustSetFlags(flags))
2630 // Use MOV/MOVS instriction
2631 emitIns_R_R(INS_mov, attr, reg1, reg2, flags);
2636 if (insSetsFlags(flags) && (ins != INS_ror) && isLowRegister(reg1) && isLowRegister(reg2))
2644 sf = insMustSetFlags(flags);
2650 assert(size == EA_1BYTE);
2655 assert(size == EA_2BYTE);
2657 assert(insOptsNone(opt));
2658 assert(insDoesNotSetFlags(flags));
2659 assert((imm & 0x018) == imm); // required for encoding
2661 if ((imm == 0) && isLowRegister(reg1) && isLowRegister(reg2))
2663 // Use Thumb-1 encoding
2664 emitIns_R_R(ins, attr, reg1, reg2, INS_FLAGS_NOT_SET);
2669 sf = INS_FLAGS_NOT_SET;
2674 #ifdef FEATURE_PLI_INSTRUCTION
2676 #endif // FEATURE_PLI_INSTRUCTION
2677 assert(insOptsNone(opt));
2678 assert(insDoesNotSetFlags(flags));
2679 assert((imm & 0x003) == imm); // required for encoding
2682 sf = INS_FLAGS_NOT_SET;
2687 assert(size == EA_1BYTE);
2688 assert(insDoesNotSetFlags(flags));
2690 if (isLowRegister(reg1) && isLowRegister(reg2) && insOptsNone(opt) && ((imm & 0x001f) == imm))
2693 sf = INS_FLAGS_NOT_SET;
2696 goto COMMON_THUMB2_LDST;
2699 assert(size == EA_1BYTE);
2700 goto COMMON_THUMB2_LDST;
2704 assert(size == EA_2BYTE);
2705 assert(insDoesNotSetFlags(flags));
2707 if (isLowRegister(reg1) && isLowRegister(reg2) && insOptsNone(opt) && ((imm & 0x003e) == imm))
2710 sf = INS_FLAGS_NOT_SET;
2713 goto COMMON_THUMB2_LDST;
2716 assert(size == EA_2BYTE);
2717 goto COMMON_THUMB2_LDST;
2723 assert(fmt == IF_NONE);
2724 assert(insDoesNotSetFlags(flags));
2725 assert(offsetFitsInVectorMem(imm)); // required for encoding
2726 if (insOptAnyInc(opt))
2728 if (insOptsPostInc(opt))
2732 else // insOptsPreDec(opt)
2739 assert(insOptsNone(opt));
2742 sf = INS_FLAGS_NOT_SET;
2748 assert(size == EA_4BYTE);
2749 assert(insDoesNotSetFlags(flags));
2751 // Can we possibly encode the immediate 'imm' using a Thumb-1 encoding?
2752 if (isLowRegister(reg1) && insOptsNone(opt) && ((imm & 0x03fc) == imm))
2757 sf = INS_FLAGS_NOT_SET;
2760 else if (reg2 == REG_PC)
2765 sf = INS_FLAGS_NOT_SET;
2769 else if (isLowRegister(reg2))
2771 // Only the smaller range 'imm' can be encoded
2772 if ((imm & 0x07c) == imm)
2775 sf = INS_FLAGS_NOT_SET;
2781 // If we did not find a thumb-1 encoding above
2786 assert(fmt == IF_NONE);
2787 assert(insDoesNotSetFlags(flags));
2788 sf = INS_FLAGS_NOT_SET;
2790 if (insOptAnyInc(opt))
2792 if (insOptsPostInc(opt))
2794 else // insOptsPreDec(opt)
2797 if (unsigned_abs(imm) <= 0x00ff)
2803 assert(!"Instruction cannot be encoded");
2808 assert(insOptsNone(opt));
2809 if ((reg2 == REG_PC) && (unsigned_abs(imm) <= 0x0fff))
2813 else if ((imm & 0x0fff) == imm)
2817 else if (unsigned_abs(imm) <= 0x0ff)
2823 // Load imm into a register
2824 regNumber rsvdReg = codeGen->rsGetRsvdReg();
2825 codeGen->instGen_Set_Reg_To_Imm(EA_4BYTE, rsvdReg, (ssize_t)imm);
2826 emitIns_R_R_R(ins, attr, reg1, reg2, rsvdReg);
2834 assert(insOptsNone(opt));
2835 assert(insDoesNotSetFlags(flags));
2836 sf = INS_FLAGS_NOT_SET;
2838 if ((imm & 0x03fc) == imm)
2844 assert(!"Instruction cannot be encoded");
2849 assert(!"Unexpected instruction");
2851 assert((fmt == IF_T1_C) || (fmt == IF_T1_E) || (fmt == IF_T1_G) || (fmt == IF_T1_J2) || (fmt == IF_T1_J3) ||
2852 (fmt == IF_T2_C1) || (fmt == IF_T2_C2) || (fmt == IF_T2_C6) || (fmt == IF_T2_C7) || (fmt == IF_T2_C8) ||
2853 (fmt == IF_T2_H0) || (fmt == IF_T2_H1) || (fmt == IF_T2_K1) || (fmt == IF_T2_K4) || (fmt == IF_T2_L0) ||
2854 (fmt == IF_T2_M0) || (fmt == IF_T2_VLDST) || (fmt == IF_T2_M1));
2855 assert(sf != INS_FLAGS_DONT_CARE);
2857 instrDesc* id = emitNewInstrSC(attr, imm);
2858 insSize isz = emitInsSize(fmt);
2872 /*****************************************************************************
2874 * Add an instruction referencing three registers.
2877 void emitter::emitIns_R_R_R(instruction ins,
2882 insFlags flags /* = INS_FLAGS_DONT_CARE */)
2884 emitAttr size = EA_SIZE(attr);
2885 insFormat fmt = IF_NONE;
2886 insFlags sf = INS_FLAGS_DONT_CARE;
2888 /* Figure out the encoding format of the instruction */
2892 // Encodings do not support SP in the reg3 slot
2895 // Swap reg2 and reg3
2902 assert(reg3 != REG_SP);
2904 if (isLowRegister(reg1) && isLowRegister(reg2) && isLowRegister(reg3) && insSetsFlags(flags))
2911 if ((ins == INS_add) && insDoesNotSetFlags(flags))
2915 // Use the Thumb-1 regdest,reg encoding
2916 emitIns_R_R(ins, attr, reg1, reg3, flags);
2921 // Use the Thumb-1 regdest,reg encoding
2922 emitIns_R_R(ins, attr, reg1, reg2, flags);
2927 // Use the Thumb-2 reg,reg,reg with shift encoding
2928 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, flags);
2939 // Try to encode as a Thumb-1 instruction
2940 emitIns_R_R(ins, attr, reg1, reg3, flags);
2946 // Use the Thumb-2 three register encoding, with imm=0
2947 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, flags);
2953 if (reg1 == reg2 && insSetsFlags(flags) && isLowRegister(reg1) && isLowRegister(reg3))
2955 // Use the Thumb-1 regdest,reg encoding
2956 emitIns_R_R(ins, attr, reg1, reg3, flags);
2963 sf = insMustSetFlags(flags);
2967 if (insMustSetFlags(flags))
2969 if ((reg1 == reg2) && isLowRegister(reg1))
2971 // Use the Thumb-1 regdest,reg encoding
2972 emitIns_R_R(ins, attr, reg1, reg3, flags);
2975 if ((reg1 == reg3) && isLowRegister(reg1))
2977 // Use the Thumb-1 regdest,reg encoding
2978 emitIns_R_R(ins, attr, reg1, reg2, flags);
2983 assert(!"Instruction cannot be encoded");
2988 #if !defined(USE_HELPERS_FOR_INT_DIV)
2991 #endif // !USE_HELPERS_FOR_INT_DIV
2993 assert(insDoesNotSetFlags(flags));
2995 sf = INS_FLAGS_NOT_SET;
3001 assert(size == EA_1BYTE);
3002 goto COMMON_THUMB1_LDST;
3007 assert(size == EA_2BYTE);
3008 goto COMMON_THUMB1_LDST;
3012 assert(size == EA_4BYTE);
3015 assert(insDoesNotSetFlags(flags));
3017 if (isLowRegister(reg1) && isLowRegister(reg2) && isLowRegister(reg3))
3020 sf = INS_FLAGS_NOT_SET;
3024 // Use the Thumb-2 reg,reg,reg with shift encoding
3025 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, flags);
3034 if (size == EA_8BYTE)
3036 assert(isDoubleReg(reg1));
3037 assert(isDoubleReg(reg2));
3038 assert(isDoubleReg(reg3));
3042 assert(isFloatReg(reg1));
3043 assert(isFloatReg(reg2));
3044 assert(isFloatReg(reg3));
3047 sf = INS_FLAGS_NOT_SET;
3051 assert(isDoubleReg(reg1));
3052 assert(isGeneralRegister(reg2));
3053 assert(isGeneralRegister(reg3));
3055 sf = INS_FLAGS_NOT_SET;
3059 assert(isGeneralRegister(reg1));
3060 assert(isGeneralRegister(reg2));
3061 assert(isDoubleReg(reg3));
3063 sf = INS_FLAGS_NOT_SET;
3068 assert(insDoesNotSetFlags(flags));
3070 sf = INS_FLAGS_NOT_SET;
3076 assert((fmt == IF_T1_H) || (fmt == IF_T2_C4) || (fmt == IF_T2_C5) || (fmt == IF_T2_VFP3) || (fmt == IF_T2_VMOVD) ||
3078 assert(sf != INS_FLAGS_DONT_CARE);
3080 instrDesc* id = emitNewInstr(attr);
3081 insSize isz = emitInsSize(fmt);
3095 /*****************************************************************************
3097 * Add an instruction referencing two registers and two constants.
3100 void emitter::emitIns_R_R_I_I(instruction ins,
3106 insFlags flags /* = INS_FLAGS_DONT_CARE */)
3108 insFormat fmt = IF_NONE;
3109 insFlags sf = INS_FLAGS_DONT_CARE;
3113 int msb = lsb + width - 1;
3114 int imm = 0; /* combined immediate */
3116 assert((lsb >= 0) && (lsb <= 31)); // required for encodings
3117 assert((width > 0) && (width <= 32)); // required for encodings
3118 assert((msb >= 0) && (msb <= 31)); // required for encodings
3119 assert(msb >= lsb); // required for encodings
3121 /* Figure out the encoding format of the instruction */
3125 assert(insDoesNotSetFlags(flags));
3126 imm = (lsb << 5) | msb;
3129 sf = INS_FLAGS_NOT_SET;
3134 assert(insDoesNotSetFlags(flags));
3135 imm = (lsb << 5) | (width - 1);
3138 sf = INS_FLAGS_NOT_SET;
3144 assert((fmt == IF_T2_D0));
3145 assert(sf != INS_FLAGS_DONT_CARE);
3147 instrDesc* id = emitNewInstrSC(attr, imm);
3148 insSize isz = emitInsSize(fmt);
3161 /*****************************************************************************
3163 * Add an instruction referencing three registers and a constant.
3166 void emitter::emitIns_R_R_R_I(instruction ins,
3172 insFlags flags /* = INS_FLAGS_DONT_CARE */,
3173 insOpts opt /* = INS_OPTS_NONE */)
3175 emitAttr size = EA_SIZE(attr);
3176 insFormat fmt = IF_NONE;
3177 insFlags sf = INS_FLAGS_DONT_CARE;
3179 /* Figure out the encoding format of the instruction */
3187 if (isLowRegister(reg1) && isLowRegister(reg2) && isLowRegister(reg3) && insSetsFlags(flags))
3189 // Use the Thumb-1 reg,reg,reg encoding
3190 emitIns_R_R_R(ins, attr, reg1, reg2, reg3, flags);
3193 if ((ins == INS_add) && insDoesNotSetFlags(flags))
3197 // Use the Thumb-1 regdest,reg encoding
3198 emitIns_R_R(ins, attr, reg1, reg3, flags);
3203 // Use the Thumb-1 regdest,reg encoding
3204 emitIns_R_R(ins, attr, reg1, reg2, flags);
3218 assert((imm >= 0) && (imm <= 31)); // required for encoding
3219 assert(!insOptAnyInc(opt));
3222 if (opt == INS_OPTS_LSL) // left shift of zero
3223 opt = INS_OPTS_NONE; // is a nop
3225 assert(insOptsNone(opt));
3226 if (isLowRegister(reg1) && isLowRegister(reg2) && isLowRegister(reg3) && insSetsFlags(flags))
3230 // Use the Thumb-1 regdest,reg encoding
3231 emitIns_R_R(ins, attr, reg1, reg3, flags);
3234 if ((reg1 == reg3) && (ins != INS_bic) && (ins != INS_orn) && (ins != INS_sbc))
3236 // Use the Thumb-1 regdest,reg encoding
3237 emitIns_R_R(ins, attr, reg1, reg2, flags);
3242 else // imm > 0 && imm <= 31)
3244 assert(insOptAnyShift(opt));
3245 if (insOptsRRX(opt))
3249 sf = insMustSetFlags(flags);
3255 assert(size == EA_1BYTE);
3256 goto COMMON_THUMB2_LDST;
3261 assert(size == EA_2BYTE);
3262 goto COMMON_THUMB2_LDST;
3266 assert(size == EA_4BYTE);
3269 assert(insDoesNotSetFlags(flags));
3270 assert((imm & 0x0003) == imm); // required for encoding
3272 if ((imm == 0) && insOptsNone(opt) && isLowRegister(reg1) && isLowRegister(reg2) && isLowRegister(reg3))
3274 // Use the Thumb-1 reg,reg,reg encoding
3275 emitIns_R_R_R(ins, attr, reg1, reg2, reg3, flags);
3278 assert(insOptsNone(opt) || insOptsLSL(opt));
3280 sf = INS_FLAGS_NOT_SET;
3285 assert(insDoesNotSetFlags(flags));
3286 assert((imm & 0x03) == 0);
3287 sf = INS_FLAGS_NOT_SET;
3289 if (insOptAnyInc(opt))
3291 if (insOptsPostInc(opt))
3293 else // insOptsPreDec(opt)
3298 assert(insOptsNone(opt));
3301 if (unsigned_abs(imm) <= 0x03fc)
3308 assert(!"Instruction cannot be encoded");
3315 assert((fmt == IF_T2_C0) || (fmt == IF_T2_E0) || (fmt == IF_T2_G0));
3316 assert(sf != INS_FLAGS_DONT_CARE);
3318 // 3-reg ops can't use the small instrdesc
3319 instrDescCns* id = emitAllocInstrCns(attr);
3320 id->idSetIsLargeCns();
3321 id->idcCnsVal = imm;
3325 id->idInsSize(emitInsSize(fmt));
3337 /*****************************************************************************
3339 * Add an instruction referencing four registers.
3342 void emitter::emitIns_R_R_R_R(
3343 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, regNumber reg4)
3345 insFormat fmt = IF_NONE;
3346 insFlags sf = INS_FLAGS_NOT_SET;
3348 /* Figure out the encoding format of the instruction */
3356 assert(reg1 != reg2); // Illegal encoding
3366 assert((fmt == IF_T2_F1) || (fmt == IF_T2_F2));
3368 instrDesc* id = emitNewInstr(attr);
3369 insSize isz = emitInsSize(fmt);
3384 /*****************************************************************************
3386 * Add an instruction with a static data member operand. If 'size' is 0, the
3387 * instruction operates on the address of the static member instead of its
3388 * value (e.g. "push offset clsvar", rather than "push dword ptr [clsvar]").
3391 void emitter::emitIns_C(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, int offs)
3396 /*****************************************************************************
3398 * Add an instruction referencing stack-based local variable.
3401 void emitter::emitIns_S(instruction ins, emitAttr attr, int varx, int offs)
3406 /*****************************************************************************
3408 * Add an instruction referencing a register and a stack-based local variable.
3410 void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
3414 assert(!"Please use ins_Load() to select the correct instruction");
3440 insFormat fmt = IF_NONE;
3441 insFlags sf = INS_FLAGS_NOT_SET;
3444 /* Figure out the variable's frame position */
3449 base = emitComp->lvaFrameAddress(varx, emitComp->funCurrentFunc()->funKind != FUNC_ROOT, ®2, offs);
3452 undisp = unsigned_abs(disp);
3454 if (CodeGen::instIsFP(ins))
3456 // all fp mem ops take 8 bit immediate, multiplied by 4, plus sign
3458 // Note if undisp is not a multiple of four we will fail later on
3459 // when we try to encode this instruction
3460 // Its better to fail later with a better error message than
3461 // to fail here when the RBM_OPT_RSVD is not available
3463 if (undisp <= 0x03fb)
3469 regNumber rsvdReg = codeGen->rsGetRsvdReg();
3470 emitIns_genStackOffset(rsvdReg, varx, offs);
3471 emitIns_R_R(INS_add, EA_4BYTE, rsvdReg, reg2);
3472 emitIns_R_R_I(ins, attr, reg1, rsvdReg, 0);
3476 else if (emitInsIsLoadOrStore(ins))
3478 if (isLowRegister(reg1) && (reg2 == REG_SP) && (ins == INS_ldr) && ((disp & 0x03fc) == disp && disp <= 0x03f8))
3482 else if (disp >= 0 && disp <= 0x0ffb)
3486 else if (undisp <= 0x0fb)
3492 // Load disp into a register
3493 regNumber rsvdReg = codeGen->rsGetRsvdReg();
3494 emitIns_genStackOffset(rsvdReg, varx, offs);
3498 else if (ins == INS_add)
3500 if (isLowRegister(reg1) && (reg2 == REG_SP) && ((disp & 0x03fc) == disp && disp <= 0x03f8))
3504 else if (undisp <= 0x0ffb)
3511 // add/sub => addw/subw instruction
3512 // Note that even when using the w prefix the immediate is still only 12 bits?
3513 ins = (ins == INS_add) ? INS_addw : INS_subw;
3518 // Load disp into a register
3519 regNumber rsvdReg = codeGen->rsGetRsvdReg();
3520 emitIns_genStackOffset(rsvdReg, varx, offs);
3521 emitIns_R_R_R(ins, attr, reg1, reg2, rsvdReg);
3525 else if (ins == INS_movw || ins == INS_movt)
3530 assert((fmt == IF_T1_J2) || (fmt == IF_T2_E0) || (fmt == IF_T2_H0) || (fmt == IF_T2_K1) || (fmt == IF_T2_L0) ||
3531 (fmt == IF_T2_N) || (fmt == IF_T2_VLDST) || (fmt == IF_T2_M0));
3532 assert(sf != INS_FLAGS_DONT_CARE);
3534 instrDesc* id = emitNewInstrCns(attr, disp);
3535 insSize isz = emitInsSize(fmt);
3541 id->idInsOpt(INS_OPTS_NONE);
3544 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
3545 id->idSetIsLclVar();
3547 id->idSetIsLclFPBase();
3550 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
3557 // generate the offset of &varx + offs into a register
3558 void emitter::emitIns_genStackOffset(regNumber r, int varx, int offs)
3564 base = emitComp->lvaFrameAddress(varx, emitComp->funCurrentFunc()->funKind != FUNC_ROOT, ®Base, offs);
3567 emitIns_R_S(INS_movw, EA_4BYTE, r, varx, offs);
3569 if ((disp & 0xffff) != disp)
3571 emitIns_R_S(INS_movt, EA_4BYTE, r, varx, offs);
3575 /*****************************************************************************
3577 * Add an instruction referencing a stack-based local variable and a register
3579 void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
3583 assert(!"Please use ins_Store() to select the correct instruction");
3599 insFormat fmt = IF_NONE;
3600 insFlags sf = INS_FLAGS_NOT_SET;
3603 /* Figure out the variable's frame position */
3608 base = emitComp->lvaFrameAddress(varx, emitComp->funCurrentFunc()->funKind != FUNC_ROOT, ®2, offs);
3611 undisp = unsigned_abs(disp);
3613 if (CodeGen::instIsFP(ins))
3615 // all fp mem ops take 8 bit immediate, multiplied by 4, plus sign
3617 // Note if undisp is not a multiple of four we will fail later on
3618 // when we try to encode this instruction
3619 // Its better to fail later with a better error message than
3620 // to fail here when the RBM_OPT_RSVD is not available
3622 if (undisp <= 0x03fb)
3628 regNumber rsvdReg = codeGen->rsGetRsvdReg();
3629 emitIns_genStackOffset(rsvdReg, varx, offs);
3630 emitIns_R_R(INS_add, EA_4BYTE, rsvdReg, reg2);
3631 emitIns_R_R_I(ins, attr, reg1, rsvdReg, 0);
3635 else if (isLowRegister(reg1) && (reg2 == REG_SP) && (ins == INS_str) && ((disp & 0x03fc) == disp && disp <= 0x03f8))
3639 else if (disp >= 0 && disp <= 0x0ffb)
3643 else if (undisp <= 0x0fb)
3649 // Load disp into a register
3650 regNumber rsvdReg = codeGen->rsGetRsvdReg();
3651 emitIns_genStackOffset(rsvdReg, varx, offs);
3654 assert((fmt == IF_T1_J2) || (fmt == IF_T2_E0) || (fmt == IF_T2_H0) || (fmt == IF_T2_VLDST) || (fmt == IF_T2_K1));
3655 assert(sf != INS_FLAGS_DONT_CARE);
3657 instrDesc* id = emitNewInstrCns(attr, disp);
3658 insSize isz = emitInsSize(fmt);
3664 id->idInsOpt(INS_OPTS_NONE);
3667 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
3668 id->idSetIsLclVar();
3670 id->idSetIsLclFPBase();
3672 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
3679 /*****************************************************************************
3681 * Add an instruction referencing stack-based local variable and an immediate
3683 void emitter::emitIns_S_I(instruction ins, emitAttr attr, int varx, int offs, int val)
3688 /*****************************************************************************
3690 * Add an instruction with a register + static member operands.
3692 void emitter::emitIns_R_C(instruction ins, emitAttr attr, regNumber reg, CORINFO_FIELD_HANDLE fldHnd, int offs)
3696 assert(!"Please use ins_Load() to select the correct instruction");
3698 assert(emitInsIsLoad(ins) || (ins == INS_lea));
3704 int doff = Compiler::eeGetJitDataOffs(fldHnd);
3705 ssize_t addr = NULL;
3709 NYI_ARM("JitDataOffset static fields");
3711 else if (fldHnd == FLD_GLOBAL_FS)
3713 NYI_ARM("Thread-Local-Storage static fields");
3715 else if (fldHnd == FLD_GLOBAL_DS)
3717 addr = (ssize_t)offs;
3722 assert(!jitStaticFldIsGlobAddr(fldHnd));
3723 addr = (ssize_t)emitComp->info.compCompHnd->getFieldAddress(fldHnd, NULL);
3725 NO_WAY("could not obtain address of static field");
3728 // We can use reg to load the constant address,
3729 // as long as it is not a floating point register
3730 regNumber regTmp = reg;
3732 if (isFloatReg(regTmp))
3734 #ifndef LEGACY_BACKEND
3735 assert(!"emitIns_R_C() cannot be called with floating point target");
3736 #else // LEGACY_BACKEND
3737 regTmp = codeGen->regSet.rsPickFreeReg(RBM_ALLINT & ~genRegMask(reg));
3738 #endif // LEGACY_BACKEND
3741 // Load address of CLS_VAR into a register
3742 codeGen->instGen_Set_Reg_To_Imm(EA_HANDLE_CNS_RELOC, regTmp, addr);
3744 if ((ins != INS_add) || (offs != 0) || (reg != regTmp))
3746 emitIns_R_R_I(ins, attr, reg, regTmp, offs);
3750 /*****************************************************************************
3752 * Add an instruction with a static member + register operands.
3755 void emitter::emitIns_C_R(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, regNumber reg, int offs)
3757 #ifndef LEGACY_BACKEND
3758 assert(!"emitIns_C_R not supported for RyuJIT backend");
3759 #else // LEGACY_BACKEND
3762 assert(!"Please use ins_Store() to select the correct instruction");
3764 assert(emitInsIsStore(ins));
3766 int doff = Compiler::eeGetJitDataOffs(fldHnd);
3767 ssize_t addr = NULL;
3771 NYI_ARM("JitDataOffset static fields");
3773 else if (fldHnd == FLD_GLOBAL_FS)
3775 NYI_ARM("Thread-Local-Storage static fields");
3777 else if (fldHnd == FLD_GLOBAL_DS)
3779 addr = (ssize_t)offs;
3784 assert(!jitStaticFldIsGlobAddr(fldHnd));
3785 addr = (ssize_t)emitComp->info.compCompHnd->getFieldAddress(fldHnd, NULL);
3787 NO_WAY("could not obtain address of static field");
3790 regNumber regTmp = codeGen->regSet.rsPickFreeReg(RBM_ALLINT & ~genRegMask(reg));
3792 // Load address of CLS_VAR into a register
3793 codeGen->instGen_Set_Reg_To_Imm(EA_HANDLE_CNS_RELOC, regTmp, addr);
3795 emitIns_R_R_I(ins, attr, reg, regTmp, offs);
3796 #endif // LEGACY_BACKEND
3799 /*****************************************************************************
3801 * Add an instruction with a static member + constant.
3804 void emitter::emitIns_C_I(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, int offs, ssize_t val)
3809 /*****************************************************************************
3811 * The following adds instructions referencing address modes.
3814 void emitter::emitIns_I_AR(instruction ins, emitAttr attr, int val, regNumber reg, int offs)
3816 NYI("emitIns_I_AR");
3819 void emitter::emitIns_R_AR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
3823 assert(!"Please use ins_Load() to select the correct instruction");
3828 if (emitter::emitIns_valid_imm_for_add(offs, INS_FLAGS_DONT_CARE))
3830 emitIns_R_R_I(INS_add, attr, ireg, reg, offs);
3834 #ifndef LEGACY_BACKEND
3835 assert(!"emitIns_R_AR: immediate doesn't fit in the instruction");
3836 #else // LEGACY_BACKEND
3837 // Load val into a register
3838 regNumber immReg = codeGen->regSet.rsGrabReg(RBM_ALLINT & ~genRegMask(ireg) & ~genRegMask(reg));
3839 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, immReg, (ssize_t)offs);
3840 emitIns_R_R_R(INS_add, attr, ireg, reg, immReg);
3841 #endif // LEGACY_BACKEND
3845 else if (emitInsIsLoad(ins))
3847 emitIns_R_R_I(ins, attr, ireg, reg, offs);
3850 else if ((ins == INS_mov) || (ins == INS_ldr))
3852 if (EA_SIZE(attr) == EA_4BYTE)
3854 emitIns_R_R_I(INS_ldr, attr, ireg, reg, offs);
3858 else if (ins == INS_vldr)
3860 emitIns_R_R_I(ins, attr, ireg, reg, offs);
3862 NYI("emitIns_R_AR");
3865 void emitter::emitIns_R_AI(instruction ins, emitAttr attr, regNumber ireg, ssize_t disp)
3867 if (emitInsIsLoad(ins))
3869 // We can use ireg to load the constant address,
3870 // as long as it is not a floating point register
3871 regNumber regTmp = ireg;
3873 if (isFloatReg(regTmp))
3875 #ifndef LEGACY_BACKEND
3876 assert(!"emitIns_R_AI with floating point reg");
3877 #else // LEGACY_BACKEND
3878 regTmp = codeGen->regSet.rsPickFreeReg(RBM_ALLINT & ~genRegMask(ireg));
3879 #endif // LEGACY_BACKEND
3882 codeGen->instGen_Set_Reg_To_Imm(EA_IS_RELOC(attr) ? EA_HANDLE_CNS_RELOC : EA_PTRSIZE, regTmp, disp);
3883 emitIns_R_R_I(ins, EA_TYPE(attr), ireg, regTmp, 0);
3886 NYI("emitIns_R_AI");
3889 void emitter::emitIns_AR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
3893 assert(!"Please use ins_Store() to select the correct instruction");
3895 emitIns_R_R_I(ins, attr, ireg, reg, offs);
3898 void emitter::emitIns_R_ARR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
3902 assert(!"Please use ins_Load() to select the correct instruction");
3907 emitIns_R_R_R(INS_add, attr, ireg, reg, rg2);
3910 emitIns_R_R_I(INS_add, attr, ireg, ireg, disp);
3914 else if (emitInsIsLoad(ins))
3918 emitIns_R_R_R_I(ins, attr, ireg, reg, rg2, 0, INS_FLAGS_DONT_CARE, INS_OPTS_NONE);
3922 assert(!"emitIns_R_ARR: Unexpected instruction");
3925 void emitter::emitIns_ARR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
3929 assert(!"Please use ins_Store() to select the correct instruction");
3931 if (emitInsIsStore(ins))
3935 emitIns_R_R_R(ins, attr, ireg, reg, rg2);
3939 emitIns_R_R_R(INS_add, attr, ireg, reg, rg2);
3940 emitIns_R_R_I(ins, attr, ireg, ireg, disp);
3944 assert(!"emitIns_ARR_R: Unexpected instruction");
3947 void emitter::emitIns_R_ARX(
3948 instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, unsigned mul, int disp)
3952 assert(!"Please use ins_Load() to select the correct instruction");
3955 unsigned shift = genLog2((unsigned)mul);
3957 if ((ins == INS_lea) || emitInsIsLoad(ins))
3965 emitIns_R_R_R_I(ins, attr, ireg, reg, rg2, (int)shift, INS_FLAGS_DONT_CARE, INS_OPTS_LSL);
3970 bool useForm2 = false;
3971 bool mustUseForm1 = ((disp % mul) != 0) || (reg == ireg);
3974 // If all of the below things are true we can generate a Thumb-1 add instruction
3975 // followed by a Thumb-2 add instruction
3976 // We also useForm1 when reg is a low register since the second instruction
3977 // can then always be generated using a Thumb-1 add
3979 if ((reg >= REG_R8) && (ireg < REG_R8) && (rg2 < REG_R8) && ((disp >> shift) <= 7))
3988 // Thumb-1 instruction add Rd, Rx, disp>>shift
3989 // Thumb-2 instructions ldr Rd, Rb, Rd LSL shift
3991 emitIns_R_R_I(INS_add, EA_4BYTE, ireg, rg2, disp >> shift);
3992 emitIns_R_R_R_I(ins, attr, ireg, reg, ireg, shift, INS_FLAGS_NOT_SET, INS_OPTS_LSL);
3997 // Thumb-2 instruction add Rd, Rb, Rx LSL shift
3998 // Thumb-1/2 instructions ldr Rd, Rd, disp
4000 emitIns_R_R_R_I(INS_add, attr, ireg, reg, rg2, shift, INS_FLAGS_NOT_SET, INS_OPTS_LSL);
4001 emitIns_R_R_I(ins, attr, ireg, ireg, disp);
4007 assert(!"emitIns_R_ARX: Unexpected instruction");
4010 /*****************************************************************************
4012 * Record that a jump instruction uses the short encoding
4015 void emitter::emitSetShortJump(instrDescJmp* id)
4017 if (id->idjKeepLong)
4020 if (emitIsCondJump(id))
4022 id->idInsFmt(IF_T1_K);
4024 else if (emitIsCmpJump(id))
4026 // These are always only ever short!
4027 assert(id->idjShort);
4030 else if (emitIsUncondJump(id))
4032 id->idInsFmt(IF_T1_M);
4034 else if (emitIsLoadLabel(id))
4036 return; // Keep long - we don't know the alignment of the target
4040 assert(!"Unknown instruction in emitSetShortJump()");
4043 id->idjShort = true;
4046 if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
4048 printf("[8] Converting jump %u to short\n", id->idDebugOnlyInfo()->idNum);
4050 #endif // DEBUG_EMIT
4052 insSize isz = emitInsSize(id->idInsFmt());
4056 /*****************************************************************************
4058 * Record that a jump instruction uses the medium encoding
4061 void emitter::emitSetMediumJump(instrDescJmp* id)
4063 if (id->idjKeepLong)
4067 if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
4069 printf("[9] Converting jump %u to medium\n", id->idDebugOnlyInfo()->idNum);
4071 #endif // DEBUG_EMIT
4073 assert(emitIsCondJump(id));
4074 id->idInsFmt(IF_T2_J1);
4075 id->idjShort = false;
4077 insSize isz = emitInsSize(id->idInsFmt());
4081 /*****************************************************************************
4083 * Add a jmp instruction.
4084 * When dst is NULL, instrCount specifies number of instructions
4085 * to jump: positive is forward, negative is backward.
4086 * Unconditional branches have two sizes: short and long.
4087 * Conditional branches have three sizes: short, medium, and long. A long
4088 * branch is a pseudo-instruction that represents two instructions:
4089 * a short conditional branch to branch around a large unconditional
4090 * branch. Thus, we can handle branch offsets of imm24 instead of just imm20.
4093 void emitter::emitIns_J(instruction ins, BasicBlock* dst, int instrCount /* = 0 */)
4095 insFormat fmt = IF_NONE;
4099 assert(dst->bbFlags & BBF_JMP_TARGET);
4103 assert(instrCount != 0);
4106 /* Figure out the encoding format of the instruction */
4110 fmt = IF_T2_J2; /* Assume the jump will be long */
4127 fmt = IF_LARGEJMP; /* Assume the jump will be long */
4133 assert((fmt == IF_LARGEJMP) || (fmt == IF_T2_J2));
4135 instrDescJmp* id = emitNewInstrJmp();
4136 insSize isz = emitInsSize(fmt);
4143 // Mark the finally call
4144 if (ins == INS_b && emitComp->compCurBB->bbJumpKind == BBJ_CALLFINALLY)
4146 id->idDebugOnlyInfo()->idFinallyCall = true;
4150 /* Assume the jump will be long */
4155 id->idAddr()->iiaBBlabel = dst;
4156 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
4159 if (emitComp->opts.compLongAddress) // Force long branches
4160 id->idjKeepLong = 1;
4165 id->idAddr()->iiaSetInstrCount(instrCount);
4166 id->idjKeepLong = false;
4167 /* This jump must be short */
4168 emitSetShortJump(id);
4172 /* Record the jump's IG and offset within it */
4174 id->idjIG = emitCurIG;
4175 id->idjOffs = emitCurIGsize;
4177 /* Append this jump to this IG's jump list */
4179 id->idjNext = emitCurIGjmpList;
4180 emitCurIGjmpList = id;
4186 /* Figure out the max. size of the jump/call instruction */
4188 if (!id->idjKeepLong)
4190 insGroup* tgt = NULL;
4192 /* Can we guess at the jump distance? */
4196 tgt = (insGroup*)emitCodeGetCookie(dst);
4201 UNATIVE_OFFSET srcOffs;
4204 assert(JMP_SIZE_SMALL == JCC_SIZE_SMALL);
4206 /* This is a backward jump - figure out the distance */
4208 srcOffs = emitCurCodeOffset + emitCurIGsize;
4210 /* Compute the distance estimate */
4212 jmpDist = srcOffs - tgt->igOffs;
4213 assert(jmpDist >= 0);
4214 jmpDist += 4; // Adjustment for ARM PC
4219 if (JMP_DIST_SMALL_MAX_NEG <= -jmpDist)
4221 /* This jump surely will be short */
4222 emitSetShortJump(id);
4227 if (JCC_DIST_SMALL_MAX_NEG <= -jmpDist)
4229 /* This jump surely will be short */
4230 emitSetShortJump(id);
4232 else if (JCC_DIST_MEDIUM_MAX_NEG <= -jmpDist)
4234 /* This jump surely will be medium */
4235 emitSetMediumJump(id);
4250 /*****************************************************************************
4252 * Add a label instruction.
4255 void emitter::emitIns_R_L(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
4257 assert(dst->bbFlags & BBF_JMP_TARGET);
4259 insFormat fmt = IF_NONE;
4262 /* Figure out the encoding format of the instruction */
4266 id = emitNewInstrLbl();
4271 id = emitNewInstrJmp();
4277 assert((fmt == IF_T2_M1) || (fmt == IF_T2_N1));
4279 insSize isz = emitInsSize(fmt);
4287 // Mark the catch return
4288 if (emitComp->compCurBB->bbJumpKind == BBJ_EHCATCHRET)
4290 id->idDebugOnlyInfo()->idCatchRet = true;
4294 id->idAddr()->iiaBBlabel = dst;
4295 id->idjShort = false;
4300 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
4304 id->idjKeepLong = true;
4307 /* Record the jump's IG and offset within it */
4309 id->idjIG = emitCurIG;
4310 id->idjOffs = emitCurIGsize;
4312 /* Append this jump to this IG's jump list */
4314 id->idjNext = emitCurIGjmpList;
4315 emitCurIGjmpList = id;
4317 // Set the relocation flags - these give hint to zap to perform
4318 // relocation of the specified 32bit address.
4319 id->idSetRelocFlags(attr);
4329 /*****************************************************************************
4331 * Add a data label instruction.
4334 void emitter::emitIns_R_D(instruction ins, emitAttr attr, unsigned offs, regNumber reg)
4336 noway_assert((ins == INS_movw) || (ins == INS_movt));
4338 insFormat fmt = IF_T2_N2;
4339 instrDesc* id = emitNewInstrSC(attr, offs);
4340 insSize isz = emitInsSize(fmt);
4347 if (emitComp->opts.compReloc)
4349 // Set the relocation flags - these give hint to zap to perform
4350 // relocation of the specified 32bit address.
4351 id->idSetRelocFlags(attr);
4358 void emitter::emitIns_J_R(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
4360 assert(dst->bbFlags & BBF_JMP_TARGET);
4362 insFormat fmt = IF_NONE;
4372 assert(fmt == IF_T1_I);
4374 assert(isLowRegister(reg));
4376 instrDescJmp* id = emitNewInstrJmp();
4378 id->idInsFmt(IF_T1_I);
4379 id->idInsSize(emitInsSize(IF_T1_I));
4382 /* This jump better be short or-else! */
4383 id->idjShort = true;
4384 id->idAddr()->iiaBBlabel = dst;
4385 id->idjKeepLong = false;
4387 /* Record the jump's IG and offset within it */
4389 id->idjIG = emitCurIG;
4390 id->idjOffs = emitCurIGsize;
4392 /* Append this jump to this IG's jump list */
4394 id->idjNext = emitCurIGjmpList;
4395 emitCurIGjmpList = id;
4405 /*****************************************************************************
4407 * Add a call instruction (direct or indirect).
4408 * argSize<0 means that the caller will pop the arguments
4410 * The other arguments are interpreted depending on callType as shown:
4411 * Unless otherwise specified, ireg,xreg,xmul,disp should have default values.
4413 * EC_FUNC_TOKEN : addr is the method address
4414 * EC_FUNC_ADDR : addr is the absolute address of the function
4415 * if addr is NULL, it is a recursive call
4417 * If callType is one of these emitCallTypes, addr has to be NULL.
4418 * EC_INDIR_R : "call ireg".
4420 * For ARM xreg, xmul and disp are never used and should always be 0/REG_NA.
4422 * Please consult the "debugger team notification" comment in genFnProlog().
4425 void emitter::emitIns_Call(EmitCallType callType,
4426 CORINFO_METHOD_HANDLE methHnd, // used for pretty printing
4427 INDEBUG_LDISASM_COMMA(CORINFO_SIG_INFO* sigInfo) // used to report call sites to the EE
4431 VARSET_VALARG_TP ptrVars,
4432 regMaskTP gcrefRegs,
4433 regMaskTP byrefRegs,
4434 IL_OFFSETX ilOffset /* = BAD_IL_OFFSET */,
4435 regNumber ireg /* = REG_NA */,
4436 regNumber xreg /* = REG_NA */,
4437 unsigned xmul /* = 0 */,
4439 bool isJump /* = false */,
4440 bool isNoGC /* = false */,
4441 bool isProfLeaveCB /* = false */)
4443 /* Sanity check the arguments depending on callType */
4445 assert(callType < EC_COUNT);
4446 assert((callType != EC_FUNC_TOKEN && callType != EC_FUNC_ADDR) ||
4447 (ireg == REG_NA && xreg == REG_NA && xmul == 0 && disp == 0));
4448 assert(callType < EC_INDIR_R || addr == NULL);
4449 assert(callType != EC_INDIR_R || (ireg < REG_COUNT && xreg == REG_NA && xmul == 0 && disp == 0));
4451 // ARM never uses these
4452 assert(xreg == REG_NA && xmul == 0 && disp == 0);
4454 // Our stack level should be always greater than the bytes of arguments we push. Just
4456 assert((unsigned)abs(argSize) <= codeGen->genStackLevel);
4461 /* This is the saved set of registers after a normal call */
4462 regMaskTP savedSet = RBM_CALLEE_SAVED;
4464 /* some special helper calls have a different saved set registers */
4468 assert(emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
4470 // Get the set of registers that this call kills and remove it from the saved set.
4471 savedSet = RBM_ALLINT & ~emitComp->compNoGCHelperCallKillSet(Compiler::eeGetHelperNum(methHnd));
4473 // In case of Leave profiler callback, we need to preserve liveness of REG_PROFILER_RET_SCRATCH
4476 savedSet |= RBM_PROFILER_RET_SCRATCH;
4480 if (emitComp->verbose)
4482 printf("NOGC Call: savedSet=");
4483 printRegMaskInt(savedSet);
4484 emitDispRegSet(savedSet);
4491 assert(!emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
4494 /* Trim out any callee-trashed registers from the live set */
4496 gcrefRegs &= savedSet;
4497 byrefRegs &= savedSet;
4500 if (EMIT_GC_VERBOSE)
4502 printf("Call: GCvars=%s ", VarSetOps::ToString(emitComp, ptrVars));
4503 dumpConvertedVarSet(emitComp, ptrVars);
4504 printf(", gcrefRegs=");
4505 printRegMaskInt(gcrefRegs);
4506 emitDispRegSet(gcrefRegs);
4507 printf(", byrefRegs=");
4508 printRegMaskInt(byrefRegs);
4509 emitDispRegSet(byrefRegs);
4514 assert(argSize % (int)REGSIZE_BYTES == 0);
4515 argCnt = argSize / (int)REGSIZE_BYTES;
4517 /* Managed RetVal: emit sequence point for the call */
4518 if (emitComp->opts.compDbgInfo && ilOffset != BAD_IL_OFFSET)
4520 codeGen->genIPmappingAdd(ilOffset, false);
4524 We need to allocate the appropriate instruction descriptor based
4525 on whether this is a direct/indirect call, and whether we need to
4526 record an updated set of live GC variables.
4528 The stats for a ton of classes is as follows:
4530 Direct call w/o GC vars 220,216
4531 Indir. call w/o GC vars 144,781
4533 Direct call with GC vars 9,440
4534 Indir. call with GC vars 5,768
4537 if (callType >= EC_INDIR_R)
4539 /* Indirect call, virtual calls */
4541 assert(callType == EC_INDIR_R);
4543 id = emitNewInstrCallInd(argCnt, disp, ptrVars, gcrefRegs, byrefRegs, retSize);
4547 /* Helper/static/nonvirtual/function calls (direct or through handle),
4548 and calls to an absolute addr. */
4550 assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
4552 id = emitNewInstrCallDir(argCnt, ptrVars, gcrefRegs, byrefRegs, retSize);
4555 /* Update the emitter's live GC ref sets */
4557 VarSetOps::Assign(emitComp, emitThisGCrefVars, ptrVars);
4558 emitThisGCrefRegs = gcrefRegs;
4559 emitThisByrefRegs = byrefRegs;
4561 /* Set the instruction - special case jumping a function */
4563 insFormat fmt = IF_NONE;
4565 id->idSetIsNoGC(isNoGC);
4567 /* Record the address: method, indirection, or funcptr */
4569 if (callType > EC_FUNC_ADDR)
4571 /* This is an indirect call (either a virtual call or func ptr call) */
4575 case EC_INDIR_R: // the address is in a register
4577 id->idSetIsCallRegPtr();
4581 ins = INS_bx; // INS_bx Reg
4585 ins = INS_blx; // INS_blx Reg
4591 id->idInsSize(emitInsSize(fmt));
4593 assert(xreg == REG_NA);
4597 NO_WAY("unexpected instruction");
4603 /* This is a simple direct call: "call helper/method/addr" */
4605 assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
4607 // if addr is nullptr then this call is treated as a recursive call.
4608 assert(addr == nullptr || codeGen->arm_Valid_Imm_For_BL((ssize_t)addr));
4612 ins = INS_b; // INS_b imm24
4616 ins = INS_bl; // INS_bl imm24
4623 id->idInsSize(emitInsSize(fmt));
4625 id->idAddr()->iiaAddr = (BYTE*)addr;
4627 if (callType == EC_FUNC_ADDR)
4629 id->idSetIsCallAddr();
4632 if (emitComp->opts.compReloc)
4634 // Since this is an indirect call through a pointer and we don't
4635 // currently pass in emitAttr into this function we have decided
4636 // to always mark the displacement as being relocatable.
4638 id->idSetIsDspReloc();
4643 if (EMIT_GC_VERBOSE)
4645 if (id->idIsLargeCall())
4647 printf("[%02u] Rec call GC vars = %s\n", id->idDebugOnlyInfo()->idNum,
4648 VarSetOps::ToString(emitComp, ((instrDescCGCA*)id)->idcGCvars));
4652 id->idDebugOnlyInfo()->idMemCookie = (size_t)methHnd; // method token
4653 id->idDebugOnlyInfo()->idCallSig = sigInfo;
4657 if (addr != nullptr)
4659 codeGen->getDisAssembler().disSetMethod((size_t)addr, methHnd);
4661 #endif // LATE_DISASM
4667 /*****************************************************************************
4669 * Returns an encoding for the specified register (any-reg) to be used in
4670 * a Thumb-1 encoding in the M4 position
4673 inline unsigned insEncodeRegT1_M4(regNumber reg)
4675 assert(reg < REG_STK);
4680 /*****************************************************************************
4682 * Returns an encoding for the specified register (any-reg) to be used in
4683 * a Thumb-1 encoding in the D4 position
4686 inline unsigned insEncodeRegT1_D4(regNumber reg)
4688 assert(reg < REG_STK);
4690 return (reg & 0x7) | ((reg & 0x8) << 4);
4693 /*****************************************************************************
4695 * Returns an encoding for the specified register (low-only) to be used in
4696 * a Thumb-1 encoding in the M3 position
4699 inline unsigned insEncodeRegT1_M3(regNumber reg)
4701 assert(reg < REG_R8);
4706 /*****************************************************************************
4708 * Returns an encoding for the specified register (low-only) to be used in
4709 * a Thumb-1 encoding in the N3 position
4712 inline unsigned insEncodeRegT1_N3(regNumber reg)
4714 assert(reg < REG_R8);
4719 /*****************************************************************************
4721 * Returns an encoding for the specified register (low-only) to be used in
4722 * a Thumb-1 encoding in the D3 position
4725 inline unsigned insEncodeRegT1_D3(regNumber reg)
4727 assert(reg < REG_R8);
4731 /*****************************************************************************
4733 * Returns an encoding for the specified register (low-only) to be used in
4734 * a Thumb-1 encoding in the DI position
4737 inline unsigned insEncodeRegT1_DI(regNumber reg)
4739 assert(reg < REG_R8);
4744 /*****************************************************************************
4746 * Returns an encoding for the specified register to be used in
4747 * a Thumb-2 encoding in the N position
4750 inline unsigned insEncodeRegT2_N(regNumber reg)
4752 assert(reg < REG_STK);
4757 inline unsigned floatRegIndex(regNumber reg, int size)
4759 // theoretically this could support quad floats as well but for now...
4760 assert(size == EA_8BYTE || size == EA_4BYTE);
4762 if (size == EA_8BYTE)
4763 assert(emitter::isDoubleReg(reg));
4765 assert(emitter::isFloatReg(reg));
4767 unsigned result = reg - REG_F0;
4769 // the assumption here is that the register F8 also refers to D4
4770 if (size == EA_8BYTE)
4778 // variant: SOME arm VFP instructions use the convention that
4779 // for doubles, the split bit holds the msb of the register index
4780 // for singles it holds the lsb
4781 // excerpt : d = if dp_operation then UInt(D:Vd)
4782 // if single UInt(Vd:D);
4784 inline unsigned floatRegEncoding(unsigned index, int size, bool variant = false)
4786 if (!variant || size == EA_8BYTE)
4790 return ((index & 1) << 4) | (index >> 1);
4794 // thumb2 VFP M register encoding
4795 inline unsigned insEncodeRegT2_VectorM(regNumber reg, int size, bool variant)
4797 unsigned enc = floatRegIndex(reg, size);
4798 enc = floatRegEncoding(enc, size, variant);
4799 return ((enc & 0xf) << 0) | ((enc & 0x10) << 1);
4802 // thumb2 VFP N register encoding
4803 inline unsigned insEncodeRegT2_VectorN(regNumber reg, int size, bool variant)
4805 unsigned enc = floatRegIndex(reg, size);
4806 enc = floatRegEncoding(enc, size, variant);
4807 return ((enc & 0xf) << 16) | ((enc & 0x10) << 3);
4810 // thumb2 VFP D register encoding
4811 inline unsigned insEncodeRegT2_VectorD(regNumber reg, int size, bool variant)
4813 unsigned enc = floatRegIndex(reg, size);
4814 enc = floatRegEncoding(enc, size, variant);
4815 return ((enc & 0xf) << 12) | ((enc & 0x10) << 18);
4818 /*****************************************************************************
4820 * Returns an encoding for the specified register to be used in
4821 * a Thumb-2 encoding in the T position
4824 inline unsigned insEncodeRegT2_T(regNumber reg)
4826 assert(reg < REG_STK);
4831 /*****************************************************************************
4833 * Returns an encoding for the specified register to be used in
4834 * a Thumb-2 encoding in the D position
4837 inline unsigned insEncodeRegT2_D(regNumber reg)
4839 assert(reg < REG_STK);
4844 /*****************************************************************************
4846 * Returns an encoding for the specified register to be used in
4847 * a Thumb-2 encoding in the M position
4850 inline unsigned insEncodeRegT2_M(regNumber reg)
4852 assert(reg < REG_STK);
4857 /*****************************************************************************
4859 * Returns the encoding for the Set Flags bit to be used in a Thumb-2 encoding
4862 unsigned emitter::insEncodeSetFlags(insFlags sf)
4864 if (sf == INS_FLAGS_SET)
4870 /*****************************************************************************
4872 * Returns the encoding for the Shift Type bits to be used in a Thumb-2 encoding
4875 unsigned emitter::insEncodeShiftOpts(insOpts opt)
4877 if (opt == INS_OPTS_NONE)
4879 else if (opt == INS_OPTS_LSL)
4881 else if (opt == INS_OPTS_LSR)
4883 else if (opt == INS_OPTS_ASR)
4885 else if (opt == INS_OPTS_ROR)
4887 else if (opt == INS_OPTS_RRX)
4890 assert(!"Invalid insOpts");
4894 /*****************************************************************************
4896 * Returns the encoding for the PUW bits to be used in a T2_G0 Thumb-2 encoding
4899 unsigned emitter::insEncodePUW_G0(insOpts opt, int imm)
4901 unsigned result = 0;
4903 if (opt != INS_OPTS_LDST_POST_INC)
4904 result |= (1 << 24); // The P bit
4907 result |= (1 << 23); // The U bit
4909 if (opt != INS_OPTS_NONE)
4910 result |= (1 << 21); // The W bits
4914 /*****************************************************************************
4916 * Returns the encoding for the PUW bits to be used in a T2_H0 Thumb-2 encoding
4919 unsigned emitter::insEncodePUW_H0(insOpts opt, int imm)
4921 unsigned result = 0;
4923 if (opt != INS_OPTS_LDST_POST_INC)
4924 result |= (1 << 10); // The P bit
4927 result |= (1 << 9); // The U bit
4929 if (opt != INS_OPTS_NONE)
4930 result |= (1 << 8); // The W bits
4935 /*****************************************************************************
4937 * Returns the encoding for the Shift Count bits to be used in a Thumb-2 encoding
4940 inline unsigned insEncodeShiftCount(int imm)
4944 assert((imm & 0x001F) == imm);
4945 result = (imm & 0x03) << 6;
4946 result |= (imm & 0x1C) << 10;
4951 /*****************************************************************************
4953 * Returns the encoding for the immediate use by BFI/BFC Thumb-2 encodings
4956 inline unsigned insEncodeBitFieldImm(int imm)
4960 assert((imm & 0x03FF) == imm);
4961 result = (imm & 0x001f);
4962 result |= (imm & 0x0060) << 1;
4963 result |= (imm & 0x0380) << 5;
4968 /*****************************************************************************
4970 * Unscales the immediate based on the operand size in 'size'
4972 /*static*/ int emitter::insUnscaleImm(int imm, emitAttr size)
4978 assert((imm & 0x0003) == 0);
4983 assert((imm & 0x0001) == 0);
4992 assert(!"Invalid value in size");
4998 /*****************************************************************************
5000 * Emit a Thumb-1 instruction (a 16-bit integer as code)
5003 /*static*/ unsigned emitter::emitOutput_Thumb1Instr(BYTE* dst, code_t code)
5005 unsigned short word1 = code & 0xffff;
5006 assert(word1 == code);
5009 unsigned short top5bits = (word1 & 0xf800) >> 11;
5010 assert(top5bits < 29);
5013 MISALIGNED_WR_I2(dst, word1);
5015 return sizeof(short);
5017 /*****************************************************************************
5019 * Emit a Thumb-2 instruction (two 16-bit integers as code)
5022 /*static*/ unsigned emitter::emitOutput_Thumb2Instr(BYTE* dst, code_t code)
5024 unsigned short word1 = (code >> 16) & 0xffff;
5025 unsigned short word2 = (code)&0xffff;
5026 assert((code_t)((word1 << 16) | word2) == code);
5029 unsigned short top5bits = (word1 & 0xf800) >> 11;
5030 assert(top5bits >= 29);
5033 MISALIGNED_WR_I2(dst, word1);
5035 MISALIGNED_WR_I2(dst, word2);
5037 return sizeof(short) * 2;
5040 /*****************************************************************************
5042 * Output a local jump instruction.
5043 * Note that this may be invoked to overwrite an existing jump instruction at 'dst'
5044 * to handle forward branch patching.
5047 BYTE* emitter::emitOutputLJ(insGroup* ig, BYTE* dst, instrDesc* i)
5053 instrDescJmp* id = (instrDescJmp*)i;
5054 instruction ins = id->idIns();
5057 bool loadLabel = false;
5058 bool isJump = false;
5059 bool relAddr = true; // does the instruction use relative-addressing?
5066 sdistneg = JCC_DIST_SMALL_MAX_NEG;
5072 // One size fits all!
5078 sdistneg = LBL_DIST_SMALL_MAX_NEG;
5084 sdistneg = LBL_DIST_SMALL_MAX_NEG;
5090 /* Figure out the distance to the target */
5092 srcOffs = emitCurCodeOffs(dst);
5093 if (id->idAddr()->iiaHasInstrCount())
5096 int instrCount = id->idAddr()->iiaGetInstrCount();
5097 unsigned insNum = emitFindInsNum(ig, id);
5100 // Backward branches using instruction count must be within the same instruction group.
5101 assert(insNum + 1 >= (unsigned)(-instrCount));
5103 dstOffs = ig->igOffs + emitFindOffset(ig, (insNum + 1 + instrCount));
5107 dstOffs = id->idAddr()->iiaIGlabel->igOffs;
5114 // for adr, the distance is calculated from 4-byte aligned srcOffs.
5115 distVal = (ssize_t)((emitOffsetToPtr(dstOffs) - (BYTE*)(((size_t)emitOffsetToPtr(srcOffs)) & ~3)) + 1);
5119 distVal = (ssize_t)(emitOffsetToPtr(dstOffs) - emitOffsetToPtr(srcOffs));
5124 assert(ins == INS_movw || ins == INS_movt);
5125 distVal = (ssize_t)emitOffsetToPtr(dstOffs) + 1; // Or in thumb bit
5128 if (dstOffs <= srcOffs)
5130 /* This is a backward jump - distance is known at this point */
5133 if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
5135 size_t blkOffs = id->idjIG->igOffs;
5137 if (INTERESTING_JUMP_NUM == 0)
5138 printf("[3] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
5139 printf("[3] Jump block is at %08X - %02X = %08X\n", blkOffs, emitOffsAdj, blkOffs - emitOffsAdj);
5140 printf("[3] Jump is at %08X - %02X = %08X\n", srcOffs, emitOffsAdj, srcOffs - emitOffsAdj);
5141 printf("[3] Label block is at %08X - %02X = %08X\n", dstOffs, emitOffsAdj, dstOffs - emitOffsAdj);
5145 // This format only supports forward branches
5146 noway_assert(id->idInsFmt() != IF_T1_I);
5148 /* Can we use a short jump? */
5150 if (isJump && ((unsigned)(distVal - 4) >= (unsigned)sdistneg))
5152 emitSetShortJump(id);
5157 /* This is a forward jump - distance will be an upper limit */
5159 emitFwdJumps = true;
5161 /* The target offset will be closer by at least 'emitOffsAdj', but only if this
5162 jump doesn't cross the hot-cold boundary. */
5164 if (!emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
5166 dstOffs -= emitOffsAdj;
5167 distVal -= emitOffsAdj;
5170 /* Record the location of the jump for later patching */
5172 id->idjOffs = dstOffs;
5174 /* Are we overflowing the id->idjOffs bitfield? */
5175 if (id->idjOffs != dstOffs)
5176 IMPL_LIMITATION("Method is too large");
5179 if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
5181 size_t blkOffs = id->idjIG->igOffs;
5183 if (INTERESTING_JUMP_NUM == 0)
5184 printf("[4] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
5185 printf("[4] Jump block is at %08X\n", blkOffs);
5186 printf("[4] Jump is at %08X\n", srcOffs);
5187 printf("[4] Label block is at %08X - %02X = %08X\n", dstOffs + emitOffsAdj, emitOffsAdj, dstOffs);
5192 /* Adjust the offset to emit relative to the end of the instruction */
5198 if (0 && emitComp->verbose)
5200 size_t sz = 4; // Thumb-2 pretends all instructions are 4-bytes long for computing jump offsets?
5201 int distValSize = id->idjShort ? 4 : 8;
5202 printf("; %s jump [%08X/%03u] from %0*X to %0*X: dist = %08XH\n", (dstOffs <= srcOffs) ? "Fwd" : "Bwd",
5203 dspPtr(id), id->idDebugOnlyInfo()->idNum, distValSize, srcOffs + sz, distValSize, dstOffs, distVal);
5207 insFormat fmt = id->idInsFmt();
5211 /* What size jump should we use? */
5217 assert(!id->idjKeepLong);
5218 assert(emitJumpCrossHotColdBoundary(srcOffs, dstOffs) == false);
5220 assert(JMP_SIZE_SMALL == JCC_SIZE_SMALL);
5221 assert(JMP_SIZE_SMALL == 2);
5223 /* For forward jumps, record the address of the distance value */
5224 id->idjTemp.idjAddr = (distVal > 0) ? dst : NULL;
5226 dst = emitOutputShortBranch(dst, ins, fmt, distVal, id);
5232 /* For forward jumps, record the address of the distance value */
5233 id->idjTemp.idjAddr = (dstOffs > srcOffs) ? dst : NULL;
5235 if (fmt == IF_LARGEJMP)
5237 // This is a pseudo-instruction format representing a large conditional branch, to allow
5238 // us to get a greater branch target range than we can get by using a straightforward conditional
5239 // branch. It is encoded as a short conditional branch that branches around a long unconditional
5242 // Conceptually, we have:
5246 // The code we emit is:
5248 // b<!cond> L_not // 2 bytes. Note that we reverse the condition.
5249 // b L_target // 4 bytes
5252 // Note that we don't actually insert any blocks: we simply encode "b <!cond> L_not" as a branch with
5253 // the correct offset. Note also that this works for both integer and floating-point conditions, because
5254 // the condition inversion takes ordered/unordered into account, preserving NaN behavior. For example,
5255 // "GT" (greater than) is inverted to "LE" (less than, equal, or unordered).
5257 // History: previously, we generated:
5260 // but the "it" instruction was deprecated, so we can't use it.
5262 dst = emitOutputShortBranch(dst,
5263 emitJumpKindToIns(emitReverseJumpKind(
5264 emitInsToJumpKind(ins))), // reverse the conditional instruction
5266 6 - 4, /* 6 bytes from start of this large conditional pseudo-instruction to
5267 L_not. Jumps are encoded as offset from instr address + 4. */
5268 NULL /* only used for cbz/cbnz */);
5270 // Now, pretend we've got a normal unconditional branch, and fall through to the code to emit that.
5274 // The distVal was computed based on the beginning of the pseudo-instruction, which is
5275 // the IT. So subtract the size of the IT from the offset, so it is relative to the
5276 // unconditional branch.
5280 code = emitInsCode(ins, fmt);
5282 if (fmt == IF_T2_J1)
5284 // Can't use this form for jumps between the hot and cold regions
5285 assert(!id->idjKeepLong);
5286 assert(emitJumpCrossHotColdBoundary(srcOffs, dstOffs) == false);
5288 assert((distVal & 1) == 0);
5289 assert(distVal >= -1048576);
5290 assert(distVal <= 1048574);
5294 code |= ((distVal >> 1) & 0x0007ff);
5295 code |= (((distVal >> 1) & 0x01f800) << 5);
5296 code |= (((distVal >> 1) & 0x020000) >> 4);
5297 code |= (((distVal >> 1) & 0x040000) >> 7);
5299 else if (fmt == IF_T2_J2)
5301 assert((distVal & 1) == 0);
5302 if (emitComp->opts.compReloc && emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
5304 // dst isn't an actual final target location, just some intermediate
5305 // location. Thus we cannot make any guarantees about distVal (not
5306 // even the direction/sign). Instead we don't encode any offset and
5307 // rely on the relocation to do all the work
5311 assert(distVal >= CALL_DIST_MAX_NEG);
5312 assert(distVal <= CALL_DIST_MAX_POS);
5316 code |= ((distVal >> 1) & 0x0007ff);
5317 code |= (((distVal >> 1) & 0x1ff800) << 5);
5319 bool S = (distVal < 0);
5320 bool I1 = ((distVal & 0x00800000) == 0);
5321 bool I2 = ((distVal & 0x00400000) == 0);
5324 code |= (1 << 13); // J1 bit
5326 code |= (1 << 11); // J2 bit
5331 assert(!"Unknown fmt");
5334 unsigned instrSize = emitOutput_Thumb2Instr(dst, code);
5336 if (emitComp->opts.compReloc)
5338 if (emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
5340 assert(id->idjKeepLong);
5341 if (emitComp->info.compMatchedVM)
5343 void* target = emitOffsetToPtr(dstOffs);
5344 emitRecordRelocation((void*)dst, target, IMAGE_REL_BASED_THUMB_BRANCH24);
5354 /* For forward jumps, record the address of the distance value */
5355 id->idjTemp.idjAddr = (distVal > 0) ? dst : NULL;
5357 code = emitInsCode(ins, fmt);
5359 if (fmt == IF_T1_J3)
5361 assert((dstOffs & 3) == 0); // The target label must be 4-byte aligned
5362 assert(distVal >= 0);
5363 assert(distVal <= 1022);
5364 code |= ((distVal >> 2) & 0xff);
5366 dst += emitOutput_Thumb1Instr(dst, code);
5368 else if (fmt == IF_T2_M1)
5370 assert(distVal >= -4095);
5371 assert(distVal <= +4095);
5374 code |= 0x00A0 << 16;
5377 assert((distVal & 0x0fff) == distVal);
5378 code |= (distVal & 0x00ff);
5379 code |= ((distVal & 0x0700) << 4);
5381 code |= ((distVal & 0x0800) << 15);
5382 code |= id->idReg1() << 8;
5384 dst += emitOutput_Thumb2Instr(dst, code);
5386 else if (fmt == IF_T2_N1)
5388 code |= insEncodeRegT2_D(id->idReg1());
5389 unsigned imm = distVal;
5390 if (ins == INS_movw)
5396 imm = (imm >> 16) & 0xffff;
5398 ((instrDescJmp*)id)->idjTemp.idjAddr = (dstOffs > srcOffs) ? dst : NULL;
5400 assert((imm & 0x0000ffff) == imm);
5401 code |= (imm & 0x00ff);
5402 code |= ((imm & 0x0700) << 4);
5403 code |= ((imm & 0x0800) << 15);
5404 code |= ((imm & 0xf000) << 4);
5405 dst += emitOutput_Thumb2Instr(dst, code);
5407 if (id->idIsCnsReloc() || id->idIsDspReloc())
5409 assert(ins == INS_movt || ins == INS_movw);
5410 if ((ins == INS_movt) && emitComp->info.compMatchedVM)
5411 emitHandlePCRelativeMov32((void*)(dst - 8), (void*)distVal);
5416 assert(!"Unknown fmt");
5423 /*****************************************************************************
5425 * Output a short branch instruction.
5428 BYTE* emitter::emitOutputShortBranch(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, instrDescJmp* id)
5432 code = emitInsCode(ins, fmt);
5436 assert((distVal & 1) == 0);
5437 assert(distVal >= -256);
5438 assert(distVal <= 254);
5442 code |= ((distVal >> 1) & 0x7f);
5444 else if (fmt == IF_T1_M)
5446 assert((distVal & 1) == 0);
5447 assert(distVal >= -2048);
5448 assert(distVal <= 2046);
5452 code |= ((distVal >> 1) & 0x3ff);
5454 else if (fmt == IF_T1_I)
5457 assert(ins == INS_cbz || INS_cbnz);
5458 assert((distVal & 1) == 0);
5459 assert(distVal >= 0);
5460 assert(distVal <= 126);
5462 code |= ((distVal << 3) & 0x0200);
5463 code |= ((distVal << 2) & 0x00F8);
5464 code |= (id->idReg1() & 0x0007);
5468 assert(!"Unknown fmt");
5471 dst += emitOutput_Thumb1Instr(dst, code);
5476 #ifdef FEATURE_ITINSTRUCTION
5478 /*****************************************************************************
5479 * The "IT" instruction is deprecated (with a very few exceptions). Don't generate it!
5480 * Don't delete this code, though, in case we ever want to bring it back.
5481 *****************************************************************************/
5483 /*****************************************************************************
5485 * Output an IT instruction.
5488 BYTE* emitter::emitOutputIT(BYTE* dst, instruction ins, insFormat fmt, code_t condcode)
5491 code_t code, mask, bit;
5493 code = emitInsCode(ins, fmt);
5494 code |= (condcode << 4); // encode firstcond
5495 imm0 = condcode & 1; // this is firstcond[0]
5496 mask = code & 0x0f; // initialize mask encoded in opcode
5497 bit = 0x08; // where in mask we are encoding
5498 while ((mask & (bit - 1)) != 0) // are the remaining bits all zeros?
5499 { // then we are done
5500 // otherwise determine the setting of bit
5501 if ((imm0 == 1) ^ ((bit & mask) != 0))
5503 code |= bit; // set the current bit
5507 code &= ~bit; // clear the current bit
5511 dst += emitOutput_Thumb1Instr(dst, code);
5516 #endif // FEATURE_ITINSTRUCTION
5518 /*****************************************************************************
5520 * Output a 32-bit nop instruction.
5523 BYTE* emitter::emitOutputNOP(BYTE* dst, instruction ins, insFormat fmt)
5525 code_t code = emitInsCode(ins, fmt);
5527 dst += emitOutput_Thumb2Instr(dst, code);
5532 /*****************************************************************************
5534 * Append the machine code corresponding to the given instruction descriptor
5535 * to the code block at '*dp'; the base of the code block is 'bp', and 'ig'
5536 * is the instruction group that contains the instruction. Updates '*dp' to
5537 * point past the generated code, and returns the size of the instruction
5538 * descriptor in bytes.
5541 size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
5547 instruction ins = id->idIns();
5548 insFormat fmt = id->idInsFmt();
5549 emitAttr size = id->idOpSize();
5550 unsigned char callInstrSize = 0;
5554 bool dspOffs = emitComp->opts.dspGCtbls || !emitComp->opts.disDiffable;
5557 assert(REG_NA == (int)REG_NA);
5559 VARSET_TP GCvars(VarSetOps::UninitVal());
5561 /* What instruction format have we got? */
5570 regMaskTP gcrefRegs;
5571 regMaskTP byrefRegs;
5573 case IF_T1_A: // T1_A ................
5574 sz = SMALL_IDSC_SIZE;
5575 code = emitInsCode(ins, fmt);
5576 dst += emitOutput_Thumb1Instr(dst, code);
5579 #ifdef FEATURE_ITINSTRUCTION
5580 case IF_T1_B: // T1_B ........cccc.... cond
5581 assert(id->idGCref() == GCT_NONE);
5582 condcode = emitGetInsSC(id);
5583 dst = emitOutputIT(dst, ins, fmt, condcode);
5584 sz = SMALL_IDSC_SIZE;
5586 #endif // FEATURE_ITINSTRUCTION
5588 case IF_T1_C: // T1_C .....iiiiinnnddd R1 R2 imm5
5589 sz = SMALL_IDSC_SIZE;
5590 imm = emitGetInsSC(id);
5591 code = emitInsCode(ins, fmt);
5592 code |= insEncodeRegT1_D3(id->idReg1());
5593 code |= insEncodeRegT1_N3(id->idReg2());
5594 if (emitInsIsLoadOrStore(ins))
5596 imm = insUnscaleImm(imm, size);
5598 assert((imm & 0x001f) == imm);
5600 dst += emitOutput_Thumb1Instr(dst, code);
5603 case IF_T1_D0: // T1_D0 ........Dmmmmddd R1* R2*
5604 sz = SMALL_IDSC_SIZE;
5605 code = emitInsCode(ins, fmt);
5606 code |= insEncodeRegT1_D4(id->idReg1());
5607 code |= insEncodeRegT1_M4(id->idReg2());
5608 dst += emitOutput_Thumb1Instr(dst, code);
5611 case IF_T1_E: // T1_E ..........nnnddd R1 R2
5612 sz = SMALL_IDSC_SIZE;
5613 code = emitInsCode(ins, fmt);
5614 code |= insEncodeRegT1_D3(id->idReg1());
5615 code |= insEncodeRegT1_N3(id->idReg2());
5616 dst += emitOutput_Thumb1Instr(dst, code);
5619 case IF_T1_F: // T1_F .........iiiiiii SP imm7
5620 sz = emitGetInstrDescSize(id);
5621 imm = emitGetInsSC(id);
5622 code = emitInsCode(ins, fmt);
5623 imm = insUnscaleImm(imm, size);
5624 assert((imm & 0x007F) == imm);
5626 dst += emitOutput_Thumb1Instr(dst, code);
5629 case IF_T1_G: // T1_G .......iiinnnddd R1 R2 imm3
5630 sz = SMALL_IDSC_SIZE;
5631 imm = emitGetInsSC(id);
5632 code = emitInsCode(ins, fmt);
5633 code |= insEncodeRegT1_D3(id->idReg1());
5634 code |= insEncodeRegT1_N3(id->idReg2());
5635 assert((imm & 0x0007) == imm);
5637 dst += emitOutput_Thumb1Instr(dst, code);
5640 case IF_T1_H: // T1_H .......mmmnnnddd R1 R2 R3
5641 sz = emitGetInstrDescSize(id);
5642 code = emitInsCode(ins, fmt);
5643 code |= insEncodeRegT1_D3(id->idReg1());
5644 code |= insEncodeRegT1_N3(id->idReg2());
5645 code |= insEncodeRegT1_M3(id->idReg3());
5646 dst += emitOutput_Thumb1Instr(dst, code);
5649 case IF_T1_I: // T1_I ......i.iiiiiddd R1 imm6
5650 assert(id->idIsBound());
5652 dst = emitOutputLJ(ig, dst, id);
5653 sz = sizeof(instrDescJmp);
5656 case IF_T1_J0: // T1_J0 .....dddiiiiiiii R1 imm8
5657 case IF_T1_J1: // T1_J1 .....dddiiiiiiii R1 <regmask8>
5658 case IF_T1_J2: // T1_J2 .....dddiiiiiiii R1 SP imm8
5659 sz = emitGetInstrDescSize(id);
5660 imm = emitGetInsSC(id);
5661 code = emitInsCode(ins, fmt);
5662 code |= insEncodeRegT1_DI(id->idReg1());
5663 if (fmt == IF_T1_J2)
5665 imm = insUnscaleImm(imm, size);
5667 assert((imm & 0x00ff) == imm);
5669 dst += emitOutput_Thumb1Instr(dst, code);
5672 case IF_T1_L0: // T1_L0 ........iiiiiiii imm8
5673 case IF_T1_L1: // T1_L1 .......Rrrrrrrrr <regmask8>
5674 sz = emitGetInstrDescSize(id);
5675 imm = emitGetInsSC(id);
5676 code = emitInsCode(ins, fmt);
5677 if (fmt == IF_T1_L1)
5679 assert((imm & 0x3) != 0x3);
5681 code |= 0x0100; // R bit
5684 assert((imm & 0x00ff) == imm);
5686 dst += emitOutput_Thumb1Instr(dst, code);
5689 case IF_T2_A: // T2_A ................ ................
5690 sz = SMALL_IDSC_SIZE;
5691 code = emitInsCode(ins, fmt);
5692 dst += emitOutput_Thumb2Instr(dst, code);
5695 case IF_T2_B: // T2_B ................ ............iiii imm4
5696 sz = SMALL_IDSC_SIZE;
5697 imm = emitGetInsSC(id);
5698 code = emitInsCode(ins, fmt);
5699 assert((imm & 0x000F) == imm);
5701 dst += emitOutput_Thumb2Instr(dst, code);
5704 case IF_T2_C0: // T2_C0 ...........Snnnn .iiiddddiishmmmm R1 R2 R3 S, imm5, sh
5705 case IF_T2_C4: // T2_C4 ...........Snnnn ....dddd....mmmm R1 R2 R3 S
5706 case IF_T2_C5: // T2_C5 ............nnnn ....dddd....mmmm R1 R2 R3
5707 sz = emitGetInstrDescSize(id);
5708 code = emitInsCode(ins, fmt);
5709 code |= insEncodeRegT2_D(id->idReg1());
5710 code |= insEncodeRegT2_N(id->idReg2());
5711 code |= insEncodeRegT2_M(id->idReg3());
5712 if (fmt != IF_T2_C5)
5713 code |= insEncodeSetFlags(id->idInsFlags());
5714 if (fmt == IF_T2_C0)
5716 imm = emitGetInsSC(id);
5717 code |= insEncodeShiftCount(imm);
5718 code |= insEncodeShiftOpts(id->idInsOpt());
5720 dst += emitOutput_Thumb2Instr(dst, code);
5723 case IF_T2_C1: // T2_C1 ...........S.... .iiiddddiishmmmm R1 R2 S, imm5, sh
5724 case IF_T2_C2: // T2_C2 ...........S.... .iiiddddii..mmmm R1 R2 S, imm5
5725 case IF_T2_C6: // T2_C6 ................ ....dddd..iimmmm R1 R2 imm2
5726 sz = SMALL_IDSC_SIZE;
5727 imm = emitGetInsSC(id);
5728 code = emitInsCode(ins, fmt);
5729 code |= insEncodeRegT2_D(id->idReg1());
5730 code |= insEncodeRegT2_M(id->idReg2());
5731 if (fmt == IF_T2_C6)
5733 assert((imm & 0x0018) == imm);
5738 code |= insEncodeSetFlags(id->idInsFlags());
5739 code |= insEncodeShiftCount(imm);
5740 if (fmt == IF_T2_C1)
5741 code |= insEncodeShiftOpts(id->idInsOpt());
5743 dst += emitOutput_Thumb2Instr(dst, code);
5746 case IF_T2_C3: // T2_C3 ...........S.... ....dddd....mmmm R1 R2 S
5747 sz = SMALL_IDSC_SIZE;
5748 code = emitInsCode(ins, fmt);
5749 code |= insEncodeRegT2_D(id->idReg1());
5750 code |= insEncodeRegT2_M(id->idReg2());
5751 code |= insEncodeSetFlags(id->idInsFlags());
5752 dst += emitOutput_Thumb2Instr(dst, code);
5755 case IF_T2_C7: // T2_C7 ............nnnn ..........shmmmm R1 R2 imm2
5756 case IF_T2_C8: // T2_C8 ............nnnn .iii....iishmmmm R1 R2 imm5, sh
5757 sz = SMALL_IDSC_SIZE;
5758 imm = emitGetInsSC(id);
5759 code = emitInsCode(ins, fmt);
5760 code |= insEncodeRegT2_N(id->idReg1());
5761 code |= insEncodeRegT2_M(id->idReg2());
5762 if (fmt == IF_T2_C7)
5764 assert((imm & 0x0003) == imm);
5767 else if (fmt == IF_T2_C8)
5769 code |= insEncodeShiftCount(imm);
5770 code |= insEncodeShiftOpts(id->idInsOpt());
5772 dst += emitOutput_Thumb2Instr(dst, code);
5775 case IF_T2_C9: // T2_C9 ............nnnn ............mmmm R1 R2
5776 sz = SMALL_IDSC_SIZE;
5777 code = emitInsCode(ins, fmt);
5778 code |= insEncodeRegT2_N(id->idReg1());
5779 code |= insEncodeRegT2_M(id->idReg2());
5780 dst += emitOutput_Thumb2Instr(dst, code);
5783 case IF_T2_C10: // T2_C10 ............mmmm ....dddd....mmmm R1 R2
5784 sz = SMALL_IDSC_SIZE;
5785 code = emitInsCode(ins, fmt);
5786 code |= insEncodeRegT2_D(id->idReg1());
5787 code |= insEncodeRegT2_M(id->idReg2());
5788 code |= insEncodeRegT2_N(id->idReg2());
5789 dst += emitOutput_Thumb2Instr(dst, code);
5792 case IF_T2_D0: // T2_D0 ............nnnn .iiiddddii.wwwww R1 R2 imm5, imm5
5793 case IF_T2_D1: // T2_D1 ................ .iiiddddii.wwwww R1 imm5, imm5
5794 sz = SMALL_IDSC_SIZE;
5795 imm = emitGetInsSC(id);
5796 code = emitInsCode(ins, fmt);
5797 code |= insEncodeRegT2_D(id->idReg1());
5798 if (fmt == IF_T2_D0)
5799 code |= insEncodeRegT2_N(id->idReg2());
5800 code |= insEncodeBitFieldImm(imm);
5801 dst += emitOutput_Thumb2Instr(dst, code);
5804 case IF_T2_E0: // T2_E0 ............nnnn tttt......shmmmm R1 R2 R3 imm2
5805 case IF_T2_E1: // T2_E1 ............nnnn tttt............ R1 R2
5806 case IF_T2_E2: // T2_E2 ................ tttt............ R1
5807 code = emitInsCode(ins, fmt);
5808 code |= insEncodeRegT2_T(id->idReg1());
5809 if (fmt == IF_T2_E0)
5811 sz = emitGetInstrDescSize(id);
5812 code |= insEncodeRegT2_N(id->idReg2());
5813 if (id->idIsLclVar())
5815 code |= insEncodeRegT2_M(codeGen->rsGetRsvdReg());
5820 code |= insEncodeRegT2_M(id->idReg3());
5821 imm = emitGetInsSC(id);
5822 assert((imm & 0x0003) == imm);
5828 sz = SMALL_IDSC_SIZE;
5829 if (fmt != IF_T2_E2)
5831 code |= insEncodeRegT2_N(id->idReg2());
5834 dst += emitOutput_Thumb2Instr(dst, code);
5837 case IF_T2_F1: // T2_F1 ............nnnn ttttdddd....mmmm R1 R2 R3 R4
5838 sz = emitGetInstrDescSize(id);
5840 code = emitInsCode(ins, fmt);
5841 code |= insEncodeRegT2_T(id->idReg1());
5842 code |= insEncodeRegT2_D(id->idReg2());
5843 code |= insEncodeRegT2_N(id->idReg3());
5844 code |= insEncodeRegT2_M(id->idReg4());
5845 dst += emitOutput_Thumb2Instr(dst, code);
5848 case IF_T2_F2: // T2_F2 ............nnnn aaaadddd....mmmm R1 R2 R3 R4
5849 sz = emitGetInstrDescSize(id);
5850 code = emitInsCode(ins, fmt);
5851 code |= insEncodeRegT2_D(id->idReg1());
5852 code |= insEncodeRegT2_N(id->idReg2());
5853 code |= insEncodeRegT2_M(id->idReg3());
5854 code |= insEncodeRegT2_T(id->idReg4());
5855 dst += emitOutput_Thumb2Instr(dst, code);
5858 case IF_T2_G0: // T2_G0 .......PU.W.nnnn ttttTTTTiiiiiiii R1 R2 R3 imm8, PUW
5859 case IF_T2_G1: // T2_G1 ............nnnn ttttTTTT........ R1 R2 R3
5860 code = emitInsCode(ins, fmt);
5861 code |= insEncodeRegT2_T(id->idReg1());
5862 code |= insEncodeRegT2_D(id->idReg2());
5863 code |= insEncodeRegT2_N(id->idReg3());
5864 if (fmt == IF_T2_G0)
5866 sz = emitGetInstrDescSizeSC(id);
5867 imm = emitGetInsSC(id);
5868 assert(unsigned_abs(imm) <= 0x00ff);
5870 code |= insEncodePUW_G0(id->idInsOpt(), imm);
5874 sz = emitGetInstrDescSize(id);
5876 dst += emitOutput_Thumb2Instr(dst, code);
5879 case IF_T2_H0: // T2_H0 ............nnnn tttt.PUWiiiiiiii R1 R2 imm8, PUW
5880 case IF_T2_H1: // T2_H1 ............nnnn tttt....iiiiiiii R1 R2 imm8
5881 case IF_T2_H2: // T2_H2 ............nnnn ........iiiiiiii R1 imm8
5882 sz = emitGetInstrDescSizeSC(id);
5883 imm = emitGetInsSC(id);
5884 code = emitInsCode(ins, fmt);
5885 code |= insEncodeRegT2_T(id->idReg1());
5887 if (fmt != IF_T2_H2)
5888 code |= insEncodeRegT2_N(id->idReg2());
5890 if (fmt == IF_T2_H0)
5892 assert(unsigned_abs(imm) <= 0x00ff);
5893 code |= insEncodePUW_H0(id->idInsOpt(), imm);
5894 code |= unsigned_abs(imm);
5898 assert((imm & 0x00ff) == imm);
5901 dst += emitOutput_Thumb2Instr(dst, code);
5904 case IF_T2_I0: // T2_I0 ..........W.nnnn rrrrrrrrrrrrrrrr R1 W, imm16
5905 case IF_T2_I1: // T2_I1 ................ rrrrrrrrrrrrrrrr imm16
5906 sz = emitGetInstrDescSizeSC(id);
5907 code = emitInsCode(ins, fmt);
5908 if (fmt == IF_T2_I0)
5910 code |= insEncodeRegT2_N(id->idReg1());
5911 code |= (1 << 21); // W bit
5913 imm = emitGetInsSC(id);
5914 assert((imm & 0x3) != 0x3);
5916 code |= 0x8000; // PC bit
5918 code |= 0x4000; // LR bit
5920 assert(imm <= 0x1fff); // 13 bits
5922 dst += emitOutput_Thumb2Instr(dst, code);
5925 case IF_T2_K1: // T2_K1 ............nnnn ttttiiiiiiiiiiii R1 R2 imm12
5926 case IF_T2_K4: // T2_K4 ........U....... ttttiiiiiiiiiiii R1 PC U, imm12
5927 case IF_T2_K3: // T2_K3 ........U....... ....iiiiiiiiiiii PC U, imm12
5928 sz = emitGetInstrDescSize(id);
5929 imm = emitGetInsSC(id);
5930 code = emitInsCode(ins, fmt);
5931 if (fmt != IF_T2_K3)
5933 code |= insEncodeRegT2_T(id->idReg1());
5935 if (fmt == IF_T2_K1)
5937 code |= insEncodeRegT2_N(id->idReg2());
5938 assert(imm <= 0xfff); // 12 bits
5943 assert(unsigned_abs(imm) <= 0xfff); // 12 bits (signed)
5946 code |= (1 << 23); // U bit
5948 dst += emitOutput_Thumb2Instr(dst, code);
5951 case IF_T2_K2: // T2_K2 ............nnnn ....iiiiiiiiiiii R1 imm12
5952 sz = emitGetInstrDescSizeSC(id);
5953 imm = emitGetInsSC(id);
5954 code = emitInsCode(ins, fmt);
5955 code |= insEncodeRegT2_N(id->idReg1());
5956 assert(imm <= 0xfff); // 12 bits
5958 dst += emitOutput_Thumb2Instr(dst, code);
5961 case IF_T2_L0: // T2_L0 .....i.....Snnnn .iiiddddiiiiiiii R1 R2 S, imm8<<imm4
5962 case IF_T2_L1: // T2_L1 .....i.....S.... .iiiddddiiiiiiii R1 S, imm8<<imm4
5963 case IF_T2_L2: // T2_L2 .....i......nnnn .iii....iiiiiiii R1 imm8<<imm4
5964 sz = emitGetInstrDescSize(id);
5965 imm = emitGetInsSC(id);
5966 code = emitInsCode(ins, fmt);
5968 if (fmt == IF_T2_L2)
5969 code |= insEncodeRegT2_N(id->idReg1());
5972 code |= insEncodeSetFlags(id->idInsFlags());
5973 code |= insEncodeRegT2_D(id->idReg1());
5974 if (fmt == IF_T2_L0)
5975 code |= insEncodeRegT2_N(id->idReg2());
5977 assert(isModImmConst(imm)); // Funky ARM imm encoding
5978 imm = encodeModImmConst(imm);
5979 assert(imm <= 0xfff); // 12 bits
5980 code |= (imm & 0x00ff);
5981 code |= (imm & 0x0700) << 4;
5982 code |= (imm & 0x0800) << 15;
5983 dst += emitOutput_Thumb2Instr(dst, code);
5986 case IF_T2_M0: // T2_M0 .....i......nnnn .iiiddddiiiiiiii R1 R2 imm12
5987 sz = emitGetInstrDescSizeSC(id);
5988 imm = emitGetInsSC(id);
5989 code = emitInsCode(ins, fmt);
5990 code |= insEncodeRegT2_D(id->idReg1());
5991 if (fmt == IF_T2_M0)
5992 code |= insEncodeRegT2_N(id->idReg2());
5993 imm = emitGetInsSC(id);
5994 assert(imm <= 0xfff); // 12 bits
5995 code |= (imm & 0x00ff);
5996 code |= (imm & 0x0700) << 4;
5997 code |= (imm & 0x0800) << 15;
5998 dst += emitOutput_Thumb2Instr(dst, code);
6001 case IF_T2_N: // T2_N .....i......iiii .iiiddddiiiiiiii R1 imm16
6002 case IF_T2_N2: // T2_N2 .....i......iiii .iiiddddiiiiiiii R1 imm16
6003 sz = emitGetInstrDescSizeSC(id);
6004 code = emitInsCode(ins, fmt);
6005 code |= insEncodeRegT2_D(id->idReg1());
6006 imm = emitGetInsSC(id);
6007 if (fmt == IF_T2_N2)
6009 assert(!id->idIsLclVar());
6010 assert((ins == INS_movw) || (ins == INS_movt));
6011 imm += (size_t)emitConsBlock;
6012 if (!id->idIsCnsReloc() && !id->idIsDspReloc())
6017 else if (id->idIsLclVar())
6020 if (ins == INS_movw)
6026 imm = (imm >> 16) & 0xffff;
6030 if (id->idIsCnsReloc() || id->idIsDspReloc())
6032 assert((ins == INS_movt) || (ins == INS_movw));
6033 dst += emitOutput_Thumb2Instr(dst, code);
6034 if ((ins == INS_movt) && emitComp->info.compMatchedVM)
6035 emitHandlePCRelativeMov32((void*)(dst - 8), (void*)imm);
6039 assert((imm & 0x0000ffff) == imm);
6040 code |= (imm & 0x00ff);
6041 code |= ((imm & 0x0700) << 4);
6042 code |= ((imm & 0x0800) << 15);
6043 code |= ((imm & 0xf000) << 4);
6044 dst += emitOutput_Thumb2Instr(dst, code);
6049 // these are the binary operators
6051 sz = emitGetInstrDescSize(id);
6052 code = emitInsCode(ins, fmt);
6053 code |= insEncodeRegT2_VectorN(id->idReg2(), size, true);
6054 code |= insEncodeRegT2_VectorM(id->idReg3(), size, true);
6055 code |= insEncodeRegT2_VectorD(id->idReg1(), size, true);
6056 if (size == EA_8BYTE)
6058 dst += emitOutput_Thumb2Instr(dst, code);
6088 if (id->idOpSize() == EA_8BYTE)
6093 srcSize = dstSize = id->idOpSize();
6097 sz = emitGetInstrDescSize(id);
6098 code = emitInsCode(ins, fmt);
6100 code |= insEncodeRegT2_VectorD(id->idReg1(), dstSize, true);
6101 code |= insEncodeRegT2_VectorM(id->idReg2(), srcSize, true);
6103 dst += emitOutput_Thumb2Instr(dst, code);
6108 sz = emitGetInstrDescSizeSC(id);
6109 code = emitInsCode(ins, fmt);
6110 code |= insEncodeRegT2_N(id->idReg2());
6111 code |= insEncodeRegT2_VectorD(id->idReg1(), size, true);
6113 imm = emitGetInsSC(id);
6115 imm = -imm; // bit 23 at 0 means negate
6117 code |= 1 << 23; // set the positive bit
6119 // offset is +/- 1020
6121 assert(imm >> 10 == 0);
6123 // bit 8 is set for doubles
6124 if (id->idOpSize() == EA_8BYTE)
6126 dst += emitOutput_Thumb2Instr(dst, code);
6130 // 3op assemble a double from two int regs (or back)
6131 sz = emitGetInstrDescSize(id);
6132 code = emitInsCode(ins, fmt);
6133 if (ins == INS_vmov_i2d)
6135 code |= insEncodeRegT2_VectorM(id->idReg1(), size, true);
6136 code |= id->idReg2() << 12;
6137 code |= id->idReg3() << 16;
6141 assert(ins == INS_vmov_d2i);
6142 code |= id->idReg1() << 12;
6143 code |= id->idReg2() << 16;
6144 code |= insEncodeRegT2_VectorM(id->idReg3(), size, true);
6146 dst += emitOutput_Thumb2Instr(dst, code);
6150 // 2op assemble a float from one int reg (or back)
6151 sz = emitGetInstrDescSize(id);
6152 code = emitInsCode(ins, fmt);
6153 if (ins == INS_vmov_f2i)
6155 code |= insEncodeRegT2_VectorN(id->idReg2(), EA_4BYTE, true);
6156 code |= id->idReg1() << 12;
6160 assert(ins == INS_vmov_i2f);
6161 code |= insEncodeRegT2_VectorN(id->idReg1(), EA_4BYTE, true);
6162 code |= id->idReg2() << 12;
6165 dst += emitOutput_Thumb2Instr(dst, code);
6168 case IF_T1_J3: // T1_J3 .....dddiiiiiiii R1 PC imm8
6169 case IF_T2_M1: // T2_M1 .....i.......... .iiiddddiiiiiiii R1 PC imm12
6170 assert(id->idGCref() == GCT_NONE);
6171 assert(id->idIsBound());
6173 dst = emitOutputLJ(ig, dst, id);
6174 sz = sizeof(instrDescLbl);
6177 case IF_T1_K: // T1_K ....cccciiiiiiii Branch imm8, cond4
6178 case IF_T1_M: // T1_M .....iiiiiiiiiii Branch imm11
6179 case IF_T2_J1: // T2_J1 .....Scccciiiiii ..j.jiiiiiiiiiii Branch imm20, cond4
6180 case IF_T2_J2: // T2_J2 .....Siiiiiiiiii ..j.jiiiiiiiiii. Branch imm24
6181 case IF_T2_N1: // T2_N .....i......iiii .iiiddddiiiiiiii R1 imm16
6183 assert(id->idGCref() == GCT_NONE);
6184 assert(id->idIsBound());
6186 dst = emitOutputLJ(ig, dst, id);
6187 sz = sizeof(instrDescJmp);
6190 case IF_T1_D1: // T1_D1 .........mmmm... R1*
6192 code = emitInsCode(ins, fmt);
6193 code |= insEncodeRegT1_M4(id->idReg1());
6194 dst += emitOutput_Thumb1Instr(dst, code);
6195 sz = SMALL_IDSC_SIZE;
6198 case IF_T1_D2: // T1_D2 .........mmmm... R3*
6200 /* Is this a "fat" call descriptor? */
6202 if (id->idIsLargeCall())
6204 instrDescCGCA* idCall = (instrDescCGCA*)id;
6205 gcrefRegs = idCall->idcGcrefRegs;
6206 byrefRegs = idCall->idcByrefRegs;
6207 VarSetOps::Assign(emitComp, GCvars, idCall->idcGCvars);
6208 sz = sizeof(instrDescCGCA);
6212 assert(!id->idIsLargeDsp());
6213 assert(!id->idIsLargeCns());
6215 gcrefRegs = emitDecodeCallGCregs(id);
6217 VarSetOps::AssignNoCopy(emitComp, GCvars, VarSetOps::MakeEmpty(emitComp));
6218 sz = sizeof(instrDesc);
6221 code = emitInsCode(ins, fmt);
6222 code |= insEncodeRegT1_M4(id->idReg3());
6223 callInstrSize = SafeCvtAssert<unsigned char>(emitOutput_Thumb1Instr(dst, code));
6224 dst += callInstrSize;
6227 case IF_T2_J3: // T2_J3 .....Siiiiiiiiii ..j.jiiiiiiiiii. Call imm24
6229 /* Is this a "fat" call descriptor? */
6231 if (id->idIsLargeCall())
6233 instrDescCGCA* idCall = (instrDescCGCA*)id;
6234 gcrefRegs = idCall->idcGcrefRegs;
6235 byrefRegs = idCall->idcByrefRegs;
6236 VarSetOps::Assign(emitComp, GCvars, idCall->idcGCvars);
6237 sz = sizeof(instrDescCGCA);
6241 assert(!id->idIsLargeDsp());
6242 assert(!id->idIsLargeCns());
6244 gcrefRegs = emitDecodeCallGCregs(id);
6246 VarSetOps::AssignNoCopy(emitComp, GCvars, VarSetOps::MakeEmpty(emitComp));
6247 sz = sizeof(instrDesc);
6250 if (id->idAddr()->iiaAddr == NULL) /* a recursive call */
6252 addr = emitCodeBlock;
6256 addr = id->idAddr()->iiaAddr;
6258 code = emitInsCode(ins, fmt);
6260 if (id->idIsDspReloc())
6262 callInstrSize = SafeCvtAssert<unsigned char>(emitOutput_Thumb2Instr(dst, code));
6263 dst += callInstrSize;
6264 if (emitComp->info.compMatchedVM)
6265 emitRecordRelocation((void*)(dst - 4), addr, IMAGE_REL_BASED_THUMB_BRANCH24);
6269 addr = (BYTE*)((size_t)addr & ~1); // Clear the lowest bit from target address
6271 /* Calculate PC relative displacement */
6272 int disp = addr - (dst + 4);
6273 bool S = (disp < 0);
6274 bool I1 = ((disp & 0x00800000) == 0);
6275 bool I2 = ((disp & 0x00400000) == 0);
6278 code |= (1 << 26); // S bit
6280 code |= (1 << 13); // J1 bit
6282 code |= (1 << 11); // J2 bit
6284 int immLo = (disp & 0x00000ffe) >> 1;
6285 int immHi = (disp & 0x003ff000) >> 12;
6287 code |= (immHi << 16);
6291 assert((disp & 0x00fffffe) == disp);
6293 callInstrSize = SafeCvtAssert<unsigned char>(emitOutput_Thumb2Instr(dst, code));
6294 dst += callInstrSize;
6299 /* We update the GC info before the call as the variables cannot be
6300 used by the call. Killing variables before the call helps with
6301 boundary conditions if the call is CORINFO_HELP_THROW - see bug 50029.
6302 If we ever track aliased variables (which could be used by the
6303 call), we would have to keep them alive past the call. */
6305 emitUpdateLiveGCvars(GCvars, *dp);
6307 // If the method returns a GC ref, mark R0 appropriately.
6308 if (id->idGCref() == GCT_GCREF)
6309 gcrefRegs |= RBM_R0;
6310 else if (id->idGCref() == GCT_BYREF)
6311 byrefRegs |= RBM_R0;
6313 // If the GC register set has changed, report the new set.
6314 if (gcrefRegs != emitThisGCrefRegs)
6315 emitUpdateLiveGCregs(GCT_GCREF, gcrefRegs, dst);
6317 if (byrefRegs != emitThisByrefRegs)
6318 emitUpdateLiveGCregs(GCT_BYREF, byrefRegs, dst);
6320 // Some helper calls may be marked as not requiring GC info to be recorded.
6321 if ((!id->idIsNoGC()))
6323 // On ARM, as on AMD64, we don't change the stack pointer to push/pop args.
6324 // So we're not really doing a "stack pop" here (note that "args" is 0), but we use this mechanism
6325 // to record the call for GC info purposes. (It might be best to use an alternate call,
6326 // and protect "emitStackPop" under the EMIT_TRACK_STACK_DEPTH preprocessor variable.)
6327 emitStackPop(dst, /*isCall*/ true, callInstrSize, /*args*/ 0);
6329 /* Do we need to record a call location for GC purposes? */
6331 if (!emitFullGCinfo)
6333 emitRecordGCcall(dst, callInstrSize);
6339 /********************************************************************/
6341 /********************************************************************/
6346 printf("unexpected format %s\n", emitIfName(id->idInsFmt()));
6347 assert(!"don't know how to encode this instruction");
6352 // Determine if any registers now hold GC refs, or whether a register that was overwritten held a GC ref.
6353 // We assume here that "id->idGCref()" is not GC_NONE only if the instruction described by "id" writes a
6354 // GC ref to register "id->idReg1()". (It may, apparently, also not be GC_NONE in other cases, such as
6355 // for stores, but we ignore those cases here.)
6356 if (emitInsMayWriteToGCReg(id)) // True if "id->idIns()" writes to a register than can hold GC ref.
6358 // If we ever generate instructions that write to multiple registers (LDM, or POP),
6359 // then we'd need to more work here to ensure that changes in the status of GC refs are
6360 // tracked properly.
6361 if (emitInsMayWriteMultipleRegs(id))
6363 // We explicitly list the multiple-destination-target instruction that we expect to
6364 // be emitted outside of the prolog and epilog here.
6372 // For each of these, idReg1() and idReg2() are the destination registers.
6373 emitGCregDeadUpd(id->idReg1(), dst);
6374 emitGCregDeadUpd(id->idReg2(), dst);
6377 assert(false); // We need to recognize this multi-target instruction...
6382 if (id->idGCref() != GCT_NONE)
6384 emitGCregLiveUpd(id->idGCref(), id->idReg1(), dst);
6388 // I also assume that "idReg1" is the destination register of all instructions that write to registers.
6389 emitGCregDeadUpd(id->idReg1(), dst);
6394 // Now we determine if the instruction has written to a (local variable) stack location, and either written a GC
6395 // ref or overwritten one.
6396 if (emitInsWritesToLclVarStackLoc(id))
6398 int varNum = id->idAddr()->iiaLclVar.lvaVarNum();
6399 unsigned ofs = AlignDown(id->idAddr()->iiaLclVar.lvaOffset(), TARGET_POINTER_SIZE);
6401 int adr = emitComp->lvaFrameAddress(varNum, true, ®Base, ofs);
6402 if (id->idGCref() != GCT_NONE)
6404 emitGCvarLiveUpd(adr + ofs, varNum, id->idGCref(), dst);
6408 // If the type of the local is a gc ref type, update the liveness.
6412 // "Regular" (non-spill-temp) local.
6413 vt = var_types(emitComp->lvaTable[varNum].lvType);
6417 TempDsc* tmpDsc = emitComp->tmpFindNum(varNum);
6418 vt = tmpDsc->tdTempType();
6420 if (vt == TYP_REF || vt == TYP_BYREF)
6421 emitGCvarDeadUpd(adr + ofs, dst);
6426 /* Make sure we set the instruction descriptor size correctly */
6428 size_t expected = emitSizeOfInsDsc(id);
6429 assert(sz == expected);
6431 if (emitComp->opts.disAsm || emitComp->opts.dspEmit || emitComp->verbose)
6433 emitDispIns(id, false, dspOffs, true, emitCurCodeOffs(odst), *dp, (dst - *dp), ig);
6436 if (emitComp->compDebugBreak)
6438 // set JitEmitPrintRefRegs=1 will print out emitThisGCrefRegs and emitThisByrefRegs
6439 // at the beginning of this method.
6440 if (JitConfig.JitEmitPrintRefRegs() != 0)
6442 printf("Before emitOutputInstr for id->idDebugOnlyInfo()->idNum=0x%02x\n", id->idDebugOnlyInfo()->idNum);
6443 printf(" emitThisGCrefRegs(0x%p)=", dspPtr(&emitThisGCrefRegs));
6444 printRegMaskInt(emitThisGCrefRegs);
6445 emitDispRegSet(emitThisGCrefRegs);
6447 printf(" emitThisByrefRegs(0x%p)=", dspPtr(&emitThisByrefRegs));
6448 printRegMaskInt(emitThisByrefRegs);
6449 emitDispRegSet(emitThisByrefRegs);
6453 // For example, set JitBreakEmitOutputInstr=a6 will break when this method is called for
6454 // emitting instruction a6, (i.e. IN00a6 in jitdump).
6455 if ((unsigned)JitConfig.JitBreakEmitOutputInstr() == id->idDebugOnlyInfo()->idNum)
6457 assert(!"JitBreakEmitOutputInstr reached");
6462 /* All instructions are expected to generate code */
6471 /*****************************************************************************/
6472 /*****************************************************************************/
6476 static bool insAlwaysSetFlags(instruction ins)
6478 bool result = false;
6494 /*****************************************************************************
6496 * Display the instruction name, optionally the instruction
6497 * can add the "s" suffix if it must set the flags.
6499 void emitter::emitDispInst(instruction ins, insFlags flags)
6501 const char* insstr = codeGen->genInsName(ins);
6502 int len = strlen(insstr);
6504 /* Display the instruction name */
6506 printf("%s", insstr);
6507 if (insSetsFlags(flags) && !insAlwaysSetFlags(ins))
6514 // Add at least one space after the instruction name
6515 // and add spaces until we have reach the normal size of 8
6523 /*****************************************************************************
6525 * Display an reloc value
6526 * If we are formatting for an assembly listing don't print the hex value
6527 * since it will prevent us from doing assembly diffs
6529 void emitter::emitDispReloc(int value, bool addComma)
6531 if (emitComp->opts.disAsm)
6537 printf("(reloc 0x%x)", dspPtr(value));
6544 #define STRICT_ARM_ASM 0
6546 /*****************************************************************************
6548 * Display an immediate value
6550 void emitter::emitDispImm(int imm, bool addComma, bool alwaysHex /* =false */)
6552 if (!alwaysHex && (imm > -1000) && (imm < 1000))
6554 else if ((imm > 0) ||
6555 (imm == -imm) || // -0x80000000 == 0x80000000. So we don't want to add an extra "-" at the beginning.
6556 (emitComp->opts.disDiffable && (imm == 0xD1FFAB1E))) // Don't display this as negative
6557 printf("0x%02x", imm);
6558 else // val <= -1000
6559 printf("-0x%02x", -imm);
6565 /*****************************************************************************
6567 * Display an arm condition for the IT instructions
6569 void emitter::emitDispCond(int cond)
6571 const static char* armCond[16] = {"eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc",
6572 "hi", "ls", "ge", "lt", "gt", "le", "AL", "NV"}; // The last two are invalid
6573 assert(0 <= cond && (unsigned)cond < ArrLen(armCond));
6574 printf(armCond[cond]);
6577 /*****************************************************************************
6579 * Display a register range in a range format
6581 void emitter::emitDispRegRange(regNumber reg, int len, emitAttr attr)
6584 emitDispReg(reg, attr, false);
6588 emitDispReg((regNumber)(reg + len - 1), attr, false);
6593 /*****************************************************************************
6595 * Display an register mask in a list format
6597 void emitter::emitDispRegmask(int imm, bool encodedPC_LR)
6599 bool printedOne = false;
6605 hasPC = (imm & 2) != 0;
6606 hasLR = (imm & 1) != 0;
6611 hasPC = (imm & RBM_PC) != 0;
6612 hasLR = (imm & RBM_LR) != 0;
6613 imm &= ~(RBM_PC | RBM_LR);
6616 regNumber reg = REG_R0;
6626 printf("%s", emitRegName(reg));
6631 reg = regNumber(reg + 1);
6639 printf("%s", emitRegName(REG_LR));
6647 printf("%s", emitRegName(REG_PC));
6653 /*****************************************************************************
6655 * Returns the encoding for the Shift Type bits to be used in a Thumb-2 encoding
6658 void emitter::emitDispShiftOpts(insOpts opt)
6660 if (opt == INS_OPTS_LSL)
6662 else if (opt == INS_OPTS_LSR)
6664 else if (opt == INS_OPTS_ASR)
6666 else if (opt == INS_OPTS_ROR)
6668 else if (opt == INS_OPTS_RRX)
6672 /*****************************************************************************
6674 * Display a register
6676 void emitter::emitDispReg(regNumber reg, emitAttr attr, bool addComma)
6678 if (isFloatReg(reg))
6680 const char* size = attr == EA_8BYTE ? "d" : "s";
6681 printf("%s%s", size, emitFloatRegName(reg, attr) + 1);
6685 printf("%s", emitRegName(reg, attr));
6692 void emitter::emitDispFloatReg(regNumber reg, emitAttr attr, bool addComma)
6696 /*****************************************************************************
6698 * Display an addressing operand [reg]
6700 void emitter::emitDispAddrR(regNumber reg, emitAttr attr)
6703 emitDispReg(reg, attr, false);
6708 /*****************************************************************************
6710 * Display an addressing operand [reg + imm]
6712 void emitter::emitDispAddrRI(regNumber reg, int imm, emitAttr attr)
6714 bool regIsSPorFP = (reg == REG_SP) || (reg == REG_FP);
6717 emitDispReg(reg, attr, false);
6728 emitDispImm(imm, false, regIsSPorFP);
6734 /*****************************************************************************
6736 * Display an addressing operand [reg + reg]
6738 void emitter::emitDispAddrRR(regNumber reg1, regNumber reg2, emitAttr attr)
6741 emitDispReg(reg1, attr, false);
6747 emitDispReg(reg2, attr, false);
6752 /*****************************************************************************
6754 * Display an addressing operand [reg + reg * imm]
6756 void emitter::emitDispAddrRRI(regNumber reg1, regNumber reg2, int imm, emitAttr attr)
6759 emitDispReg(reg1, attr, false);
6762 emitDispReg(reg2, attr, false);
6766 emitDispImm(1 << imm, false);
6772 emitDispImm(1 << imm, false);
6775 emitDispReg(reg2, attr, false);
6781 /*****************************************************************************
6783 * Display an addressing operand [reg + imm]
6785 void emitter::emitDispAddrPUW(regNumber reg, int imm, insOpts opt, emitAttr attr)
6787 bool regIsSPorFP = (reg == REG_SP) || (reg == REG_FP);
6790 emitDispReg(reg, attr, false);
6791 if (insOptAnyInc(opt))
6804 emitDispImm(imm, false, regIsSPorFP);
6811 /*****************************************************************************
6813 * Display the gc-ness of the operand
6815 void emitter::emitDispGC(emitAttr attr)
6818 // TODO-ARM-Cleanup: Fix or delete.
6819 if (attr == EA_GCREF)
6821 else if (attr == EA_BYREF)
6826 /*****************************************************************************
6828 * Display (optionally) the instruction encoding in hex
6831 void emitter::emitDispInsHex(BYTE* code, size_t sz)
6833 // We do not display the instruction hex if we want diff-able disassembly
6834 if (!emitComp->opts.disDiffable)
6838 printf(" %04X ", (*((unsigned short*)code)));
6842 printf(" %04X %04X", (*((unsigned short*)(code + 0))), (*((unsigned short*)(code + 2))));
6847 /****************************************************************************
6849 * Display the given instruction.
6852 void emitter::emitDispInsHelp(
6853 instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* code, size_t sz, insGroup* ig)
6857 unsigned idNum = id->idDebugOnlyInfo()->idNum; // Do not remove this! It is needed for VisualStudio
6858 // conditional breakpoints
6860 printf("IN%04x: ", idNum);
6866 if (!emitComp->opts.dspEmit && !isNew && !asmfm && sz)
6869 /* Display the instruction offset */
6871 emitDispInsOffs(offset, doffs);
6873 /* Display the instruction hex code */
6875 emitDispInsHex(code, sz);
6879 /* Get the instruction and format */
6881 instruction ins = id->idIns();
6882 insFormat fmt = id->idInsFmt();
6884 emitDispInst(ins, id->idInsFlags());
6886 /* If this instruction has just been added, check its size */
6888 assert(isNew == false || (int)emitSizeOfInsDsc(id) == emitCurIGfreeNext - (BYTE*)id);
6890 /* Figure out the operand size */
6892 if (id->idGCref() == GCT_GCREF)
6894 else if (id->idGCref() == GCT_BYREF)
6897 attr = id->idOpSize();
6903 const char* methodName;
6905 case IF_T1_A: // None
6909 case IF_T1_L0: // Imm
6911 emitDispImm(emitGetInsSC(id), false);
6914 case IF_T1_B: // <cond>
6915 emitDispCond(emitGetInsSC(id));
6918 case IF_T1_L1: // <regmask8>
6919 case IF_T2_I1: // <regmask16>
6920 emitDispRegmask(emitGetInsSC(id), true);
6923 case IF_T2_E2: // Reg
6924 if (id->idIns() == INS_vmrs)
6926 if (id->idReg1() != REG_R15)
6928 emitDispReg(id->idReg1(), attr, true);
6933 printf("APSR, FPSCR");
6938 emitDispReg(id->idReg1(), attr, false);
6943 emitDispReg(id->idReg1(), attr, false);
6947 emitDispReg(id->idReg3(), attr, false);
6949 CORINFO_METHOD_HANDLE handle = (CORINFO_METHOD_HANDLE)id->idDebugOnlyInfo()->idMemCookie;
6952 methodName = emitComp->eeGetMethodFullName(handle);
6953 printf("\t\t// %s", methodName);
6958 case IF_T1_F: // SP, Imm
6959 emitDispReg(REG_SP, attr, true);
6960 emitDispImm(emitGetInsSC(id), false);
6963 case IF_T1_J0: // Reg, Imm
6967 emitDispReg(id->idReg1(), attr, true);
6968 imm = emitGetInsSC(id);
6971 if (emitComp->opts.disDiffable)
6973 if (id->idIsCnsReloc() || id->idIsDspReloc())
6975 if (emitComp->opts.disDiffable)
6977 printf("%s RELOC ", (id->idIns() == INS_movw) ? "LOW" : "HIGH");
6980 emitDispImm(imm, false, (fmt == IF_T2_N));
6984 emitDispReg(id->idReg1(), attr, true);
6985 imm = emitGetInsSC(id);
6987 dataSection* jdsc = 0;
6988 NATIVE_OFFSET offs = 0;
6990 /* Find the appropriate entry in the data section list */
6992 for (jdsc = emitConsDsc.dsdList; jdsc; jdsc = jdsc->dsNext)
6994 UNATIVE_OFFSET size = jdsc->dsSize;
6996 /* Is this a label table? */
6998 if (jdsc->dsType == dataSection::blockAbsoluteAddr)
7007 assert(jdsc != NULL);
7009 if (id->idIsDspReloc())
7013 printf("%s ADDRESS J_M%03u_DS%02u", (id->idIns() == INS_movw) ? "LOW" : "HIGH",
7014 Compiler::s_compMethodsCount, imm);
7016 // After the MOVT, dump the table
7017 if (id->idIns() == INS_movt)
7019 unsigned cnt = jdsc->dsSize / TARGET_POINTER_SIZE;
7020 BasicBlock** bbp = (BasicBlock**)jdsc->dsCont;
7022 bool isBound = (emitCodeGetCookie(*bbp) != NULL);
7026 printf("\n\n J_M%03u_DS%02u LABEL DWORD", Compiler::s_compMethodsCount, imm);
7028 /* Display the label table (it's stored as "BasicBlock*" values) */
7034 /* Convert the BasicBlock* value to an IG address */
7036 lab = (insGroup*)emitCodeGetCookie(*bbp++);
7039 printf("\n DD G_M%03u_IG%02u", Compiler::s_compMethodsCount, lab->igNum);
7046 case IF_T2_H2: // [Reg+imm]
7048 emitDispAddrRI(id->idReg1(), emitGetInsSC(id), attr);
7051 case IF_T2_K3: // [PC+imm]
7052 emitDispAddrRI(REG_PC, emitGetInsSC(id), attr);
7055 case IF_T1_J1: // reg, <regmask8>
7056 case IF_T2_I0: // reg, <regmask16>
7057 emitDispReg(id->idReg1(), attr, false);
7059 emitDispRegmask(emitGetInsSC(id), false);
7062 case IF_T1_D0: // Reg, Reg
7067 emitDispReg(id->idReg1(), attr, true);
7068 emitDispReg(id->idReg2(), attr, false);
7069 if (fmt == IF_T1_E && id->idIns() == INS_rsb)
7075 case IF_T2_E1: // Reg, [Reg]
7076 emitDispReg(id->idReg1(), attr, true);
7077 emitDispAddrR(id->idReg2(), attr);
7080 case IF_T2_D1: // Reg, Imm, Imm
7081 emitDispReg(id->idReg1(), attr, true);
7082 imm = emitGetInsSC(id);
7084 int lsb = (imm >> 5) & 0x1f;
7085 int msb = imm & 0x1f;
7087 int imm2 = msb + 1 - lsb;
7088 emitDispImm(imm1, true);
7089 emitDispImm(imm2, false);
7093 case IF_T1_C: // Reg, Reg, Imm
7100 emitDispReg(id->idReg1(), attr, true);
7101 imm = emitGetInsSC(id);
7102 if (emitInsIsLoadOrStore(ins))
7104 emitDispAddrRI(id->idReg2(), imm, attr);
7108 emitDispReg(id->idReg2(), attr, true);
7109 emitDispImm(imm, false);
7114 emitDispReg(id->idReg1(), attr, true);
7115 imm = emitGetInsSC(id);
7116 if (emitInsIsLoadOrStore(ins))
7118 emitDispAddrRI(REG_SP, imm, attr);
7122 emitDispReg(REG_SP, attr, true);
7123 emitDispImm(imm, false);
7128 emitDispReg(id->idReg1(), attr, true);
7129 emitDispAddrRI(REG_PC, emitGetInsSC(id), attr);
7134 emitDispReg(id->idReg1(), attr, true);
7135 emitDispReg(id->idReg2(), attr, false);
7136 imm = emitGetInsSC(id);
7137 if (id->idInsOpt() == INS_OPTS_RRX)
7139 emitDispShiftOpts(id->idInsOpt());
7144 emitDispShiftOpts(id->idInsOpt());
7145 emitDispImm(imm, false);
7150 imm = emitGetInsSC(id);
7151 emitDispReg(id->idReg1(), attr, true);
7152 emitDispReg(id->idReg2(), attr, (imm != 0));
7155 emitDispImm(imm, false);
7160 emitDispAddrRRI(id->idReg1(), id->idReg2(), emitGetInsSC(id), attr);
7164 emitDispReg(id->idReg1(), attr, true);
7165 emitDispAddrPUW(id->idReg2(), emitGetInsSC(id), id->idInsOpt(), attr);
7168 case IF_T1_H: // Reg, Reg, Reg
7169 emitDispReg(id->idReg1(), attr, true);
7170 if (emitInsIsLoadOrStore(ins))
7172 emitDispAddrRR(id->idReg2(), id->idReg3(), attr);
7176 emitDispReg(id->idReg2(), attr, true);
7177 emitDispReg(id->idReg3(), attr, false);
7183 emitDispReg(id->idReg1(), attr, true);
7184 emitDispReg(id->idReg2(), attr, true);
7185 emitDispReg(id->idReg3(), attr, false);
7189 emitDispReg(id->idReg1(), attr, true);
7190 emitDispReg(id->idReg2(), attr, true);
7191 emitDispReg(id->idReg3(), attr, false);
7195 switch (id->idIns())
7200 emitDispReg(id->idReg1(), EA_4BYTE, true);
7201 emitDispReg(id->idReg2(), EA_8BYTE, false);
7207 emitDispReg(id->idReg1(), EA_8BYTE, true);
7208 emitDispReg(id->idReg2(), EA_4BYTE, false);
7211 // we just use the type on the instruction
7212 // unless it is an asymmetrical one like the converts
7214 emitDispReg(id->idReg1(), attr, true);
7215 emitDispReg(id->idReg2(), attr, false);
7221 imm = emitGetInsSC(id);
7222 switch (id->idIns())
7226 emitDispReg(id->idReg1(), attr, true);
7227 emitDispAddrPUW(id->idReg2(), imm, id->idInsOpt(), attr);
7232 emitDispReg(id->idReg2(), attr, false);
7233 if (insOptAnyInc(id->idInsOpt()))
7236 emitDispRegRange(id->idReg1(), abs(imm) >> 2, attr);
7241 emitDispRegRange(id->idReg1(), abs(imm) >> 2, attr);
7250 switch (id->idIns())
7253 emitDispReg(id->idReg1(), attr, true); // EA_8BYTE
7254 emitDispReg(id->idReg2(), EA_4BYTE, true);
7255 emitDispReg(id->idReg3(), EA_4BYTE, false);
7258 emitDispReg(id->idReg1(), EA_4BYTE, true);
7259 emitDispReg(id->idReg2(), EA_4BYTE, true);
7260 emitDispReg(id->idReg3(), attr, false); // EA_8BYTE
7268 emitDispReg(id->idReg1(), attr, true);
7269 emitDispReg(id->idReg2(), attr, false);
7273 emitDispReg(id->idReg1(), attr, true);
7274 emitDispAddrRR(id->idReg2(), id->idReg3(), attr);
7277 case IF_T2_D0: // Reg, Reg, Imm, Imm
7278 emitDispReg(id->idReg1(), attr, true);
7279 emitDispReg(id->idReg2(), attr, true);
7280 imm = emitGetInsSC(id);
7283 int lsb = (imm >> 5) & 0x1f;
7284 int msb = imm & 0x1f;
7286 int imm2 = msb + 1 - lsb;
7287 emitDispImm(imm1, true);
7288 emitDispImm(imm2, false);
7292 int lsb = (imm >> 5) & 0x1f;
7293 int widthm1 = imm & 0x1f;
7295 int imm2 = widthm1 + 1;
7296 emitDispImm(imm1, true);
7297 emitDispImm(imm2, false);
7301 case IF_T2_C0: // Reg, Reg, Reg, Imm
7302 emitDispReg(id->idReg1(), attr, true);
7303 emitDispReg(id->idReg2(), attr, true);
7304 emitDispReg(id->idReg3(), attr, false);
7305 imm = emitGetInsSC(id);
7306 if (id->idInsOpt() == INS_OPTS_RRX)
7308 emitDispShiftOpts(id->idInsOpt());
7313 emitDispShiftOpts(id->idInsOpt());
7314 emitDispImm(imm, false);
7319 emitDispReg(id->idReg1(), attr, true);
7320 if (id->idIsLclVar())
7322 emitDispAddrRRI(id->idReg2(), codeGen->rsGetRsvdReg(), 0, attr);
7326 emitDispAddrRRI(id->idReg2(), id->idReg3(), emitGetInsSC(id), attr);
7331 emitDispReg(id->idReg1(), attr, true);
7332 emitDispReg(id->idReg2(), attr, true);
7333 emitDispAddrPUW(id->idReg3(), emitGetInsSC(id), id->idInsOpt(), attr);
7336 case IF_T2_F1: // Reg, Reg, Reg, Reg
7338 emitDispReg(id->idReg1(), attr, true);
7339 emitDispReg(id->idReg2(), attr, true);
7340 emitDispReg(id->idReg3(), attr, true);
7341 emitDispReg(id->idReg4(), attr, false);
7345 case IF_T2_M1: // Load Label
7346 emitDispReg(id->idReg1(), attr, true);
7347 if (id->idIsBound())
7348 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
7350 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
7353 case IF_T1_I: // Special Compare-and-branch
7354 emitDispReg(id->idReg1(), attr, true);
7357 case IF_T1_K: // Special Branch, conditional
7359 assert(((instrDescJmp*)id)->idjShort);
7364 if (fmt == IF_T2_N1)
7366 emitDispReg(id->idReg1(), attr, true);
7367 printf("%s ADDRESS ", (id->idIns() == INS_movw) ? "LOW" : "HIGH");
7375 if (id->idAddr()->iiaHasInstrCount())
7377 int instrCount = id->idAddr()->iiaGetInstrCount();
7381 printf("pc%s%d instructions", (instrCount >= 0) ? "+" : "", instrCount);
7385 unsigned insNum = emitFindInsNum(ig, id);
7386 UNATIVE_OFFSET srcOffs = ig->igOffs + emitFindOffset(ig, insNum + 1);
7387 UNATIVE_OFFSET dstOffs = ig->igOffs + emitFindOffset(ig, insNum + 1 + instrCount);
7388 ssize_t relOffs = (ssize_t)(emitOffsetToPtr(dstOffs) - emitOffsetToPtr(srcOffs));
7389 printf("pc%s%d (%d instructions)", (relOffs >= 0) ? "+" : "", relOffs, instrCount);
7392 else if (id->idIsBound())
7393 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
7395 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
7400 if (id->idIsCallAddr())
7402 offs = (ssize_t)id->idAddr()->iiaAddr;
7408 methodName = emitComp->eeGetMethodFullName((CORINFO_METHOD_HANDLE)id->idDebugOnlyInfo()->idMemCookie);
7413 if (id->idIsDspReloc())
7415 printf("%08X", offs);
7419 printf("%s", methodName);
7425 printf("unexpected format %s", emitIfName(id->idInsFmt()));
7426 assert(!"unexpectedFormat");
7430 if (id->idDebugOnlyInfo()->idVarRefOffs)
7433 emitDispFrameRef(id->idAddr()->iiaLclVar.lvaVarNum(), id->idAddr()->iiaLclVar.lvaOffset(),
7434 id->idDebugOnlyInfo()->idVarRefOffs, asmfm);
7440 void emitter::emitDispIns(
7441 instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* code, size_t sz, insGroup* ig)
7443 insFormat fmt = id->idInsFmt();
7445 /* Special-case IF_LARGEJMP */
7447 if ((fmt == IF_LARGEJMP) && id->idIsBound())
7449 // This is a pseudo-instruction format representing a large conditional branch. See the comment
7450 // in emitter::emitOutputLJ() for the full description.
7452 // For this pseudo-instruction, we will actually generate:
7454 // b<!cond> L_not // 2 bytes. Note that we reverse the condition.
7455 // b L_target // 4 bytes
7458 // These instructions don't exist in the actual instruction stream, so we need to fake them
7459 // up to display them.
7461 // Note: don't touch the actual instrDesc. If we accidentally messed it up, it would create a very
7462 // difficult to find bug.
7465 instrDescJmp* pidJmp = &idJmp;
7467 memset(&idJmp, 0, sizeof(idJmp));
7469 pidJmp->idIns(emitJumpKindToIns(emitReverseJumpKind(emitInsToJumpKind(id->idIns())))); // reverse the
7472 pidJmp->idInsFmt(IF_T1_K);
7473 pidJmp->idInsSize(emitInsSize(IF_T1_K));
7474 pidJmp->idjShort = 1;
7475 pidJmp->idAddr()->iiaSetInstrCount(1);
7476 pidJmp->idDebugOnlyInfo(id->idDebugOnlyInfo()); // share the idDebugOnlyInfo() field
7478 size_t bcondSizeOrZero = (code == NULL) ? 0 : 2; // branch is 2 bytes
7479 emitDispInsHelp(pidJmp, false, doffs, asmfm, offset, code, bcondSizeOrZero,
7480 NULL /* force display of pc-relative branch */);
7482 code += bcondSizeOrZero;
7485 // Next, display the unconditional branch
7487 // Reset the local instrDesc
7488 memset(&idJmp, 0, sizeof(idJmp));
7490 pidJmp->idIns(INS_b);
7491 pidJmp->idInsFmt(IF_T2_J2);
7492 pidJmp->idInsSize(emitInsSize(IF_T2_J2));
7493 pidJmp->idjShort = 0;
7494 if (id->idIsBound())
7496 pidJmp->idSetIsBound();
7497 pidJmp->idAddr()->iiaIGlabel = id->idAddr()->iiaIGlabel;
7501 pidJmp->idAddr()->iiaBBlabel = id->idAddr()->iiaBBlabel;
7503 pidJmp->idDebugOnlyInfo(id->idDebugOnlyInfo()); // share the idDebugOnlyInfo() field
7505 size_t brSizeOrZero = (code == NULL) ? 0 : 4; // unconditional branch is 4 bytes
7506 emitDispInsHelp(pidJmp, isNew, doffs, asmfm, offset, code, brSizeOrZero, ig);
7510 emitDispInsHelp(id, isNew, doffs, asmfm, offset, code, sz, ig);
7514 /*****************************************************************************
7516 * Display a stack frame reference.
7519 void emitter::emitDispFrameRef(int varx, int disp, int offs, bool asmfm)
7524 printf("TEMP_%02u", -varx);
7526 emitComp->gtDispLclVar(+varx, false);
7529 printf("-0x%02x", -disp);
7531 printf("+0x%02x", +disp);
7535 if (varx >= 0 && emitComp->opts.varNames)
7538 const char* varName;
7540 assert((unsigned)varx < emitComp->lvaCount);
7541 varDsc = emitComp->lvaTable + varx;
7542 varName = emitComp->compLocalVarName(varx, offs);
7546 printf("'%s", varName);
7549 printf("-%d", -disp);
7551 printf("+%d", +disp);
7560 #ifndef LEGACY_BACKEND
7562 void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataReg, GenTreeIndir* indir)
7564 // Handle unaligned floating point loads/stores
7565 if ((indir->gtFlags & GTF_IND_UNALIGNED))
7567 if (indir->OperGet() == GT_STOREIND)
7569 var_types type = indir->AsStoreInd()->Data()->TypeGet();
7570 if (type == TYP_FLOAT)
7572 regNumber tmpReg = indir->GetSingleTempReg();
7573 emitIns_R_R(INS_vmov_f2i, EA_4BYTE, tmpReg, dataReg);
7574 emitInsLoadStoreOp(INS_str, EA_4BYTE, tmpReg, indir, 0);
7577 else if (type == TYP_DOUBLE)
7579 regNumber tmpReg1 = indir->ExtractTempReg();
7580 regNumber tmpReg2 = indir->GetSingleTempReg();
7581 emitIns_R_R_R(INS_vmov_d2i, EA_8BYTE, tmpReg1, tmpReg2, dataReg);
7582 emitInsLoadStoreOp(INS_str, EA_4BYTE, tmpReg1, indir, 0);
7583 emitInsLoadStoreOp(INS_str, EA_4BYTE, tmpReg2, indir, 4);
7587 else if (indir->OperGet() == GT_IND)
7589 var_types type = indir->TypeGet();
7590 if (type == TYP_FLOAT)
7592 regNumber tmpReg = indir->GetSingleTempReg();
7593 emitInsLoadStoreOp(INS_ldr, EA_4BYTE, tmpReg, indir, 0);
7594 emitIns_R_R(INS_vmov_i2f, EA_4BYTE, dataReg, tmpReg);
7597 else if (type == TYP_DOUBLE)
7599 regNumber tmpReg1 = indir->ExtractTempReg();
7600 regNumber tmpReg2 = indir->GetSingleTempReg();
7601 emitInsLoadStoreOp(INS_ldr, EA_4BYTE, tmpReg1, indir, 0);
7602 emitInsLoadStoreOp(INS_ldr, EA_4BYTE, tmpReg2, indir, 4);
7603 emitIns_R_R_R(INS_vmov_i2d, EA_8BYTE, dataReg, tmpReg1, tmpReg2);
7609 // Proceed with ordinary loads/stores
7610 emitInsLoadStoreOp(ins, attr, dataReg, indir, 0);
7613 void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataReg, GenTreeIndir* indir, int offset)
7615 GenTree* addr = indir->Addr();
7617 if (addr->isContained())
7619 assert(addr->OperGet() == GT_LCL_VAR_ADDR || addr->OperGet() == GT_LEA);
7623 if (addr->OperGet() == GT_LEA)
7625 offset += addr->AsAddrMode()->Offset();
7626 if (addr->AsAddrMode()->gtScale > 0)
7628 assert(isPow2(addr->AsAddrMode()->gtScale));
7629 BitScanForward(&lsl, addr->AsAddrMode()->gtScale);
7633 GenTree* memBase = indir->Base();
7635 if (indir->HasIndex())
7637 assert(addr->OperGet() == GT_LEA);
7639 GenTree* index = indir->Index();
7643 regNumber tmpReg = indir->GetSingleTempReg();
7645 // If the LEA produces a GCREF or BYREF, we need to be careful to mark any temp register
7646 // computed with the base register as a BYREF.
7647 GenTreeAddrMode* lea = addr->AsAddrMode();
7648 emitAttr leaAttr = emitTypeSize(lea);
7649 emitAttr leaBasePartialAddrAttr = EA_IS_GCREF_OR_BYREF(leaAttr) ? EA_BYREF : EA_PTRSIZE;
7651 if (emitIns_valid_imm_for_add(offset, INS_FLAGS_DONT_CARE))
7655 // Generate code to set tmpReg = base + index*scale
7656 emitIns_R_R_R_I(INS_add, leaBasePartialAddrAttr, tmpReg, memBase->gtRegNum, index->gtRegNum,
7657 lsl, INS_FLAGS_DONT_CARE, INS_OPTS_LSL);
7661 // Generate code to set tmpReg = base + index
7662 emitIns_R_R_R(INS_add, leaBasePartialAddrAttr, tmpReg, memBase->gtRegNum, index->gtRegNum);
7665 noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
7667 // Then load/store dataReg from/to [tmpReg + offset]
7668 emitIns_R_R_I(ins, attr, dataReg, tmpReg, offset);
7670 else // large offset
7672 // First load/store tmpReg with the large offset constant
7673 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
7674 // Then add the base register
7676 emitIns_R_R_R(INS_add, leaBasePartialAddrAttr, tmpReg, tmpReg, memBase->gtRegNum);
7678 noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
7679 noway_assert(tmpReg != index->gtRegNum);
7681 // Then load/store dataReg from/to [tmpReg + index*scale]
7682 emitIns_R_R_R_I(ins, attr, dataReg, tmpReg, index->gtRegNum, lsl, INS_FLAGS_DONT_CARE,
7686 else // (offset == 0)
7690 // Then load/store dataReg from/to [memBase + index*scale]
7691 emitIns_R_R_R_I(ins, attr, dataReg, memBase->gtRegNum, index->gtRegNum, lsl, INS_FLAGS_DONT_CARE,
7696 // Then load/store dataReg from/to [memBase + index]
7697 emitIns_R_R_R(ins, attr, dataReg, memBase->gtRegNum, index->gtRegNum);
7703 if (emitIns_valid_imm_for_ldst_offset(offset, attr))
7705 // Then load/store dataReg from/to [memBase + offset]
7706 emitIns_R_R_I(ins, attr, dataReg, memBase->gtRegNum, offset);
7710 // We require a tmpReg to hold the offset
7711 regNumber tmpReg = indir->GetSingleTempReg();
7713 // First load/store tmpReg with the large offset constant
7714 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
7716 // Then load/store dataReg from/to [memBase + tmpReg]
7717 emitIns_R_R_R(ins, attr, dataReg, memBase->gtRegNum, tmpReg);
7725 assert(emitIns_valid_imm_for_add(offset, INS_FLAGS_DONT_CARE));
7726 emitIns_R_R_I(ins, attr, dataReg, addr->gtRegNum, offset);
7730 emitIns_R_R(ins, attr, dataReg, addr->gtRegNum);
7735 // The callee must call genConsumeReg() for any non-contained srcs
7736 // and genProduceReg() for any non-contained dsts.
7738 regNumber emitter::emitInsBinary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src)
7740 regNumber result = REG_NA;
7742 // dst can only be a reg
7743 assert(!dst->isContained());
7745 // src can be immed or reg
7746 assert(!src->isContained() || src->isContainedIntOrIImmed());
7748 // find immed (if any) - it cannot be a dst
7749 GenTreeIntConCommon* intConst = nullptr;
7750 if (src->isContainedIntOrIImmed())
7752 intConst = src->AsIntConCommon();
7757 emitIns_R_I(ins, attr, dst->gtRegNum, intConst->IconValue());
7758 return dst->gtRegNum;
7762 emitIns_R_R(ins, attr, dst->gtRegNum, src->gtRegNum);
7763 return dst->gtRegNum;
7767 regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src1, GenTree* src2)
7769 // dst can only be a reg
7770 assert(!dst->isContained());
7772 // find immed (if any) - it cannot be a dst
7773 // Only one src can be an int.
7774 GenTreeIntConCommon* intConst = nullptr;
7775 GenTree* nonIntReg = nullptr;
7777 if (varTypeIsFloating(dst))
7779 // src1 can only be a reg
7780 assert(!src1->isContained());
7781 // src2 can only be a reg
7782 assert(!src2->isContained());
7784 else // not floating point
7786 // src2 can be immed or reg
7787 assert(!src2->isContained() || src2->isContainedIntOrIImmed());
7789 // Check src2 first as we can always allow it to be a contained immediate
7790 if (src2->isContainedIntOrIImmed())
7792 intConst = src2->AsIntConCommon();
7795 // Only for commutative operations do we check src1 and allow it to be a contained immediate
7796 else if (dst->OperIsCommutative())
7798 // src1 can be immed or reg
7799 assert(!src1->isContained() || src1->isContainedIntOrIImmed());
7801 // Check src1 and allow it to be a contained immediate
7802 if (src1->isContainedIntOrIImmed())
7804 assert(!src2->isContainedIntOrIImmed());
7805 intConst = src1->AsIntConCommon();
7811 // src1 can only be a reg
7812 assert(!src1->isContained());
7816 insFlags flags = INS_FLAGS_DONT_CARE;
7817 bool isMulOverflow = false;
7818 if (dst->gtOverflowEx())
7820 if ((ins == INS_add) || (ins == INS_adc) || (ins == INS_sub) || (ins == INS_sbc))
7822 flags = INS_FLAGS_SET;
7824 else if (ins == INS_mul)
7826 isMulOverflow = true;
7827 assert(intConst == nullptr); // overflow format doesn't support an int constant operand
7831 assert(!"Invalid ins for overflow check");
7835 if (dst->gtSetFlags())
7837 assert((ins == INS_add) || (ins == INS_adc) || (ins == INS_sub) || (ins == INS_sbc) || (ins == INS_and) ||
7838 (ins == INS_orr) || (ins == INS_eor) || (ins == INS_orn));
7839 flags = INS_FLAGS_SET;
7842 if (intConst != nullptr)
7844 emitIns_R_R_I(ins, attr, dst->gtRegNum, nonIntReg->gtRegNum, intConst->IconValue(), flags);
7850 regNumber extraReg = dst->GetSingleTempReg();
7851 assert(extraReg != dst->gtRegNum);
7853 if ((dst->gtFlags & GTF_UNSIGNED) != 0)
7855 // Compute 8 byte result from 4 byte by 4 byte multiplication.
7856 emitIns_R_R_R_R(INS_umull, EA_4BYTE, dst->gtRegNum, extraReg, src1->gtRegNum, src2->gtRegNum);
7858 // Overflow exists if the result's high word is non-zero.
7859 emitIns_R_I(INS_cmp, attr, extraReg, 0);
7863 // Compute 8 byte result from 4 byte by 4 byte multiplication.
7864 emitIns_R_R_R_R(INS_smull, EA_4BYTE, dst->gtRegNum, extraReg, src1->gtRegNum, src2->gtRegNum);
7866 // Overflow exists if the result's high word is not merely a sign bit.
7867 emitIns_R_R_I(INS_cmp, attr, extraReg, dst->gtRegNum, 31, INS_FLAGS_DONT_CARE, INS_OPTS_ASR);
7872 // We can just do the arithmetic, setting the flags if needed.
7873 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum, flags);
7877 if (dst->gtOverflowEx())
7879 assert(!varTypeIsFloating(dst));
7881 emitJumpKind jumpKind;
7883 if (dst->OperGet() == GT_MUL)
7889 bool isUnsignedOverflow = ((dst->gtFlags & GTF_UNSIGNED) != 0);
7890 jumpKind = isUnsignedOverflow ? EJ_lo : EJ_vs;
7891 if (jumpKind == EJ_lo)
7893 if ((dst->OperGet() != GT_SUB) &&
7894 #ifdef LEGACY_BACKEND
7895 (dst->OperGet() != GT_ASG_SUB) &&
7897 (dst->OperGet() != GT_SUB_HI))
7904 // Jump to the block which will throw the exception.
7905 codeGen->genJumpToThrowHlpBlk(jumpKind, SCK_OVERFLOW);
7908 return dst->gtRegNum;
7911 #endif // !LEGACY_BACKEND
7912 #endif // defined(_TARGET_ARM_)