1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
5 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
6 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
10 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
11 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
18 #if defined(_TARGET_ARM_)
20 /*****************************************************************************/
21 /*****************************************************************************/
27 /*****************************************************************************/
29 const instruction emitJumpKindInstructions[] = {
32 #define JMP_SMALL(en, rev, ins) INS_##ins,
36 const emitJumpKind emitReverseJumpKinds[] = {
39 #define JMP_SMALL(en, rev, ins) EJ_##rev,
43 /*****************************************************************************
44 * Look up the instruction for a jump kind
47 /*static*/ instruction emitter::emitJumpKindToIns(emitJumpKind jumpKind)
49 assert((unsigned)jumpKind < ArrLen(emitJumpKindInstructions));
50 return emitJumpKindInstructions[jumpKind];
53 /*****************************************************************************
54 * Look up the jump kind for an instruction. It better be a conditional
55 * branch instruction with a jump kind!
58 /*static*/ emitJumpKind emitter::emitInsToJumpKind(instruction ins)
60 for (unsigned i = 0; i < ArrLen(emitJumpKindInstructions); i++)
62 if (ins == emitJumpKindInstructions[i])
64 emitJumpKind ret = (emitJumpKind)i;
65 assert(EJ_NONE < ret && ret < EJ_COUNT);
72 /*****************************************************************************
73 * Reverse the conditional jump
76 /*static*/ emitJumpKind emitter::emitReverseJumpKind(emitJumpKind jumpKind)
78 assert(jumpKind < EJ_COUNT);
79 return emitReverseJumpKinds[jumpKind];
82 /*****************************************************************************
84 * Return the allocated size (in bytes) of the given instruction descriptor.
87 size_t emitter::emitSizeOfInsDsc(instrDesc* id)
89 if (emitIsScnsInsDsc(id))
90 return SMALL_IDSC_SIZE;
92 assert((unsigned)id->idInsFmt() < emitFmtCount);
94 ID_OPS idOp = (ID_OPS)emitFmtToOps[id->idInsFmt()];
95 bool isCallIns = (id->idIns() == INS_bl) || (id->idIns() == INS_blx);
96 bool maybeCallIns = (id->idIns() == INS_b) || (id->idIns() == INS_bx);
98 // An INS_call instruction may use a "fat" direct/indirect call descriptor
99 // except for a local call to a label (i.e. call to a finally).
100 // Only ID_OP_CALL and ID_OP_SPEC check for this, so we enforce that the
101 // INS_call instruction always uses one of these idOps.
103 assert(!isCallIns || // either not a call or
104 idOp == ID_OP_CALL || // is a direct call
105 idOp == ID_OP_SPEC || // is an indirect call
106 idOp == ID_OP_JMP); // is a local call to finally clause
114 return sizeof(instrDescJmp);
117 return sizeof(instrDescLbl);
121 assert(isCallIns || maybeCallIns);
122 if (id->idIsLargeCall())
124 /* Must be a "fat" indirect call descriptor */
125 return sizeof(instrDescCGCA);
129 assert(!id->idIsLargeDsp());
130 assert(!id->idIsLargeCns());
131 return sizeof(instrDesc);
136 NO_WAY("unexpected instruction descriptor format");
140 if (id->idIsLargeCns())
142 if (id->idIsLargeDsp())
143 return sizeof(instrDescCnsDsp);
145 return sizeof(instrDescCns);
149 if (id->idIsLargeDsp())
150 return sizeof(instrDescDsp);
152 return sizeof(instrDesc);
156 bool offsetFitsInVectorMem(int disp)
158 unsigned imm = unsigned_abs(disp);
159 return ((imm & 0x03fc) == imm);
163 /*****************************************************************************
165 * The following called for each recorded instruction -- use for debugging.
167 void emitter::emitInsSanityCheck(instrDesc* id)
169 /* What instruction format have we got? */
171 switch (id->idInsFmt())
173 case IF_T1_A: // T1_A ................
174 case IF_T2_A: // T2_A ................ ................
177 case IF_T1_B: // T1_B ........cccc.... cond
178 case IF_T2_B: // T2_B ................ ............iiii imm4
179 assert(emitGetInsSC(id) < 0x10);
182 case IF_T1_C: // T1_C .....iiiiinnnddd R1 R2 imm5
183 assert(isLowRegister(id->idReg1()));
184 assert(isLowRegister(id->idReg2()));
185 if (emitInsIsLoadOrStore(id->idIns()))
187 emitAttr size = id->idOpSize();
188 int imm = emitGetInsSC(id);
190 imm = insUnscaleImm(imm, size);
195 assert(id->idSmallCns() < 0x20);
199 case IF_T1_D0: // T1_D0 ........Dmmmmddd R1* R2*
200 assert(isGeneralRegister(id->idReg1()));
201 assert(isGeneralRegister(id->idReg2()));
204 case IF_T1_D1: // T1_D1 .........mmmm... R1*
205 assert(isGeneralRegister(id->idReg1()));
208 case IF_T1_D2: // T1_D2 .........mmmm... R3*
209 assert(isGeneralRegister(id->idReg3()));
212 case IF_T1_E: // T1_E ..........nnnddd R1 R2
213 assert(isLowRegister(id->idReg1()));
214 assert(isLowRegister(id->idReg2()));
215 assert(id->idSmallCns() < 0x20);
218 case IF_T1_F: // T1_F .........iiiiiii SP imm7
219 assert(id->idReg1() == REG_SP);
220 assert(id->idOpSize() == EA_4BYTE);
221 assert((emitGetInsSC(id) & ~0x1FC) == 0);
224 case IF_T1_G: // T1_G .......iiinnnddd R1 R2 imm3
225 assert(isLowRegister(id->idReg1()));
226 assert(isLowRegister(id->idReg2()));
227 assert(id->idSmallCns() < 0x8);
230 case IF_T1_H: // T1_H .......mmmnnnddd R1 R2 R3
231 assert(isLowRegister(id->idReg1()));
232 assert(isLowRegister(id->idReg2()));
233 assert(isLowRegister(id->idReg3()));
236 case IF_T1_I: // T1_I ......i.iiiiiddd R1 imm6
237 assert(isLowRegister(id->idReg1()));
240 case IF_T1_J0: // T1_J0 .....dddiiiiiiii R1 imm8
241 assert(isLowRegister(id->idReg1()));
242 assert(emitGetInsSC(id) < 0x100);
245 case IF_T1_J1: // T1_J1 .....dddiiiiiiii R1 <regmask8>
246 assert(isLowRegister(id->idReg1()));
247 assert(emitGetInsSC(id) < 0x100);
250 case IF_T1_J2: // T1_J2 .....dddiiiiiiii R1 SP imm8
251 assert(isLowRegister(id->idReg1()));
252 assert(id->idReg2() == REG_SP);
253 assert(id->idOpSize() == EA_4BYTE);
254 assert((emitGetInsSC(id) & ~0x3FC) == 0);
257 case IF_T1_L0: // T1_L0 ........iiiiiiii imm8
258 assert(emitGetInsSC(id) < 0x100);
261 case IF_T1_L1: // T1_L1 .......Rrrrrrrrr <regmask8+2>
262 assert(emitGetInsSC(id) < 0x400);
265 case IF_T2_C0: // T2_C0 ...........Snnnn .iiiddddiishmmmm R1 R2 R3 S, imm5, sh
266 assert(isGeneralRegister(id->idReg1()));
267 assert(isGeneralRegister(id->idReg2()));
268 assert(isGeneralRegister(id->idReg3()));
269 assert(emitGetInsSC(id) < 0x20);
272 case IF_T2_C4: // T2_C4 ...........Snnnn ....dddd....mmmm R1 R2 R3 S
273 case IF_T2_C5: // T2_C5 ............nnnn ....dddd....mmmm R1 R2 R3
274 case IF_T2_G1: // T2_G1 ............nnnn ttttTTTT........ R1 R2 R3
275 assert(isGeneralRegister(id->idReg1()));
276 assert(isGeneralRegister(id->idReg2()));
277 assert(isGeneralRegister(id->idReg3()));
280 case IF_T2_C1: // T2_C1 ...........S.... .iiiddddiishmmmm R1 R2 S, imm5, sh
281 case IF_T2_C2: // T2_C2 ...........S.... .iiiddddii..mmmm R1 R2 S, imm5
282 case IF_T2_C8: // T2_C8 ............nnnn .iii....iishmmmm R1 R2 imm5, sh
283 assert(isGeneralRegister(id->idReg1()));
284 assert(isGeneralRegister(id->idReg2()));
285 assert(emitGetInsSC(id) < 0x20);
288 case IF_T2_C6: // T2_C6 ................ ....dddd..iimmmm R1 R2 imm2
289 case IF_T2_C7: // T2_C7 ............nnnn ..........shmmmm R1 R2 imm2
290 assert(isGeneralRegister(id->idReg1()));
291 assert(isGeneralRegister(id->idReg2()));
292 assert(emitGetInsSC(id) < 0x4);
295 case IF_T2_C3: // T2_C3 ...........S.... ....dddd....mmmm R1 R2 S
296 case IF_T2_C9: // T2_C9 ............nnnn ............mmmm R1 R2
297 case IF_T2_C10: // T2_C10 ............mmmm ....dddd....mmmm R1 R2
298 assert(isGeneralRegister(id->idReg1()));
299 assert(isGeneralRegister(id->idReg2()));
302 case IF_T2_D0: // T2_D0 ............nnnn .iiiddddii.wwwww R1 R2 imm5, imm5
303 assert(isGeneralRegister(id->idReg1()));
304 assert(isGeneralRegister(id->idReg2()));
305 assert(emitGetInsSC(id) < 0x400);
308 case IF_T2_D1: // T2_D1 ................ .iiiddddii.wwwww R1 imm5, imm5
309 assert(isGeneralRegister(id->idReg1()));
310 assert(emitGetInsSC(id) < 0x400);
313 case IF_T2_E0: // T2_E0 ............nnnn tttt......shmmmm R1 R2 R3 imm2
314 assert(isGeneralRegister(id->idReg1()));
315 assert(isGeneralRegister(id->idReg2()));
316 if (id->idIsLclVar())
318 assert(isGeneralRegister(codeGen->rsGetRsvdReg()));
322 assert(isGeneralRegister(id->idReg3()));
323 assert(emitGetInsSC(id) < 0x4);
327 case IF_T2_E1: // T2_E1 ............nnnn tttt............ R1 R2
328 assert(isGeneralRegister(id->idReg1()));
329 assert(isGeneralRegister(id->idReg2()));
332 case IF_T2_E2: // T2_E2 ................ tttt............ R1
333 assert(isGeneralRegister(id->idReg1()));
336 case IF_T2_F1: // T2_F1 ............nnnn ttttdddd....mmmm R1 R2 R3 R4
337 case IF_T2_F2: // T2_F2 ............nnnn aaaadddd....mmmm R1 R2 R3 R4
338 assert(isGeneralRegister(id->idReg1()));
339 assert(isGeneralRegister(id->idReg2()));
340 assert(isGeneralRegister(id->idReg3()));
341 assert(isGeneralRegister(id->idReg4()));
344 case IF_T2_G0: // T2_G0 .......PU.W.nnnn ttttTTTTiiiiiiii R1 R2 R3 imm8, PUW
345 assert(isGeneralRegister(id->idReg1()));
346 assert(isGeneralRegister(id->idReg2()));
347 assert(isGeneralRegister(id->idReg3()));
348 assert(unsigned_abs(emitGetInsSC(id)) < 0x100);
351 case IF_T2_H0: // T2_H0 ............nnnn tttt.PUWiiiiiiii R1 R2 imm8, PUW
352 assert(isGeneralRegister(id->idReg1()));
353 assert(isGeneralRegister(id->idReg2()));
354 assert(unsigned_abs(emitGetInsSC(id)) < 0x100);
357 case IF_T2_H1: // T2_H1 ............nnnn tttt....iiiiiiii R1 R2 imm8
358 assert(isGeneralRegister(id->idReg1()));
359 assert(isGeneralRegister(id->idReg2()));
360 assert(emitGetInsSC(id) < 0x100);
363 case IF_T2_H2: // T2_H2 ............nnnn ........iiiiiiii R1 imm8
364 assert(isGeneralRegister(id->idReg1()));
365 assert(emitGetInsSC(id) < 0x100);
368 case IF_T2_I0: // T2_I0 ..........W.nnnn rrrrrrrrrrrrrrrr R1 W, imm16
369 assert(isGeneralRegister(id->idReg1()));
370 assert(emitGetInsSC(id) < 0x10000);
373 case IF_T2_N: // T2_N .....i......iiii .iiiddddiiiiiiii R1 imm16
374 assert(isGeneralRegister(id->idReg1()));
377 case IF_T2_N2: // T2_N2 .....i......iiii .iiiddddiiiiiiii R1 imm16
378 assert(isGeneralRegister(id->idReg1()));
379 assert((size_t)emitGetInsSC(id) < emitDataSize());
382 case IF_T2_I1: // T2_I1 ................ rrrrrrrrrrrrrrrr imm16
383 assert(emitGetInsSC(id) < 0x10000);
386 case IF_T2_K1: // T2_K1 ............nnnn ttttiiiiiiiiiiii R1 R2 imm12
387 case IF_T2_M0: // T2_M0 .....i......nnnn .iiiddddiiiiiiii R1 R2 imm12
388 assert(isGeneralRegister(id->idReg1()));
389 assert(isGeneralRegister(id->idReg2()));
390 assert(emitGetInsSC(id) < 0x1000);
393 case IF_T2_L0: // T2_L0 .....i.....Snnnn .iiiddddiiiiiiii R1 R2 S, imm8<<imm4
394 assert(isGeneralRegister(id->idReg1()));
395 assert(isGeneralRegister(id->idReg2()));
396 assert(isModImmConst(emitGetInsSC(id)));
399 case IF_T2_K4: // T2_K4 ........U....... ttttiiiiiiiiiiii R1 PC U, imm12
400 case IF_T2_M1: // T2_M1 .....i.......... .iiiddddiiiiiiii R1 PC imm12
401 assert(isGeneralRegister(id->idReg1()));
402 assert(id->idReg2() == REG_PC);
403 assert(emitGetInsSC(id) < 0x1000);
406 case IF_T2_K3: // T2_K3 ........U....... ....iiiiiiiiiiii PC U, imm12
407 assert(id->idReg1() == REG_PC);
408 assert(emitGetInsSC(id) < 0x1000);
411 case IF_T2_K2: // T2_K2 ............nnnn ....iiiiiiiiiiii R1 imm12
412 assert(isGeneralRegister(id->idReg1()));
413 assert(emitGetInsSC(id) < 0x1000);
416 case IF_T2_L1: // T2_L1 .....i.....S.... .iiiddddiiiiiiii R1 S, imm8<<imm4
417 case IF_T2_L2: // T2_L2 .....i......nnnn .iii....iiiiiiii R1 imm8<<imm4
418 assert(isGeneralRegister(id->idReg1()));
419 assert(isModImmConst(emitGetInsSC(id)));
422 case IF_T1_J3: // T1_J3 .....dddiiiiiiii R1 PC imm8
423 assert(isGeneralRegister(id->idReg1()));
424 assert(id->idReg2() == REG_PC);
425 assert(emitGetInsSC(id) < 0x100);
428 case IF_T1_K: // T1_K ....cccciiiiiiii Branch imm8, cond4
429 case IF_T1_M: // T1_M .....iiiiiiiiiii Branch imm11
430 case IF_T2_J1: // T2_J1 .....Scccciiiiii ..j.jiiiiiiiiiii Branch imm20, cond4
431 case IF_T2_J2: // T2_J2 .....Siiiiiiiiii ..j.jiiiiiiiiii. Branch imm24
432 case IF_T2_N1: // T2_N .....i......iiii .iiiddddiiiiiiii R1 imm16
433 case IF_T2_J3: // T2_J3 .....Siiiiiiiiii ..j.jiiiiiiiiii. Call imm24
438 if (id->idOpSize() == EA_8BYTE)
440 assert(isDoubleReg(id->idReg1()));
441 assert(isDoubleReg(id->idReg2()));
442 assert(isDoubleReg(id->idReg3()));
446 assert(id->idOpSize() == EA_4BYTE);
447 assert(isFloatReg(id->idReg1()));
448 assert(isFloatReg(id->idReg2()));
449 assert(isFloatReg(id->idReg3()));
454 assert(isFloatReg(id->idReg1()));
455 assert(isFloatReg(id->idReg2()));
459 if (id->idOpSize() == EA_8BYTE)
460 assert(isDoubleReg(id->idReg1()));
462 assert(isFloatReg(id->idReg1()));
463 assert(isGeneralRegister(id->idReg2()));
464 assert(offsetFitsInVectorMem(emitGetInsSC(id)));
468 assert(id->idOpSize() == EA_8BYTE);
469 if (id->idIns() == INS_vmov_d2i)
471 assert(isGeneralRegister(id->idReg1()));
472 assert(isGeneralRegister(id->idReg2()));
473 assert(isDoubleReg(id->idReg3()));
477 assert(id->idIns() == INS_vmov_i2d);
478 assert(isDoubleReg(id->idReg1()));
479 assert(isGeneralRegister(id->idReg2()));
480 assert(isGeneralRegister(id->idReg3()));
485 assert(id->idOpSize() == EA_4BYTE);
486 if (id->idIns() == INS_vmov_i2f)
488 assert(isFloatReg(id->idReg1()));
489 assert(isGeneralRegister(id->idReg2()));
493 assert(id->idIns() == INS_vmov_f2i);
494 assert(isGeneralRegister(id->idReg1()));
495 assert(isFloatReg(id->idReg2()));
500 printf("unexpected format %s\n", emitIfName(id->idInsFmt()));
501 assert(!"Unexpected format");
507 bool emitter::emitInsMayWriteToGCReg(instrDesc* id)
509 instruction ins = id->idIns();
510 insFormat fmt = id->idInsFmt();
515 // These are the formats with "destination" or "target" registers:
556 // Some formats with "destination" or "target" registers are actually used for store instructions, for the
557 // "source" value written to memory.
558 // Similarly, PUSH has a target register, indicating the start of the set of registers to push. POP
559 // *does* write to at least one register, so we do not make that a special case.
560 // Various compare/test instructions do not write (except to the flags). Technically "teq" does not need to
562 // be in this list because it has no forms matched above, but I'm putting it here for completeness.
583 // VMOV.i2f reads from the integer register. Conversely VMOV.f2i writes to GC pointer-sized
584 // integer register that might have previously held GC pointers, so they need to be included.
585 assert(id->idGCref() == GCT_NONE);
586 return (ins == INS_vmov_f2i);
589 // VMOV.i2d reads from the integer registers. Conversely VMOV.d2i writes to GC pointer-sized
590 // integer registers that might have previously held GC pointers, so they need to be included.
591 assert(id->idGCref() == GCT_NONE);
592 return (ins == INS_vmov_d2i);
599 bool emitter::emitInsWritesToLclVarStackLoc(instrDesc* id)
601 if (!id->idIsLclVar())
604 instruction ins = id->idIns();
606 // This list is related to the list of instructions used to store local vars in emitIns_S_R().
607 // We don't accept writing to float local vars.
620 bool emitter::emitInsMayWriteMultipleRegs(instrDesc* id)
622 instruction ins = id->idIns();
640 /*****************************************************************************/
642 /*****************************************************************************
644 * Return a string that represents the given register.
647 const char* emitter::emitRegName(regNumber reg, emitAttr attr, bool varName)
649 assert(reg < REG_COUNT);
651 const char* rn = emitComp->compRegVarName(reg, varName, false);
653 assert(strlen(rn) >= 1);
658 const char* emitter::emitFloatRegName(regNumber reg, emitAttr attr, bool varName)
660 assert(reg < REG_COUNT);
662 const char* rn = emitComp->compRegVarName(reg, varName, true);
664 assert(strlen(rn) >= 1);
670 /*****************************************************************************
672 * Returns the base encoding of the given CPU instruction.
675 emitter::insFormat emitter::emitInsFormat(instruction ins)
678 const static insFormat insFormats[] =
680 #define INST1(id, nm, fp, ldst, fmt, e1 ) fmt,
681 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) fmt,
682 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) fmt,
683 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) fmt,
684 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) fmt,
685 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) fmt,
686 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) fmt,
687 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) fmt,
692 assert(ins < ArrLen(insFormats));
693 assert((insFormats[ins] != IF_NONE));
695 return insFormats[ins];
704 /*static*/ const BYTE CodeGenInterface::instInfo[] =
706 #define INST1(id, nm, fp, ldst, fmt, e1 ) ldst | INST_FP*fp,
707 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) ldst | INST_FP*fp,
708 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) ldst | INST_FP*fp,
709 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) ldst | INST_FP*fp,
710 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) ldst | INST_FP*fp,
711 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) ldst | INST_FP*fp,
712 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) ldst | INST_FP*fp,
713 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) ldst | INST_FP*fp,
718 /*****************************************************************************
720 * Returns true if the instruction is some kind of load instruction
723 bool emitter::emitInsIsLoad(instruction ins)
725 // We have pseudo ins like lea which are not included in emitInsLdStTab.
726 if (ins < ArrLen(CodeGenInterface::instInfo))
727 return (CodeGenInterface::instInfo[ins] & LD) ? true : false;
732 /*****************************************************************************
734 * Returns true if the instruction is some kind of compare or test instruction
737 bool emitter::emitInsIsCompare(instruction ins)
739 // We have pseudo ins like lea which are not included in emitInsLdStTab.
740 if (ins < ArrLen(CodeGenInterface::instInfo))
741 return (CodeGenInterface::instInfo[ins] & CMP) ? true : false;
746 /*****************************************************************************
748 * Returns true if the instruction is some kind of store instruction
751 bool emitter::emitInsIsStore(instruction ins)
753 // We have pseudo ins like lea which are not included in emitInsLdStTab.
754 if (ins < ArrLen(CodeGenInterface::instInfo))
755 return (CodeGenInterface::instInfo[ins] & ST) ? true : false;
760 /*****************************************************************************
762 * Returns true if the instruction is some kind of load/store instruction
765 bool emitter::emitInsIsLoadOrStore(instruction ins)
767 // We have pseudo ins like lea which are not included in emitInsLdStTab.
768 if (ins < ArrLen(CodeGenInterface::instInfo))
769 return (CodeGenInterface::instInfo[ins] & (LD | ST)) ? true : false;
778 /*****************************************************************************
780 * Returns the specific encoding of the given CPU instruction and format
783 emitter::code_t emitter::emitInsCode(instruction ins, insFormat fmt)
786 const static code_t insCodes1[] =
788 #define INST1(id, nm, fp, ldst, fmt, e1 ) e1,
789 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) e1,
790 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) e1,
791 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e1,
792 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e1,
793 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e1,
794 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) e1,
795 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e1,
798 const static code_t insCodes2[] =
800 #define INST1(id, nm, fp, ldst, fmt, e1 )
801 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) e2,
802 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) e2,
803 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e2,
804 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e2,
805 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e2,
806 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) e2,
807 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e2,
810 const static code_t insCodes3[] =
812 #define INST1(id, nm, fp, ldst, fmt, e1 )
813 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
814 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) e3,
815 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e3,
816 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e3,
817 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e3,
818 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) e3,
819 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e3,
822 const static code_t insCodes4[] =
824 #define INST1(id, nm, fp, ldst, fmt, e1 )
825 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
826 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
827 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e4,
828 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e4,
829 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e4,
830 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) e4,
831 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e4,
834 const static code_t insCodes5[] =
836 #define INST1(id, nm, fp, ldst, fmt, e1 )
837 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
838 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
839 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
840 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e5,
841 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e5,
842 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) e5,
843 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e5,
846 const static code_t insCodes6[] =
848 #define INST1(id, nm, fp, ldst, fmt, e1 )
849 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
850 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
851 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
852 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
853 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e6,
854 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) e6,
855 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e6,
858 const static code_t insCodes7[] =
860 #define INST1(id, nm, fp, ldst, fmt, e1 )
861 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
862 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
863 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
864 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
865 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 )
866 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) e7,
867 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e7,
870 const static code_t insCodes8[] =
872 #define INST1(id, nm, fp, ldst, fmt, e1 )
873 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
874 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
875 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
876 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
877 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 )
878 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) e8,
879 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e8,
882 const static code_t insCodes9[] =
884 #define INST1(id, nm, fp, ldst, fmt, e1 )
885 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
886 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
887 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
888 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
889 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 )
890 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 )
891 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e9,
894 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 };
895 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 };
896 const static insFormat formatEncode6A[6] = { IF_T1_H, IF_T1_C, IF_T2_E0, IF_T2_H0, IF_T2_K1, IF_T2_K4};
897 const static insFormat formatEncode6B[6] = { IF_T1_H, IF_T1_C, IF_T2_E0, IF_T2_H0, IF_T2_K1, IF_T1_J2 };
898 const static insFormat formatEncode5A[5] = { IF_T1_E, IF_T1_D0, IF_T1_J0, IF_T2_L1, IF_T2_C3 };
899 const static insFormat formatEncode5B[5] = { IF_T1_E, IF_T1_D0, IF_T1_J0, IF_T2_L2, IF_T2_C8 };
900 const static insFormat formatEncode4A[4] = { IF_T1_E, IF_T1_C, IF_T2_C4, IF_T2_C2 };
901 const static insFormat formatEncode4B[4] = { IF_T2_K2, IF_T2_H2, IF_T2_C7, IF_T2_K3 };
902 const static insFormat formatEncode3A[3] = { IF_T1_E, IF_T2_C0, IF_T2_L0 };
903 const static insFormat formatEncode3B[3] = { IF_T1_E, IF_T2_C8, IF_T2_L2 };
904 const static insFormat formatEncode3C[3] = { IF_T1_E, IF_T2_C1, IF_T2_L1 };
905 const static insFormat formatEncode3D[3] = { IF_T1_L1, IF_T2_E2, IF_T2_I1 };
906 const static insFormat formatEncode3E[3] = { IF_T2_N, IF_T2_N1, IF_T2_N2 };
907 const static insFormat formatEncode3F[3] = { IF_T1_M, IF_T2_J2, IF_T2_J3 };
908 const static insFormat formatEncode2A[2] = { IF_T1_K, IF_T2_J1 };
909 const static insFormat formatEncode2B[2] = { IF_T1_D1, IF_T1_D2 };
910 const static insFormat formatEncode2C[2] = { IF_T1_D2, IF_T2_J3 };
911 const static insFormat formatEncode2D[2] = { IF_T1_J1, IF_T2_I0 };
912 const static insFormat formatEncode2E[2] = { IF_T1_E, IF_T2_C6 };
913 const static insFormat formatEncode2F[2] = { IF_T1_E, IF_T2_C5 };
914 const static insFormat formatEncode2G[2] = { IF_T1_J3, IF_T2_M1 };
917 code_t code = BAD_CODE;
918 insFormat insFmt = emitInsFormat(ins);
925 for (index = 0; index < 9; index++)
927 if (fmt == formatEncode9[index])
936 for (index = 0; index < 8; index++)
938 if (fmt == formatEncode8[index])
947 for (index = 0; index < 6; index++)
949 if (fmt == formatEncode6A[index])
958 for (index = 0; index < 6; index++)
960 if (fmt == formatEncode6B[index])
969 for (index = 0; index < 5; index++)
971 if (fmt == formatEncode5A[index])
980 for (index = 0; index < 5; index++)
982 if (fmt == formatEncode5B[index])
991 for (index = 0; index < 4; index++)
993 if (fmt == formatEncode4A[index])
1002 for (index = 0; index < 4; index++)
1004 if (fmt == formatEncode4B[index])
1013 for (index = 0; index < 3; index++)
1015 if (fmt == formatEncode3A[index])
1024 for (index = 0; index < 3; index++)
1026 if (fmt == formatEncode3B[index])
1034 for (index = 0; index < 3; index++)
1036 if (fmt == formatEncode3C[index])
1044 for (index = 0; index < 3; index++)
1046 if (fmt == formatEncode3D[index])
1054 for (index = 0; index < 3; index++)
1056 if (fmt == formatEncode3E[index])
1064 for (index = 0; index < 3; index++)
1066 if (fmt == formatEncode3F[index])
1075 for (index = 0; index < 2; index++)
1077 if (fmt == formatEncode2A[index])
1085 for (index = 0; index < 2; index++)
1087 if (fmt == formatEncode2B[index])
1095 for (index = 0; index < 2; index++)
1097 if (fmt == formatEncode2C[index])
1105 for (index = 0; index < 2; index++)
1107 if (fmt == formatEncode2D[index])
1115 for (index = 0; index < 2; index++)
1117 if (fmt == formatEncode2E[index])
1125 for (index = 0; index < 2; index++)
1127 if (fmt == formatEncode2F[index])
1136 for (index = 0; index < 2; index++)
1138 if (fmt == formatEncode2G[index])
1157 assert(ins < ArrLen(insCodes1));
1158 code = insCodes1[ins];
1161 assert(ins < ArrLen(insCodes2));
1162 code = insCodes2[ins];
1165 assert(ins < ArrLen(insCodes3));
1166 code = insCodes3[ins];
1169 assert(ins < ArrLen(insCodes4));
1170 code = insCodes4[ins];
1173 assert(ins < ArrLen(insCodes5));
1174 code = insCodes5[ins];
1177 assert(ins < ArrLen(insCodes6));
1178 code = insCodes6[ins];
1181 assert(ins < ArrLen(insCodes7));
1182 code = insCodes7[ins];
1185 assert(ins < ArrLen(insCodes8));
1186 code = insCodes8[ins];
1189 assert(ins < ArrLen(insCodes9));
1190 code = insCodes9[ins];
1194 assert((code != BAD_CODE));
1199 /*****************************************************************************
1201 * Return the code size of the given instruction format. The 'insSize' return type enum
1202 * indicates a 16 bit, 32 bit, or 48 bit instruction.
1205 emitter::insSize emitter::emitInsSize(insFormat insFmt)
1207 if ((insFmt >= IF_T1_A) && (insFmt < IF_T2_A))
1210 if ((insFmt >= IF_T2_A) && (insFmt < IF_INVALID))
1213 if (insFmt == IF_LARGEJMP)
1216 assert(!"Invalid insFormat");
1220 /*****************************************************************************
1222 * isModImmConst() returns true when immediate 'val32' can be encoded
1223 * using the special modified immediate constant available in Thumb
1226 /*static*/ bool emitter::isModImmConst(int val32)
1228 unsigned uval32 = (unsigned)val32;
1229 unsigned imm8 = uval32 & 0xff;
1231 /* encode = 0000x */
1235 unsigned imm32a = (imm8 << 16) | imm8;
1236 /* encode = 0001x */
1237 if (imm32a == uval32)
1240 unsigned imm32b = (imm32a << 8);
1241 /* encode = 0010x */
1242 if (imm32b == uval32)
1245 unsigned imm32c = (imm32a | imm32b);
1246 /* encode = 0011x */
1247 if (imm32c == uval32)
1250 unsigned mask32 = 0x00000ff;
1252 unsigned encode = 31; /* 11111 */
1258 temp = uval32 & ~mask32;
1262 } while (encode >= 8);
1267 /*****************************************************************************
1269 * encodeModImmConst() returns the special ARM 12-bit immediate encoding.
1270 * that is used to encode the immediate. (4-bits, 8-bits)
1271 * If the imm can not be encoded then 0x0BADC0DE is returned.
1274 /*static*/ int emitter::encodeModImmConst(int val32)
1276 unsigned uval32 = (unsigned)val32;
1277 unsigned imm8 = uval32 & 0xff;
1278 unsigned encode = imm8 >> 7;
1285 /* encode = 0000x */
1291 imm32a = (imm8 << 16) | imm8;
1292 /* encode = 0001x */
1293 if (imm32a == uval32)
1299 imm32b = (imm32a << 8);
1300 /* encode = 0010x */
1301 if (imm32b == uval32)
1307 imm32c = (imm32a | imm32b);
1308 /* encode = 0011x */
1309 if (imm32c == uval32)
1317 encode = 31; /* 11111 */
1321 temp = uval32 & ~mask32;
1324 imm8 = (uval32 & mask32) >> (32 - encode);
1325 assert((imm8 & 0x80) != 0);
1329 } while (encode >= 8);
1331 assert(!"encodeModImmConst failed!");
1335 unsigned result = (encode << 7) | (imm8 & 0x7f);
1336 assert(result <= 0x0fff);
1337 assert(result >= 0);
1341 /*****************************************************************************
1343 * emitIns_valid_imm_for_alu() returns true when the immediate 'imm'
1344 * can be encoded using the 12-bit funky Arm immediate encoding
1346 /*static*/ bool emitter::emitIns_valid_imm_for_alu(int imm)
1348 if (isModImmConst(imm))
1353 /*****************************************************************************
1355 * emitIns_valid_imm_for_mov() returns true when the immediate 'imm'
1356 * can be encoded using a single mov or mvn instruction.
1358 /*static*/ bool emitter::emitIns_valid_imm_for_mov(int imm)
1360 if ((imm & 0x0000ffff) == imm) // 16-bit immediate
1362 if (isModImmConst(imm)) // funky arm immediate
1364 if (isModImmConst(~imm)) // funky arm immediate via mvn
1369 /*****************************************************************************
1371 * emitIns_valid_imm_for_small_mov() returns true when the immediate 'imm'
1372 * can be encoded using a single 2-byte mov instruction.
1374 /*static*/ bool emitter::emitIns_valid_imm_for_small_mov(regNumber reg, int imm, insFlags flags)
1376 return isLowRegister(reg) && insSetsFlags(flags) && ((imm & 0x00ff) == imm);
1379 /*****************************************************************************
1381 * emitins_valid_imm_for_add() returns true when the immediate 'imm'
1382 * can be encoded using a single add or sub instruction.
1384 /*static*/ bool emitter::emitIns_valid_imm_for_add(int imm, insFlags flags)
1386 if ((unsigned_abs(imm) <= 0x00000fff) && (flags != INS_FLAGS_SET)) // 12-bit immediate via add/sub
1388 if (isModImmConst(imm)) // funky arm immediate
1390 if (isModImmConst(-imm)) // funky arm immediate via sub
1395 /*****************************************************************************
1397 * emitins_valid_imm_for_cmp() returns true if this 'imm'
1398 * can be encoded as a input operand to an cmp instruction.
1400 /*static*/ bool emitter::emitIns_valid_imm_for_cmp(int imm, insFlags flags)
1402 if (isModImmConst(imm)) // funky arm immediate
1404 if (isModImmConst(-imm)) // funky arm immediate via sub
1409 /*****************************************************************************
1411 * emitIns_valid_imm_for_add_sp() returns true when the immediate 'imm'
1412 * can be encoded in "add Rd,SP,i10".
1414 /*static*/ bool emitter::emitIns_valid_imm_for_add_sp(int imm)
1416 if ((imm & 0x03fc) == imm)
1421 /*****************************************************************************
1423 * emitIns_valid_imm_for_ldst_offset() returns true when the immediate 'imm'
1424 * can be encoded as the offset in a ldr/str instruction.
1426 /*static*/ bool emitter::emitIns_valid_imm_for_ldst_offset(int imm, emitAttr size)
1428 if ((imm & 0x0fff) == imm)
1429 return true; // encodable using IF_T2_K1
1430 if (unsigned_abs(imm) <= 0x0ff)
1431 return true; // encodable using IF_T2_H0
1435 /*****************************************************************************
1437 * emitIns_valid_imm_for_vldst_offset() returns true when the immediate 'imm'
1438 * can be encoded as the offset in a vldr/vstr instruction, i.e. when it is
1439 * a non-negative multiple of 4 that is less than 1024.
1441 /*static*/ bool emitter::emitIns_valid_imm_for_vldst_offset(int imm)
1443 if ((imm & 0x3fc) == imm)
1448 /*****************************************************************************
1450 * Add an instruction with no operands.
1453 void emitter::emitIns(instruction ins)
1455 instrDesc* id = emitNewInstrSmall(EA_4BYTE);
1456 insFormat fmt = emitInsFormat(ins);
1457 insSize isz = emitInsSize(fmt);
1459 assert((fmt == IF_T1_A) || (fmt == IF_T2_A));
1469 /*****************************************************************************
1471 * Add an instruction with a single immediate value.
1474 void emitter::emitIns_I(instruction ins, emitAttr attr, ssize_t imm)
1476 insFormat fmt = IF_NONE;
1480 bool onlyT1 = false;
1482 /* Figure out the encoding format of the instruction */
1485 #ifdef FEATURE_ITINSTRUCTION
1501 assert((imm & 0x0F) == imm);
1505 #endif // FEATURE_ITINSTRUCTION
1508 assert((imm & 0xA000) == 0); // Cannot push PC or SP
1510 if (imm & 0x4000) // Is the LR being pushed?
1513 goto COMMON_PUSH_POP;
1516 assert((imm & 0x2000) == 0); // Cannot pop SP
1517 assert((imm & 0xC000) != 0xC000); // Cannot pop both PC and LR
1519 if (imm & 0x8000) // Is the PC being popped?
1521 if (imm & 0x4000) // Is the LR being popped?
1529 if (((imm - 1) & imm) == 0) // Is only one or zero bits set in imm?
1531 if (((imm == 0) && !hasLR) || // imm has no bits set, but hasLR is set
1532 (!hasPC && !hasLR)) // imm has one bit set, and neither of hasPC/hasLR are set
1534 onlyT1 = true; // if only one bit is set we must use the T1 encoding
1538 imm &= ~0xE000; // ensure that PC, LR and SP bits are removed from imm
1540 if (((imm & 0x00ff) == imm) && !useT2)
1550 // We have to use the Thumb-2 push single register encoding
1551 regNumber reg = genRegNumFromMask(imm);
1552 emitIns_R(ins, attr, reg);
1557 // Encode the PC and LR bits as the lowest two bits
1570 // TODO-ARM-Cleanup: Enable or delete.
1571 case INS_bkpt: // Windows uses a different encoding
1572 if ((imm & 0x0000ffff) == imm)
1578 assert(!"Instruction cannot be encoded");
1585 if ((imm & 0x000f) == imm)
1592 assert(!"Instruction cannot be encoded");
1599 assert((fmt == IF_T1_B) || (fmt == IF_T1_L0) || (fmt == IF_T1_L1) || (fmt == IF_T2_I1) || (fmt == IF_T2_B));
1601 instrDesc* id = emitNewInstrSC(attr, imm);
1602 insSize isz = emitInsSize(fmt);
1612 /*****************************************************************************
1614 * Add an instruction referencing a single register.
1617 void emitter::emitIns_R(instruction ins, emitAttr attr, regNumber reg)
1619 emitAttr size = EA_SIZE(attr);
1620 insFormat fmt = IF_NONE;
1622 /* Figure out the encoding format of the instruction */
1627 if (isLowRegister(reg))
1629 int regmask = 1 << ((int)reg);
1630 emitIns_I(ins, attr, regmask);
1633 assert(size == EA_PTRSIZE);
1638 assert(size == EA_PTRSIZE);
1643 assert(size == EA_PTRSIZE);
1648 emitIns_R_R_I(ins, attr, reg, reg, 0);
1654 assert((fmt == IF_T1_D1) || (fmt == IF_T2_E2));
1656 instrDesc* id = emitNewInstrSmall(attr);
1657 insSize isz = emitInsSize(fmt);
1668 /*****************************************************************************
1670 * Add an instruction referencing a register and a constant.
1673 void emitter::emitIns_R_I(
1674 instruction ins, emitAttr attr, regNumber reg, ssize_t imm, insFlags flags /* = INS_FLAGS_DONT_CARE */)
1677 insFormat fmt = IF_NONE;
1678 insFlags sf = INS_FLAGS_DONT_CARE;
1680 /* Figure out the encoding format of the instruction */
1685 if ((reg == REG_SP) && insDoesNotSetFlags(flags) && ((imm & 0x01fc) == imm))
1688 sf = INS_FLAGS_NOT_SET;
1690 else if (isLowRegister(reg) && insSetsFlags(flags) && (unsigned_abs(imm) <= 0x00ff))
1694 assert((ins == INS_add) || (ins == INS_sub));
1697 else // ins == INS_sub
1706 // otherwise we have to use a Thumb-2 encoding
1707 emitIns_R_R_I(ins, attr, reg, reg, imm, flags);
1713 emitIns_R_R_I(ins, attr, reg, reg, imm, flags);
1719 if (attr == EA_8BYTE)
1721 assert(isDoubleReg(reg));
1727 assert(attr == EA_4BYTE);
1728 assert(isFloatReg(reg));
1731 assert(((reg - REG_F0) + imm) <= 32);
1734 if (ins == INS_vpush)
1737 sf = INS_FLAGS_NOT_SET;
1743 sf = INS_FLAGS_NOT_SET;
1748 bool onlyT1 = false;
1750 assert((imm & 0x2000) == 0); // Cannot pop SP
1751 assert((imm & 0xC000) != 0xC000); // Cannot pop both PC and LR
1752 assert((imm & 0xFFFF0000) == 0); // Can only contain lower 16 bits
1754 if (imm & 0x8000) // Is the PC being popped?
1757 if (imm & 0x4000) // Is the LR being pushed?
1763 if (!isLowRegister(reg))
1766 if (((imm - 1) & imm) == 0) // Is only one or zero bits set in imm?
1768 if (((imm == 0) && !hasLR) || // imm has no bits set, but hasLR is set
1769 (!hasPC && !hasLR)) // imm has one bit set, and neither of hasPC/hasLR are set
1771 onlyT1 = true; // if only one bit is set we must use the T1 encoding
1775 imm &= ~0xE000; // ensure that PC, LR and SP bits are removed from imm
1777 if (((imm & 0x00ff) == imm) && !useT2)
1787 assert(!"Instruction cannot be encoded");
1788 // We have to use the Thumb-2 str single register encoding
1789 // reg = genRegNumFromMask(imm);
1790 // emitIns_R(ins, attr, reg);
1795 // Encode the PC and LR bits as the lowest two bits
1797 if (fmt == IF_T2_I0)
1821 // use the Reg, Reg, Imm encoding
1822 emitIns_R_R_I(ins, attr, reg, reg, imm, flags);
1826 assert(!EA_IS_CNS_RELOC(attr));
1828 if (isLowRegister(reg) && insSetsFlags(flags) && ((imm & 0x00ff) == imm))
1833 else if (isModImmConst(imm))
1836 sf = insMustSetFlags(flags);
1838 else if (isModImmConst(~imm)) // See if we can use move negated instruction instead
1843 sf = insMustSetFlags(flags);
1845 else if (insDoesNotSetFlags(flags) && ((imm & 0x0000ffff) == imm))
1847 // mov => movw instruction
1850 sf = INS_FLAGS_NOT_SET;
1854 assert(!"Instruction cannot be encoded");
1860 assert(insDoesNotSetFlags(flags));
1861 sf = INS_FLAGS_NOT_SET;
1862 if ((imm & 0x0000ffff) == imm || EA_IS_RELOC(attr))
1868 assert(!"Instruction cannot be encoded");
1873 if (isModImmConst(imm))
1876 sf = insMustSetFlags(flags);
1880 assert(!"Instruction cannot be encoded");
1885 assert(!EA_IS_CNS_RELOC(attr));
1886 assert(insSetsFlags(flags));
1888 if (isLowRegister(reg) && ((imm & 0x0ff) == imm))
1892 else if (isModImmConst(imm))
1896 else if (isModImmConst(-imm))
1904 assert(!"emitIns_R_I: immediate doesn't fit into the instruction");
1912 assert(insSetsFlags(flags));
1914 if (isModImmConst(imm))
1920 assert(!"Instruction cannot be encoded");
1924 #ifdef FEATURE_PLI_INSTRUCTION
1926 assert(insDoesNotSetFlags(flags));
1927 if ((reg == REG_SP) && (unsigned_abs(imm) <= 0x0fff))
1930 sf = INS_FLAGS_NOT_SET;
1933 #endif // FEATURE_PLI_INSTRUCTION
1937 assert(insDoesNotSetFlags(flags));
1938 sf = INS_FLAGS_NOT_SET;
1939 if ((imm >= 0) && (imm <= 0x0fff))
1943 else if ((imm < 0) && (-imm <= 0x00ff))
1950 assert(!"Instruction cannot be encoded");
1957 assert((fmt == IF_T1_F) || (fmt == IF_T1_J0) || (fmt == IF_T1_J1) || (fmt == IF_T2_H2) || (fmt == IF_T2_I0) ||
1958 (fmt == IF_T2_K2) || (fmt == IF_T2_K3) || (fmt == IF_T2_L1) || (fmt == IF_T2_L2) || (fmt == IF_T2_M1) ||
1959 (fmt == IF_T2_N) || (fmt == IF_T2_VLDST));
1961 assert(sf != INS_FLAGS_DONT_CARE);
1963 instrDesc* id = emitNewInstrSC(attr, imm);
1964 insSize isz = emitInsSize(fmt);
1976 /*****************************************************************************
1978 * Add an instruction referencing two registers
1981 void emitter::emitIns_R_R(
1982 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insFlags flags /* = INS_FLAGS_DONT_CARE */)
1985 emitAttr size = EA_SIZE(attr);
1986 insFormat fmt = IF_NONE;
1987 insFlags sf = INS_FLAGS_DONT_CARE;
1989 /* Figure out the encoding format of the instruction */
1993 if (insDoesNotSetFlags(flags))
1996 sf = INS_FLAGS_NOT_SET;
2002 // Use the Thumb-1 reg,reg,reg encoding
2003 emitIns_R_R_R(ins, attr, reg1, reg1, reg2, flags);
2007 if (insDoesNotSetFlags(flags))
2009 assert(reg1 != reg2);
2011 sf = INS_FLAGS_NOT_SET;
2013 else // insSetsFlags(flags)
2016 if (isLowRegister(reg1) && isLowRegister(reg2))
2028 assert(insSetsFlags(flags));
2030 if (isLowRegister(reg1) && isLowRegister(reg2))
2032 fmt = IF_T1_E; // both are low registers
2036 fmt = IF_T1_D0; // one or both are high registers
2041 assert(isGeneralRegister(reg1));
2042 assert(isFloatReg(reg2));
2044 sf = INS_FLAGS_NOT_SET;
2048 assert(isFloatReg(reg1));
2049 assert(isGeneralRegister(reg2));
2051 sf = INS_FLAGS_NOT_SET;
2057 assert(isFloatReg(reg1));
2058 assert(isDoubleReg(reg2));
2064 assert(isDoubleReg(reg1));
2065 assert(isFloatReg(reg2));
2072 assert(size == EA_4BYTE);
2073 assert(isFloatReg(reg1));
2074 assert(isFloatReg(reg2));
2078 assert(reg1 != reg2);
2085 if (size == EA_8BYTE)
2087 assert(isDoubleReg(reg1));
2088 assert(isDoubleReg(reg2));
2092 assert(isFloatReg(reg1));
2093 assert(isFloatReg(reg2));
2099 sf = INS_FLAGS_NOT_SET;
2106 emitIns_R_R_R(ins, attr, reg1, reg1, reg2);
2120 emitIns_R_R_I(ins, attr, reg1, reg2, 0);
2129 if (insSetsFlags(flags) && isLowRegister(reg1) && isLowRegister(reg2))
2138 // assert below fired for bug 281892 where the two operands of an OR were
2139 // the same static field load which got cse'd.
2140 // there's no reason why this assert would be true in general
2141 // assert(reg1 != reg2);
2142 // Use the Thumb-2 three register encoding
2143 emitIns_R_R_R_I(ins, attr, reg1, reg1, reg2, 0, flags);
2150 // assert below fired for bug 296394 where the two operands of an
2151 // arithmetic right shift were the same local variable
2152 // there's no reason why this assert would be true in general
2153 // assert(reg1 != reg2);
2154 if (insSetsFlags(flags) && isLowRegister(reg1) && isLowRegister(reg2))
2161 // Use the Thumb-2 three register encoding
2162 emitIns_R_R_R(ins, attr, reg1, reg1, reg2, flags);
2168 // We will prefer the T2 encoding, unless (flags == INS_FLAGS_SET)
2169 // The thumb-1 instruction executes much slower as it must always set the flags
2171 if (insMustSetFlags(flags) && isLowRegister(reg1) && isLowRegister(reg2))
2178 // Use the Thumb-2 three register encoding
2179 emitIns_R_R_R(ins, attr, reg1, reg2, reg1, flags);
2187 if (insSetsFlags(flags) && isLowRegister(reg1) && isLowRegister(reg2))
2194 // Use the Thumb-2 register with shift encoding
2195 emitIns_R_R_I(ins, attr, reg1, reg2, 0, flags);
2202 assert(size == EA_4BYTE);
2207 assert(size == EA_4BYTE);
2209 assert(insDoesNotSetFlags(flags));
2210 if (isLowRegister(reg1) && isLowRegister(reg2))
2213 sf = INS_FLAGS_NOT_SET;
2217 // Use the Thumb-2 reg,reg with rotation encoding
2218 emitIns_R_R_I(ins, attr, reg1, reg2, 0, INS_FLAGS_NOT_SET);
2224 assert(size == EA_1BYTE);
2225 assert(insDoesNotSetFlags(flags));
2227 sf = INS_FLAGS_NOT_SET;
2231 assert(size == EA_2BYTE);
2232 assert(insDoesNotSetFlags(flags));
2234 sf = INS_FLAGS_NOT_SET;
2238 assert(insDoesNotSetFlags(flags));
2240 sf = INS_FLAGS_NOT_SET;
2245 assert(size == EA_1BYTE);
2246 assert(insDoesNotSetFlags(flags));
2248 sf = INS_FLAGS_NOT_SET;
2253 assert(size == EA_2BYTE);
2254 assert(insDoesNotSetFlags(flags));
2256 sf = INS_FLAGS_NOT_SET;
2260 printf("did not expect instruction %s\n", codeGen->genInsName(ins));
2265 assert((fmt == IF_T1_D0) || (fmt == IF_T1_E) || (fmt == IF_T2_C3) || (fmt == IF_T2_C9) || (fmt == IF_T2_C10) ||
2266 (fmt == IF_T2_VFP2) || (fmt == IF_T2_VMOVD) || (fmt == IF_T2_VMOVS) || (fmt == IF_T2_E1));
2268 assert(sf != INS_FLAGS_DONT_CARE);
2270 instrDesc* id = emitNewInstrSmall(attr);
2271 insSize isz = emitInsSize(fmt);
2284 /*****************************************************************************
2286 * Add an instruction referencing a register and two constants.
2289 void emitter::emitIns_R_I_I(
2290 instruction ins, emitAttr attr, regNumber reg, int imm1, int imm2, insFlags flags /* = INS_FLAGS_DONT_CARE */)
2293 insFormat fmt = IF_NONE;
2294 insFlags sf = INS_FLAGS_DONT_CARE;
2295 int imm = 0; // combined immediates
2297 /* Figure out the encoding format of the instruction */
2303 int msb = lsb + imm2 - 1;
2305 assert((lsb >= 0) && (lsb <= 31)); // required for encoding of INS_bfc
2306 assert((msb >= 0) && (msb <= 31)); // required for encoding of INS_bfc
2307 assert(msb >= lsb); // required for encoding of INS_bfc
2309 imm = (lsb << 5) | msb;
2311 assert(insDoesNotSetFlags(flags));
2313 sf = INS_FLAGS_NOT_SET;
2320 assert(fmt == IF_T2_D1);
2321 assert(sf != INS_FLAGS_DONT_CARE);
2323 instrDesc* id = emitNewInstrSC(attr, imm);
2324 insSize isz = emitInsSize(fmt);
2336 /*****************************************************************************
2338 * Add an instruction referencing two registers and a constant.
2341 void emitter::emitIns_R_R_I(instruction ins,
2346 insFlags flags /* = INS_FLAGS_DONT_CARE */,
2347 insOpts opt /* = INS_OPTS_NONE */)
2349 emitAttr size = EA_SIZE(attr);
2350 insFormat fmt = IF_NONE;
2351 insFlags sf = INS_FLAGS_DONT_CARE;
2358 /* Figure out the encoding format of the instruction */
2362 assert(insOptsNone(opt));
2364 // Can we possibly encode the immediate 'imm' using a Thumb-1 encoding?
2365 if ((reg2 == REG_SP) && insDoesNotSetFlags(flags) && ((imm & 0x03fc) == imm))
2367 if ((reg1 == REG_SP) && ((imm & 0x01fc) == imm))
2369 // Use Thumb-1 encoding
2370 emitIns_R_I(ins, attr, reg1, imm, flags);
2373 else if (isLowRegister(reg1))
2376 sf = INS_FLAGS_NOT_SET;
2383 assert(insOptsNone(opt));
2385 // Is it just a mov?
2386 if ((imm == 0) && insDoesNotSetFlags(flags))
2388 // Is the mov even necessary?
2389 // Fix 383915 ARM ILGEN
2392 emitIns_R_R(INS_mov, attr, reg1, reg2, flags);
2396 // Can we encode the immediate 'imm' using a Thumb-1 encoding?
2397 else if (isLowRegister(reg1) && isLowRegister(reg2) && insSetsFlags(flags) && (unsigned_abs(imm) <= 0x0007))
2401 assert((ins == INS_add) || (ins == INS_sub));
2411 else if ((reg1 == reg2) && isLowRegister(reg1) && insSetsFlags(flags) && (unsigned_abs(imm) <= 0x00ff))
2415 assert((ins == INS_add) || (ins == INS_sub));
2422 // Use Thumb-1 encoding
2423 emitIns_R_I(ins, attr, reg1, imm, flags);
2426 else if (isModImmConst(imm))
2429 sf = insMustSetFlags(flags);
2431 else if (isModImmConst(-imm))
2433 assert((ins == INS_add) || (ins == INS_sub));
2434 ins = (ins == INS_add) ? INS_sub : INS_add;
2437 sf = insMustSetFlags(flags);
2439 else if (insDoesNotSetFlags(flags) && (unsigned_abs(imm) <= 0x0fff))
2443 assert((ins == INS_add) || (ins == INS_sub));
2444 ins = (ins == INS_add) ? INS_sub : INS_add;
2447 // add/sub => addw/subw instruction
2448 // Note that even when using the w prefix the immediate is still only 12 bits?
2449 ins = (ins == INS_add) ? INS_addw : INS_subw;
2451 sf = INS_FLAGS_NOT_SET;
2453 else if (insDoesNotSetFlags(flags) && (reg1 != REG_SP) && (reg1 != REG_PC))
2455 // movw,movt reg1, imm
2456 codeGen->instGen_Set_Reg_To_Imm(attr, reg1, (ins == INS_sub ? -1 : 1) * imm);
2459 emitIns_R_R(INS_add, attr, reg1, reg2);
2465 assert(!"Instruction cannot be encoded");
2473 assert(insOptsNone(opt));
2474 if (isModImmConst(imm))
2477 sf = insMustSetFlags(flags);
2479 else if (isModImmConst(~imm))
2482 sf = insMustSetFlags(flags);
2487 else if (ins == INS_bic)
2489 else if (ins == INS_orr)
2491 else if (ins == INS_orn)
2494 assert(!"Instruction cannot be encoded");
2498 assert(!"Instruction cannot be encoded");
2503 assert(insOptsNone(opt));
2504 if (imm == 0 && isLowRegister(reg1) && isLowRegister(reg2) && insSetsFlags(flags))
2515 assert(insOptsNone(opt));
2516 if (isModImmConst(imm))
2519 sf = insMustSetFlags(flags);
2523 assert(!"Instruction cannot be encoded");
2528 assert(insOptsNone(opt));
2529 assert(insDoesNotSetFlags(flags));
2530 assert(reg2 == REG_PC);
2531 sf = INS_FLAGS_NOT_SET;
2533 if (isLowRegister(reg1) && ((imm & 0x00ff) == imm))
2537 else if ((imm & 0x0fff) == imm)
2543 assert(!"Instruction cannot be encoded");
2548 assert((imm >= 0) && (imm <= 31)); // required for encoding
2549 assert(!insOptAnyInc(opt));
2552 assert(insOptsNone(opt));
2553 if (isLowRegister(reg1) && isLowRegister(reg2) && insSetsFlags(flags))
2555 // Use the Thumb-1 reg,reg encoding
2556 emitIns_R_R(ins, attr, reg1, reg2, flags);
2560 else // imm > 0 && imm <= 31
2562 assert(insOptAnyShift(opt));
2565 sf = insMustSetFlags(flags);
2572 assert(insSetsFlags(flags));
2573 assert((imm >= 0) && (imm <= 31)); // required for encoding
2574 assert(!insOptAnyInc(opt));
2577 assert(insOptsNone(opt));
2580 // Use the Thumb-1 reg,reg encoding
2581 emitIns_R_R(ins, attr, reg1, reg2, flags);
2584 if (((ins == INS_cmn) || (ins == INS_tst)) && isLowRegister(reg1) && isLowRegister(reg2))
2586 // Use the Thumb-1 reg,reg encoding
2587 emitIns_R_R(ins, attr, reg1, reg2, flags);
2591 else // imm > 0 && imm <= 31)
2593 assert(insOptAnyShift(opt));
2594 if (insOptsRRX(opt))
2606 assert(insOptsNone(opt));
2608 // On ARM, the immediate shift count of LSL and ROR must be between 1 and 31. For LSR and ASR, it is between
2609 // 1 and 32, though we don't ever use 32. Although x86 allows an immediate shift count of 8-bits in
2610 // instruction encoding, the CPU looks at only the lower 5 bits. As per ECMA, specifying a shift count to
2611 // the IL SHR, SHL, or SHL.UN instruction that is greater than or equal to the width of the type will yield
2612 // an undefined value. We choose that undefined value in this case to match x86 behavior, by only using the
2613 // lower 5 bits of the constant shift count.
2618 // Additional Fix 383915 ARM ILGEN
2619 if ((reg1 != reg2) || insMustSetFlags(flags))
2621 // Use MOV/MOVS instriction
2622 emitIns_R_R(INS_mov, attr, reg1, reg2, flags);
2627 if (insSetsFlags(flags) && (ins != INS_ror) && isLowRegister(reg1) && isLowRegister(reg2))
2635 sf = insMustSetFlags(flags);
2641 assert(size == EA_4BYTE);
2646 assert(size == EA_4BYTE);
2648 assert(insOptsNone(opt));
2649 assert(insDoesNotSetFlags(flags));
2650 assert((imm & 0x018) == imm); // required for encoding
2652 if ((imm == 0) && isLowRegister(reg1) && isLowRegister(reg2))
2654 // Use Thumb-1 encoding
2655 emitIns_R_R(ins, attr, reg1, reg2, INS_FLAGS_NOT_SET);
2660 sf = INS_FLAGS_NOT_SET;
2665 #ifdef FEATURE_PLI_INSTRUCTION
2667 #endif // FEATURE_PLI_INSTRUCTION
2668 assert(insOptsNone(opt));
2669 assert(insDoesNotSetFlags(flags));
2670 assert((imm & 0x003) == imm); // required for encoding
2673 sf = INS_FLAGS_NOT_SET;
2678 assert(size == EA_1BYTE);
2679 assert(insDoesNotSetFlags(flags));
2681 if (isLowRegister(reg1) && isLowRegister(reg2) && insOptsNone(opt) && ((imm & 0x001f) == imm))
2684 sf = INS_FLAGS_NOT_SET;
2687 goto COMMON_THUMB2_LDST;
2690 assert(size == EA_1BYTE);
2691 goto COMMON_THUMB2_LDST;
2695 assert(size == EA_2BYTE);
2696 assert(insDoesNotSetFlags(flags));
2698 if (isLowRegister(reg1) && isLowRegister(reg2) && insOptsNone(opt) && ((imm & 0x003e) == imm))
2701 sf = INS_FLAGS_NOT_SET;
2704 goto COMMON_THUMB2_LDST;
2707 assert(size == EA_2BYTE);
2708 goto COMMON_THUMB2_LDST;
2714 assert(fmt == IF_NONE);
2715 assert(insDoesNotSetFlags(flags));
2716 assert(offsetFitsInVectorMem(imm)); // required for encoding
2717 if (insOptAnyInc(opt))
2719 if (insOptsPostInc(opt))
2723 else // insOptsPreDec(opt)
2730 assert(insOptsNone(opt));
2733 sf = INS_FLAGS_NOT_SET;
2739 assert(size == EA_4BYTE);
2740 assert(insDoesNotSetFlags(flags));
2742 // Can we possibly encode the immediate 'imm' using a Thumb-1 encoding?
2743 if (isLowRegister(reg1) && insOptsNone(opt) && ((imm & 0x03fc) == imm))
2748 sf = INS_FLAGS_NOT_SET;
2751 else if (reg2 == REG_PC)
2756 sf = INS_FLAGS_NOT_SET;
2760 else if (isLowRegister(reg2))
2762 // Only the smaller range 'imm' can be encoded
2763 if ((imm & 0x07c) == imm)
2766 sf = INS_FLAGS_NOT_SET;
2772 // If we did not find a thumb-1 encoding above
2777 assert(fmt == IF_NONE);
2778 assert(insDoesNotSetFlags(flags));
2779 sf = INS_FLAGS_NOT_SET;
2781 if (insOptAnyInc(opt))
2783 if (insOptsPostInc(opt))
2785 else // insOptsPreDec(opt)
2788 if (unsigned_abs(imm) <= 0x00ff)
2794 assert(!"Instruction cannot be encoded");
2799 assert(insOptsNone(opt));
2800 if ((reg2 == REG_PC) && (unsigned_abs(imm) <= 0x0fff))
2804 else if ((imm & 0x0fff) == imm)
2808 else if (unsigned_abs(imm) <= 0x0ff)
2814 // Load imm into a register
2815 regNumber rsvdReg = codeGen->rsGetRsvdReg();
2816 codeGen->instGen_Set_Reg_To_Imm(EA_4BYTE, rsvdReg, (ssize_t)imm);
2817 emitIns_R_R_R(ins, attr, reg1, reg2, rsvdReg);
2825 assert(insOptsNone(opt));
2826 assert(insDoesNotSetFlags(flags));
2827 sf = INS_FLAGS_NOT_SET;
2829 if ((imm & 0x03fc) == imm)
2835 assert(!"Instruction cannot be encoded");
2840 assert(!"Unexpected instruction");
2842 assert((fmt == IF_T1_C) || (fmt == IF_T1_E) || (fmt == IF_T1_G) || (fmt == IF_T1_J2) || (fmt == IF_T1_J3) ||
2843 (fmt == IF_T2_C1) || (fmt == IF_T2_C2) || (fmt == IF_T2_C6) || (fmt == IF_T2_C7) || (fmt == IF_T2_C8) ||
2844 (fmt == IF_T2_H0) || (fmt == IF_T2_H1) || (fmt == IF_T2_K1) || (fmt == IF_T2_K4) || (fmt == IF_T2_L0) ||
2845 (fmt == IF_T2_M0) || (fmt == IF_T2_VLDST) || (fmt == IF_T2_M1));
2846 assert(sf != INS_FLAGS_DONT_CARE);
2848 instrDesc* id = emitNewInstrSC(attr, imm);
2849 insSize isz = emitInsSize(fmt);
2863 /*****************************************************************************
2865 * Add an instruction referencing three registers.
2868 void emitter::emitIns_R_R_R(instruction ins,
2873 insFlags flags /* = INS_FLAGS_DONT_CARE */)
2875 emitAttr size = EA_SIZE(attr);
2876 insFormat fmt = IF_NONE;
2877 insFlags sf = INS_FLAGS_DONT_CARE;
2879 /* Figure out the encoding format of the instruction */
2883 // Encodings do not support SP in the reg3 slot
2886 // Swap reg2 and reg3
2893 assert(reg3 != REG_SP);
2895 if (isLowRegister(reg1) && isLowRegister(reg2) && isLowRegister(reg3) && insSetsFlags(flags))
2902 if ((ins == INS_add) && insDoesNotSetFlags(flags))
2906 // Use the Thumb-1 regdest,reg encoding
2907 emitIns_R_R(ins, attr, reg1, reg3, flags);
2912 // Use the Thumb-1 regdest,reg encoding
2913 emitIns_R_R(ins, attr, reg1, reg2, flags);
2918 // Use the Thumb-2 reg,reg,reg with shift encoding
2919 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, flags);
2930 // Try to encode as a Thumb-1 instruction
2931 emitIns_R_R(ins, attr, reg1, reg3, flags);
2937 // Use the Thumb-2 three register encoding, with imm=0
2938 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, flags);
2944 if (reg1 == reg2 && insSetsFlags(flags) && isLowRegister(reg1) && isLowRegister(reg3))
2946 // Use the Thumb-1 regdest,reg encoding
2947 emitIns_R_R(ins, attr, reg1, reg3, flags);
2954 sf = insMustSetFlags(flags);
2958 if (insMustSetFlags(flags))
2960 if ((reg1 == reg2) && isLowRegister(reg1))
2962 // Use the Thumb-1 regdest,reg encoding
2963 emitIns_R_R(ins, attr, reg1, reg3, flags);
2966 if ((reg1 == reg3) && isLowRegister(reg1))
2968 // Use the Thumb-1 regdest,reg encoding
2969 emitIns_R_R(ins, attr, reg1, reg2, flags);
2974 assert(!"Instruction cannot be encoded");
2979 #if !defined(USE_HELPERS_FOR_INT_DIV)
2982 #endif // !USE_HELPERS_FOR_INT_DIV
2984 assert(insDoesNotSetFlags(flags));
2986 sf = INS_FLAGS_NOT_SET;
2992 assert(size == EA_1BYTE);
2993 goto COMMON_THUMB1_LDST;
2998 assert(size == EA_2BYTE);
2999 goto COMMON_THUMB1_LDST;
3003 assert(size == EA_4BYTE);
3006 assert(insDoesNotSetFlags(flags));
3008 if (isLowRegister(reg1) && isLowRegister(reg2) && isLowRegister(reg3))
3011 sf = INS_FLAGS_NOT_SET;
3015 // Use the Thumb-2 reg,reg,reg with shift encoding
3016 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, flags);
3025 if (size == EA_8BYTE)
3027 assert(isDoubleReg(reg1));
3028 assert(isDoubleReg(reg2));
3029 assert(isDoubleReg(reg3));
3033 assert(isFloatReg(reg1));
3034 assert(isFloatReg(reg2));
3035 assert(isFloatReg(reg3));
3038 sf = INS_FLAGS_NOT_SET;
3042 assert(isDoubleReg(reg1));
3043 assert(isGeneralRegister(reg2));
3044 assert(isGeneralRegister(reg3));
3046 sf = INS_FLAGS_NOT_SET;
3050 assert(isGeneralRegister(reg1));
3051 assert(isGeneralRegister(reg2));
3052 assert(isDoubleReg(reg3));
3054 sf = INS_FLAGS_NOT_SET;
3059 assert(insDoesNotSetFlags(flags));
3061 sf = INS_FLAGS_NOT_SET;
3067 assert((fmt == IF_T1_H) || (fmt == IF_T2_C4) || (fmt == IF_T2_C5) || (fmt == IF_T2_VFP3) || (fmt == IF_T2_VMOVD) ||
3069 assert(sf != INS_FLAGS_DONT_CARE);
3071 instrDesc* id = emitNewInstr(attr);
3072 insSize isz = emitInsSize(fmt);
3086 /*****************************************************************************
3088 * Add an instruction referencing two registers and two constants.
3091 void emitter::emitIns_R_R_I_I(instruction ins,
3097 insFlags flags /* = INS_FLAGS_DONT_CARE */)
3099 insFormat fmt = IF_NONE;
3100 insFlags sf = INS_FLAGS_DONT_CARE;
3104 int msb = lsb + width - 1;
3105 int imm = 0; /* combined immediate */
3107 assert((lsb >= 0) && (lsb <= 31)); // required for encodings
3108 assert((width > 0) && (width <= 32)); // required for encodings
3109 assert((msb >= 0) && (msb <= 31)); // required for encodings
3110 assert(msb >= lsb); // required for encodings
3112 /* Figure out the encoding format of the instruction */
3116 assert(insDoesNotSetFlags(flags));
3117 imm = (lsb << 5) | msb;
3120 sf = INS_FLAGS_NOT_SET;
3125 assert(insDoesNotSetFlags(flags));
3126 imm = (lsb << 5) | (width - 1);
3129 sf = INS_FLAGS_NOT_SET;
3135 assert((fmt == IF_T2_D0));
3136 assert(sf != INS_FLAGS_DONT_CARE);
3138 instrDesc* id = emitNewInstrSC(attr, imm);
3139 insSize isz = emitInsSize(fmt);
3152 /*****************************************************************************
3154 * Add an instruction referencing three registers and a constant.
3157 void emitter::emitIns_R_R_R_I(instruction ins,
3163 insFlags flags /* = INS_FLAGS_DONT_CARE */,
3164 insOpts opt /* = INS_OPTS_NONE */)
3166 emitAttr size = EA_SIZE(attr);
3167 insFormat fmt = IF_NONE;
3168 insFlags sf = INS_FLAGS_DONT_CARE;
3170 /* Figure out the encoding format of the instruction */
3178 if (isLowRegister(reg1) && isLowRegister(reg2) && isLowRegister(reg3) && insSetsFlags(flags))
3180 // Use the Thumb-1 reg,reg,reg encoding
3181 emitIns_R_R_R(ins, attr, reg1, reg2, reg3, flags);
3184 if ((ins == INS_add) && insDoesNotSetFlags(flags))
3188 // Use the Thumb-1 regdest,reg encoding
3189 emitIns_R_R(ins, attr, reg1, reg3, flags);
3194 // Use the Thumb-1 regdest,reg encoding
3195 emitIns_R_R(ins, attr, reg1, reg2, flags);
3209 assert((imm >= 0) && (imm <= 31)); // required for encoding
3210 assert(!insOptAnyInc(opt));
3213 if (opt == INS_OPTS_LSL) // left shift of zero
3214 opt = INS_OPTS_NONE; // is a nop
3216 assert(insOptsNone(opt));
3217 if (isLowRegister(reg1) && isLowRegister(reg2) && isLowRegister(reg3) && insSetsFlags(flags))
3221 // Use the Thumb-1 regdest,reg encoding
3222 emitIns_R_R(ins, attr, reg1, reg3, flags);
3225 if ((reg1 == reg3) && (ins != INS_bic) && (ins != INS_orn) && (ins != INS_sbc))
3227 // Use the Thumb-1 regdest,reg encoding
3228 emitIns_R_R(ins, attr, reg1, reg2, flags);
3233 else // imm > 0 && imm <= 31)
3235 assert(insOptAnyShift(opt));
3236 if (insOptsRRX(opt))
3240 sf = insMustSetFlags(flags);
3246 assert(size == EA_1BYTE);
3247 goto COMMON_THUMB2_LDST;
3252 assert(size == EA_2BYTE);
3253 goto COMMON_THUMB2_LDST;
3257 assert(size == EA_4BYTE);
3260 assert(insDoesNotSetFlags(flags));
3261 assert((imm & 0x0003) == imm); // required for encoding
3263 if ((imm == 0) && insOptsNone(opt) && isLowRegister(reg1) && isLowRegister(reg2) && isLowRegister(reg3))
3265 // Use the Thumb-1 reg,reg,reg encoding
3266 emitIns_R_R_R(ins, attr, reg1, reg2, reg3, flags);
3269 assert(insOptsNone(opt) || insOptsLSL(opt));
3271 sf = INS_FLAGS_NOT_SET;
3276 assert(insDoesNotSetFlags(flags));
3277 assert((imm & 0x03) == 0);
3278 sf = INS_FLAGS_NOT_SET;
3280 if (insOptAnyInc(opt))
3282 if (insOptsPostInc(opt))
3284 else // insOptsPreDec(opt)
3289 assert(insOptsNone(opt));
3292 if (unsigned_abs(imm) <= 0x03fc)
3299 assert(!"Instruction cannot be encoded");
3306 assert((fmt == IF_T2_C0) || (fmt == IF_T2_E0) || (fmt == IF_T2_G0));
3307 assert(sf != INS_FLAGS_DONT_CARE);
3309 // 3-reg ops can't use the small instrdesc
3310 instrDescCns* id = emitAllocInstrCns(attr);
3311 id->idSetIsLargeCns();
3312 id->idcCnsVal = imm;
3316 id->idInsSize(emitInsSize(fmt));
3328 /*****************************************************************************
3330 * Add an instruction referencing four registers.
3333 void emitter::emitIns_R_R_R_R(
3334 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, regNumber reg4)
3336 insFormat fmt = IF_NONE;
3337 insFlags sf = INS_FLAGS_NOT_SET;
3339 /* Figure out the encoding format of the instruction */
3347 assert(reg1 != reg2); // Illegal encoding
3357 assert((fmt == IF_T2_F1) || (fmt == IF_T2_F2));
3359 instrDesc* id = emitNewInstr(attr);
3360 insSize isz = emitInsSize(fmt);
3375 /*****************************************************************************
3377 * Add an instruction with a static data member operand. If 'size' is 0, the
3378 * instruction operates on the address of the static member instead of its
3379 * value (e.g. "push offset clsvar", rather than "push dword ptr [clsvar]").
3382 void emitter::emitIns_C(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, int offs)
3387 /*****************************************************************************
3389 * Add an instruction referencing stack-based local variable.
3392 void emitter::emitIns_S(instruction ins, emitAttr attr, int varx, int offs)
3397 /*****************************************************************************
3399 * Add an instruction referencing a register and a stack-based local variable.
3401 void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
3405 assert(!"Please use ins_Load() to select the correct instruction");
3431 insFormat fmt = IF_NONE;
3432 insFlags sf = INS_FLAGS_NOT_SET;
3435 /* Figure out the variable's frame position */
3440 base = emitComp->lvaFrameAddress(varx, emitComp->funCurrentFunc()->funKind != FUNC_ROOT, ®2, offs);
3443 undisp = unsigned_abs(disp);
3445 if (CodeGen::instIsFP(ins))
3447 // all fp mem ops take 8 bit immediate, multiplied by 4, plus sign
3449 // Note if undisp is not a multiple of four we will fail later on
3450 // when we try to encode this instruction
3451 // Its better to fail later with a better error message than
3452 // to fail here when the RBM_OPT_RSVD is not available
3454 if (undisp <= 0x03fc)
3460 regNumber rsvdReg = codeGen->rsGetRsvdReg();
3461 emitIns_genStackOffset(rsvdReg, varx, offs);
3462 emitIns_R_R(INS_add, EA_4BYTE, rsvdReg, reg2);
3463 emitIns_R_R_I(ins, attr, reg1, rsvdReg, 0);
3467 else if (emitInsIsLoadOrStore(ins))
3469 if (isLowRegister(reg1) && (reg2 == REG_SP) && (ins == INS_ldr) && ((disp & 0x03fc) == disp))
3473 else if (disp >= 0 && disp <= 0x0fff)
3477 else if (undisp <= 0x0ff)
3483 // Load disp into a register
3484 regNumber rsvdReg = codeGen->rsGetRsvdReg();
3485 emitIns_genStackOffset(rsvdReg, varx, offs);
3489 else if (ins == INS_add)
3491 if (isLowRegister(reg1) && (reg2 == REG_SP) && ((disp & 0x03fc) == disp))
3495 else if (undisp <= 0x0fff)
3502 // add/sub => addw/subw instruction
3503 // Note that even when using the w prefix the immediate is still only 12 bits?
3504 ins = (ins == INS_add) ? INS_addw : INS_subw;
3509 // Load disp into a register
3510 regNumber rsvdReg = codeGen->rsGetRsvdReg();
3511 emitIns_genStackOffset(rsvdReg, varx, offs);
3512 emitIns_R_R_R(ins, attr, reg1, reg2, rsvdReg);
3516 else if (ins == INS_movw || ins == INS_movt)
3521 assert((fmt == IF_T1_J2) || (fmt == IF_T2_E0) || (fmt == IF_T2_H0) || (fmt == IF_T2_K1) || (fmt == IF_T2_L0) ||
3522 (fmt == IF_T2_N) || (fmt == IF_T2_VLDST) || (fmt == IF_T2_M0));
3523 assert(sf != INS_FLAGS_DONT_CARE);
3525 instrDesc* id = emitNewInstrCns(attr, disp);
3526 insSize isz = emitInsSize(fmt);
3532 id->idInsOpt(INS_OPTS_NONE);
3535 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
3536 id->idSetIsLclVar();
3538 id->idSetIsLclFPBase();
3541 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
3548 // generate the offset of &varx + offs into a register
3549 void emitter::emitIns_genStackOffset(regNumber r, int varx, int offs)
3555 base = emitComp->lvaFrameAddress(varx, emitComp->funCurrentFunc()->funKind != FUNC_ROOT, ®Base, offs);
3558 emitIns_R_S(INS_movw, EA_4BYTE, r, varx, offs);
3560 if ((disp & 0xffff) != disp)
3562 emitIns_R_S(INS_movt, EA_4BYTE, r, varx, offs);
3566 /*****************************************************************************
3568 * Add an instruction referencing a stack-based local variable and a register
3570 void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
3574 assert(!"Please use ins_Store() to select the correct instruction");
3590 insFormat fmt = IF_NONE;
3591 insFlags sf = INS_FLAGS_NOT_SET;
3594 /* Figure out the variable's frame position */
3599 base = emitComp->lvaFrameAddress(varx, emitComp->funCurrentFunc()->funKind != FUNC_ROOT, ®2, offs);
3602 undisp = unsigned_abs(disp);
3604 if (CodeGen::instIsFP(ins))
3606 // all fp mem ops take 8 bit immediate, multiplied by 4, plus sign
3608 // Note if undisp is not a multiple of four we will fail later on
3609 // when we try to encode this instruction
3610 // Its better to fail later with a better error message than
3611 // to fail here when the RBM_OPT_RSVD is not available
3613 if (undisp <= 0x03fc)
3619 regNumber rsvdReg = codeGen->rsGetRsvdReg();
3620 emitIns_genStackOffset(rsvdReg, varx, offs);
3621 emitIns_R_R(INS_add, EA_4BYTE, rsvdReg, reg2);
3622 emitIns_R_R_I(ins, attr, reg1, rsvdReg, 0);
3626 else if (isLowRegister(reg1) && (reg2 == REG_SP) && (ins == INS_str) && ((disp & 0x03fc) == disp))
3630 else if (disp >= 0 && disp <= 0x0fff)
3634 else if (undisp <= 0x0ff)
3640 // Load disp into a register
3641 regNumber rsvdReg = codeGen->rsGetRsvdReg();
3642 emitIns_genStackOffset(rsvdReg, varx, offs);
3645 assert((fmt == IF_T1_J2) || (fmt == IF_T2_E0) || (fmt == IF_T2_H0) || (fmt == IF_T2_VLDST) || (fmt == IF_T2_K1));
3646 assert(sf != INS_FLAGS_DONT_CARE);
3648 instrDesc* id = emitNewInstrCns(attr, disp);
3649 insSize isz = emitInsSize(fmt);
3655 id->idInsOpt(INS_OPTS_NONE);
3658 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
3659 id->idSetIsLclVar();
3661 id->idSetIsLclFPBase();
3663 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
3670 /*****************************************************************************
3672 * Add an instruction referencing stack-based local variable and an immediate
3674 void emitter::emitIns_S_I(instruction ins, emitAttr attr, int varx, int offs, int val)
3679 /*****************************************************************************
3681 * Add an instruction with a register + static member operands.
3683 void emitter::emitIns_R_C(instruction ins, emitAttr attr, regNumber reg, CORINFO_FIELD_HANDLE fldHnd, int offs)
3687 assert(!"Please use ins_Load() to select the correct instruction");
3689 assert(emitInsIsLoad(ins) || (ins == INS_lea));
3695 int doff = Compiler::eeGetJitDataOffs(fldHnd);
3696 ssize_t addr = NULL;
3700 NYI_ARM("JitDataOffset static fields");
3702 else if (fldHnd == FLD_GLOBAL_FS)
3704 NYI_ARM("Thread-Local-Storage static fields");
3706 else if (fldHnd == FLD_GLOBAL_DS)
3708 addr = (ssize_t)offs;
3713 assert(!jitStaticFldIsGlobAddr(fldHnd));
3714 addr = (ssize_t)emitComp->info.compCompHnd->getFieldAddress(fldHnd, NULL);
3716 NO_WAY("could not obtain address of static field");
3719 // We can use reg to load the constant address,
3720 // as long as it is not a floating point register
3721 regNumber regTmp = reg;
3723 if (isFloatReg(regTmp))
3725 assert(!"emitIns_R_C() cannot be called with floating point target");
3729 // Load address of CLS_VAR into a register
3730 codeGen->instGen_Set_Reg_To_Imm(EA_HANDLE_CNS_RELOC, regTmp, addr);
3732 if ((ins != INS_add) || (offs != 0) || (reg != regTmp))
3734 emitIns_R_R_I(ins, attr, reg, regTmp, offs);
3738 /*****************************************************************************
3740 * Add an instruction with a static member + register operands.
3743 void emitter::emitIns_C_R(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, regNumber reg, int offs)
3745 assert(!"emitIns_C_R not supported");
3748 /*****************************************************************************
3750 * Add an instruction with a static member + constant.
3753 void emitter::emitIns_C_I(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, int offs, ssize_t val)
3758 /*****************************************************************************
3760 * The following adds instructions referencing address modes.
3763 void emitter::emitIns_I_AR(instruction ins, emitAttr attr, int val, regNumber reg, int offs)
3765 NYI("emitIns_I_AR");
3768 void emitter::emitIns_R_AR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
3772 assert(!"Please use ins_Load() to select the correct instruction");
3777 if (emitter::emitIns_valid_imm_for_add(offs, INS_FLAGS_DONT_CARE))
3779 emitIns_R_R_I(INS_add, attr, ireg, reg, offs);
3783 assert(!"emitIns_R_AR: immediate doesn't fit in the instruction");
3787 else if (emitInsIsLoad(ins))
3789 emitIns_R_R_I(ins, attr, ireg, reg, offs);
3792 else if ((ins == INS_mov) || (ins == INS_ldr))
3794 if (EA_SIZE(attr) == EA_4BYTE)
3796 emitIns_R_R_I(INS_ldr, attr, ireg, reg, offs);
3800 else if (ins == INS_vldr)
3802 emitIns_R_R_I(ins, attr, ireg, reg, offs);
3804 NYI("emitIns_R_AR");
3807 void emitter::emitIns_R_AI(instruction ins, emitAttr attr, regNumber ireg, ssize_t disp)
3809 if (emitInsIsLoad(ins))
3811 // We can use ireg to load the constant address,
3812 // as long as it is not a floating point register
3813 regNumber regTmp = ireg;
3815 if (isFloatReg(regTmp))
3817 assert(!"emitIns_R_AI with floating point reg");
3821 codeGen->instGen_Set_Reg_To_Imm(EA_IS_RELOC(attr) ? EA_HANDLE_CNS_RELOC : EA_PTRSIZE, regTmp, disp);
3822 emitIns_R_R_I(ins, EA_TYPE(attr), ireg, regTmp, 0);
3825 NYI("emitIns_R_AI");
3828 void emitter::emitIns_AR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
3832 assert(!"Please use ins_Store() to select the correct instruction");
3834 emitIns_R_R_I(ins, attr, ireg, reg, offs);
3837 void emitter::emitIns_R_ARR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
3841 assert(!"Please use ins_Load() to select the correct instruction");
3846 emitIns_R_R_R(INS_add, attr, ireg, reg, rg2);
3849 emitIns_R_R_I(INS_add, attr, ireg, ireg, disp);
3853 else if (emitInsIsLoad(ins))
3857 emitIns_R_R_R_I(ins, attr, ireg, reg, rg2, 0, INS_FLAGS_DONT_CARE, INS_OPTS_NONE);
3861 assert(!"emitIns_R_ARR: Unexpected instruction");
3864 void emitter::emitIns_ARR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
3868 assert(!"Please use ins_Store() to select the correct instruction");
3870 if (emitInsIsStore(ins))
3874 emitIns_R_R_R(ins, attr, ireg, reg, rg2);
3878 emitIns_R_R_R(INS_add, attr, ireg, reg, rg2);
3879 emitIns_R_R_I(ins, attr, ireg, ireg, disp);
3883 assert(!"emitIns_ARR_R: Unexpected instruction");
3886 void emitter::emitIns_R_ARX(
3887 instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, unsigned mul, int disp)
3891 assert(!"Please use ins_Load() to select the correct instruction");
3894 unsigned shift = genLog2((unsigned)mul);
3896 if ((ins == INS_lea) || emitInsIsLoad(ins))
3904 emitIns_R_R_R_I(ins, attr, ireg, reg, rg2, (int)shift, INS_FLAGS_DONT_CARE, INS_OPTS_LSL);
3909 bool useForm2 = false;
3910 bool mustUseForm1 = ((disp % mul) != 0) || (reg == ireg);
3913 // If all of the below things are true we can generate a Thumb-1 add instruction
3914 // followed by a Thumb-2 add instruction
3915 // We also useForm1 when reg is a low register since the second instruction
3916 // can then always be generated using a Thumb-1 add
3918 if ((reg >= REG_R8) && (ireg < REG_R8) && (rg2 < REG_R8) && ((disp >> shift) <= 7))
3927 // Thumb-1 instruction add Rd, Rx, disp>>shift
3928 // Thumb-2 instructions ldr Rd, Rb, Rd LSL shift
3930 emitIns_R_R_I(INS_add, EA_4BYTE, ireg, rg2, disp >> shift);
3931 emitIns_R_R_R_I(ins, attr, ireg, reg, ireg, shift, INS_FLAGS_NOT_SET, INS_OPTS_LSL);
3936 // Thumb-2 instruction add Rd, Rb, Rx LSL shift
3937 // Thumb-1/2 instructions ldr Rd, Rd, disp
3939 emitIns_R_R_R_I(INS_add, attr, ireg, reg, rg2, shift, INS_FLAGS_NOT_SET, INS_OPTS_LSL);
3940 emitIns_R_R_I(ins, attr, ireg, ireg, disp);
3946 assert(!"emitIns_R_ARX: Unexpected instruction");
3949 /*****************************************************************************
3951 * Record that a jump instruction uses the short encoding
3954 void emitter::emitSetShortJump(instrDescJmp* id)
3956 if (id->idjKeepLong)
3959 if (emitIsCondJump(id))
3961 id->idInsFmt(IF_T1_K);
3963 else if (emitIsCmpJump(id))
3965 // These are always only ever short!
3966 assert(id->idjShort);
3969 else if (emitIsUncondJump(id))
3971 id->idInsFmt(IF_T1_M);
3973 else if (emitIsLoadLabel(id))
3975 return; // Keep long - we don't know the alignment of the target
3979 assert(!"Unknown instruction in emitSetShortJump()");
3982 id->idjShort = true;
3985 if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
3987 printf("[8] Converting jump %u to short\n", id->idDebugOnlyInfo()->idNum);
3989 #endif // DEBUG_EMIT
3991 insSize isz = emitInsSize(id->idInsFmt());
3995 /*****************************************************************************
3997 * Record that a jump instruction uses the medium encoding
4000 void emitter::emitSetMediumJump(instrDescJmp* id)
4002 if (id->idjKeepLong)
4006 if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
4008 printf("[9] Converting jump %u to medium\n", id->idDebugOnlyInfo()->idNum);
4010 #endif // DEBUG_EMIT
4012 assert(emitIsCondJump(id));
4013 id->idInsFmt(IF_T2_J1);
4014 id->idjShort = false;
4016 insSize isz = emitInsSize(id->idInsFmt());
4020 /*****************************************************************************
4022 * Add a jmp instruction.
4023 * When dst is NULL, instrCount specifies number of instructions
4024 * to jump: positive is forward, negative is backward.
4025 * Unconditional branches have two sizes: short and long.
4026 * Conditional branches have three sizes: short, medium, and long. A long
4027 * branch is a pseudo-instruction that represents two instructions:
4028 * a short conditional branch to branch around a large unconditional
4029 * branch. Thus, we can handle branch offsets of imm24 instead of just imm20.
4032 void emitter::emitIns_J(instruction ins, BasicBlock* dst, int instrCount /* = 0 */)
4034 insFormat fmt = IF_NONE;
4038 assert(dst->bbFlags & BBF_JMP_TARGET);
4042 assert(instrCount != 0);
4045 /* Figure out the encoding format of the instruction */
4049 fmt = IF_T2_J2; /* Assume the jump will be long */
4066 fmt = IF_LARGEJMP; /* Assume the jump will be long */
4072 assert((fmt == IF_LARGEJMP) || (fmt == IF_T2_J2));
4074 instrDescJmp* id = emitNewInstrJmp();
4075 insSize isz = emitInsSize(fmt);
4082 // Mark the finally call
4083 if (ins == INS_b && emitComp->compCurBB->bbJumpKind == BBJ_CALLFINALLY)
4085 id->idDebugOnlyInfo()->idFinallyCall = true;
4089 /* Assume the jump will be long */
4094 id->idAddr()->iiaBBlabel = dst;
4095 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
4098 if (emitComp->opts.compLongAddress) // Force long branches
4099 id->idjKeepLong = 1;
4104 id->idAddr()->iiaSetInstrCount(instrCount);
4105 id->idjKeepLong = false;
4106 /* This jump must be short */
4107 emitSetShortJump(id);
4111 /* Record the jump's IG and offset within it */
4113 id->idjIG = emitCurIG;
4114 id->idjOffs = emitCurIGsize;
4116 /* Append this jump to this IG's jump list */
4118 id->idjNext = emitCurIGjmpList;
4119 emitCurIGjmpList = id;
4125 /* Figure out the max. size of the jump/call instruction */
4127 if (!id->idjKeepLong)
4129 insGroup* tgt = NULL;
4131 /* Can we guess at the jump distance? */
4135 tgt = (insGroup*)emitCodeGetCookie(dst);
4140 UNATIVE_OFFSET srcOffs;
4143 assert(JMP_SIZE_SMALL == JCC_SIZE_SMALL);
4145 /* This is a backward jump - figure out the distance */
4147 srcOffs = emitCurCodeOffset + emitCurIGsize;
4149 /* Compute the distance estimate */
4151 jmpDist = srcOffs - tgt->igOffs;
4152 assert(jmpDist >= 0);
4153 jmpDist += 4; // Adjustment for ARM PC
4158 if (JMP_DIST_SMALL_MAX_NEG <= -jmpDist)
4160 /* This jump surely will be short */
4161 emitSetShortJump(id);
4166 if (JCC_DIST_SMALL_MAX_NEG <= -jmpDist)
4168 /* This jump surely will be short */
4169 emitSetShortJump(id);
4171 else if (JCC_DIST_MEDIUM_MAX_NEG <= -jmpDist)
4173 /* This jump surely will be medium */
4174 emitSetMediumJump(id);
4189 /*****************************************************************************
4191 * Add a label instruction.
4194 void emitter::emitIns_R_L(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
4196 assert(dst->bbFlags & BBF_JMP_TARGET);
4198 insFormat fmt = IF_NONE;
4201 /* Figure out the encoding format of the instruction */
4205 id = emitNewInstrLbl();
4210 id = emitNewInstrJmp();
4216 assert((fmt == IF_T2_M1) || (fmt == IF_T2_N1));
4218 insSize isz = emitInsSize(fmt);
4226 // Mark the catch return
4227 if (emitComp->compCurBB->bbJumpKind == BBJ_EHCATCHRET)
4229 id->idDebugOnlyInfo()->idCatchRet = true;
4233 id->idAddr()->iiaBBlabel = dst;
4234 id->idjShort = false;
4239 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
4243 id->idjKeepLong = true;
4246 /* Record the jump's IG and offset within it */
4248 id->idjIG = emitCurIG;
4249 id->idjOffs = emitCurIGsize;
4251 /* Append this jump to this IG's jump list */
4253 id->idjNext = emitCurIGjmpList;
4254 emitCurIGjmpList = id;
4256 // Set the relocation flags - these give hint to zap to perform
4257 // relocation of the specified 32bit address.
4258 id->idSetRelocFlags(attr);
4268 /*****************************************************************************
4270 * Add a data label instruction.
4273 void emitter::emitIns_R_D(instruction ins, emitAttr attr, unsigned offs, regNumber reg)
4275 noway_assert((ins == INS_movw) || (ins == INS_movt));
4277 insFormat fmt = IF_T2_N2;
4278 instrDesc* id = emitNewInstrSC(attr, offs);
4279 insSize isz = emitInsSize(fmt);
4286 if (emitComp->opts.compReloc)
4288 // Set the relocation flags - these give hint to zap to perform
4289 // relocation of the specified 32bit address.
4290 id->idSetRelocFlags(attr);
4297 void emitter::emitIns_J_R(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
4299 assert(dst->bbFlags & BBF_JMP_TARGET);
4301 insFormat fmt = IF_NONE;
4311 assert(fmt == IF_T1_I);
4313 assert(isLowRegister(reg));
4315 instrDescJmp* id = emitNewInstrJmp();
4317 id->idInsFmt(IF_T1_I);
4318 id->idInsSize(emitInsSize(IF_T1_I));
4321 /* This jump better be short or-else! */
4322 id->idjShort = true;
4323 id->idAddr()->iiaBBlabel = dst;
4324 id->idjKeepLong = false;
4326 /* Record the jump's IG and offset within it */
4328 id->idjIG = emitCurIG;
4329 id->idjOffs = emitCurIGsize;
4331 /* Append this jump to this IG's jump list */
4333 id->idjNext = emitCurIGjmpList;
4334 emitCurIGjmpList = id;
4344 /*****************************************************************************
4346 * Add a call instruction (direct or indirect).
4347 * argSize<0 means that the caller will pop the arguments
4349 * The other arguments are interpreted depending on callType as shown:
4350 * Unless otherwise specified, ireg,xreg,xmul,disp should have default values.
4352 * EC_FUNC_TOKEN : addr is the method address
4353 * EC_FUNC_ADDR : addr is the absolute address of the function
4354 * if addr is NULL, it is a recursive call
4356 * If callType is one of these emitCallTypes, addr has to be NULL.
4357 * EC_INDIR_R : "call ireg".
4359 * For ARM xreg, xmul and disp are never used and should always be 0/REG_NA.
4361 * Please consult the "debugger team notification" comment in genFnProlog().
4364 void emitter::emitIns_Call(EmitCallType callType,
4365 CORINFO_METHOD_HANDLE methHnd, // used for pretty printing
4366 INDEBUG_LDISASM_COMMA(CORINFO_SIG_INFO* sigInfo) // used to report call sites to the EE
4370 VARSET_VALARG_TP ptrVars,
4371 regMaskTP gcrefRegs,
4372 regMaskTP byrefRegs,
4373 IL_OFFSETX ilOffset /* = BAD_IL_OFFSET */,
4374 regNumber ireg /* = REG_NA */,
4375 regNumber xreg /* = REG_NA */,
4376 unsigned xmul /* = 0 */,
4378 bool isJump /* = false */,
4379 bool isNoGC /* = false */,
4380 bool isProfLeaveCB /* = false */)
4382 /* Sanity check the arguments depending on callType */
4384 assert(callType < EC_COUNT);
4385 assert((callType != EC_FUNC_TOKEN && callType != EC_FUNC_ADDR) ||
4386 (ireg == REG_NA && xreg == REG_NA && xmul == 0 && disp == 0));
4387 assert(callType < EC_INDIR_R || addr == NULL);
4388 assert(callType != EC_INDIR_R || (ireg < REG_COUNT && xreg == REG_NA && xmul == 0 && disp == 0));
4390 // ARM never uses these
4391 assert(xreg == REG_NA && xmul == 0 && disp == 0);
4393 // Our stack level should be always greater than the bytes of arguments we push. Just
4395 assert((unsigned)abs(argSize) <= codeGen->genStackLevel);
4400 /* This is the saved set of registers after a normal call */
4401 regMaskTP savedSet = RBM_CALLEE_SAVED;
4403 /* some special helper calls have a different saved set registers */
4407 assert(emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
4409 // Get the set of registers that this call kills and remove it from the saved set.
4410 savedSet = RBM_ALLINT & ~emitComp->compNoGCHelperCallKillSet(Compiler::eeGetHelperNum(methHnd));
4412 // In case of Leave profiler callback, we need to preserve liveness of REG_PROFILER_RET_SCRATCH
4415 savedSet |= RBM_PROFILER_RET_SCRATCH;
4419 if (emitComp->verbose)
4421 printf("NOGC Call: savedSet=");
4422 printRegMaskInt(savedSet);
4423 emitDispRegSet(savedSet);
4430 assert(!emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
4433 /* Trim out any callee-trashed registers from the live set */
4435 gcrefRegs &= savedSet;
4436 byrefRegs &= savedSet;
4439 if (EMIT_GC_VERBOSE)
4441 printf("Call: GCvars=%s ", VarSetOps::ToString(emitComp, ptrVars));
4442 dumpConvertedVarSet(emitComp, ptrVars);
4443 printf(", gcrefRegs=");
4444 printRegMaskInt(gcrefRegs);
4445 emitDispRegSet(gcrefRegs);
4446 printf(", byrefRegs=");
4447 printRegMaskInt(byrefRegs);
4448 emitDispRegSet(byrefRegs);
4453 assert(argSize % (int)REGSIZE_BYTES == 0);
4454 argCnt = argSize / (int)REGSIZE_BYTES;
4456 /* Managed RetVal: emit sequence point for the call */
4457 if (emitComp->opts.compDbgInfo && ilOffset != BAD_IL_OFFSET)
4459 codeGen->genIPmappingAdd(ilOffset, false);
4463 We need to allocate the appropriate instruction descriptor based
4464 on whether this is a direct/indirect call, and whether we need to
4465 record an updated set of live GC variables.
4467 The stats for a ton of classes is as follows:
4469 Direct call w/o GC vars 220,216
4470 Indir. call w/o GC vars 144,781
4472 Direct call with GC vars 9,440
4473 Indir. call with GC vars 5,768
4476 if (callType >= EC_INDIR_R)
4478 /* Indirect call, virtual calls */
4480 assert(callType == EC_INDIR_R);
4482 id = emitNewInstrCallInd(argCnt, disp, ptrVars, gcrefRegs, byrefRegs, retSize);
4486 /* Helper/static/nonvirtual/function calls (direct or through handle),
4487 and calls to an absolute addr. */
4489 assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
4491 id = emitNewInstrCallDir(argCnt, ptrVars, gcrefRegs, byrefRegs, retSize);
4494 /* Update the emitter's live GC ref sets */
4496 VarSetOps::Assign(emitComp, emitThisGCrefVars, ptrVars);
4497 emitThisGCrefRegs = gcrefRegs;
4498 emitThisByrefRegs = byrefRegs;
4500 /* Set the instruction - special case jumping a function */
4502 insFormat fmt = IF_NONE;
4504 id->idSetIsNoGC(isNoGC);
4506 /* Record the address: method, indirection, or funcptr */
4508 if (callType > EC_FUNC_ADDR)
4510 /* This is an indirect call (either a virtual call or func ptr call) */
4514 case EC_INDIR_R: // the address is in a register
4516 id->idSetIsCallRegPtr();
4520 ins = INS_bx; // INS_bx Reg
4524 ins = INS_blx; // INS_blx Reg
4530 id->idInsSize(emitInsSize(fmt));
4532 assert(xreg == REG_NA);
4536 NO_WAY("unexpected instruction");
4542 /* This is a simple direct call: "call helper/method/addr" */
4544 assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
4546 // if addr is nullptr then this call is treated as a recursive call.
4547 assert(addr == nullptr || codeGen->arm_Valid_Imm_For_BL((ssize_t)addr));
4551 ins = INS_b; // INS_b imm24
4555 ins = INS_bl; // INS_bl imm24
4562 id->idInsSize(emitInsSize(fmt));
4564 id->idAddr()->iiaAddr = (BYTE*)addr;
4566 if (callType == EC_FUNC_ADDR)
4568 id->idSetIsCallAddr();
4571 if (emitComp->opts.compReloc)
4573 // Since this is an indirect call through a pointer and we don't
4574 // currently pass in emitAttr into this function we have decided
4575 // to always mark the displacement as being relocatable.
4577 id->idSetIsDspReloc();
4582 if (EMIT_GC_VERBOSE)
4584 if (id->idIsLargeCall())
4586 printf("[%02u] Rec call GC vars = %s\n", id->idDebugOnlyInfo()->idNum,
4587 VarSetOps::ToString(emitComp, ((instrDescCGCA*)id)->idcGCvars));
4591 id->idDebugOnlyInfo()->idMemCookie = (size_t)methHnd; // method token
4592 id->idDebugOnlyInfo()->idCallSig = sigInfo;
4596 if (addr != nullptr)
4598 codeGen->getDisAssembler().disSetMethod((size_t)addr, methHnd);
4600 #endif // LATE_DISASM
4606 /*****************************************************************************
4608 * Returns an encoding for the specified register (any-reg) to be used in
4609 * a Thumb-1 encoding in the M4 position
4612 inline unsigned insEncodeRegT1_M4(regNumber reg)
4614 assert(reg < REG_STK);
4619 /*****************************************************************************
4621 * Returns an encoding for the specified register (any-reg) to be used in
4622 * a Thumb-1 encoding in the D4 position
4625 inline unsigned insEncodeRegT1_D4(regNumber reg)
4627 assert(reg < REG_STK);
4629 return (reg & 0x7) | ((reg & 0x8) << 4);
4632 /*****************************************************************************
4634 * Returns an encoding for the specified register (low-only) to be used in
4635 * a Thumb-1 encoding in the M3 position
4638 inline unsigned insEncodeRegT1_M3(regNumber reg)
4640 assert(reg < REG_R8);
4645 /*****************************************************************************
4647 * Returns an encoding for the specified register (low-only) to be used in
4648 * a Thumb-1 encoding in the N3 position
4651 inline unsigned insEncodeRegT1_N3(regNumber reg)
4653 assert(reg < REG_R8);
4658 /*****************************************************************************
4660 * Returns an encoding for the specified register (low-only) to be used in
4661 * a Thumb-1 encoding in the D3 position
4664 inline unsigned insEncodeRegT1_D3(regNumber reg)
4666 assert(reg < REG_R8);
4670 /*****************************************************************************
4672 * Returns an encoding for the specified register (low-only) to be used in
4673 * a Thumb-1 encoding in the DI position
4676 inline unsigned insEncodeRegT1_DI(regNumber reg)
4678 assert(reg < REG_R8);
4683 /*****************************************************************************
4685 * Returns an encoding for the specified register to be used in
4686 * a Thumb-2 encoding in the N position
4689 inline unsigned insEncodeRegT2_N(regNumber reg)
4691 assert(reg < REG_STK);
4696 inline unsigned floatRegIndex(regNumber reg, int size)
4698 // theoretically this could support quad floats as well but for now...
4699 assert(size == EA_8BYTE || size == EA_4BYTE);
4701 if (size == EA_8BYTE)
4702 assert(emitter::isDoubleReg(reg));
4704 assert(emitter::isFloatReg(reg));
4706 unsigned result = reg - REG_F0;
4708 // the assumption here is that the register F8 also refers to D4
4709 if (size == EA_8BYTE)
4717 // variant: SOME arm VFP instructions use the convention that
4718 // for doubles, the split bit holds the msb of the register index
4719 // for singles it holds the lsb
4720 // excerpt : d = if dp_operation then UInt(D:Vd)
4721 // if single UInt(Vd:D);
4723 inline unsigned floatRegEncoding(unsigned index, int size, bool variant = false)
4725 if (!variant || size == EA_8BYTE)
4729 return ((index & 1) << 4) | (index >> 1);
4733 // thumb2 VFP M register encoding
4734 inline unsigned insEncodeRegT2_VectorM(regNumber reg, int size, bool variant)
4736 unsigned enc = floatRegIndex(reg, size);
4737 enc = floatRegEncoding(enc, size, variant);
4738 return ((enc & 0xf) << 0) | ((enc & 0x10) << 1);
4741 // thumb2 VFP N register encoding
4742 inline unsigned insEncodeRegT2_VectorN(regNumber reg, int size, bool variant)
4744 unsigned enc = floatRegIndex(reg, size);
4745 enc = floatRegEncoding(enc, size, variant);
4746 return ((enc & 0xf) << 16) | ((enc & 0x10) << 3);
4749 // thumb2 VFP D register encoding
4750 inline unsigned insEncodeRegT2_VectorD(regNumber reg, int size, bool variant)
4752 unsigned enc = floatRegIndex(reg, size);
4753 enc = floatRegEncoding(enc, size, variant);
4754 return ((enc & 0xf) << 12) | ((enc & 0x10) << 18);
4757 /*****************************************************************************
4759 * Returns an encoding for the specified register to be used in
4760 * a Thumb-2 encoding in the T position
4763 inline unsigned insEncodeRegT2_T(regNumber reg)
4765 assert(reg < REG_STK);
4770 /*****************************************************************************
4772 * Returns an encoding for the specified register to be used in
4773 * a Thumb-2 encoding in the D position
4776 inline unsigned insEncodeRegT2_D(regNumber reg)
4778 assert(reg < REG_STK);
4783 /*****************************************************************************
4785 * Returns an encoding for the specified register to be used in
4786 * a Thumb-2 encoding in the M position
4789 inline unsigned insEncodeRegT2_M(regNumber reg)
4791 assert(reg < REG_STK);
4796 /*****************************************************************************
4798 * Returns the encoding for the Set Flags bit to be used in a Thumb-2 encoding
4801 unsigned emitter::insEncodeSetFlags(insFlags sf)
4803 if (sf == INS_FLAGS_SET)
4809 /*****************************************************************************
4811 * Returns the encoding for the Shift Type bits to be used in a Thumb-2 encoding
4814 unsigned emitter::insEncodeShiftOpts(insOpts opt)
4816 if (opt == INS_OPTS_NONE)
4818 else if (opt == INS_OPTS_LSL)
4820 else if (opt == INS_OPTS_LSR)
4822 else if (opt == INS_OPTS_ASR)
4824 else if (opt == INS_OPTS_ROR)
4826 else if (opt == INS_OPTS_RRX)
4829 assert(!"Invalid insOpts");
4833 /*****************************************************************************
4835 * Returns the encoding for the PUW bits to be used in a T2_G0 Thumb-2 encoding
4838 unsigned emitter::insEncodePUW_G0(insOpts opt, int imm)
4840 unsigned result = 0;
4842 if (opt != INS_OPTS_LDST_POST_INC)
4843 result |= (1 << 24); // The P bit
4846 result |= (1 << 23); // The U bit
4848 if (opt != INS_OPTS_NONE)
4849 result |= (1 << 21); // The W bits
4853 /*****************************************************************************
4855 * Returns the encoding for the PUW bits to be used in a T2_H0 Thumb-2 encoding
4858 unsigned emitter::insEncodePUW_H0(insOpts opt, int imm)
4860 unsigned result = 0;
4862 if (opt != INS_OPTS_LDST_POST_INC)
4863 result |= (1 << 10); // The P bit
4866 result |= (1 << 9); // The U bit
4868 if (opt != INS_OPTS_NONE)
4869 result |= (1 << 8); // The W bits
4874 /*****************************************************************************
4876 * Returns the encoding for the Shift Count bits to be used in a Thumb-2 encoding
4879 inline unsigned insEncodeShiftCount(int imm)
4883 assert((imm & 0x001F) == imm);
4884 result = (imm & 0x03) << 6;
4885 result |= (imm & 0x1C) << 10;
4890 /*****************************************************************************
4892 * Returns the encoding for the immediate use by BFI/BFC Thumb-2 encodings
4895 inline unsigned insEncodeBitFieldImm(int imm)
4899 assert((imm & 0x03FF) == imm);
4900 result = (imm & 0x001f);
4901 result |= (imm & 0x0060) << 1;
4902 result |= (imm & 0x0380) << 5;
4907 /*****************************************************************************
4909 * Unscales the immediate based on the operand size in 'size'
4911 /*static*/ int emitter::insUnscaleImm(int imm, emitAttr size)
4917 assert((imm & 0x0003) == 0);
4922 assert((imm & 0x0001) == 0);
4931 assert(!"Invalid value in size");
4937 /*****************************************************************************
4939 * Emit a Thumb-1 instruction (a 16-bit integer as code)
4942 /*static*/ unsigned emitter::emitOutput_Thumb1Instr(BYTE* dst, code_t code)
4944 unsigned short word1 = code & 0xffff;
4945 assert(word1 == code);
4948 unsigned short top5bits = (word1 & 0xf800) >> 11;
4949 assert(top5bits < 29);
4952 MISALIGNED_WR_I2(dst, word1);
4954 return sizeof(short);
4956 /*****************************************************************************
4958 * Emit a Thumb-2 instruction (two 16-bit integers as code)
4961 /*static*/ unsigned emitter::emitOutput_Thumb2Instr(BYTE* dst, code_t code)
4963 unsigned short word1 = (code >> 16) & 0xffff;
4964 unsigned short word2 = (code)&0xffff;
4965 assert((code_t)((word1 << 16) | word2) == code);
4968 unsigned short top5bits = (word1 & 0xf800) >> 11;
4969 assert(top5bits >= 29);
4972 MISALIGNED_WR_I2(dst, word1);
4974 MISALIGNED_WR_I2(dst, word2);
4976 return sizeof(short) * 2;
4979 /*****************************************************************************
4981 * Output a local jump instruction.
4982 * Note that this may be invoked to overwrite an existing jump instruction at 'dst'
4983 * to handle forward branch patching.
4986 BYTE* emitter::emitOutputLJ(insGroup* ig, BYTE* dst, instrDesc* i)
4992 instrDescJmp* id = (instrDescJmp*)i;
4993 instruction ins = id->idIns();
4996 bool loadLabel = false;
4997 bool isJump = false;
4998 bool relAddr = true; // does the instruction use relative-addressing?
5005 sdistneg = JCC_DIST_SMALL_MAX_NEG;
5011 // One size fits all!
5017 sdistneg = LBL_DIST_SMALL_MAX_NEG;
5023 sdistneg = LBL_DIST_SMALL_MAX_NEG;
5029 /* Figure out the distance to the target */
5031 srcOffs = emitCurCodeOffs(dst);
5032 if (id->idAddr()->iiaHasInstrCount())
5035 int instrCount = id->idAddr()->iiaGetInstrCount();
5036 unsigned insNum = emitFindInsNum(ig, id);
5039 // Backward branches using instruction count must be within the same instruction group.
5040 assert(insNum + 1 >= (unsigned)(-instrCount));
5042 dstOffs = ig->igOffs + emitFindOffset(ig, (insNum + 1 + instrCount));
5046 dstOffs = id->idAddr()->iiaIGlabel->igOffs;
5053 // for adr, the distance is calculated from 4-byte aligned srcOffs.
5054 distVal = (ssize_t)((emitOffsetToPtr(dstOffs) - (BYTE*)(((size_t)emitOffsetToPtr(srcOffs)) & ~3)) + 1);
5058 distVal = (ssize_t)(emitOffsetToPtr(dstOffs) - emitOffsetToPtr(srcOffs));
5063 assert(ins == INS_movw || ins == INS_movt);
5064 distVal = (ssize_t)emitOffsetToPtr(dstOffs) + 1; // Or in thumb bit
5067 if (dstOffs <= srcOffs)
5069 /* This is a backward jump - distance is known at this point */
5072 if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
5074 size_t blkOffs = id->idjIG->igOffs;
5076 if (INTERESTING_JUMP_NUM == 0)
5077 printf("[3] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
5078 printf("[3] Jump block is at %08X - %02X = %08X\n", blkOffs, emitOffsAdj, blkOffs - emitOffsAdj);
5079 printf("[3] Jump is at %08X - %02X = %08X\n", srcOffs, emitOffsAdj, srcOffs - emitOffsAdj);
5080 printf("[3] Label block is at %08X - %02X = %08X\n", dstOffs, emitOffsAdj, dstOffs - emitOffsAdj);
5084 // This format only supports forward branches
5085 noway_assert(id->idInsFmt() != IF_T1_I);
5087 /* Can we use a short jump? */
5089 if (isJump && ((unsigned)(distVal - 4) >= (unsigned)sdistneg))
5091 emitSetShortJump(id);
5096 /* This is a forward jump - distance will be an upper limit */
5098 emitFwdJumps = true;
5100 /* The target offset will be closer by at least 'emitOffsAdj', but only if this
5101 jump doesn't cross the hot-cold boundary. */
5103 if (!emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
5105 dstOffs -= emitOffsAdj;
5106 distVal -= emitOffsAdj;
5109 /* Record the location of the jump for later patching */
5111 id->idjOffs = dstOffs;
5113 /* Are we overflowing the id->idjOffs bitfield? */
5114 if (id->idjOffs != dstOffs)
5115 IMPL_LIMITATION("Method is too large");
5118 if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
5120 size_t blkOffs = id->idjIG->igOffs;
5122 if (INTERESTING_JUMP_NUM == 0)
5123 printf("[4] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
5124 printf("[4] Jump block is at %08X\n", blkOffs);
5125 printf("[4] Jump is at %08X\n", srcOffs);
5126 printf("[4] Label block is at %08X - %02X = %08X\n", dstOffs + emitOffsAdj, emitOffsAdj, dstOffs);
5131 /* Adjust the offset to emit relative to the end of the instruction */
5137 if (0 && emitComp->verbose)
5139 size_t sz = 4; // Thumb-2 pretends all instructions are 4-bytes long for computing jump offsets?
5140 int distValSize = id->idjShort ? 4 : 8;
5141 printf("; %s jump [%08X/%03u] from %0*X to %0*X: dist = %08XH\n", (dstOffs <= srcOffs) ? "Fwd" : "Bwd",
5142 dspPtr(id), id->idDebugOnlyInfo()->idNum, distValSize, srcOffs + sz, distValSize, dstOffs, distVal);
5146 insFormat fmt = id->idInsFmt();
5150 /* What size jump should we use? */
5156 assert(!id->idjKeepLong);
5157 assert(emitJumpCrossHotColdBoundary(srcOffs, dstOffs) == false);
5159 assert(JMP_SIZE_SMALL == JCC_SIZE_SMALL);
5160 assert(JMP_SIZE_SMALL == 2);
5162 /* For forward jumps, record the address of the distance value */
5163 id->idjTemp.idjAddr = (distVal > 0) ? dst : NULL;
5165 dst = emitOutputShortBranch(dst, ins, fmt, distVal, id);
5171 /* For forward jumps, record the address of the distance value */
5172 id->idjTemp.idjAddr = (dstOffs > srcOffs) ? dst : NULL;
5174 if (fmt == IF_LARGEJMP)
5176 // This is a pseudo-instruction format representing a large conditional branch, to allow
5177 // us to get a greater branch target range than we can get by using a straightforward conditional
5178 // branch. It is encoded as a short conditional branch that branches around a long unconditional
5181 // Conceptually, we have:
5185 // The code we emit is:
5187 // b<!cond> L_not // 2 bytes. Note that we reverse the condition.
5188 // b L_target // 4 bytes
5191 // Note that we don't actually insert any blocks: we simply encode "b <!cond> L_not" as a branch with
5192 // the correct offset. Note also that this works for both integer and floating-point conditions, because
5193 // the condition inversion takes ordered/unordered into account, preserving NaN behavior. For example,
5194 // "GT" (greater than) is inverted to "LE" (less than, equal, or unordered).
5196 // History: previously, we generated:
5199 // but the "it" instruction was deprecated, so we can't use it.
5201 dst = emitOutputShortBranch(dst,
5202 emitJumpKindToIns(emitReverseJumpKind(
5203 emitInsToJumpKind(ins))), // reverse the conditional instruction
5205 6 - 4, /* 6 bytes from start of this large conditional pseudo-instruction to
5206 L_not. Jumps are encoded as offset from instr address + 4. */
5207 NULL /* only used for cbz/cbnz */);
5209 // Now, pretend we've got a normal unconditional branch, and fall through to the code to emit that.
5213 // The distVal was computed based on the beginning of the pseudo-instruction, which is
5214 // the IT. So subtract the size of the IT from the offset, so it is relative to the
5215 // unconditional branch.
5219 code = emitInsCode(ins, fmt);
5221 if (fmt == IF_T2_J1)
5223 // Can't use this form for jumps between the hot and cold regions
5224 assert(!id->idjKeepLong);
5225 assert(emitJumpCrossHotColdBoundary(srcOffs, dstOffs) == false);
5227 assert((distVal & 1) == 0);
5228 assert(distVal >= -1048576);
5229 assert(distVal <= 1048574);
5233 code |= ((distVal >> 1) & 0x0007ff);
5234 code |= (((distVal >> 1) & 0x01f800) << 5);
5235 code |= (((distVal >> 1) & 0x020000) >> 4);
5236 code |= (((distVal >> 1) & 0x040000) >> 7);
5238 else if (fmt == IF_T2_J2)
5240 assert((distVal & 1) == 0);
5241 if (emitComp->opts.compReloc && emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
5243 // dst isn't an actual final target location, just some intermediate
5244 // location. Thus we cannot make any guarantees about distVal (not
5245 // even the direction/sign). Instead we don't encode any offset and
5246 // rely on the relocation to do all the work
5250 assert(distVal >= CALL_DIST_MAX_NEG);
5251 assert(distVal <= CALL_DIST_MAX_POS);
5255 code |= ((distVal >> 1) & 0x0007ff);
5256 code |= (((distVal >> 1) & 0x1ff800) << 5);
5258 bool S = (distVal < 0);
5259 bool I1 = ((distVal & 0x00800000) == 0);
5260 bool I2 = ((distVal & 0x00400000) == 0);
5263 code |= (1 << 13); // J1 bit
5265 code |= (1 << 11); // J2 bit
5270 assert(!"Unknown fmt");
5273 unsigned instrSize = emitOutput_Thumb2Instr(dst, code);
5275 if (emitComp->opts.compReloc)
5277 if (emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
5279 assert(id->idjKeepLong);
5280 if (emitComp->info.compMatchedVM)
5282 void* target = emitOffsetToPtr(dstOffs);
5283 emitRecordRelocation((void*)dst, target, IMAGE_REL_BASED_THUMB_BRANCH24);
5293 /* For forward jumps, record the address of the distance value */
5294 id->idjTemp.idjAddr = (distVal > 0) ? dst : NULL;
5296 code = emitInsCode(ins, fmt);
5298 if (fmt == IF_T1_J3)
5300 assert((dstOffs & 3) == 0); // The target label must be 4-byte aligned
5301 assert(distVal >= 0);
5302 assert(distVal <= 1022);
5303 code |= ((distVal >> 2) & 0xff);
5305 dst += emitOutput_Thumb1Instr(dst, code);
5307 else if (fmt == IF_T2_M1)
5309 assert(distVal >= -4095);
5310 assert(distVal <= +4095);
5313 code |= 0x00A0 << 16;
5316 assert((distVal & 0x0fff) == distVal);
5317 code |= (distVal & 0x00ff);
5318 code |= ((distVal & 0x0700) << 4);
5320 code |= ((distVal & 0x0800) << 15);
5321 code |= id->idReg1() << 8;
5323 dst += emitOutput_Thumb2Instr(dst, code);
5325 else if (fmt == IF_T2_N1)
5327 code |= insEncodeRegT2_D(id->idReg1());
5328 unsigned imm = distVal;
5329 if (ins == INS_movw)
5335 imm = (imm >> 16) & 0xffff;
5337 ((instrDescJmp*)id)->idjTemp.idjAddr = (dstOffs > srcOffs) ? dst : NULL;
5339 assert((imm & 0x0000ffff) == imm);
5340 code |= (imm & 0x00ff);
5341 code |= ((imm & 0x0700) << 4);
5342 code |= ((imm & 0x0800) << 15);
5343 code |= ((imm & 0xf000) << 4);
5344 dst += emitOutput_Thumb2Instr(dst, code);
5346 if (id->idIsCnsReloc() || id->idIsDspReloc())
5348 assert(ins == INS_movt || ins == INS_movw);
5349 if ((ins == INS_movt) && emitComp->info.compMatchedVM)
5350 emitHandlePCRelativeMov32((void*)(dst - 8), (void*)distVal);
5355 assert(!"Unknown fmt");
5362 /*****************************************************************************
5364 * Output a short branch instruction.
5367 BYTE* emitter::emitOutputShortBranch(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, instrDescJmp* id)
5371 code = emitInsCode(ins, fmt);
5375 assert((distVal & 1) == 0);
5376 assert(distVal >= -256);
5377 assert(distVal <= 254);
5381 code |= ((distVal >> 1) & 0x7f);
5383 else if (fmt == IF_T1_M)
5385 assert((distVal & 1) == 0);
5386 assert(distVal >= -2048);
5387 assert(distVal <= 2046);
5391 code |= ((distVal >> 1) & 0x3ff);
5393 else if (fmt == IF_T1_I)
5396 assert(ins == INS_cbz || INS_cbnz);
5397 assert((distVal & 1) == 0);
5398 assert(distVal >= 0);
5399 assert(distVal <= 126);
5401 code |= ((distVal << 3) & 0x0200);
5402 code |= ((distVal << 2) & 0x00F8);
5403 code |= (id->idReg1() & 0x0007);
5407 assert(!"Unknown fmt");
5410 dst += emitOutput_Thumb1Instr(dst, code);
5415 #ifdef FEATURE_ITINSTRUCTION
5417 /*****************************************************************************
5418 * The "IT" instruction is deprecated (with a very few exceptions). Don't generate it!
5419 * Don't delete this code, though, in case we ever want to bring it back.
5420 *****************************************************************************/
5422 /*****************************************************************************
5424 * Output an IT instruction.
5427 BYTE* emitter::emitOutputIT(BYTE* dst, instruction ins, insFormat fmt, code_t condcode)
5430 code_t code, mask, bit;
5432 code = emitInsCode(ins, fmt);
5433 code |= (condcode << 4); // encode firstcond
5434 imm0 = condcode & 1; // this is firstcond[0]
5435 mask = code & 0x0f; // initialize mask encoded in opcode
5436 bit = 0x08; // where in mask we are encoding
5437 while ((mask & (bit - 1)) != 0) // are the remaining bits all zeros?
5438 { // then we are done
5439 // otherwise determine the setting of bit
5440 if ((imm0 == 1) ^ ((bit & mask) != 0))
5442 code |= bit; // set the current bit
5446 code &= ~bit; // clear the current bit
5450 dst += emitOutput_Thumb1Instr(dst, code);
5455 #endif // FEATURE_ITINSTRUCTION
5457 /*****************************************************************************
5459 * Append the machine code corresponding to the given instruction descriptor
5460 * to the code block at '*dp'; the base of the code block is 'bp', and 'ig'
5461 * is the instruction group that contains the instruction. Updates '*dp' to
5462 * point past the generated code, and returns the size of the instruction
5463 * descriptor in bytes.
5466 size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
5472 instruction ins = id->idIns();
5473 insFormat fmt = id->idInsFmt();
5474 emitAttr size = id->idOpSize();
5475 unsigned char callInstrSize = 0;
5478 bool dspOffs = emitComp->opts.dspGCtbls || !emitComp->opts.disDiffable;
5481 assert(REG_NA == (int)REG_NA);
5483 VARSET_TP GCvars(VarSetOps::UninitVal());
5485 /* What instruction format have we got? */
5491 regMaskTP gcrefRegs;
5492 regMaskTP byrefRegs;
5494 case IF_T1_A: // T1_A ................
5495 sz = SMALL_IDSC_SIZE;
5496 code = emitInsCode(ins, fmt);
5497 dst += emitOutput_Thumb1Instr(dst, code);
5500 #ifdef FEATURE_ITINSTRUCTION
5501 case IF_T1_B: // T1_B ........cccc.... cond
5503 assert(id->idGCref() == GCT_NONE);
5504 ssize_t condcode = emitGetInsSC(id);
5505 dst = emitOutputIT(dst, ins, fmt, condcode);
5506 sz = SMALL_IDSC_SIZE;
5509 #endif // FEATURE_ITINSTRUCTION
5511 case IF_T1_C: // T1_C .....iiiiinnnddd R1 R2 imm5
5512 sz = SMALL_IDSC_SIZE;
5513 imm = emitGetInsSC(id);
5514 code = emitInsCode(ins, fmt);
5515 code |= insEncodeRegT1_D3(id->idReg1());
5516 code |= insEncodeRegT1_N3(id->idReg2());
5517 if (emitInsIsLoadOrStore(ins))
5519 imm = insUnscaleImm(imm, size);
5521 assert((imm & 0x001f) == imm);
5523 dst += emitOutput_Thumb1Instr(dst, code);
5526 case IF_T1_D0: // T1_D0 ........Dmmmmddd R1* R2*
5527 sz = SMALL_IDSC_SIZE;
5528 code = emitInsCode(ins, fmt);
5529 code |= insEncodeRegT1_D4(id->idReg1());
5530 code |= insEncodeRegT1_M4(id->idReg2());
5531 dst += emitOutput_Thumb1Instr(dst, code);
5534 case IF_T1_E: // T1_E ..........nnnddd R1 R2
5535 sz = SMALL_IDSC_SIZE;
5536 code = emitInsCode(ins, fmt);
5537 code |= insEncodeRegT1_D3(id->idReg1());
5538 code |= insEncodeRegT1_N3(id->idReg2());
5539 dst += emitOutput_Thumb1Instr(dst, code);
5542 case IF_T1_F: // T1_F .........iiiiiii SP imm7
5543 sz = emitGetInstrDescSize(id);
5544 imm = emitGetInsSC(id);
5545 code = emitInsCode(ins, fmt);
5546 imm = insUnscaleImm(imm, size);
5547 assert((imm & 0x007F) == imm);
5549 dst += emitOutput_Thumb1Instr(dst, code);
5552 case IF_T1_G: // T1_G .......iiinnnddd R1 R2 imm3
5553 sz = SMALL_IDSC_SIZE;
5554 imm = emitGetInsSC(id);
5555 code = emitInsCode(ins, fmt);
5556 code |= insEncodeRegT1_D3(id->idReg1());
5557 code |= insEncodeRegT1_N3(id->idReg2());
5558 assert((imm & 0x0007) == imm);
5560 dst += emitOutput_Thumb1Instr(dst, code);
5563 case IF_T1_H: // T1_H .......mmmnnnddd R1 R2 R3
5564 sz = emitGetInstrDescSize(id);
5565 code = emitInsCode(ins, fmt);
5566 code |= insEncodeRegT1_D3(id->idReg1());
5567 code |= insEncodeRegT1_N3(id->idReg2());
5568 code |= insEncodeRegT1_M3(id->idReg3());
5569 dst += emitOutput_Thumb1Instr(dst, code);
5572 case IF_T1_I: // T1_I ......i.iiiiiddd R1 imm6
5573 assert(id->idIsBound());
5575 dst = emitOutputLJ(ig, dst, id);
5576 sz = sizeof(instrDescJmp);
5579 case IF_T1_J0: // T1_J0 .....dddiiiiiiii R1 imm8
5580 case IF_T1_J1: // T1_J1 .....dddiiiiiiii R1 <regmask8>
5581 case IF_T1_J2: // T1_J2 .....dddiiiiiiii R1 SP imm8
5582 sz = emitGetInstrDescSize(id);
5583 imm = emitGetInsSC(id);
5584 code = emitInsCode(ins, fmt);
5585 code |= insEncodeRegT1_DI(id->idReg1());
5586 if (fmt == IF_T1_J2)
5588 imm = insUnscaleImm(imm, size);
5590 assert((imm & 0x00ff) == imm);
5592 dst += emitOutput_Thumb1Instr(dst, code);
5595 case IF_T1_L0: // T1_L0 ........iiiiiiii imm8
5596 case IF_T1_L1: // T1_L1 .......Rrrrrrrrr <regmask8>
5597 sz = emitGetInstrDescSize(id);
5598 imm = emitGetInsSC(id);
5599 code = emitInsCode(ins, fmt);
5600 if (fmt == IF_T1_L1)
5602 assert((imm & 0x3) != 0x3);
5604 code |= 0x0100; // R bit
5607 assert((imm & 0x00ff) == imm);
5609 dst += emitOutput_Thumb1Instr(dst, code);
5612 case IF_T2_A: // T2_A ................ ................
5613 sz = SMALL_IDSC_SIZE;
5614 code = emitInsCode(ins, fmt);
5615 dst += emitOutput_Thumb2Instr(dst, code);
5618 case IF_T2_B: // T2_B ................ ............iiii imm4
5619 sz = SMALL_IDSC_SIZE;
5620 imm = emitGetInsSC(id);
5621 code = emitInsCode(ins, fmt);
5622 assert((imm & 0x000F) == imm);
5624 dst += emitOutput_Thumb2Instr(dst, code);
5627 case IF_T2_C0: // T2_C0 ...........Snnnn .iiiddddiishmmmm R1 R2 R3 S, imm5, sh
5628 case IF_T2_C4: // T2_C4 ...........Snnnn ....dddd....mmmm R1 R2 R3 S
5629 case IF_T2_C5: // T2_C5 ............nnnn ....dddd....mmmm R1 R2 R3
5630 sz = emitGetInstrDescSize(id);
5631 code = emitInsCode(ins, fmt);
5632 code |= insEncodeRegT2_D(id->idReg1());
5633 code |= insEncodeRegT2_N(id->idReg2());
5634 code |= insEncodeRegT2_M(id->idReg3());
5635 if (fmt != IF_T2_C5)
5636 code |= insEncodeSetFlags(id->idInsFlags());
5637 if (fmt == IF_T2_C0)
5639 imm = emitGetInsSC(id);
5640 code |= insEncodeShiftCount(imm);
5641 code |= insEncodeShiftOpts(id->idInsOpt());
5643 dst += emitOutput_Thumb2Instr(dst, code);
5646 case IF_T2_C1: // T2_C1 ...........S.... .iiiddddiishmmmm R1 R2 S, imm5, sh
5647 case IF_T2_C2: // T2_C2 ...........S.... .iiiddddii..mmmm R1 R2 S, imm5
5648 case IF_T2_C6: // T2_C6 ................ ....dddd..iimmmm R1 R2 imm2
5649 sz = SMALL_IDSC_SIZE;
5650 imm = emitGetInsSC(id);
5651 code = emitInsCode(ins, fmt);
5652 code |= insEncodeRegT2_D(id->idReg1());
5653 code |= insEncodeRegT2_M(id->idReg2());
5654 if (fmt == IF_T2_C6)
5656 assert((imm & 0x0018) == imm);
5661 code |= insEncodeSetFlags(id->idInsFlags());
5662 code |= insEncodeShiftCount(imm);
5663 if (fmt == IF_T2_C1)
5664 code |= insEncodeShiftOpts(id->idInsOpt());
5666 dst += emitOutput_Thumb2Instr(dst, code);
5669 case IF_T2_C3: // T2_C3 ...........S.... ....dddd....mmmm R1 R2 S
5670 sz = SMALL_IDSC_SIZE;
5671 code = emitInsCode(ins, fmt);
5672 code |= insEncodeRegT2_D(id->idReg1());
5673 code |= insEncodeRegT2_M(id->idReg2());
5674 code |= insEncodeSetFlags(id->idInsFlags());
5675 dst += emitOutput_Thumb2Instr(dst, code);
5678 case IF_T2_C7: // T2_C7 ............nnnn ..........shmmmm R1 R2 imm2
5679 case IF_T2_C8: // T2_C8 ............nnnn .iii....iishmmmm R1 R2 imm5, sh
5680 sz = SMALL_IDSC_SIZE;
5681 imm = emitGetInsSC(id);
5682 code = emitInsCode(ins, fmt);
5683 code |= insEncodeRegT2_N(id->idReg1());
5684 code |= insEncodeRegT2_M(id->idReg2());
5685 if (fmt == IF_T2_C7)
5687 assert((imm & 0x0003) == imm);
5690 else if (fmt == IF_T2_C8)
5692 code |= insEncodeShiftCount(imm);
5693 code |= insEncodeShiftOpts(id->idInsOpt());
5695 dst += emitOutput_Thumb2Instr(dst, code);
5698 case IF_T2_C9: // T2_C9 ............nnnn ............mmmm R1 R2
5699 sz = SMALL_IDSC_SIZE;
5700 code = emitInsCode(ins, fmt);
5701 code |= insEncodeRegT2_N(id->idReg1());
5702 code |= insEncodeRegT2_M(id->idReg2());
5703 dst += emitOutput_Thumb2Instr(dst, code);
5706 case IF_T2_C10: // T2_C10 ............mmmm ....dddd....mmmm R1 R2
5707 sz = SMALL_IDSC_SIZE;
5708 code = emitInsCode(ins, fmt);
5709 code |= insEncodeRegT2_D(id->idReg1());
5710 code |= insEncodeRegT2_M(id->idReg2());
5711 code |= insEncodeRegT2_N(id->idReg2());
5712 dst += emitOutput_Thumb2Instr(dst, code);
5715 case IF_T2_D0: // T2_D0 ............nnnn .iiiddddii.wwwww R1 R2 imm5, imm5
5716 case IF_T2_D1: // T2_D1 ................ .iiiddddii.wwwww R1 imm5, imm5
5717 sz = SMALL_IDSC_SIZE;
5718 imm = emitGetInsSC(id);
5719 code = emitInsCode(ins, fmt);
5720 code |= insEncodeRegT2_D(id->idReg1());
5721 if (fmt == IF_T2_D0)
5722 code |= insEncodeRegT2_N(id->idReg2());
5723 code |= insEncodeBitFieldImm(imm);
5724 dst += emitOutput_Thumb2Instr(dst, code);
5727 case IF_T2_E0: // T2_E0 ............nnnn tttt......shmmmm R1 R2 R3 imm2
5728 case IF_T2_E1: // T2_E1 ............nnnn tttt............ R1 R2
5729 case IF_T2_E2: // T2_E2 ................ tttt............ R1
5730 code = emitInsCode(ins, fmt);
5731 code |= insEncodeRegT2_T(id->idReg1());
5732 if (fmt == IF_T2_E0)
5734 sz = emitGetInstrDescSize(id);
5735 code |= insEncodeRegT2_N(id->idReg2());
5736 if (id->idIsLclVar())
5738 code |= insEncodeRegT2_M(codeGen->rsGetRsvdReg());
5743 code |= insEncodeRegT2_M(id->idReg3());
5744 imm = emitGetInsSC(id);
5745 assert((imm & 0x0003) == imm);
5751 sz = SMALL_IDSC_SIZE;
5752 if (fmt != IF_T2_E2)
5754 code |= insEncodeRegT2_N(id->idReg2());
5757 dst += emitOutput_Thumb2Instr(dst, code);
5760 case IF_T2_F1: // T2_F1 ............nnnn ttttdddd....mmmm R1 R2 R3 R4
5761 sz = emitGetInstrDescSize(id);
5763 code = emitInsCode(ins, fmt);
5764 code |= insEncodeRegT2_T(id->idReg1());
5765 code |= insEncodeRegT2_D(id->idReg2());
5766 code |= insEncodeRegT2_N(id->idReg3());
5767 code |= insEncodeRegT2_M(id->idReg4());
5768 dst += emitOutput_Thumb2Instr(dst, code);
5771 case IF_T2_F2: // T2_F2 ............nnnn aaaadddd....mmmm R1 R2 R3 R4
5772 sz = emitGetInstrDescSize(id);
5773 code = emitInsCode(ins, fmt);
5774 code |= insEncodeRegT2_D(id->idReg1());
5775 code |= insEncodeRegT2_N(id->idReg2());
5776 code |= insEncodeRegT2_M(id->idReg3());
5777 code |= insEncodeRegT2_T(id->idReg4());
5778 dst += emitOutput_Thumb2Instr(dst, code);
5781 case IF_T2_G0: // T2_G0 .......PU.W.nnnn ttttTTTTiiiiiiii R1 R2 R3 imm8, PUW
5782 case IF_T2_G1: // T2_G1 ............nnnn ttttTTTT........ R1 R2 R3
5783 code = emitInsCode(ins, fmt);
5784 code |= insEncodeRegT2_T(id->idReg1());
5785 code |= insEncodeRegT2_D(id->idReg2());
5786 code |= insEncodeRegT2_N(id->idReg3());
5787 if (fmt == IF_T2_G0)
5789 sz = emitGetInstrDescSizeSC(id);
5790 imm = emitGetInsSC(id);
5791 assert(unsigned_abs(imm) <= 0x00ff);
5793 code |= insEncodePUW_G0(id->idInsOpt(), imm);
5797 sz = emitGetInstrDescSize(id);
5799 dst += emitOutput_Thumb2Instr(dst, code);
5802 case IF_T2_H0: // T2_H0 ............nnnn tttt.PUWiiiiiiii R1 R2 imm8, PUW
5803 case IF_T2_H1: // T2_H1 ............nnnn tttt....iiiiiiii R1 R2 imm8
5804 case IF_T2_H2: // T2_H2 ............nnnn ........iiiiiiii R1 imm8
5805 sz = emitGetInstrDescSizeSC(id);
5806 imm = emitGetInsSC(id);
5807 code = emitInsCode(ins, fmt);
5808 code |= insEncodeRegT2_T(id->idReg1());
5810 if (fmt != IF_T2_H2)
5811 code |= insEncodeRegT2_N(id->idReg2());
5813 if (fmt == IF_T2_H0)
5815 assert(unsigned_abs(imm) <= 0x00ff);
5816 code |= insEncodePUW_H0(id->idInsOpt(), imm);
5817 code |= unsigned_abs(imm);
5821 assert((imm & 0x00ff) == imm);
5824 dst += emitOutput_Thumb2Instr(dst, code);
5827 case IF_T2_I0: // T2_I0 ..........W.nnnn rrrrrrrrrrrrrrrr R1 W, imm16
5828 case IF_T2_I1: // T2_I1 ................ rrrrrrrrrrrrrrrr imm16
5829 sz = emitGetInstrDescSizeSC(id);
5830 code = emitInsCode(ins, fmt);
5831 if (fmt == IF_T2_I0)
5833 code |= insEncodeRegT2_N(id->idReg1());
5834 code |= (1 << 21); // W bit
5836 imm = emitGetInsSC(id);
5837 assert((imm & 0x3) != 0x3);
5839 code |= 0x8000; // PC bit
5841 code |= 0x4000; // LR bit
5843 assert(imm <= 0x1fff); // 13 bits
5845 dst += emitOutput_Thumb2Instr(dst, code);
5848 case IF_T2_K1: // T2_K1 ............nnnn ttttiiiiiiiiiiii R1 R2 imm12
5849 case IF_T2_K4: // T2_K4 ........U....... ttttiiiiiiiiiiii R1 PC U, imm12
5850 case IF_T2_K3: // T2_K3 ........U....... ....iiiiiiiiiiii PC U, imm12
5851 sz = emitGetInstrDescSize(id);
5852 imm = emitGetInsSC(id);
5853 code = emitInsCode(ins, fmt);
5854 if (fmt != IF_T2_K3)
5856 code |= insEncodeRegT2_T(id->idReg1());
5858 if (fmt == IF_T2_K1)
5860 code |= insEncodeRegT2_N(id->idReg2());
5861 assert(imm <= 0xfff); // 12 bits
5866 assert(unsigned_abs(imm) <= 0xfff); // 12 bits (signed)
5869 code |= (1 << 23); // U bit
5871 dst += emitOutput_Thumb2Instr(dst, code);
5874 case IF_T2_K2: // T2_K2 ............nnnn ....iiiiiiiiiiii R1 imm12
5875 sz = emitGetInstrDescSizeSC(id);
5876 imm = emitGetInsSC(id);
5877 code = emitInsCode(ins, fmt);
5878 code |= insEncodeRegT2_N(id->idReg1());
5879 assert(imm <= 0xfff); // 12 bits
5881 dst += emitOutput_Thumb2Instr(dst, code);
5884 case IF_T2_L0: // T2_L0 .....i.....Snnnn .iiiddddiiiiiiii R1 R2 S, imm8<<imm4
5885 case IF_T2_L1: // T2_L1 .....i.....S.... .iiiddddiiiiiiii R1 S, imm8<<imm4
5886 case IF_T2_L2: // T2_L2 .....i......nnnn .iii....iiiiiiii R1 imm8<<imm4
5887 sz = emitGetInstrDescSize(id);
5888 imm = emitGetInsSC(id);
5889 code = emitInsCode(ins, fmt);
5891 if (fmt == IF_T2_L2)
5892 code |= insEncodeRegT2_N(id->idReg1());
5895 code |= insEncodeSetFlags(id->idInsFlags());
5896 code |= insEncodeRegT2_D(id->idReg1());
5897 if (fmt == IF_T2_L0)
5898 code |= insEncodeRegT2_N(id->idReg2());
5900 assert(isModImmConst(imm)); // Funky ARM imm encoding
5901 imm = encodeModImmConst(imm);
5902 assert(imm <= 0xfff); // 12 bits
5903 code |= (imm & 0x00ff);
5904 code |= (imm & 0x0700) << 4;
5905 code |= (imm & 0x0800) << 15;
5906 dst += emitOutput_Thumb2Instr(dst, code);
5909 case IF_T2_M0: // T2_M0 .....i......nnnn .iiiddddiiiiiiii R1 R2 imm12
5910 sz = emitGetInstrDescSizeSC(id);
5911 imm = emitGetInsSC(id);
5912 code = emitInsCode(ins, fmt);
5913 code |= insEncodeRegT2_D(id->idReg1());
5914 if (fmt == IF_T2_M0)
5915 code |= insEncodeRegT2_N(id->idReg2());
5916 imm = emitGetInsSC(id);
5917 assert(imm <= 0xfff); // 12 bits
5918 code |= (imm & 0x00ff);
5919 code |= (imm & 0x0700) << 4;
5920 code |= (imm & 0x0800) << 15;
5921 dst += emitOutput_Thumb2Instr(dst, code);
5924 case IF_T2_N: // T2_N .....i......iiii .iiiddddiiiiiiii R1 imm16
5925 case IF_T2_N2: // T2_N2 .....i......iiii .iiiddddiiiiiiii R1 imm16
5926 sz = emitGetInstrDescSizeSC(id);
5927 code = emitInsCode(ins, fmt);
5928 code |= insEncodeRegT2_D(id->idReg1());
5929 imm = emitGetInsSC(id);
5930 if (fmt == IF_T2_N2)
5932 assert(!id->idIsLclVar());
5933 assert((ins == INS_movw) || (ins == INS_movt));
5934 imm += (size_t)emitConsBlock;
5935 if (!id->idIsCnsReloc() && !id->idIsDspReloc())
5940 else if (id->idIsLclVar())
5943 if (ins == INS_movw)
5949 imm = (imm >> 16) & 0xffff;
5953 if (id->idIsCnsReloc() || id->idIsDspReloc())
5955 assert((ins == INS_movt) || (ins == INS_movw));
5956 dst += emitOutput_Thumb2Instr(dst, code);
5957 if ((ins == INS_movt) && emitComp->info.compMatchedVM)
5958 emitHandlePCRelativeMov32((void*)(dst - 8), (void*)imm);
5962 assert((imm & 0x0000ffff) == imm);
5963 code |= (imm & 0x00ff);
5964 code |= ((imm & 0x0700) << 4);
5965 code |= ((imm & 0x0800) << 15);
5966 code |= ((imm & 0xf000) << 4);
5967 dst += emitOutput_Thumb2Instr(dst, code);
5972 // these are the binary operators
5974 sz = emitGetInstrDescSize(id);
5975 code = emitInsCode(ins, fmt);
5976 code |= insEncodeRegT2_VectorN(id->idReg2(), size, true);
5977 code |= insEncodeRegT2_VectorM(id->idReg3(), size, true);
5978 code |= insEncodeRegT2_VectorD(id->idReg1(), size, true);
5979 if (size == EA_8BYTE)
5981 dst += emitOutput_Thumb2Instr(dst, code);
6011 if (id->idOpSize() == EA_8BYTE)
6016 srcSize = dstSize = id->idOpSize();
6020 sz = emitGetInstrDescSize(id);
6021 code = emitInsCode(ins, fmt);
6023 code |= insEncodeRegT2_VectorD(id->idReg1(), dstSize, true);
6024 code |= insEncodeRegT2_VectorM(id->idReg2(), srcSize, true);
6026 dst += emitOutput_Thumb2Instr(dst, code);
6031 sz = emitGetInstrDescSizeSC(id);
6032 code = emitInsCode(ins, fmt);
6033 code |= insEncodeRegT2_N(id->idReg2());
6034 code |= insEncodeRegT2_VectorD(id->idReg1(), size, true);
6036 imm = emitGetInsSC(id);
6038 imm = -imm; // bit 23 at 0 means negate
6040 code |= 1 << 23; // set the positive bit
6042 // offset is +/- 1020
6044 assert(imm >> 10 == 0);
6046 // bit 8 is set for doubles
6047 if (id->idOpSize() == EA_8BYTE)
6049 dst += emitOutput_Thumb2Instr(dst, code);
6053 // 3op assemble a double from two int regs (or back)
6054 sz = emitGetInstrDescSize(id);
6055 code = emitInsCode(ins, fmt);
6056 if (ins == INS_vmov_i2d)
6058 code |= insEncodeRegT2_VectorM(id->idReg1(), size, true);
6059 code |= id->idReg2() << 12;
6060 code |= id->idReg3() << 16;
6064 assert(ins == INS_vmov_d2i);
6065 code |= id->idReg1() << 12;
6066 code |= id->idReg2() << 16;
6067 code |= insEncodeRegT2_VectorM(id->idReg3(), size, true);
6069 dst += emitOutput_Thumb2Instr(dst, code);
6073 // 2op assemble a float from one int reg (or back)
6074 sz = emitGetInstrDescSize(id);
6075 code = emitInsCode(ins, fmt);
6076 if (ins == INS_vmov_f2i)
6078 code |= insEncodeRegT2_VectorN(id->idReg2(), EA_4BYTE, true);
6079 code |= id->idReg1() << 12;
6083 assert(ins == INS_vmov_i2f);
6084 code |= insEncodeRegT2_VectorN(id->idReg1(), EA_4BYTE, true);
6085 code |= id->idReg2() << 12;
6088 dst += emitOutput_Thumb2Instr(dst, code);
6091 case IF_T1_J3: // T1_J3 .....dddiiiiiiii R1 PC imm8
6092 case IF_T2_M1: // T2_M1 .....i.......... .iiiddddiiiiiiii R1 PC imm12
6093 assert(id->idGCref() == GCT_NONE);
6094 assert(id->idIsBound());
6096 dst = emitOutputLJ(ig, dst, id);
6097 sz = sizeof(instrDescLbl);
6100 case IF_T1_K: // T1_K ....cccciiiiiiii Branch imm8, cond4
6101 case IF_T1_M: // T1_M .....iiiiiiiiiii Branch imm11
6102 case IF_T2_J1: // T2_J1 .....Scccciiiiii ..j.jiiiiiiiiiii Branch imm20, cond4
6103 case IF_T2_J2: // T2_J2 .....Siiiiiiiiii ..j.jiiiiiiiiii. Branch imm24
6104 case IF_T2_N1: // T2_N .....i......iiii .iiiddddiiiiiiii R1 imm16
6106 assert(id->idGCref() == GCT_NONE);
6107 assert(id->idIsBound());
6109 dst = emitOutputLJ(ig, dst, id);
6110 sz = sizeof(instrDescJmp);
6113 case IF_T1_D1: // T1_D1 .........mmmm... R1*
6115 code = emitInsCode(ins, fmt);
6116 code |= insEncodeRegT1_M4(id->idReg1());
6117 dst += emitOutput_Thumb1Instr(dst, code);
6118 sz = SMALL_IDSC_SIZE;
6121 case IF_T1_D2: // T1_D2 .........mmmm... R3*
6123 /* Is this a "fat" call descriptor? */
6125 if (id->idIsLargeCall())
6127 instrDescCGCA* idCall = (instrDescCGCA*)id;
6128 gcrefRegs = idCall->idcGcrefRegs;
6129 byrefRegs = idCall->idcByrefRegs;
6130 VarSetOps::Assign(emitComp, GCvars, idCall->idcGCvars);
6131 sz = sizeof(instrDescCGCA);
6135 assert(!id->idIsLargeDsp());
6136 assert(!id->idIsLargeCns());
6138 gcrefRegs = emitDecodeCallGCregs(id);
6140 VarSetOps::AssignNoCopy(emitComp, GCvars, VarSetOps::MakeEmpty(emitComp));
6141 sz = sizeof(instrDesc);
6144 code = emitInsCode(ins, fmt);
6145 code |= insEncodeRegT1_M4(id->idReg3());
6146 callInstrSize = SafeCvtAssert<unsigned char>(emitOutput_Thumb1Instr(dst, code));
6147 dst += callInstrSize;
6150 case IF_T2_J3: // T2_J3 .....Siiiiiiiiii ..j.jiiiiiiiiii. Call imm24
6152 /* Is this a "fat" call descriptor? */
6154 if (id->idIsLargeCall())
6156 instrDescCGCA* idCall = (instrDescCGCA*)id;
6157 gcrefRegs = idCall->idcGcrefRegs;
6158 byrefRegs = idCall->idcByrefRegs;
6159 VarSetOps::Assign(emitComp, GCvars, idCall->idcGCvars);
6160 sz = sizeof(instrDescCGCA);
6164 assert(!id->idIsLargeDsp());
6165 assert(!id->idIsLargeCns());
6167 gcrefRegs = emitDecodeCallGCregs(id);
6169 VarSetOps::AssignNoCopy(emitComp, GCvars, VarSetOps::MakeEmpty(emitComp));
6170 sz = sizeof(instrDesc);
6173 if (id->idAddr()->iiaAddr == NULL) /* a recursive call */
6175 addr = emitCodeBlock;
6179 addr = id->idAddr()->iiaAddr;
6181 code = emitInsCode(ins, fmt);
6183 if (id->idIsDspReloc())
6185 callInstrSize = SafeCvtAssert<unsigned char>(emitOutput_Thumb2Instr(dst, code));
6186 dst += callInstrSize;
6187 if (emitComp->info.compMatchedVM)
6188 emitRecordRelocation((void*)(dst - 4), addr, IMAGE_REL_BASED_THUMB_BRANCH24);
6192 addr = (BYTE*)((size_t)addr & ~1); // Clear the lowest bit from target address
6194 /* Calculate PC relative displacement */
6195 int disp = addr - (dst + 4);
6196 bool S = (disp < 0);
6197 bool I1 = ((disp & 0x00800000) == 0);
6198 bool I2 = ((disp & 0x00400000) == 0);
6201 code |= (1 << 26); // S bit
6203 code |= (1 << 13); // J1 bit
6205 code |= (1 << 11); // J2 bit
6207 int immLo = (disp & 0x00000ffe) >> 1;
6208 int immHi = (disp & 0x003ff000) >> 12;
6210 code |= (immHi << 16);
6214 assert((disp & 0x00fffffe) == disp);
6216 callInstrSize = SafeCvtAssert<unsigned char>(emitOutput_Thumb2Instr(dst, code));
6217 dst += callInstrSize;
6222 /* We update the GC info before the call as the variables cannot be
6223 used by the call. Killing variables before the call helps with
6224 boundary conditions if the call is CORINFO_HELP_THROW - see bug 50029.
6225 If we ever track aliased variables (which could be used by the
6226 call), we would have to keep them alive past the call. */
6228 emitUpdateLiveGCvars(GCvars, *dp);
6230 // If the method returns a GC ref, mark R0 appropriately.
6231 if (id->idGCref() == GCT_GCREF)
6232 gcrefRegs |= RBM_R0;
6233 else if (id->idGCref() == GCT_BYREF)
6234 byrefRegs |= RBM_R0;
6236 // If the GC register set has changed, report the new set.
6237 if (gcrefRegs != emitThisGCrefRegs)
6238 emitUpdateLiveGCregs(GCT_GCREF, gcrefRegs, dst);
6240 if (byrefRegs != emitThisByrefRegs)
6241 emitUpdateLiveGCregs(GCT_BYREF, byrefRegs, dst);
6243 // Some helper calls may be marked as not requiring GC info to be recorded.
6244 if ((!id->idIsNoGC()))
6246 // On ARM, as on AMD64, we don't change the stack pointer to push/pop args.
6247 // So we're not really doing a "stack pop" here (note that "args" is 0), but we use this mechanism
6248 // to record the call for GC info purposes. (It might be best to use an alternate call,
6249 // and protect "emitStackPop" under the EMIT_TRACK_STACK_DEPTH preprocessor variable.)
6250 emitStackPop(dst, /*isCall*/ true, callInstrSize, /*args*/ 0);
6252 /* Do we need to record a call location for GC purposes? */
6254 if (!emitFullGCinfo)
6256 emitRecordGCcall(dst, callInstrSize);
6262 /********************************************************************/
6264 /********************************************************************/
6269 printf("unexpected format %s\n", emitIfName(id->idInsFmt()));
6270 assert(!"don't know how to encode this instruction");
6275 // Determine if any registers now hold GC refs, or whether a register that was overwritten held a GC ref.
6276 // We assume here that "id->idGCref()" is not GC_NONE only if the instruction described by "id" writes a
6277 // GC ref to register "id->idReg1()". (It may, apparently, also not be GC_NONE in other cases, such as
6278 // for stores, but we ignore those cases here.)
6279 if (emitInsMayWriteToGCReg(id)) // True if "id->idIns()" writes to a register than can hold GC ref.
6281 // If we ever generate instructions that write to multiple registers (LDM, or POP),
6282 // then we'd need to more work here to ensure that changes in the status of GC refs are
6283 // tracked properly.
6284 if (emitInsMayWriteMultipleRegs(id))
6286 // We explicitly list the multiple-destination-target instruction that we expect to
6287 // be emitted outside of the prolog and epilog here.
6295 // For each of these, idReg1() and idReg2() are the destination registers.
6296 emitGCregDeadUpd(id->idReg1(), dst);
6297 emitGCregDeadUpd(id->idReg2(), dst);
6300 assert(false); // We need to recognize this multi-target instruction...
6305 if (id->idGCref() != GCT_NONE)
6307 emitGCregLiveUpd(id->idGCref(), id->idReg1(), dst);
6311 // I also assume that "idReg1" is the destination register of all instructions that write to registers.
6312 emitGCregDeadUpd(id->idReg1(), dst);
6317 // Now we determine if the instruction has written to a (local variable) stack location, and either written a GC
6318 // ref or overwritten one.
6319 if (emitInsWritesToLclVarStackLoc(id))
6321 int varNum = id->idAddr()->iiaLclVar.lvaVarNum();
6322 unsigned ofs = AlignDown(id->idAddr()->iiaLclVar.lvaOffset(), TARGET_POINTER_SIZE);
6324 int adr = emitComp->lvaFrameAddress(varNum, true, ®Base, ofs);
6325 if (id->idGCref() != GCT_NONE)
6327 emitGCvarLiveUpd(adr + ofs, varNum, id->idGCref(), dst);
6331 // If the type of the local is a gc ref type, update the liveness.
6335 // "Regular" (non-spill-temp) local.
6336 vt = var_types(emitComp->lvaTable[varNum].lvType);
6340 TempDsc* tmpDsc = codeGen->regSet.tmpFindNum(varNum);
6341 vt = tmpDsc->tdTempType();
6343 if (vt == TYP_REF || vt == TYP_BYREF)
6344 emitGCvarDeadUpd(adr + ofs, dst);
6349 /* Make sure we set the instruction descriptor size correctly */
6351 size_t expected = emitSizeOfInsDsc(id);
6352 assert(sz == expected);
6354 if (emitComp->opts.disAsm || emitComp->opts.dspEmit || emitComp->verbose)
6356 emitDispIns(id, false, dspOffs, true, emitCurCodeOffs(odst), *dp, (dst - *dp), ig);
6359 if (emitComp->compDebugBreak)
6361 // set JitEmitPrintRefRegs=1 will print out emitThisGCrefRegs and emitThisByrefRegs
6362 // at the beginning of this method.
6363 if (JitConfig.JitEmitPrintRefRegs() != 0)
6365 printf("Before emitOutputInstr for id->idDebugOnlyInfo()->idNum=0x%02x\n", id->idDebugOnlyInfo()->idNum);
6366 printf(" emitThisGCrefRegs(0x%p)=", dspPtr(&emitThisGCrefRegs));
6367 printRegMaskInt(emitThisGCrefRegs);
6368 emitDispRegSet(emitThisGCrefRegs);
6370 printf(" emitThisByrefRegs(0x%p)=", dspPtr(&emitThisByrefRegs));
6371 printRegMaskInt(emitThisByrefRegs);
6372 emitDispRegSet(emitThisByrefRegs);
6376 // For example, set JitBreakEmitOutputInstr=a6 will break when this method is called for
6377 // emitting instruction a6, (i.e. IN00a6 in jitdump).
6378 if ((unsigned)JitConfig.JitBreakEmitOutputInstr() == id->idDebugOnlyInfo()->idNum)
6380 assert(!"JitBreakEmitOutputInstr reached");
6385 /* All instructions are expected to generate code */
6394 /*****************************************************************************/
6395 /*****************************************************************************/
6399 static bool insAlwaysSetFlags(instruction ins)
6401 bool result = false;
6417 /*****************************************************************************
6419 * Display the instruction name, optionally the instruction
6420 * can add the "s" suffix if it must set the flags.
6422 void emitter::emitDispInst(instruction ins, insFlags flags)
6424 const char* insstr = codeGen->genInsName(ins);
6425 int len = strlen(insstr);
6427 /* Display the instruction name */
6429 printf("%s", insstr);
6430 if (insSetsFlags(flags) && !insAlwaysSetFlags(ins))
6437 // Add at least one space after the instruction name
6438 // and add spaces until we have reach the normal size of 8
6446 #define STRICT_ARM_ASM 0
6448 /*****************************************************************************
6450 * Display an immediate value
6452 void emitter::emitDispImm(int imm, bool addComma, bool alwaysHex /* =false */)
6454 if (!alwaysHex && (imm > -1000) && (imm < 1000))
6456 else if ((imm > 0) ||
6457 (imm == -imm) || // -0x80000000 == 0x80000000. So we don't want to add an extra "-" at the beginning.
6458 (emitComp->opts.disDiffable && (imm == 0xD1FFAB1E))) // Don't display this as negative
6459 printf("0x%02x", imm);
6460 else // val <= -1000
6461 printf("-0x%02x", -imm);
6467 /*****************************************************************************
6469 * Display an arm condition for the IT instructions
6471 void emitter::emitDispCond(int cond)
6473 const static char* armCond[16] = {"eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc",
6474 "hi", "ls", "ge", "lt", "gt", "le", "AL", "NV"}; // The last two are invalid
6475 assert(0 <= cond && (unsigned)cond < ArrLen(armCond));
6476 printf(armCond[cond]);
6479 /*****************************************************************************
6481 * Display a register range in a range format
6483 void emitter::emitDispRegRange(regNumber reg, int len, emitAttr attr)
6486 emitDispReg(reg, attr, false);
6490 emitDispReg((regNumber)(reg + len - 1), attr, false);
6495 /*****************************************************************************
6497 * Display an register mask in a list format
6499 void emitter::emitDispRegmask(int imm, bool encodedPC_LR)
6501 bool printedOne = false;
6507 hasPC = (imm & 2) != 0;
6508 hasLR = (imm & 1) != 0;
6513 hasPC = (imm & RBM_PC) != 0;
6514 hasLR = (imm & RBM_LR) != 0;
6515 imm &= ~(RBM_PC | RBM_LR);
6518 regNumber reg = REG_R0;
6528 printf("%s", emitRegName(reg));
6533 reg = regNumber(reg + 1);
6541 printf("%s", emitRegName(REG_LR));
6549 printf("%s", emitRegName(REG_PC));
6555 /*****************************************************************************
6557 * Returns the encoding for the Shift Type bits to be used in a Thumb-2 encoding
6560 void emitter::emitDispShiftOpts(insOpts opt)
6562 if (opt == INS_OPTS_LSL)
6564 else if (opt == INS_OPTS_LSR)
6566 else if (opt == INS_OPTS_ASR)
6568 else if (opt == INS_OPTS_ROR)
6570 else if (opt == INS_OPTS_RRX)
6574 /*****************************************************************************
6576 * Display a register
6578 void emitter::emitDispReg(regNumber reg, emitAttr attr, bool addComma)
6580 if (isFloatReg(reg))
6582 const char* size = attr == EA_8BYTE ? "d" : "s";
6583 printf("%s%s", size, emitFloatRegName(reg, attr) + 1);
6587 printf("%s", emitRegName(reg, attr));
6594 /*****************************************************************************
6596 * Display an addressing operand [reg]
6598 void emitter::emitDispAddrR(regNumber reg, emitAttr attr)
6601 emitDispReg(reg, attr, false);
6606 /*****************************************************************************
6608 * Display an addressing operand [reg + imm]
6610 void emitter::emitDispAddrRI(regNumber reg, int imm, emitAttr attr)
6612 bool regIsSPorFP = (reg == REG_SP) || (reg == REG_FP);
6615 emitDispReg(reg, attr, false);
6626 emitDispImm(imm, false, regIsSPorFP);
6632 /*****************************************************************************
6634 * Display an addressing operand [reg + reg]
6636 void emitter::emitDispAddrRR(regNumber reg1, regNumber reg2, emitAttr attr)
6639 emitDispReg(reg1, attr, false);
6645 emitDispReg(reg2, attr, false);
6650 /*****************************************************************************
6652 * Display an addressing operand [reg + reg * imm]
6654 void emitter::emitDispAddrRRI(regNumber reg1, regNumber reg2, int imm, emitAttr attr)
6657 emitDispReg(reg1, attr, false);
6660 emitDispReg(reg2, attr, false);
6664 emitDispImm(1 << imm, false);
6670 emitDispImm(1 << imm, false);
6673 emitDispReg(reg2, attr, false);
6679 /*****************************************************************************
6681 * Display an addressing operand [reg + imm]
6683 void emitter::emitDispAddrPUW(regNumber reg, int imm, insOpts opt, emitAttr attr)
6685 bool regIsSPorFP = (reg == REG_SP) || (reg == REG_FP);
6688 emitDispReg(reg, attr, false);
6689 if (insOptAnyInc(opt))
6702 emitDispImm(imm, false, regIsSPorFP);
6709 /*****************************************************************************
6711 * Display the gc-ness of the operand
6713 void emitter::emitDispGC(emitAttr attr)
6716 // TODO-ARM-Cleanup: Fix or delete.
6717 if (attr == EA_GCREF)
6719 else if (attr == EA_BYREF)
6724 /*****************************************************************************
6726 * Display (optionally) the instruction encoding in hex
6729 void emitter::emitDispInsHex(BYTE* code, size_t sz)
6731 // We do not display the instruction hex if we want diff-able disassembly
6732 if (!emitComp->opts.disDiffable)
6736 printf(" %04X ", (*((unsigned short*)code)));
6740 printf(" %04X %04X", (*((unsigned short*)(code + 0))), (*((unsigned short*)(code + 2))));
6745 /****************************************************************************
6747 * Display the given instruction.
6750 void emitter::emitDispInsHelp(
6751 instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* code, size_t sz, insGroup* ig)
6755 unsigned idNum = id->idDebugOnlyInfo()->idNum; // Do not remove this! It is needed for VisualStudio
6756 // conditional breakpoints
6758 printf("IN%04x: ", idNum);
6764 if (!emitComp->opts.dspEmit && !isNew && !asmfm && sz)
6767 /* Display the instruction offset */
6769 emitDispInsOffs(offset, doffs);
6771 /* Display the instruction hex code */
6773 emitDispInsHex(code, sz);
6777 /* Get the instruction and format */
6779 instruction ins = id->idIns();
6780 insFormat fmt = id->idInsFmt();
6782 emitDispInst(ins, id->idInsFlags());
6784 /* If this instruction has just been added, check its size */
6786 assert(isNew == false || (int)emitSizeOfInsDsc(id) == emitCurIGfreeNext - (BYTE*)id);
6788 /* Figure out the operand size */
6790 if (id->idGCref() == GCT_GCREF)
6792 else if (id->idGCref() == GCT_BYREF)
6795 attr = id->idOpSize();
6801 const char* methodName;
6803 case IF_T1_A: // None
6807 case IF_T1_L0: // Imm
6809 emitDispImm(emitGetInsSC(id), false);
6812 case IF_T1_B: // <cond>
6813 emitDispCond(emitGetInsSC(id));
6816 case IF_T1_L1: // <regmask8>
6817 case IF_T2_I1: // <regmask16>
6818 emitDispRegmask(emitGetInsSC(id), true);
6821 case IF_T2_E2: // Reg
6822 if (id->idIns() == INS_vmrs)
6824 if (id->idReg1() != REG_R15)
6826 emitDispReg(id->idReg1(), attr, true);
6831 printf("APSR, FPSCR");
6836 emitDispReg(id->idReg1(), attr, false);
6841 emitDispReg(id->idReg1(), attr, false);
6845 emitDispReg(id->idReg3(), attr, false);
6847 CORINFO_METHOD_HANDLE handle = (CORINFO_METHOD_HANDLE)id->idDebugOnlyInfo()->idMemCookie;
6850 methodName = emitComp->eeGetMethodFullName(handle);
6851 printf("\t\t// %s", methodName);
6856 case IF_T1_F: // SP, Imm
6857 emitDispReg(REG_SP, attr, true);
6858 emitDispImm(emitGetInsSC(id), false);
6861 case IF_T1_J0: // Reg, Imm
6865 emitDispReg(id->idReg1(), attr, true);
6866 imm = emitGetInsSC(id);
6869 if (emitComp->opts.disDiffable)
6871 if (id->idIsCnsReloc() || id->idIsDspReloc())
6873 if (emitComp->opts.disDiffable)
6875 printf("%s RELOC ", (id->idIns() == INS_movw) ? "LOW" : "HIGH");
6878 emitDispImm(imm, false, (fmt == IF_T2_N));
6882 emitDispReg(id->idReg1(), attr, true);
6883 imm = emitGetInsSC(id);
6885 dataSection* jdsc = 0;
6886 NATIVE_OFFSET offs = 0;
6888 /* Find the appropriate entry in the data section list */
6890 for (jdsc = emitConsDsc.dsdList; jdsc; jdsc = jdsc->dsNext)
6892 UNATIVE_OFFSET size = jdsc->dsSize;
6894 /* Is this a label table? */
6896 if (jdsc->dsType == dataSection::blockAbsoluteAddr)
6905 assert(jdsc != NULL);
6907 if (id->idIsDspReloc())
6911 printf("%s ADDRESS J_M%03u_DS%02u", (id->idIns() == INS_movw) ? "LOW" : "HIGH",
6912 Compiler::s_compMethodsCount, imm);
6914 // After the MOVT, dump the table
6915 if (id->idIns() == INS_movt)
6917 unsigned cnt = jdsc->dsSize / TARGET_POINTER_SIZE;
6918 BasicBlock** bbp = (BasicBlock**)jdsc->dsCont;
6920 bool isBound = (emitCodeGetCookie(*bbp) != NULL);
6924 printf("\n\n J_M%03u_DS%02u LABEL DWORD", Compiler::s_compMethodsCount, imm);
6926 /* Display the label table (it's stored as "BasicBlock*" values) */
6932 /* Convert the BasicBlock* value to an IG address */
6934 lab = (insGroup*)emitCodeGetCookie(*bbp++);
6937 printf("\n DD G_M%03u_IG%02u", Compiler::s_compMethodsCount, lab->igNum);
6944 case IF_T2_H2: // [Reg+imm]
6946 emitDispAddrRI(id->idReg1(), emitGetInsSC(id), attr);
6949 case IF_T2_K3: // [PC+imm]
6950 emitDispAddrRI(REG_PC, emitGetInsSC(id), attr);
6953 case IF_T1_J1: // reg, <regmask8>
6954 case IF_T2_I0: // reg, <regmask16>
6955 emitDispReg(id->idReg1(), attr, false);
6957 emitDispRegmask(emitGetInsSC(id), false);
6960 case IF_T1_D0: // Reg, Reg
6965 emitDispReg(id->idReg1(), attr, true);
6966 emitDispReg(id->idReg2(), attr, false);
6967 if (fmt == IF_T1_E && id->idIns() == INS_rsb)
6973 case IF_T2_E1: // Reg, [Reg]
6974 emitDispReg(id->idReg1(), attr, true);
6975 emitDispAddrR(id->idReg2(), attr);
6978 case IF_T2_D1: // Reg, Imm, Imm
6979 emitDispReg(id->idReg1(), attr, true);
6980 imm = emitGetInsSC(id);
6982 int lsb = (imm >> 5) & 0x1f;
6983 int msb = imm & 0x1f;
6985 int imm2 = msb + 1 - lsb;
6986 emitDispImm(imm1, true);
6987 emitDispImm(imm2, false);
6991 case IF_T1_C: // Reg, Reg, Imm
6998 emitDispReg(id->idReg1(), attr, true);
6999 imm = emitGetInsSC(id);
7000 if (emitInsIsLoadOrStore(ins))
7002 emitDispAddrRI(id->idReg2(), imm, attr);
7006 emitDispReg(id->idReg2(), attr, true);
7007 emitDispImm(imm, false);
7012 emitDispReg(id->idReg1(), attr, true);
7013 imm = emitGetInsSC(id);
7014 if (emitInsIsLoadOrStore(ins))
7016 emitDispAddrRI(REG_SP, imm, attr);
7020 emitDispReg(REG_SP, attr, true);
7021 emitDispImm(imm, false);
7026 emitDispReg(id->idReg1(), attr, true);
7027 emitDispAddrRI(REG_PC, emitGetInsSC(id), attr);
7032 emitDispReg(id->idReg1(), attr, true);
7033 emitDispReg(id->idReg2(), attr, false);
7034 imm = emitGetInsSC(id);
7035 if (id->idInsOpt() == INS_OPTS_RRX)
7037 emitDispShiftOpts(id->idInsOpt());
7042 emitDispShiftOpts(id->idInsOpt());
7043 emitDispImm(imm, false);
7048 imm = emitGetInsSC(id);
7049 emitDispReg(id->idReg1(), attr, true);
7050 emitDispReg(id->idReg2(), attr, (imm != 0));
7053 emitDispImm(imm, false);
7058 emitDispAddrRRI(id->idReg1(), id->idReg2(), emitGetInsSC(id), attr);
7062 emitDispReg(id->idReg1(), attr, true);
7063 emitDispAddrPUW(id->idReg2(), emitGetInsSC(id), id->idInsOpt(), attr);
7066 case IF_T1_H: // Reg, Reg, Reg
7067 emitDispReg(id->idReg1(), attr, true);
7068 if (emitInsIsLoadOrStore(ins))
7070 emitDispAddrRR(id->idReg2(), id->idReg3(), attr);
7074 emitDispReg(id->idReg2(), attr, true);
7075 emitDispReg(id->idReg3(), attr, false);
7081 emitDispReg(id->idReg1(), attr, true);
7082 emitDispReg(id->idReg2(), attr, true);
7083 emitDispReg(id->idReg3(), attr, false);
7087 emitDispReg(id->idReg1(), attr, true);
7088 emitDispReg(id->idReg2(), attr, true);
7089 emitDispReg(id->idReg3(), attr, false);
7093 switch (id->idIns())
7098 emitDispReg(id->idReg1(), EA_4BYTE, true);
7099 emitDispReg(id->idReg2(), EA_8BYTE, false);
7105 emitDispReg(id->idReg1(), EA_8BYTE, true);
7106 emitDispReg(id->idReg2(), EA_4BYTE, false);
7109 // we just use the type on the instruction
7110 // unless it is an asymmetrical one like the converts
7112 emitDispReg(id->idReg1(), attr, true);
7113 emitDispReg(id->idReg2(), attr, false);
7119 imm = emitGetInsSC(id);
7120 switch (id->idIns())
7124 emitDispReg(id->idReg1(), attr, true);
7125 emitDispAddrPUW(id->idReg2(), imm, id->idInsOpt(), attr);
7130 emitDispReg(id->idReg2(), attr, false);
7131 if (insOptAnyInc(id->idInsOpt()))
7134 emitDispRegRange(id->idReg1(), abs(imm) >> 2, attr);
7139 emitDispRegRange(id->idReg1(), abs(imm) >> 2, attr);
7148 switch (id->idIns())
7151 emitDispReg(id->idReg1(), attr, true); // EA_8BYTE
7152 emitDispReg(id->idReg2(), EA_4BYTE, true);
7153 emitDispReg(id->idReg3(), EA_4BYTE, false);
7156 emitDispReg(id->idReg1(), EA_4BYTE, true);
7157 emitDispReg(id->idReg2(), EA_4BYTE, true);
7158 emitDispReg(id->idReg3(), attr, false); // EA_8BYTE
7166 emitDispReg(id->idReg1(), attr, true);
7167 emitDispReg(id->idReg2(), attr, false);
7171 emitDispReg(id->idReg1(), attr, true);
7172 emitDispAddrRR(id->idReg2(), id->idReg3(), attr);
7175 case IF_T2_D0: // Reg, Reg, Imm, Imm
7176 emitDispReg(id->idReg1(), attr, true);
7177 emitDispReg(id->idReg2(), attr, true);
7178 imm = emitGetInsSC(id);
7181 int lsb = (imm >> 5) & 0x1f;
7182 int msb = imm & 0x1f;
7184 int imm2 = msb + 1 - lsb;
7185 emitDispImm(imm1, true);
7186 emitDispImm(imm2, false);
7190 int lsb = (imm >> 5) & 0x1f;
7191 int widthm1 = imm & 0x1f;
7193 int imm2 = widthm1 + 1;
7194 emitDispImm(imm1, true);
7195 emitDispImm(imm2, false);
7199 case IF_T2_C0: // Reg, Reg, Reg, Imm
7200 emitDispReg(id->idReg1(), attr, true);
7201 emitDispReg(id->idReg2(), attr, true);
7202 emitDispReg(id->idReg3(), attr, false);
7203 imm = emitGetInsSC(id);
7204 if (id->idInsOpt() == INS_OPTS_RRX)
7206 emitDispShiftOpts(id->idInsOpt());
7211 emitDispShiftOpts(id->idInsOpt());
7212 emitDispImm(imm, false);
7217 emitDispReg(id->idReg1(), attr, true);
7218 if (id->idIsLclVar())
7220 emitDispAddrRRI(id->idReg2(), codeGen->rsGetRsvdReg(), 0, attr);
7224 emitDispAddrRRI(id->idReg2(), id->idReg3(), emitGetInsSC(id), attr);
7229 emitDispReg(id->idReg1(), attr, true);
7230 emitDispReg(id->idReg2(), attr, true);
7231 emitDispAddrPUW(id->idReg3(), emitGetInsSC(id), id->idInsOpt(), attr);
7234 case IF_T2_F1: // Reg, Reg, Reg, Reg
7236 emitDispReg(id->idReg1(), attr, true);
7237 emitDispReg(id->idReg2(), attr, true);
7238 emitDispReg(id->idReg3(), attr, true);
7239 emitDispReg(id->idReg4(), attr, false);
7243 case IF_T2_M1: // Load Label
7244 emitDispReg(id->idReg1(), attr, true);
7245 if (id->idIsBound())
7246 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
7248 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
7251 case IF_T1_I: // Special Compare-and-branch
7252 emitDispReg(id->idReg1(), attr, true);
7255 case IF_T1_K: // Special Branch, conditional
7257 assert(((instrDescJmp*)id)->idjShort);
7262 if (fmt == IF_T2_N1)
7264 emitDispReg(id->idReg1(), attr, true);
7265 printf("%s ADDRESS ", (id->idIns() == INS_movw) ? "LOW" : "HIGH");
7273 if (id->idAddr()->iiaHasInstrCount())
7275 int instrCount = id->idAddr()->iiaGetInstrCount();
7279 printf("pc%s%d instructions", (instrCount >= 0) ? "+" : "", instrCount);
7283 unsigned insNum = emitFindInsNum(ig, id);
7284 UNATIVE_OFFSET srcOffs = ig->igOffs + emitFindOffset(ig, insNum + 1);
7285 UNATIVE_OFFSET dstOffs = ig->igOffs + emitFindOffset(ig, insNum + 1 + instrCount);
7286 ssize_t relOffs = (ssize_t)(emitOffsetToPtr(dstOffs) - emitOffsetToPtr(srcOffs));
7287 printf("pc%s%d (%d instructions)", (relOffs >= 0) ? "+" : "", relOffs, instrCount);
7290 else if (id->idIsBound())
7291 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
7293 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
7298 if (id->idIsCallAddr())
7300 offs = (ssize_t)id->idAddr()->iiaAddr;
7306 methodName = emitComp->eeGetMethodFullName((CORINFO_METHOD_HANDLE)id->idDebugOnlyInfo()->idMemCookie);
7311 if (id->idIsDspReloc())
7313 printf("%08X", offs);
7317 printf("%s", methodName);
7323 printf("unexpected format %s", emitIfName(id->idInsFmt()));
7324 assert(!"unexpectedFormat");
7328 if (id->idDebugOnlyInfo()->idVarRefOffs)
7331 emitDispFrameRef(id->idAddr()->iiaLclVar.lvaVarNum(), id->idAddr()->iiaLclVar.lvaOffset(),
7332 id->idDebugOnlyInfo()->idVarRefOffs, asmfm);
7338 void emitter::emitDispIns(
7339 instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* code, size_t sz, insGroup* ig)
7341 insFormat fmt = id->idInsFmt();
7343 /* Special-case IF_LARGEJMP */
7345 if ((fmt == IF_LARGEJMP) && id->idIsBound())
7347 // This is a pseudo-instruction format representing a large conditional branch. See the comment
7348 // in emitter::emitOutputLJ() for the full description.
7350 // For this pseudo-instruction, we will actually generate:
7352 // b<!cond> L_not // 2 bytes. Note that we reverse the condition.
7353 // b L_target // 4 bytes
7356 // These instructions don't exist in the actual instruction stream, so we need to fake them
7357 // up to display them.
7359 // Note: don't touch the actual instrDesc. If we accidentally messed it up, it would create a very
7360 // difficult to find bug.
7363 instrDescJmp* pidJmp = &idJmp;
7365 memset(&idJmp, 0, sizeof(idJmp));
7367 pidJmp->idIns(emitJumpKindToIns(emitReverseJumpKind(emitInsToJumpKind(id->idIns())))); // reverse the
7370 pidJmp->idInsFmt(IF_T1_K);
7371 pidJmp->idInsSize(emitInsSize(IF_T1_K));
7372 pidJmp->idjShort = 1;
7373 pidJmp->idAddr()->iiaSetInstrCount(1);
7374 pidJmp->idDebugOnlyInfo(id->idDebugOnlyInfo()); // share the idDebugOnlyInfo() field
7376 size_t bcondSizeOrZero = (code == NULL) ? 0 : 2; // branch is 2 bytes
7377 emitDispInsHelp(pidJmp, false, doffs, asmfm, offset, code, bcondSizeOrZero,
7378 NULL /* force display of pc-relative branch */);
7380 code += bcondSizeOrZero;
7383 // Next, display the unconditional branch
7385 // Reset the local instrDesc
7386 memset(&idJmp, 0, sizeof(idJmp));
7388 pidJmp->idIns(INS_b);
7389 pidJmp->idInsFmt(IF_T2_J2);
7390 pidJmp->idInsSize(emitInsSize(IF_T2_J2));
7391 pidJmp->idjShort = 0;
7392 if (id->idIsBound())
7394 pidJmp->idSetIsBound();
7395 pidJmp->idAddr()->iiaIGlabel = id->idAddr()->iiaIGlabel;
7399 pidJmp->idAddr()->iiaBBlabel = id->idAddr()->iiaBBlabel;
7401 pidJmp->idDebugOnlyInfo(id->idDebugOnlyInfo()); // share the idDebugOnlyInfo() field
7403 size_t brSizeOrZero = (code == NULL) ? 0 : 4; // unconditional branch is 4 bytes
7404 emitDispInsHelp(pidJmp, isNew, doffs, asmfm, offset, code, brSizeOrZero, ig);
7408 emitDispInsHelp(id, isNew, doffs, asmfm, offset, code, sz, ig);
7412 /*****************************************************************************
7414 * Display a stack frame reference.
7417 void emitter::emitDispFrameRef(int varx, int disp, int offs, bool asmfm)
7422 printf("TEMP_%02u", -varx);
7424 emitComp->gtDispLclVar(+varx, false);
7427 printf("-0x%02x", -disp);
7429 printf("+0x%02x", +disp);
7433 if (varx >= 0 && emitComp->opts.varNames)
7436 const char* varName;
7438 assert((unsigned)varx < emitComp->lvaCount);
7439 varDsc = emitComp->lvaTable + varx;
7440 varName = emitComp->compLocalVarName(varx, offs);
7444 printf("'%s", varName);
7447 printf("-%d", -disp);
7449 printf("+%d", +disp);
7458 void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataReg, GenTreeIndir* indir)
7460 // Handle unaligned floating point loads/stores
7461 if ((indir->gtFlags & GTF_IND_UNALIGNED))
7463 if (indir->OperGet() == GT_STOREIND)
7465 var_types type = indir->AsStoreInd()->Data()->TypeGet();
7466 if (type == TYP_FLOAT)
7468 regNumber tmpReg = indir->GetSingleTempReg();
7469 emitIns_R_R(INS_vmov_f2i, EA_4BYTE, tmpReg, dataReg);
7470 emitInsLoadStoreOp(INS_str, EA_4BYTE, tmpReg, indir, 0);
7473 else if (type == TYP_DOUBLE)
7475 regNumber tmpReg1 = indir->ExtractTempReg();
7476 regNumber tmpReg2 = indir->GetSingleTempReg();
7477 emitIns_R_R_R(INS_vmov_d2i, EA_8BYTE, tmpReg1, tmpReg2, dataReg);
7478 emitInsLoadStoreOp(INS_str, EA_4BYTE, tmpReg1, indir, 0);
7479 emitInsLoadStoreOp(INS_str, EA_4BYTE, tmpReg2, indir, 4);
7483 else if (indir->OperGet() == GT_IND)
7485 var_types type = indir->TypeGet();
7486 if (type == TYP_FLOAT)
7488 regNumber tmpReg = indir->GetSingleTempReg();
7489 emitInsLoadStoreOp(INS_ldr, EA_4BYTE, tmpReg, indir, 0);
7490 emitIns_R_R(INS_vmov_i2f, EA_4BYTE, dataReg, tmpReg);
7493 else if (type == TYP_DOUBLE)
7495 regNumber tmpReg1 = indir->ExtractTempReg();
7496 regNumber tmpReg2 = indir->GetSingleTempReg();
7497 emitInsLoadStoreOp(INS_ldr, EA_4BYTE, tmpReg1, indir, 0);
7498 emitInsLoadStoreOp(INS_ldr, EA_4BYTE, tmpReg2, indir, 4);
7499 emitIns_R_R_R(INS_vmov_i2d, EA_8BYTE, dataReg, tmpReg1, tmpReg2);
7505 // Proceed with ordinary loads/stores
7506 emitInsLoadStoreOp(ins, attr, dataReg, indir, 0);
7509 void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataReg, GenTreeIndir* indir, int offset)
7511 GenTree* addr = indir->Addr();
7513 if (addr->isContained())
7515 assert(addr->OperGet() == GT_LCL_VAR_ADDR || addr->OperGet() == GT_LEA);
7519 if (addr->OperGet() == GT_LEA)
7521 offset += addr->AsAddrMode()->Offset();
7522 if (addr->AsAddrMode()->gtScale > 0)
7524 assert(isPow2(addr->AsAddrMode()->gtScale));
7525 BitScanForward(&lsl, addr->AsAddrMode()->gtScale);
7529 GenTree* memBase = indir->Base();
7531 if (indir->HasIndex())
7533 assert(addr->OperGet() == GT_LEA);
7535 GenTree* index = indir->Index();
7539 regNumber tmpReg = indir->GetSingleTempReg();
7541 // If the LEA produces a GCREF or BYREF, we need to be careful to mark any temp register
7542 // computed with the base register as a BYREF.
7543 GenTreeAddrMode* lea = addr->AsAddrMode();
7544 emitAttr leaAttr = emitTypeSize(lea);
7545 emitAttr leaBasePartialAddrAttr = EA_IS_GCREF_OR_BYREF(leaAttr) ? EA_BYREF : EA_PTRSIZE;
7547 if (emitIns_valid_imm_for_add(offset, INS_FLAGS_DONT_CARE))
7551 // Generate code to set tmpReg = base + index*scale
7552 emitIns_R_R_R_I(INS_add, leaBasePartialAddrAttr, tmpReg, memBase->gtRegNum, index->gtRegNum,
7553 lsl, INS_FLAGS_DONT_CARE, INS_OPTS_LSL);
7557 // Generate code to set tmpReg = base + index
7558 emitIns_R_R_R(INS_add, leaBasePartialAddrAttr, tmpReg, memBase->gtRegNum, index->gtRegNum);
7561 noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
7563 // Then load/store dataReg from/to [tmpReg + offset]
7564 emitIns_R_R_I(ins, attr, dataReg, tmpReg, offset);
7566 else // large offset
7568 // First load/store tmpReg with the large offset constant
7569 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
7570 // Then add the base register
7572 emitIns_R_R_R(INS_add, leaBasePartialAddrAttr, tmpReg, tmpReg, memBase->gtRegNum);
7574 noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
7575 noway_assert(tmpReg != index->gtRegNum);
7577 // Then load/store dataReg from/to [tmpReg + index*scale]
7578 emitIns_R_R_R_I(ins, attr, dataReg, tmpReg, index->gtRegNum, lsl, INS_FLAGS_DONT_CARE,
7582 else // (offset == 0)
7586 // Then load/store dataReg from/to [memBase + index*scale]
7587 emitIns_R_R_R_I(ins, attr, dataReg, memBase->gtRegNum, index->gtRegNum, lsl, INS_FLAGS_DONT_CARE,
7592 // Then load/store dataReg from/to [memBase + index]
7593 emitIns_R_R_R(ins, attr, dataReg, memBase->gtRegNum, index->gtRegNum);
7599 if (emitIns_valid_imm_for_ldst_offset(offset, attr))
7601 // Then load/store dataReg from/to [memBase + offset]
7602 emitIns_R_R_I(ins, attr, dataReg, memBase->gtRegNum, offset);
7606 // We require a tmpReg to hold the offset
7607 regNumber tmpReg = indir->GetSingleTempReg();
7609 // First load/store tmpReg with the large offset constant
7610 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
7612 // Then load/store dataReg from/to [memBase + tmpReg]
7613 emitIns_R_R_R(ins, attr, dataReg, memBase->gtRegNum, tmpReg);
7621 assert(emitIns_valid_imm_for_add(offset, INS_FLAGS_DONT_CARE));
7622 emitIns_R_R_I(ins, attr, dataReg, addr->gtRegNum, offset);
7626 emitIns_R_R(ins, attr, dataReg, addr->gtRegNum);
7631 // The callee must call genConsumeReg() for any non-contained srcs
7632 // and genProduceReg() for any non-contained dsts.
7634 regNumber emitter::emitInsBinary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src)
7636 regNumber result = REG_NA;
7638 // dst can only be a reg
7639 assert(!dst->isContained());
7641 // src can be immed or reg
7642 assert(!src->isContained() || src->isContainedIntOrIImmed());
7644 // find immed (if any) - it cannot be a dst
7645 GenTreeIntConCommon* intConst = nullptr;
7646 if (src->isContainedIntOrIImmed())
7648 intConst = src->AsIntConCommon();
7653 emitIns_R_I(ins, attr, dst->gtRegNum, intConst->IconValue());
7654 return dst->gtRegNum;
7658 emitIns_R_R(ins, attr, dst->gtRegNum, src->gtRegNum);
7659 return dst->gtRegNum;
7663 regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src1, GenTree* src2)
7665 // dst can only be a reg
7666 assert(!dst->isContained());
7668 // find immed (if any) - it cannot be a dst
7669 // Only one src can be an int.
7670 GenTreeIntConCommon* intConst = nullptr;
7671 GenTree* nonIntReg = nullptr;
7673 if (varTypeIsFloating(dst))
7675 // src1 can only be a reg
7676 assert(!src1->isContained());
7677 // src2 can only be a reg
7678 assert(!src2->isContained());
7680 else // not floating point
7682 // src2 can be immed or reg
7683 assert(!src2->isContained() || src2->isContainedIntOrIImmed());
7685 // Check src2 first as we can always allow it to be a contained immediate
7686 if (src2->isContainedIntOrIImmed())
7688 intConst = src2->AsIntConCommon();
7691 // Only for commutative operations do we check src1 and allow it to be a contained immediate
7692 else if (dst->OperIsCommutative())
7694 // src1 can be immed or reg
7695 assert(!src1->isContained() || src1->isContainedIntOrIImmed());
7697 // Check src1 and allow it to be a contained immediate
7698 if (src1->isContainedIntOrIImmed())
7700 assert(!src2->isContainedIntOrIImmed());
7701 intConst = src1->AsIntConCommon();
7707 // src1 can only be a reg
7708 assert(!src1->isContained());
7712 insFlags flags = INS_FLAGS_DONT_CARE;
7713 bool isMulOverflow = false;
7714 if (dst->gtOverflowEx())
7716 if ((ins == INS_add) || (ins == INS_adc) || (ins == INS_sub) || (ins == INS_sbc))
7718 flags = INS_FLAGS_SET;
7720 else if (ins == INS_mul)
7722 isMulOverflow = true;
7723 assert(intConst == nullptr); // overflow format doesn't support an int constant operand
7727 assert(!"Invalid ins for overflow check");
7731 if (dst->gtSetFlags())
7733 assert((ins == INS_add) || (ins == INS_adc) || (ins == INS_sub) || (ins == INS_sbc) || (ins == INS_and) ||
7734 (ins == INS_orr) || (ins == INS_eor) || (ins == INS_orn));
7735 flags = INS_FLAGS_SET;
7738 if (intConst != nullptr)
7740 emitIns_R_R_I(ins, attr, dst->gtRegNum, nonIntReg->gtRegNum, intConst->IconValue(), flags);
7746 regNumber extraReg = dst->GetSingleTempReg();
7747 assert(extraReg != dst->gtRegNum);
7749 if ((dst->gtFlags & GTF_UNSIGNED) != 0)
7751 // Compute 8 byte result from 4 byte by 4 byte multiplication.
7752 emitIns_R_R_R_R(INS_umull, EA_4BYTE, dst->gtRegNum, extraReg, src1->gtRegNum, src2->gtRegNum);
7754 // Overflow exists if the result's high word is non-zero.
7755 emitIns_R_I(INS_cmp, attr, extraReg, 0);
7759 // Compute 8 byte result from 4 byte by 4 byte multiplication.
7760 emitIns_R_R_R_R(INS_smull, EA_4BYTE, dst->gtRegNum, extraReg, src1->gtRegNum, src2->gtRegNum);
7762 // Overflow exists if the result's high word is not merely a sign bit.
7763 emitIns_R_R_I(INS_cmp, attr, extraReg, dst->gtRegNum, 31, INS_FLAGS_DONT_CARE, INS_OPTS_ASR);
7768 // We can just do the arithmetic, setting the flags if needed.
7769 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum, flags);
7773 if (dst->gtOverflowEx())
7775 assert(!varTypeIsFloating(dst));
7777 emitJumpKind jumpKind;
7779 if (dst->OperGet() == GT_MUL)
7785 bool isUnsignedOverflow = ((dst->gtFlags & GTF_UNSIGNED) != 0);
7786 jumpKind = isUnsignedOverflow ? EJ_lo : EJ_vs;
7787 if (jumpKind == EJ_lo)
7789 if ((dst->OperGet() != GT_SUB) && (dst->OperGet() != GT_SUB_HI))
7796 // Jump to the block which will throw the exception.
7797 codeGen->genJumpToThrowHlpBlk(jumpKind, SCK_OVERFLOW);
7800 return dst->gtRegNum;
7803 #endif // defined(_TARGET_ARM_)