1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
5 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
6 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
10 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
11 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
18 #if defined(_TARGET_ARM_)
20 /*****************************************************************************/
21 /*****************************************************************************/
27 /*****************************************************************************/
29 const instruction emitJumpKindInstructions[] = {
32 #define JMP_SMALL(en, rev, ins) INS_##ins,
36 const emitJumpKind emitReverseJumpKinds[] = {
39 #define JMP_SMALL(en, rev, ins) EJ_##rev,
43 /*****************************************************************************
44 * Look up the instruction for a jump kind
47 /*static*/ instruction emitter::emitJumpKindToIns(emitJumpKind jumpKind)
49 assert((unsigned)jumpKind < ArrLen(emitJumpKindInstructions));
50 return emitJumpKindInstructions[jumpKind];
53 /*****************************************************************************
54 * Look up the jump kind for an instruction. It better be a conditional
55 * branch instruction with a jump kind!
58 /*static*/ emitJumpKind emitter::emitInsToJumpKind(instruction ins)
60 for (unsigned i = 0; i < ArrLen(emitJumpKindInstructions); i++)
62 if (ins == emitJumpKindInstructions[i])
64 emitJumpKind ret = (emitJumpKind)i;
65 assert(EJ_NONE < ret && ret < EJ_COUNT);
72 /*****************************************************************************
73 * Reverse the conditional jump
76 /*static*/ emitJumpKind emitter::emitReverseJumpKind(emitJumpKind jumpKind)
78 assert(jumpKind < EJ_COUNT);
79 return emitReverseJumpKinds[jumpKind];
82 /*****************************************************************************
84 * Return the allocated size (in bytes) of the given instruction descriptor.
87 size_t emitter::emitSizeOfInsDsc(instrDesc* id)
89 if (emitIsScnsInsDsc(id))
90 return SMALL_IDSC_SIZE;
92 assert((unsigned)id->idInsFmt() < emitFmtCount);
94 ID_OPS idOp = (ID_OPS)emitFmtToOps[id->idInsFmt()];
95 bool isCallIns = (id->idIns() == INS_bl) || (id->idIns() == INS_blx);
96 bool maybeCallIns = (id->idIns() == INS_b) || (id->idIns() == INS_bx);
98 // An INS_call instruction may use a "fat" direct/indirect call descriptor
99 // except for a local call to a label (i.e. call to a finally).
100 // Only ID_OP_CALL and ID_OP_SPEC check for this, so we enforce that the
101 // INS_call instruction always uses one of these idOps.
103 assert(!isCallIns || // either not a call or
104 idOp == ID_OP_CALL || // is a direct call
105 idOp == ID_OP_SPEC || // is an indirect call
106 idOp == ID_OP_JMP); // is a local call to finally clause
114 return sizeof(instrDescJmp);
117 return sizeof(instrDescLbl);
121 assert(isCallIns || maybeCallIns);
122 if (id->idIsLargeCall())
124 /* Must be a "fat" indirect call descriptor */
125 return sizeof(instrDescCGCA);
129 assert(!id->idIsLargeDsp());
130 assert(!id->idIsLargeCns());
131 return sizeof(instrDesc);
136 NO_WAY("unexpected instruction descriptor format");
140 if (id->idInsFmt() == IF_T2_N3)
142 assert((id->idIns() == INS_movw) || (id->idIns() == INS_movt));
143 return sizeof(instrDescReloc);
146 if (id->idIsLargeCns())
148 if (id->idIsLargeDsp())
149 return sizeof(instrDescCnsDsp);
151 return sizeof(instrDescCns);
155 if (id->idIsLargeDsp())
156 return sizeof(instrDescDsp);
158 return sizeof(instrDesc);
162 bool offsetFitsInVectorMem(int disp)
164 unsigned imm = unsigned_abs(disp);
165 return ((imm & 0x03fc) == imm);
169 /*****************************************************************************
171 * The following called for each recorded instruction -- use for debugging.
173 void emitter::emitInsSanityCheck(instrDesc* id)
175 /* What instruction format have we got? */
177 switch (id->idInsFmt())
179 case IF_T1_A: // T1_A ................
180 case IF_T2_A: // T2_A ................ ................
183 case IF_T1_B: // T1_B ........cccc.... cond
184 case IF_T2_B: // T2_B ................ ............iiii imm4
185 assert(emitGetInsSC(id) < 0x10);
188 case IF_T1_C: // T1_C .....iiiiinnnddd R1 R2 imm5
189 assert(isLowRegister(id->idReg1()));
190 assert(isLowRegister(id->idReg2()));
191 if (emitInsIsLoadOrStore(id->idIns()))
193 emitAttr size = id->idOpSize();
194 int imm = emitGetInsSC(id);
196 imm = insUnscaleImm(imm, size);
201 assert(id->idSmallCns() < 0x20);
205 case IF_T1_D0: // T1_D0 ........Dmmmmddd R1* R2*
206 assert(isGeneralRegister(id->idReg1()));
207 assert(isGeneralRegister(id->idReg2()));
210 case IF_T1_D1: // T1_D1 .........mmmm... R1*
211 assert(isGeneralRegister(id->idReg1()));
214 case IF_T1_D2: // T1_D2 .........mmmm... R3*
215 assert(isGeneralRegister(id->idReg3()));
218 case IF_T1_E: // T1_E ..........nnnddd R1 R2
219 assert(isLowRegister(id->idReg1()));
220 assert(isLowRegister(id->idReg2()));
221 assert(id->idSmallCns() < 0x20);
224 case IF_T1_F: // T1_F .........iiiiiii SP imm7
225 assert(id->idReg1() == REG_SP);
226 assert(id->idOpSize() == EA_4BYTE);
227 assert((emitGetInsSC(id) & ~0x1FC) == 0);
230 case IF_T1_G: // T1_G .......iiinnnddd R1 R2 imm3
231 assert(isLowRegister(id->idReg1()));
232 assert(isLowRegister(id->idReg2()));
233 assert(id->idSmallCns() < 0x8);
236 case IF_T1_H: // T1_H .......mmmnnnddd R1 R2 R3
237 assert(isLowRegister(id->idReg1()));
238 assert(isLowRegister(id->idReg2()));
239 assert(isLowRegister(id->idReg3()));
242 case IF_T1_I: // T1_I ......i.iiiiiddd R1 imm6
243 assert(isLowRegister(id->idReg1()));
246 case IF_T1_J0: // T1_J0 .....dddiiiiiiii R1 imm8
247 assert(isLowRegister(id->idReg1()));
248 assert(emitGetInsSC(id) < 0x100);
251 case IF_T1_J1: // T1_J1 .....dddiiiiiiii R1 <regmask8>
252 assert(isLowRegister(id->idReg1()));
253 assert(emitGetInsSC(id) < 0x100);
256 case IF_T1_J2: // T1_J2 .....dddiiiiiiii R1 SP imm8
257 assert(isLowRegister(id->idReg1()));
258 assert(id->idReg2() == REG_SP);
259 assert(id->idOpSize() == EA_4BYTE);
260 assert((emitGetInsSC(id) & ~0x3FC) == 0);
263 case IF_T1_L0: // T1_L0 ........iiiiiiii imm8
264 assert(emitGetInsSC(id) < 0x100);
267 case IF_T1_L1: // T1_L1 .......Rrrrrrrrr <regmask8+2>
268 assert(emitGetInsSC(id) < 0x400);
271 case IF_T2_C0: // T2_C0 ...........Snnnn .iiiddddiishmmmm R1 R2 R3 S, imm5, sh
272 assert(isGeneralRegister(id->idReg1()));
273 assert(isGeneralRegister(id->idReg2()));
274 assert(isGeneralRegister(id->idReg3()));
275 assert(emitGetInsSC(id) < 0x20);
278 case IF_T2_C4: // T2_C4 ...........Snnnn ....dddd....mmmm R1 R2 R3 S
279 case IF_T2_C5: // T2_C5 ............nnnn ....dddd....mmmm R1 R2 R3
280 case IF_T2_G1: // T2_G1 ............nnnn ttttTTTT........ R1 R2 R3
281 assert(isGeneralRegister(id->idReg1()));
282 assert(isGeneralRegister(id->idReg2()));
283 assert(isGeneralRegister(id->idReg3()));
286 case IF_T2_C1: // T2_C1 ...........S.... .iiiddddiishmmmm R1 R2 S, imm5, sh
287 case IF_T2_C2: // T2_C2 ...........S.... .iiiddddii..mmmm R1 R2 S, imm5
288 case IF_T2_C8: // T2_C8 ............nnnn .iii....iishmmmm R1 R2 imm5, sh
289 assert(isGeneralRegister(id->idReg1()));
290 assert(isGeneralRegister(id->idReg2()));
291 assert(emitGetInsSC(id) < 0x20);
294 case IF_T2_C6: // T2_C6 ................ ....dddd..iimmmm R1 R2 imm2
295 case IF_T2_C7: // T2_C7 ............nnnn ..........shmmmm R1 R2 imm2
296 assert(isGeneralRegister(id->idReg1()));
297 assert(isGeneralRegister(id->idReg2()));
298 assert(emitGetInsSC(id) < 0x4);
301 case IF_T2_C3: // T2_C3 ...........S.... ....dddd....mmmm R1 R2 S
302 case IF_T2_C9: // T2_C9 ............nnnn ............mmmm R1 R2
303 case IF_T2_C10: // T2_C10 ............mmmm ....dddd....mmmm R1 R2
304 assert(isGeneralRegister(id->idReg1()));
305 assert(isGeneralRegister(id->idReg2()));
308 case IF_T2_D0: // T2_D0 ............nnnn .iiiddddii.wwwww R1 R2 imm5, imm5
309 assert(isGeneralRegister(id->idReg1()));
310 assert(isGeneralRegister(id->idReg2()));
311 assert(emitGetInsSC(id) < 0x400);
314 case IF_T2_D1: // T2_D1 ................ .iiiddddii.wwwww R1 imm5, imm5
315 assert(isGeneralRegister(id->idReg1()));
316 assert(emitGetInsSC(id) < 0x400);
319 case IF_T2_E0: // T2_E0 ............nnnn tttt......shmmmm R1 R2 R3 imm2
320 assert(isGeneralRegister(id->idReg1()));
321 assert(isGeneralRegister(id->idReg2()));
322 if (id->idIsLclVar())
324 assert(isGeneralRegister(codeGen->rsGetRsvdReg()));
328 assert(isGeneralRegister(id->idReg3()));
329 assert(emitGetInsSC(id) < 0x4);
333 case IF_T2_E1: // T2_E1 ............nnnn tttt............ R1 R2
334 assert(isGeneralRegister(id->idReg1()));
335 assert(isGeneralRegister(id->idReg2()));
338 case IF_T2_E2: // T2_E2 ................ tttt............ R1
339 assert(isGeneralRegister(id->idReg1()));
342 case IF_T2_F1: // T2_F1 ............nnnn ttttdddd....mmmm R1 R2 R3 R4
343 case IF_T2_F2: // T2_F2 ............nnnn aaaadddd....mmmm R1 R2 R3 R4
344 assert(isGeneralRegister(id->idReg1()));
345 assert(isGeneralRegister(id->idReg2()));
346 assert(isGeneralRegister(id->idReg3()));
347 assert(isGeneralRegister(id->idReg4()));
350 case IF_T2_G0: // T2_G0 .......PU.W.nnnn ttttTTTTiiiiiiii R1 R2 R3 imm8, PUW
351 assert(isGeneralRegister(id->idReg1()));
352 assert(isGeneralRegister(id->idReg2()));
353 assert(isGeneralRegister(id->idReg3()));
354 assert(unsigned_abs(emitGetInsSC(id)) < 0x100);
357 case IF_T2_H0: // T2_H0 ............nnnn tttt.PUWiiiiiiii R1 R2 imm8, PUW
358 assert(isGeneralRegister(id->idReg1()));
359 assert(isGeneralRegister(id->idReg2()));
360 assert(unsigned_abs(emitGetInsSC(id)) < 0x100);
363 case IF_T2_H1: // T2_H1 ............nnnn tttt....iiiiiiii R1 R2 imm8
364 assert(isGeneralRegister(id->idReg1()));
365 assert(isGeneralRegister(id->idReg2()));
366 assert(emitGetInsSC(id) < 0x100);
369 case IF_T2_H2: // T2_H2 ............nnnn ........iiiiiiii R1 imm8
370 assert(isGeneralRegister(id->idReg1()));
371 assert(emitGetInsSC(id) < 0x100);
374 case IF_T2_I0: // T2_I0 ..........W.nnnn rrrrrrrrrrrrrrrr R1 W, imm16
375 assert(isGeneralRegister(id->idReg1()));
376 assert(emitGetInsSC(id) < 0x10000);
379 case IF_T2_N: // T2_N .....i......iiii .iiiddddiiiiiiii R1 imm16
380 assert(isGeneralRegister(id->idReg1()));
381 assert(!id->idIsReloc());
384 case IF_T2_N2: // T2_N2 .....i......iiii .iiiddddiiiiiiii R1 imm16
385 assert(isGeneralRegister(id->idReg1()));
386 assert((size_t)emitGetInsSC(id) < emitDataSize());
389 case IF_T2_N3: // T2_N3 .....i......iiii .iiiddddiiiiiiii R1 imm16
390 assert(isGeneralRegister(id->idReg1()));
391 assert(id->idIsReloc());
394 case IF_T2_I1: // T2_I1 ................ rrrrrrrrrrrrrrrr imm16
395 assert(emitGetInsSC(id) < 0x10000);
398 case IF_T2_K1: // T2_K1 ............nnnn ttttiiiiiiiiiiii R1 R2 imm12
399 case IF_T2_M0: // T2_M0 .....i......nnnn .iiiddddiiiiiiii R1 R2 imm12
400 assert(isGeneralRegister(id->idReg1()));
401 assert(isGeneralRegister(id->idReg2()));
402 assert(emitGetInsSC(id) < 0x1000);
405 case IF_T2_L0: // T2_L0 .....i.....Snnnn .iiiddddiiiiiiii R1 R2 S, imm8<<imm4
406 assert(isGeneralRegister(id->idReg1()));
407 assert(isGeneralRegister(id->idReg2()));
408 assert(isModImmConst(emitGetInsSC(id)));
411 case IF_T2_K4: // T2_K4 ........U....... ttttiiiiiiiiiiii R1 PC U, imm12
412 case IF_T2_M1: // T2_M1 .....i.......... .iiiddddiiiiiiii R1 PC imm12
413 assert(isGeneralRegister(id->idReg1()));
414 assert(id->idReg2() == REG_PC);
415 assert(emitGetInsSC(id) < 0x1000);
418 case IF_T2_K3: // T2_K3 ........U....... ....iiiiiiiiiiii PC U, imm12
419 assert(id->idReg1() == REG_PC);
420 assert(emitGetInsSC(id) < 0x1000);
423 case IF_T2_K2: // T2_K2 ............nnnn ....iiiiiiiiiiii R1 imm12
424 assert(isGeneralRegister(id->idReg1()));
425 assert(emitGetInsSC(id) < 0x1000);
428 case IF_T2_L1: // T2_L1 .....i.....S.... .iiiddddiiiiiiii R1 S, imm8<<imm4
429 case IF_T2_L2: // T2_L2 .....i......nnnn .iii....iiiiiiii R1 imm8<<imm4
430 assert(isGeneralRegister(id->idReg1()));
431 assert(isModImmConst(emitGetInsSC(id)));
434 case IF_T1_J3: // T1_J3 .....dddiiiiiiii R1 PC imm8
435 assert(isGeneralRegister(id->idReg1()));
436 assert(id->idReg2() == REG_PC);
437 assert(emitGetInsSC(id) < 0x100);
440 case IF_T1_K: // T1_K ....cccciiiiiiii Branch imm8, cond4
441 case IF_T1_M: // T1_M .....iiiiiiiiiii Branch imm11
442 case IF_T2_J1: // T2_J1 .....Scccciiiiii ..j.jiiiiiiiiiii Branch imm20, cond4
443 case IF_T2_J2: // T2_J2 .....Siiiiiiiiii ..j.jiiiiiiiiii. Branch imm24
444 case IF_T2_N1: // T2_N .....i......iiii .iiiddddiiiiiiii R1 imm16
445 case IF_T2_J3: // T2_J3 .....Siiiiiiiiii ..j.jiiiiiiiiii. Call imm24
450 if (id->idOpSize() == EA_8BYTE)
452 assert(isDoubleReg(id->idReg1()));
453 assert(isDoubleReg(id->idReg2()));
454 assert(isDoubleReg(id->idReg3()));
458 assert(id->idOpSize() == EA_4BYTE);
459 assert(isFloatReg(id->idReg1()));
460 assert(isFloatReg(id->idReg2()));
461 assert(isFloatReg(id->idReg3()));
466 assert(isFloatReg(id->idReg1()));
467 assert(isFloatReg(id->idReg2()));
471 if (id->idOpSize() == EA_8BYTE)
472 assert(isDoubleReg(id->idReg1()));
474 assert(isFloatReg(id->idReg1()));
475 assert(isGeneralRegister(id->idReg2()));
476 assert(offsetFitsInVectorMem(emitGetInsSC(id)));
480 assert(id->idOpSize() == EA_8BYTE);
481 if (id->idIns() == INS_vmov_d2i)
483 assert(isGeneralRegister(id->idReg1()));
484 assert(isGeneralRegister(id->idReg2()));
485 assert(isDoubleReg(id->idReg3()));
489 assert(id->idIns() == INS_vmov_i2d);
490 assert(isDoubleReg(id->idReg1()));
491 assert(isGeneralRegister(id->idReg2()));
492 assert(isGeneralRegister(id->idReg3()));
497 assert(id->idOpSize() == EA_4BYTE);
498 if (id->idIns() == INS_vmov_i2f)
500 assert(isFloatReg(id->idReg1()));
501 assert(isGeneralRegister(id->idReg2()));
505 assert(id->idIns() == INS_vmov_f2i);
506 assert(isGeneralRegister(id->idReg1()));
507 assert(isFloatReg(id->idReg2()));
512 printf("unexpected format %s\n", emitIfName(id->idInsFmt()));
513 assert(!"Unexpected format");
519 bool emitter::emitInsMayWriteToGCReg(instrDesc* id)
521 instruction ins = id->idIns();
522 insFormat fmt = id->idInsFmt();
527 // These are the formats with "destination" or "target" registers:
569 // Some formats with "destination" or "target" registers are actually used for store instructions, for the
570 // "source" value written to memory.
571 // Similarly, PUSH has a target register, indicating the start of the set of registers to push. POP
572 // *does* write to at least one register, so we do not make that a special case.
573 // Various compare/test instructions do not write (except to the flags). Technically "teq" does not need to
575 // be in this list because it has no forms matched above, but I'm putting it here for completeness.
596 // VMOV.i2f reads from the integer register. Conversely VMOV.f2i writes to GC pointer-sized
597 // integer register that might have previously held GC pointers, so they need to be included.
598 assert(id->idGCref() == GCT_NONE);
599 return (ins == INS_vmov_f2i);
602 // VMOV.i2d reads from the integer registers. Conversely VMOV.d2i writes to GC pointer-sized
603 // integer registers that might have previously held GC pointers, so they need to be included.
604 assert(id->idGCref() == GCT_NONE);
605 return (ins == INS_vmov_d2i);
612 bool emitter::emitInsWritesToLclVarStackLoc(instrDesc* id)
614 if (!id->idIsLclVar())
617 instruction ins = id->idIns();
619 // This list is related to the list of instructions used to store local vars in emitIns_S_R().
620 // We don't accept writing to float local vars.
633 bool emitter::emitInsMayWriteMultipleRegs(instrDesc* id)
635 instruction ins = id->idIns();
653 /*****************************************************************************/
655 /*****************************************************************************
657 * Return a string that represents the given register.
660 const char* emitter::emitRegName(regNumber reg, emitAttr attr, bool varName)
662 assert(reg < REG_COUNT);
664 const char* rn = emitComp->compRegVarName(reg, varName, false);
666 assert(strlen(rn) >= 1);
671 const char* emitter::emitFloatRegName(regNumber reg, emitAttr attr, bool varName)
673 assert(reg < REG_COUNT);
675 const char* rn = emitComp->compRegVarName(reg, varName, true);
677 assert(strlen(rn) >= 1);
683 /*****************************************************************************
685 * Returns the base encoding of the given CPU instruction.
688 emitter::insFormat emitter::emitInsFormat(instruction ins)
691 const static insFormat insFormats[] =
693 #define INST1(id, nm, fp, ldst, fmt, e1 ) fmt,
694 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) fmt,
695 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) fmt,
696 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) fmt,
697 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) fmt,
698 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) fmt,
699 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) fmt,
700 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) fmt,
705 assert(ins < ArrLen(insFormats));
706 assert((insFormats[ins] != IF_NONE));
708 return insFormats[ins];
717 /*static*/ const BYTE CodeGenInterface::instInfo[] =
719 #define INST1(id, nm, fp, ldst, fmt, e1 ) ldst | INST_FP*fp,
720 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) ldst | INST_FP*fp,
721 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) ldst | INST_FP*fp,
722 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) ldst | INST_FP*fp,
723 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) ldst | INST_FP*fp,
724 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) ldst | INST_FP*fp,
725 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) ldst | INST_FP*fp,
726 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) ldst | INST_FP*fp,
731 /*****************************************************************************
733 * Returns true if the instruction is some kind of load instruction
736 bool emitter::emitInsIsLoad(instruction ins)
738 // We have pseudo ins like lea which are not included in emitInsLdStTab.
739 if (ins < ArrLen(CodeGenInterface::instInfo))
740 return (CodeGenInterface::instInfo[ins] & LD) ? true : false;
745 /*****************************************************************************
747 * Returns true if the instruction is some kind of compare or test instruction
750 bool emitter::emitInsIsCompare(instruction ins)
752 // We have pseudo ins like lea which are not included in emitInsLdStTab.
753 if (ins < ArrLen(CodeGenInterface::instInfo))
754 return (CodeGenInterface::instInfo[ins] & CMP) ? true : false;
759 /*****************************************************************************
761 * Returns true if the instruction is some kind of store instruction
764 bool emitter::emitInsIsStore(instruction ins)
766 // We have pseudo ins like lea which are not included in emitInsLdStTab.
767 if (ins < ArrLen(CodeGenInterface::instInfo))
768 return (CodeGenInterface::instInfo[ins] & ST) ? true : false;
773 /*****************************************************************************
775 * Returns true if the instruction is some kind of load/store instruction
778 bool emitter::emitInsIsLoadOrStore(instruction ins)
780 // We have pseudo ins like lea which are not included in emitInsLdStTab.
781 if (ins < ArrLen(CodeGenInterface::instInfo))
782 return (CodeGenInterface::instInfo[ins] & (LD | ST)) ? true : false;
791 /*****************************************************************************
793 * Returns the specific encoding of the given CPU instruction and format
796 emitter::code_t emitter::emitInsCode(instruction ins, insFormat fmt)
799 const static code_t insCodes1[] =
801 #define INST1(id, nm, fp, ldst, fmt, e1 ) e1,
802 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) e1,
803 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) e1,
804 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e1,
805 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e1,
806 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e1,
807 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) e1,
808 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e1,
811 const static code_t insCodes2[] =
813 #define INST1(id, nm, fp, ldst, fmt, e1 )
814 #define INST2(id, nm, fp, ldst, fmt, e1, e2 ) e2,
815 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) e2,
816 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e2,
817 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e2,
818 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e2,
819 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) e2,
820 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e2,
823 const static code_t insCodes3[] =
825 #define INST1(id, nm, fp, ldst, fmt, e1 )
826 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
827 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 ) e3,
828 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e3,
829 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e3,
830 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e3,
831 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) e3,
832 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e3,
835 const static code_t insCodes4[] =
837 #define INST1(id, nm, fp, ldst, fmt, e1 )
838 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
839 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
840 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 ) e4,
841 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e4,
842 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e4,
843 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) e4,
844 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e4,
847 const static code_t insCodes5[] =
849 #define INST1(id, nm, fp, ldst, fmt, e1 )
850 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
851 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
852 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
853 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 ) e5,
854 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e5,
855 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) e5,
856 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e5,
859 const static code_t insCodes6[] =
861 #define INST1(id, nm, fp, ldst, fmt, e1 )
862 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
863 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
864 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
865 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
866 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 ) e6,
867 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) e6,
868 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e6,
871 const static code_t insCodes7[] =
873 #define INST1(id, nm, fp, ldst, fmt, e1 )
874 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
875 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
876 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
877 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
878 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 )
879 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) e7,
880 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e7,
883 const static code_t insCodes8[] =
885 #define INST1(id, nm, fp, ldst, fmt, e1 )
886 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
887 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
888 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
889 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
890 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 )
891 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 ) e8,
892 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e8,
895 const static code_t insCodes9[] =
897 #define INST1(id, nm, fp, ldst, fmt, e1 )
898 #define INST2(id, nm, fp, ldst, fmt, e1, e2 )
899 #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3 )
900 #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4 )
901 #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5 )
902 #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6 )
903 #define INST8(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8 )
904 #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e9,
907 const static insFormat formatEncode9[9] = { IF_T1_D0, IF_T1_H, IF_T1_J0, IF_T1_G, IF_T2_L0, IF_T2_C0, IF_T1_F, IF_T1_J2, IF_T1_J3 };
908 const static insFormat formatEncode8[8] = { IF_T1_H, IF_T1_C, IF_T2_E0, IF_T2_H0, IF_T2_K1, IF_T2_K4, IF_T1_J2, IF_T1_J3 };
909 const static insFormat formatEncode6A[6] = { IF_T1_H, IF_T1_C, IF_T2_E0, IF_T2_H0, IF_T2_K1, IF_T2_K4};
910 const static insFormat formatEncode6B[6] = { IF_T1_H, IF_T1_C, IF_T2_E0, IF_T2_H0, IF_T2_K1, IF_T1_J2 };
911 const static insFormat formatEncode5A[5] = { IF_T1_E, IF_T1_D0, IF_T1_J0, IF_T2_L1, IF_T2_C3 };
912 const static insFormat formatEncode5B[5] = { IF_T1_E, IF_T1_D0, IF_T1_J0, IF_T2_L2, IF_T2_C8 };
913 const static insFormat formatEncode4A[4] = { IF_T1_E, IF_T1_C, IF_T2_C4, IF_T2_C2 };
914 const static insFormat formatEncode4B[4] = { IF_T2_K2, IF_T2_H2, IF_T2_C7, IF_T2_K3 };
915 const static insFormat formatEncode4C[4] = { IF_T2_N, IF_T2_N1, IF_T2_N2, IF_T2_N3 };
916 const static insFormat formatEncode3A[3] = { IF_T1_E, IF_T2_C0, IF_T2_L0 };
917 const static insFormat formatEncode3B[3] = { IF_T1_E, IF_T2_C8, IF_T2_L2 };
918 const static insFormat formatEncode3C[3] = { IF_T1_E, IF_T2_C1, IF_T2_L1 };
919 const static insFormat formatEncode3D[3] = { IF_T1_L1, IF_T2_E2, IF_T2_I1 };
920 const static insFormat formatEncode3E[3] = { IF_T1_M, IF_T2_J2, IF_T2_J3 };
921 const static insFormat formatEncode2A[2] = { IF_T1_K, IF_T2_J1 };
922 const static insFormat formatEncode2B[2] = { IF_T1_D1, IF_T1_D2 };
923 const static insFormat formatEncode2C[2] = { IF_T1_D2, IF_T2_J3 };
924 const static insFormat formatEncode2D[2] = { IF_T1_J1, IF_T2_I0 };
925 const static insFormat formatEncode2E[2] = { IF_T1_E, IF_T2_C6 };
926 const static insFormat formatEncode2F[2] = { IF_T1_E, IF_T2_C5 };
927 const static insFormat formatEncode2G[2] = { IF_T1_J3, IF_T2_M1 };
930 code_t code = BAD_CODE;
931 insFormat insFmt = emitInsFormat(ins);
938 for (index = 0; index < 9; index++)
940 if (fmt == formatEncode9[index])
949 for (index = 0; index < 8; index++)
951 if (fmt == formatEncode8[index])
960 for (index = 0; index < 6; index++)
962 if (fmt == formatEncode6A[index])
971 for (index = 0; index < 6; index++)
973 if (fmt == formatEncode6B[index])
982 for (index = 0; index < 5; index++)
984 if (fmt == formatEncode5A[index])
993 for (index = 0; index < 5; index++)
995 if (fmt == formatEncode5B[index])
1004 for (index = 0; index < 4; index++)
1006 if (fmt == formatEncode4A[index])
1015 for (index = 0; index < 4; index++)
1017 if (fmt == formatEncode4B[index])
1026 for (index = 0; index < 4; index++)
1028 if (fmt == formatEncode4C[index])
1037 for (index = 0; index < 3; index++)
1039 if (fmt == formatEncode3A[index])
1048 for (index = 0; index < 3; index++)
1050 if (fmt == formatEncode3B[index])
1058 for (index = 0; index < 3; index++)
1060 if (fmt == formatEncode3C[index])
1068 for (index = 0; index < 3; index++)
1070 if (fmt == formatEncode3D[index])
1078 for (index = 0; index < 3; index++)
1080 if (fmt == formatEncode3E[index])
1089 for (index = 0; index < 2; index++)
1091 if (fmt == formatEncode2A[index])
1099 for (index = 0; index < 2; index++)
1101 if (fmt == formatEncode2B[index])
1109 for (index = 0; index < 2; index++)
1111 if (fmt == formatEncode2C[index])
1119 for (index = 0; index < 2; index++)
1121 if (fmt == formatEncode2D[index])
1129 for (index = 0; index < 2; index++)
1131 if (fmt == formatEncode2E[index])
1139 for (index = 0; index < 2; index++)
1141 if (fmt == formatEncode2F[index])
1150 for (index = 0; index < 2; index++)
1152 if (fmt == formatEncode2G[index])
1171 assert(ins < ArrLen(insCodes1));
1172 code = insCodes1[ins];
1175 assert(ins < ArrLen(insCodes2));
1176 code = insCodes2[ins];
1179 assert(ins < ArrLen(insCodes3));
1180 code = insCodes3[ins];
1183 assert(ins < ArrLen(insCodes4));
1184 code = insCodes4[ins];
1187 assert(ins < ArrLen(insCodes5));
1188 code = insCodes5[ins];
1191 assert(ins < ArrLen(insCodes6));
1192 code = insCodes6[ins];
1195 assert(ins < ArrLen(insCodes7));
1196 code = insCodes7[ins];
1199 assert(ins < ArrLen(insCodes8));
1200 code = insCodes8[ins];
1203 assert(ins < ArrLen(insCodes9));
1204 code = insCodes9[ins];
1208 assert((code != BAD_CODE));
1213 /*****************************************************************************
1215 * Return the code size of the given instruction format. The 'insSize' return type enum
1216 * indicates a 16 bit, 32 bit, or 48 bit instruction.
1219 emitter::insSize emitter::emitInsSize(insFormat insFmt)
1221 if ((insFmt >= IF_T1_A) && (insFmt < IF_T2_A))
1224 if ((insFmt >= IF_T2_A) && (insFmt < IF_INVALID))
1227 if (insFmt == IF_LARGEJMP)
1230 assert(!"Invalid insFormat");
1234 /*****************************************************************************
1236 * isModImmConst() returns true when immediate 'val32' can be encoded
1237 * using the special modified immediate constant available in Thumb
1240 /*static*/ bool emitter::isModImmConst(int val32)
1242 unsigned uval32 = (unsigned)val32;
1243 unsigned imm8 = uval32 & 0xff;
1245 /* encode = 0000x */
1249 unsigned imm32a = (imm8 << 16) | imm8;
1250 /* encode = 0001x */
1251 if (imm32a == uval32)
1254 unsigned imm32b = (imm32a << 8);
1255 /* encode = 0010x */
1256 if (imm32b == uval32)
1259 unsigned imm32c = (imm32a | imm32b);
1260 /* encode = 0011x */
1261 if (imm32c == uval32)
1264 unsigned mask32 = 0x00000ff;
1266 unsigned encode = 31; /* 11111 */
1272 temp = uval32 & ~mask32;
1276 } while (encode >= 8);
1281 /*****************************************************************************
1283 * encodeModImmConst() returns the special ARM 12-bit immediate encoding.
1284 * that is used to encode the immediate. (4-bits, 8-bits)
1285 * If the imm can not be encoded then 0x0BADC0DE is returned.
1288 /*static*/ int emitter::encodeModImmConst(int val32)
1290 unsigned uval32 = (unsigned)val32;
1291 unsigned imm8 = uval32 & 0xff;
1292 unsigned encode = imm8 >> 7;
1299 /* encode = 0000x */
1305 imm32a = (imm8 << 16) | imm8;
1306 /* encode = 0001x */
1307 if (imm32a == uval32)
1313 imm32b = (imm32a << 8);
1314 /* encode = 0010x */
1315 if (imm32b == uval32)
1321 imm32c = (imm32a | imm32b);
1322 /* encode = 0011x */
1323 if (imm32c == uval32)
1331 encode = 31; /* 11111 */
1335 temp = uval32 & ~mask32;
1338 imm8 = (uval32 & mask32) >> (32 - encode);
1339 assert((imm8 & 0x80) != 0);
1343 } while (encode >= 8);
1345 assert(!"encodeModImmConst failed!");
1349 unsigned result = (encode << 7) | (imm8 & 0x7f);
1350 assert(result <= 0x0fff);
1351 assert(result >= 0);
1355 /*****************************************************************************
1357 * emitIns_valid_imm_for_alu() returns true when the immediate 'imm'
1358 * can be encoded using the 12-bit funky Arm immediate encoding
1360 /*static*/ bool emitter::emitIns_valid_imm_for_alu(int imm)
1362 if (isModImmConst(imm))
1367 /*****************************************************************************
1369 * emitIns_valid_imm_for_mov() returns true when the immediate 'imm'
1370 * can be encoded using a single mov or mvn instruction.
1372 /*static*/ bool emitter::emitIns_valid_imm_for_mov(int imm)
1374 if ((imm & 0x0000ffff) == imm) // 16-bit immediate
1376 if (isModImmConst(imm)) // funky arm immediate
1378 if (isModImmConst(~imm)) // funky arm immediate via mvn
1383 /*****************************************************************************
1385 * emitIns_valid_imm_for_small_mov() returns true when the immediate 'imm'
1386 * can be encoded using a single 2-byte mov instruction.
1388 /*static*/ bool emitter::emitIns_valid_imm_for_small_mov(regNumber reg, int imm, insFlags flags)
1390 return isLowRegister(reg) && insSetsFlags(flags) && ((imm & 0x00ff) == imm);
1393 /*****************************************************************************
1395 * emitins_valid_imm_for_add() returns true when the immediate 'imm'
1396 * can be encoded using a single add or sub instruction.
1398 /*static*/ bool emitter::emitIns_valid_imm_for_add(int imm, insFlags flags)
1400 if ((unsigned_abs(imm) <= 0x00000fff) && (flags != INS_FLAGS_SET)) // 12-bit immediate via add/sub
1402 if (isModImmConst(imm)) // funky arm immediate
1404 if (isModImmConst(-imm)) // funky arm immediate via sub
1409 /*****************************************************************************
1411 * emitins_valid_imm_for_cmp() returns true if this 'imm'
1412 * can be encoded as a input operand to an cmp instruction.
1414 /*static*/ bool emitter::emitIns_valid_imm_for_cmp(int imm, insFlags flags)
1416 if (isModImmConst(imm)) // funky arm immediate
1418 if (isModImmConst(-imm)) // funky arm immediate via sub
1423 /*****************************************************************************
1425 * emitIns_valid_imm_for_add_sp() returns true when the immediate 'imm'
1426 * can be encoded in "add Rd,SP,i10".
1428 /*static*/ bool emitter::emitIns_valid_imm_for_add_sp(int imm)
1430 if ((imm & 0x03fc) == imm)
1435 /*****************************************************************************
1437 * emitIns_valid_imm_for_ldst_offset() returns true when the immediate 'imm'
1438 * can be encoded as the offset in a ldr/str instruction.
1440 /*static*/ bool emitter::emitIns_valid_imm_for_ldst_offset(int imm, emitAttr size)
1442 if ((imm & 0x0fff) == imm)
1443 return true; // encodable using IF_T2_K1
1444 if (unsigned_abs(imm) <= 0x0ff)
1445 return true; // encodable using IF_T2_H0
1449 /*****************************************************************************
1451 * emitIns_valid_imm_for_vldst_offset() returns true when the immediate 'imm'
1452 * can be encoded as the offset in a vldr/vstr instruction, i.e. when it is
1453 * a non-negative multiple of 4 that is less than 1024.
1455 /*static*/ bool emitter::emitIns_valid_imm_for_vldst_offset(int imm)
1457 if ((imm & 0x3fc) == imm)
1462 /*****************************************************************************
1464 * Add an instruction with no operands.
1467 void emitter::emitIns(instruction ins)
1469 instrDesc* id = emitNewInstrSmall(EA_4BYTE);
1470 insFormat fmt = emitInsFormat(ins);
1471 insSize isz = emitInsSize(fmt);
1473 assert((fmt == IF_T1_A) || (fmt == IF_T2_A));
1483 /*****************************************************************************
1485 * Add an instruction with a single immediate value.
1488 void emitter::emitIns_I(instruction ins, emitAttr attr, target_ssize_t imm)
1490 insFormat fmt = IF_NONE;
1494 bool onlyT1 = false;
1496 /* Figure out the encoding format of the instruction */
1499 #ifdef FEATURE_ITINSTRUCTION
1515 assert((imm & 0x0F) == imm);
1519 #endif // FEATURE_ITINSTRUCTION
1522 assert((imm & 0xA000) == 0); // Cannot push PC or SP
1524 if (imm & 0x4000) // Is the LR being pushed?
1527 goto COMMON_PUSH_POP;
1530 assert((imm & 0x2000) == 0); // Cannot pop SP
1531 assert((imm & 0xC000) != 0xC000); // Cannot pop both PC and LR
1533 if (imm & 0x8000) // Is the PC being popped?
1535 if (imm & 0x4000) // Is the LR being popped?
1543 if (((imm - 1) & imm) == 0) // Is only one or zero bits set in imm?
1545 if (((imm == 0) && !hasLR) || // imm has no bits set, but hasLR is set
1546 (!hasPC && !hasLR)) // imm has one bit set, and neither of hasPC/hasLR are set
1548 onlyT1 = true; // if only one bit is set we must use the T1 encoding
1552 imm &= ~0xE000; // ensure that PC, LR and SP bits are removed from imm
1554 if (((imm & 0x00ff) == imm) && !useT2)
1564 // We have to use the Thumb-2 push single register encoding
1565 regNumber reg = genRegNumFromMask(imm);
1566 emitIns_R(ins, attr, reg);
1571 // Encode the PC and LR bits as the lowest two bits
1584 // TODO-ARM-Cleanup: Enable or delete.
1585 case INS_bkpt: // Windows uses a different encoding
1586 if ((imm & 0x0000ffff) == imm)
1592 assert(!"Instruction cannot be encoded");
1599 if ((imm & 0x000f) == imm)
1606 assert(!"Instruction cannot be encoded");
1613 assert((fmt == IF_T1_B) || (fmt == IF_T1_L0) || (fmt == IF_T1_L1) || (fmt == IF_T2_I1) || (fmt == IF_T2_B));
1615 instrDesc* id = emitNewInstrSC(attr, imm);
1616 insSize isz = emitInsSize(fmt);
1626 /*****************************************************************************
1628 * Add an instruction referencing a single register.
1631 void emitter::emitIns_R(instruction ins, emitAttr attr, regNumber reg)
1633 emitAttr size = EA_SIZE(attr);
1634 insFormat fmt = IF_NONE;
1636 /* Figure out the encoding format of the instruction */
1641 if (isLowRegister(reg))
1643 int regmask = 1 << ((int)reg);
1644 emitIns_I(ins, attr, regmask);
1647 assert(size == EA_PTRSIZE);
1652 assert(size == EA_PTRSIZE);
1657 assert(size == EA_PTRSIZE);
1662 emitIns_R_R_I(ins, attr, reg, reg, 0);
1668 assert((fmt == IF_T1_D1) || (fmt == IF_T2_E2));
1670 instrDesc* id = emitNewInstrSmall(attr);
1671 insSize isz = emitInsSize(fmt);
1682 /*****************************************************************************
1684 * Add an instruction referencing a register and a constant.
1687 void emitter::emitIns_R_I(
1688 instruction ins, emitAttr attr, regNumber reg, target_ssize_t imm, insFlags flags /* = INS_FLAGS_DONT_CARE */)
1691 insFormat fmt = IF_NONE;
1692 insFlags sf = INS_FLAGS_DONT_CARE;
1694 /* Figure out the encoding format of the instruction */
1699 if ((reg == REG_SP) && insDoesNotSetFlags(flags) && ((imm & 0x01fc) == imm))
1702 sf = INS_FLAGS_NOT_SET;
1704 else if (isLowRegister(reg) && insSetsFlags(flags) && (unsigned_abs(imm) <= 0x00ff))
1708 assert((ins == INS_add) || (ins == INS_sub));
1711 else // ins == INS_sub
1720 // otherwise we have to use a Thumb-2 encoding
1721 emitIns_R_R_I(ins, attr, reg, reg, imm, flags);
1727 emitIns_R_R_I(ins, attr, reg, reg, imm, flags);
1733 if (attr == EA_8BYTE)
1735 assert(isDoubleReg(reg));
1741 assert(attr == EA_4BYTE);
1742 assert(isFloatReg(reg));
1745 assert(((reg - REG_F0) + imm) <= 32);
1748 if (ins == INS_vpush)
1751 sf = INS_FLAGS_NOT_SET;
1757 sf = INS_FLAGS_NOT_SET;
1762 bool onlyT1 = false;
1764 assert((imm & 0x2000) == 0); // Cannot pop SP
1765 assert((imm & 0xC000) != 0xC000); // Cannot pop both PC and LR
1766 assert((imm & 0xFFFF0000) == 0); // Can only contain lower 16 bits
1768 if (imm & 0x8000) // Is the PC being popped?
1771 if (imm & 0x4000) // Is the LR being pushed?
1777 if (!isLowRegister(reg))
1780 if (((imm - 1) & imm) == 0) // Is only one or zero bits set in imm?
1782 if (((imm == 0) && !hasLR) || // imm has no bits set, but hasLR is set
1783 (!hasPC && !hasLR)) // imm has one bit set, and neither of hasPC/hasLR are set
1785 onlyT1 = true; // if only one bit is set we must use the T1 encoding
1789 imm &= ~0xE000; // ensure that PC, LR and SP bits are removed from imm
1791 if (((imm & 0x00ff) == imm) && !useT2)
1801 assert(!"Instruction cannot be encoded");
1802 // We have to use the Thumb-2 str single register encoding
1803 // reg = genRegNumFromMask(imm);
1804 // emitIns_R(ins, attr, reg);
1809 // Encode the PC and LR bits as the lowest two bits
1811 if (fmt == IF_T2_I0)
1835 // use the Reg, Reg, Imm encoding
1836 emitIns_R_R_I(ins, attr, reg, reg, imm, flags);
1840 assert(!EA_IS_CNS_RELOC(attr));
1842 if (isLowRegister(reg) && insSetsFlags(flags) && ((imm & 0x00ff) == imm))
1847 else if (isModImmConst(imm))
1850 sf = insMustSetFlags(flags);
1852 else if (isModImmConst(~imm)) // See if we can use move negated instruction instead
1857 sf = insMustSetFlags(flags);
1859 else if (insDoesNotSetFlags(flags) && ((imm & 0x0000ffff) == imm))
1861 // mov => movw instruction
1864 sf = INS_FLAGS_NOT_SET;
1868 assert(!"Instruction cannot be encoded");
1874 assert(!EA_IS_RELOC(attr));
1875 assert(insDoesNotSetFlags(flags));
1877 if ((imm & 0x0000ffff) == imm)
1880 sf = INS_FLAGS_NOT_SET;
1884 assert(!"Instruction cannot be encoded");
1889 if (isModImmConst(imm))
1892 sf = insMustSetFlags(flags);
1896 assert(!"Instruction cannot be encoded");
1901 assert(!EA_IS_CNS_RELOC(attr));
1902 assert(insSetsFlags(flags));
1904 if (isLowRegister(reg) && ((imm & 0x0ff) == imm))
1908 else if (isModImmConst(imm))
1912 else if (isModImmConst(-imm))
1920 assert(!"emitIns_R_I: immediate doesn't fit into the instruction");
1928 assert(insSetsFlags(flags));
1930 if (isModImmConst(imm))
1936 assert(!"Instruction cannot be encoded");
1940 #ifdef FEATURE_PLI_INSTRUCTION
1942 assert(insDoesNotSetFlags(flags));
1943 if ((reg == REG_SP) && (unsigned_abs(imm) <= 0x0fff))
1946 sf = INS_FLAGS_NOT_SET;
1949 #endif // FEATURE_PLI_INSTRUCTION
1953 assert(insDoesNotSetFlags(flags));
1954 sf = INS_FLAGS_NOT_SET;
1955 if ((imm >= 0) && (imm <= 0x0fff))
1959 else if ((imm < 0) && (-imm <= 0x00ff))
1966 assert(!"Instruction cannot be encoded");
1973 assert((fmt == IF_T1_F) || (fmt == IF_T1_J0) || (fmt == IF_T1_J1) || (fmt == IF_T2_H2) || (fmt == IF_T2_I0) ||
1974 (fmt == IF_T2_K2) || (fmt == IF_T2_K3) || (fmt == IF_T2_L1) || (fmt == IF_T2_L2) || (fmt == IF_T2_M1) ||
1975 (fmt == IF_T2_N) || (fmt == IF_T2_VLDST));
1977 assert(sf != INS_FLAGS_DONT_CARE);
1979 instrDesc* id = emitNewInstrSC(attr, imm);
1980 insSize isz = emitInsSize(fmt);
1992 void emitter::emitIns_MovRelocatableImmediate(instruction ins, emitAttr attr, regNumber reg, BYTE* addr)
1994 assert(EA_IS_RELOC(attr));
1995 assert((ins == INS_movw) || (ins == INS_movt));
1997 insFormat fmt = IF_T2_N3;
1998 insFlags sf = INS_FLAGS_NOT_SET;
2000 instrDesc* id = emitNewInstrReloc(attr, addr);
2001 insSize isz = emitInsSize(fmt);
2013 /*****************************************************************************
2015 * Add an instruction referencing two registers
2018 void emitter::emitIns_R_R(
2019 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insFlags flags /* = INS_FLAGS_DONT_CARE */)
2022 emitAttr size = EA_SIZE(attr);
2023 insFormat fmt = IF_NONE;
2024 insFlags sf = INS_FLAGS_DONT_CARE;
2026 /* Figure out the encoding format of the instruction */
2030 if (insDoesNotSetFlags(flags))
2033 sf = INS_FLAGS_NOT_SET;
2039 // Use the Thumb-1 reg,reg,reg encoding
2040 emitIns_R_R_R(ins, attr, reg1, reg1, reg2, flags);
2044 if (insDoesNotSetFlags(flags))
2046 assert(reg1 != reg2);
2048 sf = INS_FLAGS_NOT_SET;
2050 else // insSetsFlags(flags)
2053 if (isLowRegister(reg1) && isLowRegister(reg2))
2065 assert(insSetsFlags(flags));
2067 if (isLowRegister(reg1) && isLowRegister(reg2))
2069 fmt = IF_T1_E; // both are low registers
2073 fmt = IF_T1_D0; // one or both are high registers
2078 assert(isGeneralRegister(reg1));
2079 assert(isFloatReg(reg2));
2081 sf = INS_FLAGS_NOT_SET;
2085 assert(isFloatReg(reg1));
2086 assert(isGeneralRegister(reg2));
2088 sf = INS_FLAGS_NOT_SET;
2094 assert(isFloatReg(reg1));
2095 assert(isDoubleReg(reg2));
2101 assert(isDoubleReg(reg1));
2102 assert(isFloatReg(reg2));
2109 assert(size == EA_4BYTE);
2110 assert(isFloatReg(reg1));
2111 assert(isFloatReg(reg2));
2115 assert(reg1 != reg2);
2122 if (size == EA_8BYTE)
2124 assert(isDoubleReg(reg1));
2125 assert(isDoubleReg(reg2));
2129 assert(isFloatReg(reg1));
2130 assert(isFloatReg(reg2));
2136 sf = INS_FLAGS_NOT_SET;
2143 emitIns_R_R_R(ins, attr, reg1, reg1, reg2);
2157 emitIns_R_R_I(ins, attr, reg1, reg2, 0);
2166 if (insSetsFlags(flags) && isLowRegister(reg1) && isLowRegister(reg2))
2175 // assert below fired for bug 281892 where the two operands of an OR were
2176 // the same static field load which got cse'd.
2177 // there's no reason why this assert would be true in general
2178 // assert(reg1 != reg2);
2179 // Use the Thumb-2 three register encoding
2180 emitIns_R_R_R_I(ins, attr, reg1, reg1, reg2, 0, flags);
2187 // assert below fired for bug 296394 where the two operands of an
2188 // arithmetic right shift were the same local variable
2189 // there's no reason why this assert would be true in general
2190 // assert(reg1 != reg2);
2191 if (insSetsFlags(flags) && isLowRegister(reg1) && isLowRegister(reg2))
2198 // Use the Thumb-2 three register encoding
2199 emitIns_R_R_R(ins, attr, reg1, reg1, reg2, flags);
2205 // We will prefer the T2 encoding, unless (flags == INS_FLAGS_SET)
2206 // The thumb-1 instruction executes much slower as it must always set the flags
2208 if (insMustSetFlags(flags) && isLowRegister(reg1) && isLowRegister(reg2))
2215 // Use the Thumb-2 three register encoding
2216 emitIns_R_R_R(ins, attr, reg1, reg2, reg1, flags);
2224 if (insSetsFlags(flags) && isLowRegister(reg1) && isLowRegister(reg2))
2231 // Use the Thumb-2 register with shift encoding
2232 emitIns_R_R_I(ins, attr, reg1, reg2, 0, flags);
2239 assert(size == EA_4BYTE);
2244 assert(size == EA_4BYTE);
2246 assert(insDoesNotSetFlags(flags));
2247 if (isLowRegister(reg1) && isLowRegister(reg2))
2250 sf = INS_FLAGS_NOT_SET;
2254 // Use the Thumb-2 reg,reg with rotation encoding
2255 emitIns_R_R_I(ins, attr, reg1, reg2, 0, INS_FLAGS_NOT_SET);
2261 assert(size == EA_1BYTE);
2262 assert(insDoesNotSetFlags(flags));
2264 sf = INS_FLAGS_NOT_SET;
2268 assert(size == EA_2BYTE);
2269 assert(insDoesNotSetFlags(flags));
2271 sf = INS_FLAGS_NOT_SET;
2275 assert(insDoesNotSetFlags(flags));
2277 sf = INS_FLAGS_NOT_SET;
2282 assert(size == EA_1BYTE);
2283 assert(insDoesNotSetFlags(flags));
2285 sf = INS_FLAGS_NOT_SET;
2290 assert(size == EA_2BYTE);
2291 assert(insDoesNotSetFlags(flags));
2293 sf = INS_FLAGS_NOT_SET;
2297 printf("did not expect instruction %s\n", codeGen->genInsName(ins));
2302 assert((fmt == IF_T1_D0) || (fmt == IF_T1_E) || (fmt == IF_T2_C3) || (fmt == IF_T2_C9) || (fmt == IF_T2_C10) ||
2303 (fmt == IF_T2_VFP2) || (fmt == IF_T2_VMOVD) || (fmt == IF_T2_VMOVS) || (fmt == IF_T2_E1));
2305 assert(sf != INS_FLAGS_DONT_CARE);
2307 instrDesc* id = emitNewInstrSmall(attr);
2308 insSize isz = emitInsSize(fmt);
2321 /*****************************************************************************
2323 * Add an instruction referencing a register and two constants.
2326 void emitter::emitIns_R_I_I(
2327 instruction ins, emitAttr attr, regNumber reg, int imm1, int imm2, insFlags flags /* = INS_FLAGS_DONT_CARE */)
2330 insFormat fmt = IF_NONE;
2331 insFlags sf = INS_FLAGS_DONT_CARE;
2332 int imm = 0; // combined immediates
2334 /* Figure out the encoding format of the instruction */
2340 int msb = lsb + imm2 - 1;
2342 assert((lsb >= 0) && (lsb <= 31)); // required for encoding of INS_bfc
2343 assert((msb >= 0) && (msb <= 31)); // required for encoding of INS_bfc
2344 assert(msb >= lsb); // required for encoding of INS_bfc
2346 imm = (lsb << 5) | msb;
2348 assert(insDoesNotSetFlags(flags));
2350 sf = INS_FLAGS_NOT_SET;
2357 assert(fmt == IF_T2_D1);
2358 assert(sf != INS_FLAGS_DONT_CARE);
2360 instrDesc* id = emitNewInstrSC(attr, imm);
2361 insSize isz = emitInsSize(fmt);
2373 /*****************************************************************************
2375 * Add an instruction referencing two registers and a constant.
2378 void emitter::emitIns_R_R_I(instruction ins,
2383 insFlags flags /* = INS_FLAGS_DONT_CARE */,
2384 insOpts opt /* = INS_OPTS_NONE */)
2386 emitAttr size = EA_SIZE(attr);
2387 insFormat fmt = IF_NONE;
2388 insFlags sf = INS_FLAGS_DONT_CARE;
2395 /* Figure out the encoding format of the instruction */
2399 assert(insOptsNone(opt));
2401 // Can we possibly encode the immediate 'imm' using a Thumb-1 encoding?
2402 if ((reg2 == REG_SP) && insDoesNotSetFlags(flags) && ((imm & 0x03fc) == imm))
2404 if ((reg1 == REG_SP) && ((imm & 0x01fc) == imm))
2406 // Use Thumb-1 encoding
2407 emitIns_R_I(ins, attr, reg1, imm, flags);
2410 else if (isLowRegister(reg1))
2413 sf = INS_FLAGS_NOT_SET;
2420 assert(insOptsNone(opt));
2422 // Is it just a mov?
2423 if ((imm == 0) && insDoesNotSetFlags(flags))
2425 // Is the mov even necessary?
2426 // Fix 383915 ARM ILGEN
2429 emitIns_R_R(INS_mov, attr, reg1, reg2, flags);
2433 // Can we encode the immediate 'imm' using a Thumb-1 encoding?
2434 else if (isLowRegister(reg1) && isLowRegister(reg2) && insSetsFlags(flags) && (unsigned_abs(imm) <= 0x0007))
2438 assert((ins == INS_add) || (ins == INS_sub));
2448 else if ((reg1 == reg2) && isLowRegister(reg1) && insSetsFlags(flags) && (unsigned_abs(imm) <= 0x00ff))
2452 assert((ins == INS_add) || (ins == INS_sub));
2459 // Use Thumb-1 encoding
2460 emitIns_R_I(ins, attr, reg1, imm, flags);
2463 else if (isModImmConst(imm))
2466 sf = insMustSetFlags(flags);
2468 else if (isModImmConst(-imm))
2470 assert((ins == INS_add) || (ins == INS_sub));
2471 ins = (ins == INS_add) ? INS_sub : INS_add;
2474 sf = insMustSetFlags(flags);
2476 else if (insDoesNotSetFlags(flags) && (unsigned_abs(imm) <= 0x0fff))
2480 assert((ins == INS_add) || (ins == INS_sub));
2481 ins = (ins == INS_add) ? INS_sub : INS_add;
2484 // add/sub => addw/subw instruction
2485 // Note that even when using the w prefix the immediate is still only 12 bits?
2486 ins = (ins == INS_add) ? INS_addw : INS_subw;
2488 sf = INS_FLAGS_NOT_SET;
2490 else if (insDoesNotSetFlags(flags) && (reg1 != REG_SP) && (reg1 != REG_PC))
2492 // movw,movt reg1, imm
2493 codeGen->instGen_Set_Reg_To_Imm(attr, reg1, (ins == INS_sub ? -1 : 1) * imm);
2496 emitIns_R_R(INS_add, attr, reg1, reg2);
2502 assert(!"Instruction cannot be encoded");
2510 assert(insOptsNone(opt));
2511 if (isModImmConst(imm))
2514 sf = insMustSetFlags(flags);
2516 else if (isModImmConst(~imm))
2519 sf = insMustSetFlags(flags);
2524 else if (ins == INS_bic)
2526 else if (ins == INS_orr)
2528 else if (ins == INS_orn)
2531 assert(!"Instruction cannot be encoded");
2535 assert(!"Instruction cannot be encoded");
2540 assert(insOptsNone(opt));
2541 if (imm == 0 && isLowRegister(reg1) && isLowRegister(reg2) && insSetsFlags(flags))
2552 assert(insOptsNone(opt));
2553 if (isModImmConst(imm))
2556 sf = insMustSetFlags(flags);
2560 assert(!"Instruction cannot be encoded");
2565 assert(insOptsNone(opt));
2566 assert(insDoesNotSetFlags(flags));
2567 assert(reg2 == REG_PC);
2568 sf = INS_FLAGS_NOT_SET;
2570 if (isLowRegister(reg1) && ((imm & 0x00ff) == imm))
2574 else if ((imm & 0x0fff) == imm)
2580 assert(!"Instruction cannot be encoded");
2585 assert((imm >= 0) && (imm <= 31)); // required for encoding
2586 assert(!insOptAnyInc(opt));
2589 assert(insOptsNone(opt));
2590 if (isLowRegister(reg1) && isLowRegister(reg2) && insSetsFlags(flags))
2592 // Use the Thumb-1 reg,reg encoding
2593 emitIns_R_R(ins, attr, reg1, reg2, flags);
2597 else // imm > 0 && imm <= 31
2599 assert(insOptAnyShift(opt));
2602 sf = insMustSetFlags(flags);
2609 assert(insSetsFlags(flags));
2610 assert((imm >= 0) && (imm <= 31)); // required for encoding
2611 assert(!insOptAnyInc(opt));
2614 assert(insOptsNone(opt));
2617 // Use the Thumb-1 reg,reg encoding
2618 emitIns_R_R(ins, attr, reg1, reg2, flags);
2621 if (((ins == INS_cmn) || (ins == INS_tst)) && isLowRegister(reg1) && isLowRegister(reg2))
2623 // Use the Thumb-1 reg,reg encoding
2624 emitIns_R_R(ins, attr, reg1, reg2, flags);
2628 else // imm > 0 && imm <= 31)
2630 assert(insOptAnyShift(opt));
2631 if (insOptsRRX(opt))
2643 assert(insOptsNone(opt));
2645 // On ARM, the immediate shift count of LSL and ROR must be between 1 and 31. For LSR and ASR, it is between
2646 // 1 and 32, though we don't ever use 32. Although x86 allows an immediate shift count of 8-bits in
2647 // instruction encoding, the CPU looks at only the lower 5 bits. As per ECMA, specifying a shift count to
2648 // the IL SHR, SHL, or SHL.UN instruction that is greater than or equal to the width of the type will yield
2649 // an undefined value. We choose that undefined value in this case to match x86 behavior, by only using the
2650 // lower 5 bits of the constant shift count.
2655 // Additional Fix 383915 ARM ILGEN
2656 if ((reg1 != reg2) || insMustSetFlags(flags))
2658 // Use MOV/MOVS instriction
2659 emitIns_R_R(INS_mov, attr, reg1, reg2, flags);
2664 if (insSetsFlags(flags) && (ins != INS_ror) && isLowRegister(reg1) && isLowRegister(reg2))
2672 sf = insMustSetFlags(flags);
2678 assert(size == EA_4BYTE);
2683 assert(size == EA_4BYTE);
2685 assert(insOptsNone(opt));
2686 assert(insDoesNotSetFlags(flags));
2687 assert((imm & 0x018) == imm); // required for encoding
2689 if ((imm == 0) && isLowRegister(reg1) && isLowRegister(reg2))
2691 // Use Thumb-1 encoding
2692 emitIns_R_R(ins, attr, reg1, reg2, INS_FLAGS_NOT_SET);
2697 sf = INS_FLAGS_NOT_SET;
2702 #ifdef FEATURE_PLI_INSTRUCTION
2704 #endif // FEATURE_PLI_INSTRUCTION
2705 assert(insOptsNone(opt));
2706 assert(insDoesNotSetFlags(flags));
2707 assert((imm & 0x003) == imm); // required for encoding
2710 sf = INS_FLAGS_NOT_SET;
2715 assert(size == EA_1BYTE);
2716 assert(insDoesNotSetFlags(flags));
2718 if (isLowRegister(reg1) && isLowRegister(reg2) && insOptsNone(opt) && ((imm & 0x001f) == imm))
2721 sf = INS_FLAGS_NOT_SET;
2724 goto COMMON_THUMB2_LDST;
2727 assert(size == EA_1BYTE);
2728 goto COMMON_THUMB2_LDST;
2732 assert(size == EA_2BYTE);
2733 assert(insDoesNotSetFlags(flags));
2735 if (isLowRegister(reg1) && isLowRegister(reg2) && insOptsNone(opt) && ((imm & 0x003e) == imm))
2738 sf = INS_FLAGS_NOT_SET;
2741 goto COMMON_THUMB2_LDST;
2744 assert(size == EA_2BYTE);
2745 goto COMMON_THUMB2_LDST;
2751 assert(fmt == IF_NONE);
2752 assert(insDoesNotSetFlags(flags));
2753 assert(offsetFitsInVectorMem(imm)); // required for encoding
2754 if (insOptAnyInc(opt))
2756 if (insOptsPostInc(opt))
2760 else // insOptsPreDec(opt)
2767 assert(insOptsNone(opt));
2770 sf = INS_FLAGS_NOT_SET;
2776 assert(size == EA_4BYTE);
2777 assert(insDoesNotSetFlags(flags));
2779 // Can we possibly encode the immediate 'imm' using a Thumb-1 encoding?
2780 if (isLowRegister(reg1) && insOptsNone(opt) && ((imm & 0x03fc) == imm))
2785 sf = INS_FLAGS_NOT_SET;
2788 else if (reg2 == REG_PC)
2793 sf = INS_FLAGS_NOT_SET;
2797 else if (isLowRegister(reg2))
2799 // Only the smaller range 'imm' can be encoded
2800 if ((imm & 0x07c) == imm)
2803 sf = INS_FLAGS_NOT_SET;
2809 // If we did not find a thumb-1 encoding above
2814 assert(fmt == IF_NONE);
2815 assert(insDoesNotSetFlags(flags));
2816 sf = INS_FLAGS_NOT_SET;
2818 if (insOptAnyInc(opt))
2820 if (insOptsPostInc(opt))
2822 else // insOptsPreDec(opt)
2825 if (unsigned_abs(imm) <= 0x00ff)
2831 assert(!"Instruction cannot be encoded");
2836 assert(insOptsNone(opt));
2837 if ((reg2 == REG_PC) && (unsigned_abs(imm) <= 0x0fff))
2841 else if ((imm & 0x0fff) == imm)
2845 else if (unsigned_abs(imm) <= 0x0ff)
2851 // Load imm into a register
2852 regNumber rsvdReg = codeGen->rsGetRsvdReg();
2853 codeGen->instGen_Set_Reg_To_Imm(EA_4BYTE, rsvdReg, (ssize_t)imm);
2854 emitIns_R_R_R(ins, attr, reg1, reg2, rsvdReg);
2862 assert(insOptsNone(opt));
2863 assert(insDoesNotSetFlags(flags));
2864 sf = INS_FLAGS_NOT_SET;
2866 if ((imm & 0x03fc) == imm)
2872 assert(!"Instruction cannot be encoded");
2877 assert(!"Unexpected instruction");
2879 assert((fmt == IF_T1_C) || (fmt == IF_T1_E) || (fmt == IF_T1_G) || (fmt == IF_T1_J2) || (fmt == IF_T1_J3) ||
2880 (fmt == IF_T2_C1) || (fmt == IF_T2_C2) || (fmt == IF_T2_C6) || (fmt == IF_T2_C7) || (fmt == IF_T2_C8) ||
2881 (fmt == IF_T2_H0) || (fmt == IF_T2_H1) || (fmt == IF_T2_K1) || (fmt == IF_T2_K4) || (fmt == IF_T2_L0) ||
2882 (fmt == IF_T2_M0) || (fmt == IF_T2_VLDST) || (fmt == IF_T2_M1));
2883 assert(sf != INS_FLAGS_DONT_CARE);
2885 instrDesc* id = emitNewInstrSC(attr, imm);
2886 insSize isz = emitInsSize(fmt);
2900 /*****************************************************************************
2902 * Add an instruction referencing three registers.
2905 void emitter::emitIns_R_R_R(instruction ins,
2910 insFlags flags /* = INS_FLAGS_DONT_CARE */)
2912 emitAttr size = EA_SIZE(attr);
2913 insFormat fmt = IF_NONE;
2914 insFlags sf = INS_FLAGS_DONT_CARE;
2916 /* Figure out the encoding format of the instruction */
2920 // Encodings do not support SP in the reg3 slot
2923 // Swap reg2 and reg3
2930 assert(reg3 != REG_SP);
2932 if (isLowRegister(reg1) && isLowRegister(reg2) && isLowRegister(reg3) && insSetsFlags(flags))
2939 if ((ins == INS_add) && insDoesNotSetFlags(flags))
2943 // Use the Thumb-1 regdest,reg encoding
2944 emitIns_R_R(ins, attr, reg1, reg3, flags);
2949 // Use the Thumb-1 regdest,reg encoding
2950 emitIns_R_R(ins, attr, reg1, reg2, flags);
2955 // Use the Thumb-2 reg,reg,reg with shift encoding
2956 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, flags);
2967 // Try to encode as a Thumb-1 instruction
2968 emitIns_R_R(ins, attr, reg1, reg3, flags);
2974 // Use the Thumb-2 three register encoding, with imm=0
2975 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, flags);
2981 if (reg1 == reg2 && insSetsFlags(flags) && isLowRegister(reg1) && isLowRegister(reg3))
2983 // Use the Thumb-1 regdest,reg encoding
2984 emitIns_R_R(ins, attr, reg1, reg3, flags);
2991 sf = insMustSetFlags(flags);
2995 if (insMustSetFlags(flags))
2997 if ((reg1 == reg2) && isLowRegister(reg1))
2999 // Use the Thumb-1 regdest,reg encoding
3000 emitIns_R_R(ins, attr, reg1, reg3, flags);
3003 if ((reg1 == reg3) && isLowRegister(reg1))
3005 // Use the Thumb-1 regdest,reg encoding
3006 emitIns_R_R(ins, attr, reg1, reg2, flags);
3011 assert(!"Instruction cannot be encoded");
3016 #if !defined(USE_HELPERS_FOR_INT_DIV)
3019 #endif // !USE_HELPERS_FOR_INT_DIV
3021 assert(insDoesNotSetFlags(flags));
3023 sf = INS_FLAGS_NOT_SET;
3029 assert(size == EA_1BYTE);
3030 goto COMMON_THUMB1_LDST;
3035 assert(size == EA_2BYTE);
3036 goto COMMON_THUMB1_LDST;
3040 assert(size == EA_4BYTE);
3043 assert(insDoesNotSetFlags(flags));
3045 if (isLowRegister(reg1) && isLowRegister(reg2) && isLowRegister(reg3))
3048 sf = INS_FLAGS_NOT_SET;
3052 // Use the Thumb-2 reg,reg,reg with shift encoding
3053 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, flags);
3062 if (size == EA_8BYTE)
3064 assert(isDoubleReg(reg1));
3065 assert(isDoubleReg(reg2));
3066 assert(isDoubleReg(reg3));
3070 assert(isFloatReg(reg1));
3071 assert(isFloatReg(reg2));
3072 assert(isFloatReg(reg3));
3075 sf = INS_FLAGS_NOT_SET;
3079 assert(isDoubleReg(reg1));
3080 assert(isGeneralRegister(reg2));
3081 assert(isGeneralRegister(reg3));
3083 sf = INS_FLAGS_NOT_SET;
3087 assert(isGeneralRegister(reg1));
3088 assert(isGeneralRegister(reg2));
3089 assert(isDoubleReg(reg3));
3091 sf = INS_FLAGS_NOT_SET;
3096 assert(insDoesNotSetFlags(flags));
3098 sf = INS_FLAGS_NOT_SET;
3104 assert((fmt == IF_T1_H) || (fmt == IF_T2_C4) || (fmt == IF_T2_C5) || (fmt == IF_T2_VFP3) || (fmt == IF_T2_VMOVD) ||
3106 assert(sf != INS_FLAGS_DONT_CARE);
3108 instrDesc* id = emitNewInstr(attr);
3109 insSize isz = emitInsSize(fmt);
3123 /*****************************************************************************
3125 * Add an instruction referencing two registers and two constants.
3128 void emitter::emitIns_R_R_I_I(instruction ins,
3134 insFlags flags /* = INS_FLAGS_DONT_CARE */)
3136 insFormat fmt = IF_NONE;
3137 insFlags sf = INS_FLAGS_DONT_CARE;
3141 int msb = lsb + width - 1;
3142 int imm = 0; /* combined immediate */
3144 assert((lsb >= 0) && (lsb <= 31)); // required for encodings
3145 assert((width > 0) && (width <= 32)); // required for encodings
3146 assert((msb >= 0) && (msb <= 31)); // required for encodings
3147 assert(msb >= lsb); // required for encodings
3149 /* Figure out the encoding format of the instruction */
3153 assert(insDoesNotSetFlags(flags));
3154 imm = (lsb << 5) | msb;
3157 sf = INS_FLAGS_NOT_SET;
3162 assert(insDoesNotSetFlags(flags));
3163 imm = (lsb << 5) | (width - 1);
3166 sf = INS_FLAGS_NOT_SET;
3172 assert((fmt == IF_T2_D0));
3173 assert(sf != INS_FLAGS_DONT_CARE);
3175 instrDesc* id = emitNewInstrSC(attr, imm);
3176 insSize isz = emitInsSize(fmt);
3189 /*****************************************************************************
3191 * Add an instruction referencing three registers and a constant.
3194 void emitter::emitIns_R_R_R_I(instruction ins,
3200 insFlags flags /* = INS_FLAGS_DONT_CARE */,
3201 insOpts opt /* = INS_OPTS_NONE */)
3203 emitAttr size = EA_SIZE(attr);
3204 insFormat fmt = IF_NONE;
3205 insFlags sf = INS_FLAGS_DONT_CARE;
3207 /* Figure out the encoding format of the instruction */
3215 if (isLowRegister(reg1) && isLowRegister(reg2) && isLowRegister(reg3) && insSetsFlags(flags))
3217 // Use the Thumb-1 reg,reg,reg encoding
3218 emitIns_R_R_R(ins, attr, reg1, reg2, reg3, flags);
3221 if ((ins == INS_add) && insDoesNotSetFlags(flags))
3225 // Use the Thumb-1 regdest,reg encoding
3226 emitIns_R_R(ins, attr, reg1, reg3, flags);
3231 // Use the Thumb-1 regdest,reg encoding
3232 emitIns_R_R(ins, attr, reg1, reg2, flags);
3246 assert((imm >= 0) && (imm <= 31)); // required for encoding
3247 assert(!insOptAnyInc(opt));
3250 if (opt == INS_OPTS_LSL) // left shift of zero
3251 opt = INS_OPTS_NONE; // is a nop
3253 assert(insOptsNone(opt));
3254 if (isLowRegister(reg1) && isLowRegister(reg2) && isLowRegister(reg3) && insSetsFlags(flags))
3258 // Use the Thumb-1 regdest,reg encoding
3259 emitIns_R_R(ins, attr, reg1, reg3, flags);
3262 if ((reg1 == reg3) && (ins != INS_bic) && (ins != INS_orn) && (ins != INS_sbc))
3264 // Use the Thumb-1 regdest,reg encoding
3265 emitIns_R_R(ins, attr, reg1, reg2, flags);
3270 else // imm > 0 && imm <= 31)
3272 assert(insOptAnyShift(opt));
3273 if (insOptsRRX(opt))
3277 sf = insMustSetFlags(flags);
3283 assert(size == EA_1BYTE);
3284 goto COMMON_THUMB2_LDST;
3289 assert(size == EA_2BYTE);
3290 goto COMMON_THUMB2_LDST;
3294 assert(size == EA_4BYTE);
3297 assert(insDoesNotSetFlags(flags));
3298 assert((imm & 0x0003) == imm); // required for encoding
3300 if ((imm == 0) && insOptsNone(opt) && isLowRegister(reg1) && isLowRegister(reg2) && isLowRegister(reg3))
3302 // Use the Thumb-1 reg,reg,reg encoding
3303 emitIns_R_R_R(ins, attr, reg1, reg2, reg3, flags);
3306 assert(insOptsNone(opt) || insOptsLSL(opt));
3308 sf = INS_FLAGS_NOT_SET;
3313 assert(insDoesNotSetFlags(flags));
3314 assert((imm & 0x03) == 0);
3315 sf = INS_FLAGS_NOT_SET;
3317 if (insOptAnyInc(opt))
3319 if (insOptsPostInc(opt))
3321 else // insOptsPreDec(opt)
3326 assert(insOptsNone(opt));
3329 if (unsigned_abs(imm) <= 0x03fc)
3336 assert(!"Instruction cannot be encoded");
3343 assert((fmt == IF_T2_C0) || (fmt == IF_T2_E0) || (fmt == IF_T2_G0));
3344 assert(sf != INS_FLAGS_DONT_CARE);
3346 // 3-reg ops can't use the small instrdesc
3347 instrDescCns* id = emitAllocInstrCns(attr);
3348 id->idSetIsLargeCns();
3349 id->idcCnsVal = imm;
3353 id->idInsSize(emitInsSize(fmt));
3365 /*****************************************************************************
3367 * Add an instruction referencing four registers.
3370 void emitter::emitIns_R_R_R_R(
3371 instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, regNumber reg4)
3373 insFormat fmt = IF_NONE;
3374 insFlags sf = INS_FLAGS_NOT_SET;
3376 /* Figure out the encoding format of the instruction */
3384 assert(reg1 != reg2); // Illegal encoding
3394 assert((fmt == IF_T2_F1) || (fmt == IF_T2_F2));
3396 instrDesc* id = emitNewInstr(attr);
3397 insSize isz = emitInsSize(fmt);
3412 /*****************************************************************************
3414 * Add an instruction with a static data member operand. If 'size' is 0, the
3415 * instruction operates on the address of the static member instead of its
3416 * value (e.g. "push offset clsvar", rather than "push dword ptr [clsvar]").
3419 void emitter::emitIns_C(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, int offs)
3424 /*****************************************************************************
3426 * Add an instruction referencing stack-based local variable.
3429 void emitter::emitIns_S(instruction ins, emitAttr attr, int varx, int offs)
3434 /*****************************************************************************
3436 * Add an instruction referencing a register and a stack-based local variable.
3438 void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
3442 assert(!"Please use ins_Load() to select the correct instruction");
3468 insFormat fmt = IF_NONE;
3469 insFlags sf = INS_FLAGS_NOT_SET;
3472 /* Figure out the variable's frame position */
3477 base = emitComp->lvaFrameAddress(varx, emitComp->funCurrentFunc()->funKind != FUNC_ROOT, ®2, offs);
3480 undisp = unsigned_abs(disp);
3482 if (CodeGen::instIsFP(ins))
3484 // all fp mem ops take 8 bit immediate, multiplied by 4, plus sign
3486 // Note if undisp is not a multiple of four we will fail later on
3487 // when we try to encode this instruction
3488 // Its better to fail later with a better error message than
3489 // to fail here when the RBM_OPT_RSVD is not available
3491 if (undisp <= 0x03fc)
3497 regNumber rsvdReg = codeGen->rsGetRsvdReg();
3498 emitIns_genStackOffset(rsvdReg, varx, offs);
3499 emitIns_R_R(INS_add, EA_4BYTE, rsvdReg, reg2);
3500 emitIns_R_R_I(ins, attr, reg1, rsvdReg, 0);
3504 else if (emitInsIsLoadOrStore(ins))
3506 if (isLowRegister(reg1) && (reg2 == REG_SP) && (ins == INS_ldr) && ((disp & 0x03fc) == disp))
3510 else if (disp >= 0 && disp <= 0x0fff)
3514 else if (undisp <= 0x0ff)
3520 // Load disp into a register
3521 regNumber rsvdReg = codeGen->rsGetRsvdReg();
3522 emitIns_genStackOffset(rsvdReg, varx, offs);
3526 else if (ins == INS_add)
3528 if (isLowRegister(reg1) && (reg2 == REG_SP) && ((disp & 0x03fc) == disp))
3532 else if (undisp <= 0x0fff)
3539 // add/sub => addw/subw instruction
3540 // Note that even when using the w prefix the immediate is still only 12 bits?
3541 ins = (ins == INS_add) ? INS_addw : INS_subw;
3546 // Load disp into a register
3547 regNumber rsvdReg = codeGen->rsGetRsvdReg();
3548 emitIns_genStackOffset(rsvdReg, varx, offs);
3549 emitIns_R_R_R(ins, attr, reg1, reg2, rsvdReg);
3553 else if (ins == INS_movw || ins == INS_movt)
3558 assert((fmt == IF_T1_J2) || (fmt == IF_T2_E0) || (fmt == IF_T2_H0) || (fmt == IF_T2_K1) || (fmt == IF_T2_L0) ||
3559 (fmt == IF_T2_N) || (fmt == IF_T2_VLDST) || (fmt == IF_T2_M0));
3560 assert(sf != INS_FLAGS_DONT_CARE);
3562 instrDesc* id = emitNewInstrCns(attr, disp);
3563 insSize isz = emitInsSize(fmt);
3569 id->idInsOpt(INS_OPTS_NONE);
3572 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
3573 id->idSetIsLclVar();
3575 id->idSetIsLclFPBase();
3578 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
3585 // generate the offset of &varx + offs into a register
3586 void emitter::emitIns_genStackOffset(regNumber r, int varx, int offs)
3592 base = emitComp->lvaFrameAddress(varx, emitComp->funCurrentFunc()->funKind != FUNC_ROOT, ®Base, offs);
3595 emitIns_R_S(INS_movw, EA_4BYTE, r, varx, offs);
3597 if ((disp & 0xffff) != disp)
3599 emitIns_R_S(INS_movt, EA_4BYTE, r, varx, offs);
3603 /*****************************************************************************
3605 * Add an instruction referencing a stack-based local variable and a register
3607 void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
3611 assert(!"Please use ins_Store() to select the correct instruction");
3627 insFormat fmt = IF_NONE;
3628 insFlags sf = INS_FLAGS_NOT_SET;
3631 /* Figure out the variable's frame position */
3636 base = emitComp->lvaFrameAddress(varx, emitComp->funCurrentFunc()->funKind != FUNC_ROOT, ®2, offs);
3639 undisp = unsigned_abs(disp);
3641 if (CodeGen::instIsFP(ins))
3643 // all fp mem ops take 8 bit immediate, multiplied by 4, plus sign
3645 // Note if undisp is not a multiple of four we will fail later on
3646 // when we try to encode this instruction
3647 // Its better to fail later with a better error message than
3648 // to fail here when the RBM_OPT_RSVD is not available
3650 if (undisp <= 0x03fc)
3656 regNumber rsvdReg = codeGen->rsGetRsvdReg();
3657 emitIns_genStackOffset(rsvdReg, varx, offs);
3658 emitIns_R_R(INS_add, EA_4BYTE, rsvdReg, reg2);
3659 emitIns_R_R_I(ins, attr, reg1, rsvdReg, 0);
3663 else if (isLowRegister(reg1) && (reg2 == REG_SP) && (ins == INS_str) && ((disp & 0x03fc) == disp))
3667 else if (disp >= 0 && disp <= 0x0fff)
3671 else if (undisp <= 0x0ff)
3677 // Load disp into a register
3678 regNumber rsvdReg = codeGen->rsGetRsvdReg();
3679 emitIns_genStackOffset(rsvdReg, varx, offs);
3682 assert((fmt == IF_T1_J2) || (fmt == IF_T2_E0) || (fmt == IF_T2_H0) || (fmt == IF_T2_VLDST) || (fmt == IF_T2_K1));
3683 assert(sf != INS_FLAGS_DONT_CARE);
3685 instrDesc* id = emitNewInstrCns(attr, disp);
3686 insSize isz = emitInsSize(fmt);
3692 id->idInsOpt(INS_OPTS_NONE);
3695 id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
3696 id->idSetIsLclVar();
3698 id->idSetIsLclFPBase();
3700 id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
3707 /*****************************************************************************
3709 * Add an instruction referencing stack-based local variable and an immediate
3711 void emitter::emitIns_S_I(instruction ins, emitAttr attr, int varx, int offs, int val)
3716 /*****************************************************************************
3718 * Add an instruction with a register + static member operands.
3720 void emitter::emitIns_R_C(instruction ins, emitAttr attr, regNumber reg, CORINFO_FIELD_HANDLE fldHnd, int offs)
3724 assert(!"Please use ins_Load() to select the correct instruction");
3726 assert(emitInsIsLoad(ins) || (ins == INS_lea));
3732 int doff = Compiler::eeGetJitDataOffs(fldHnd);
3733 ssize_t addr = NULL;
3737 NYI_ARM("JitDataOffset static fields");
3739 else if (fldHnd == FLD_GLOBAL_FS)
3741 NYI_ARM("Thread-Local-Storage static fields");
3743 else if (fldHnd == FLD_GLOBAL_DS)
3745 addr = (ssize_t)offs;
3750 assert(!jitStaticFldIsGlobAddr(fldHnd));
3751 addr = (ssize_t)emitComp->info.compCompHnd->getFieldAddress(fldHnd, NULL);
3753 NO_WAY("could not obtain address of static field");
3756 // We can use reg to load the constant address,
3757 // as long as it is not a floating point register
3758 regNumber regTmp = reg;
3760 if (isFloatReg(regTmp))
3762 assert(!"emitIns_R_C() cannot be called with floating point target");
3766 // Load address of CLS_VAR into a register
3767 codeGen->instGen_Set_Reg_To_Imm(EA_HANDLE_CNS_RELOC, regTmp, addr);
3769 if ((ins != INS_add) || (offs != 0) || (reg != regTmp))
3771 emitIns_R_R_I(ins, attr, reg, regTmp, offs);
3775 /*****************************************************************************
3777 * Add an instruction with a static member + register operands.
3780 void emitter::emitIns_C_R(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, regNumber reg, int offs)
3782 assert(!"emitIns_C_R not supported");
3785 /*****************************************************************************
3787 * Add an instruction with a static member + constant.
3790 void emitter::emitIns_C_I(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, int offs, ssize_t val)
3795 /*****************************************************************************
3797 * The following adds instructions referencing address modes.
3800 void emitter::emitIns_I_AR(instruction ins, emitAttr attr, int val, regNumber reg, int offs)
3802 NYI("emitIns_I_AR");
3805 void emitter::emitIns_R_AR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
3809 assert(!"Please use ins_Load() to select the correct instruction");
3814 if (emitter::emitIns_valid_imm_for_add(offs, INS_FLAGS_DONT_CARE))
3816 emitIns_R_R_I(INS_add, attr, ireg, reg, offs);
3820 assert(!"emitIns_R_AR: immediate doesn't fit in the instruction");
3824 else if (emitInsIsLoad(ins))
3826 emitIns_R_R_I(ins, attr, ireg, reg, offs);
3829 else if ((ins == INS_mov) || (ins == INS_ldr))
3831 if (EA_SIZE(attr) == EA_4BYTE)
3833 emitIns_R_R_I(INS_ldr, attr, ireg, reg, offs);
3837 else if (ins == INS_vldr)
3839 emitIns_R_R_I(ins, attr, ireg, reg, offs);
3841 NYI("emitIns_R_AR");
3844 void emitter::emitIns_R_AI(instruction ins, emitAttr attr, regNumber ireg, ssize_t disp)
3846 if (emitInsIsLoad(ins))
3848 // We can use ireg to load the constant address,
3849 // as long as it is not a floating point register
3850 regNumber regTmp = ireg;
3852 if (isFloatReg(regTmp))
3854 assert(!"emitIns_R_AI with floating point reg");
3858 codeGen->instGen_Set_Reg_To_Imm(EA_IS_RELOC(attr) ? EA_HANDLE_CNS_RELOC : EA_PTRSIZE, regTmp, disp);
3859 emitIns_R_R_I(ins, EA_TYPE(attr), ireg, regTmp, 0);
3862 NYI("emitIns_R_AI");
3865 void emitter::emitIns_AR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
3869 assert(!"Please use ins_Store() to select the correct instruction");
3871 emitIns_R_R_I(ins, attr, ireg, reg, offs);
3874 void emitter::emitIns_R_ARR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
3878 assert(!"Please use ins_Load() to select the correct instruction");
3883 emitIns_R_R_R(INS_add, attr, ireg, reg, rg2);
3886 emitIns_R_R_I(INS_add, attr, ireg, ireg, disp);
3890 else if (emitInsIsLoad(ins))
3894 emitIns_R_R_R_I(ins, attr, ireg, reg, rg2, 0, INS_FLAGS_DONT_CARE, INS_OPTS_NONE);
3898 assert(!"emitIns_R_ARR: Unexpected instruction");
3901 void emitter::emitIns_ARR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
3905 assert(!"Please use ins_Store() to select the correct instruction");
3907 if (emitInsIsStore(ins))
3911 emitIns_R_R_R(ins, attr, ireg, reg, rg2);
3915 emitIns_R_R_R(INS_add, attr, ireg, reg, rg2);
3916 emitIns_R_R_I(ins, attr, ireg, ireg, disp);
3920 assert(!"emitIns_ARR_R: Unexpected instruction");
3923 void emitter::emitIns_R_ARX(
3924 instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, unsigned mul, int disp)
3928 assert(!"Please use ins_Load() to select the correct instruction");
3931 unsigned shift = genLog2((unsigned)mul);
3933 if ((ins == INS_lea) || emitInsIsLoad(ins))
3941 emitIns_R_R_R_I(ins, attr, ireg, reg, rg2, (int)shift, INS_FLAGS_DONT_CARE, INS_OPTS_LSL);
3946 bool useForm2 = false;
3947 bool mustUseForm1 = ((disp % mul) != 0) || (reg == ireg);
3950 // If all of the below things are true we can generate a Thumb-1 add instruction
3951 // followed by a Thumb-2 add instruction
3952 // We also useForm1 when reg is a low register since the second instruction
3953 // can then always be generated using a Thumb-1 add
3955 if ((reg >= REG_R8) && (ireg < REG_R8) && (rg2 < REG_R8) && ((disp >> shift) <= 7))
3964 // Thumb-1 instruction add Rd, Rx, disp>>shift
3965 // Thumb-2 instructions ldr Rd, Rb, Rd LSL shift
3967 emitIns_R_R_I(INS_add, EA_4BYTE, ireg, rg2, disp >> shift);
3968 emitIns_R_R_R_I(ins, attr, ireg, reg, ireg, shift, INS_FLAGS_NOT_SET, INS_OPTS_LSL);
3973 // Thumb-2 instruction add Rd, Rb, Rx LSL shift
3974 // Thumb-1/2 instructions ldr Rd, Rd, disp
3976 emitIns_R_R_R_I(INS_add, attr, ireg, reg, rg2, shift, INS_FLAGS_NOT_SET, INS_OPTS_LSL);
3977 emitIns_R_R_I(ins, attr, ireg, ireg, disp);
3983 assert(!"emitIns_R_ARX: Unexpected instruction");
3986 /*****************************************************************************
3988 * Record that a jump instruction uses the short encoding
3991 void emitter::emitSetShortJump(instrDescJmp* id)
3993 if (id->idjKeepLong)
3996 if (emitIsCondJump(id))
3998 id->idInsFmt(IF_T1_K);
4000 else if (emitIsCmpJump(id))
4002 // These are always only ever short!
4003 assert(id->idjShort);
4006 else if (emitIsUncondJump(id))
4008 id->idInsFmt(IF_T1_M);
4010 else if (emitIsLoadLabel(id))
4012 return; // Keep long - we don't know the alignment of the target
4016 assert(!"Unknown instruction in emitSetShortJump()");
4019 id->idjShort = true;
4022 if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
4024 printf("[8] Converting jump %u to short\n", id->idDebugOnlyInfo()->idNum);
4026 #endif // DEBUG_EMIT
4028 insSize isz = emitInsSize(id->idInsFmt());
4032 /*****************************************************************************
4034 * Record that a jump instruction uses the medium encoding
4037 void emitter::emitSetMediumJump(instrDescJmp* id)
4039 if (id->idjKeepLong)
4043 if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
4045 printf("[9] Converting jump %u to medium\n", id->idDebugOnlyInfo()->idNum);
4047 #endif // DEBUG_EMIT
4049 assert(emitIsCondJump(id));
4050 id->idInsFmt(IF_T2_J1);
4051 id->idjShort = false;
4053 insSize isz = emitInsSize(id->idInsFmt());
4057 /*****************************************************************************
4059 * Add a jmp instruction.
4060 * When dst is NULL, instrCount specifies number of instructions
4061 * to jump: positive is forward, negative is backward.
4062 * Unconditional branches have two sizes: short and long.
4063 * Conditional branches have three sizes: short, medium, and long. A long
4064 * branch is a pseudo-instruction that represents two instructions:
4065 * a short conditional branch to branch around a large unconditional
4066 * branch. Thus, we can handle branch offsets of imm24 instead of just imm20.
4069 void emitter::emitIns_J(instruction ins, BasicBlock* dst, int instrCount /* = 0 */)
4071 insFormat fmt = IF_NONE;
4075 assert(dst->bbFlags & BBF_JMP_TARGET);
4079 assert(instrCount != 0);
4082 /* Figure out the encoding format of the instruction */
4086 fmt = IF_T2_J2; /* Assume the jump will be long */
4103 fmt = IF_LARGEJMP; /* Assume the jump will be long */
4109 assert((fmt == IF_LARGEJMP) || (fmt == IF_T2_J2));
4111 instrDescJmp* id = emitNewInstrJmp();
4112 insSize isz = emitInsSize(fmt);
4119 // Mark the finally call
4120 if (ins == INS_b && emitComp->compCurBB->bbJumpKind == BBJ_CALLFINALLY)
4122 id->idDebugOnlyInfo()->idFinallyCall = true;
4126 /* Assume the jump will be long */
4131 id->idAddr()->iiaBBlabel = dst;
4132 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
4135 if (emitComp->opts.compLongAddress) // Force long branches
4136 id->idjKeepLong = 1;
4141 id->idAddr()->iiaSetInstrCount(instrCount);
4142 id->idjKeepLong = false;
4143 /* This jump must be short */
4144 emitSetShortJump(id);
4148 /* Record the jump's IG and offset within it */
4150 id->idjIG = emitCurIG;
4151 id->idjOffs = emitCurIGsize;
4153 /* Append this jump to this IG's jump list */
4155 id->idjNext = emitCurIGjmpList;
4156 emitCurIGjmpList = id;
4162 /* Figure out the max. size of the jump/call instruction */
4164 if (!id->idjKeepLong)
4166 insGroup* tgt = NULL;
4168 /* Can we guess at the jump distance? */
4172 tgt = (insGroup*)emitCodeGetCookie(dst);
4177 UNATIVE_OFFSET srcOffs;
4180 assert(JMP_SIZE_SMALL == JCC_SIZE_SMALL);
4182 /* This is a backward jump - figure out the distance */
4184 srcOffs = emitCurCodeOffset + emitCurIGsize;
4186 /* Compute the distance estimate */
4188 jmpDist = srcOffs - tgt->igOffs;
4189 assert(jmpDist >= 0);
4190 jmpDist += 4; // Adjustment for ARM PC
4195 if (JMP_DIST_SMALL_MAX_NEG <= -jmpDist)
4197 /* This jump surely will be short */
4198 emitSetShortJump(id);
4203 if (JCC_DIST_SMALL_MAX_NEG <= -jmpDist)
4205 /* This jump surely will be short */
4206 emitSetShortJump(id);
4208 else if (JCC_DIST_MEDIUM_MAX_NEG <= -jmpDist)
4210 /* This jump surely will be medium */
4211 emitSetMediumJump(id);
4226 /*****************************************************************************
4228 * Add a label instruction.
4231 void emitter::emitIns_R_L(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
4233 assert(dst->bbFlags & BBF_JMP_TARGET);
4235 insFormat fmt = IF_NONE;
4238 /* Figure out the encoding format of the instruction */
4242 id = emitNewInstrLbl();
4247 id = emitNewInstrJmp();
4253 assert((fmt == IF_T2_M1) || (fmt == IF_T2_N1));
4255 insSize isz = emitInsSize(fmt);
4263 // Mark the catch return
4264 if (emitComp->compCurBB->bbJumpKind == BBJ_EHCATCHRET)
4266 id->idDebugOnlyInfo()->idCatchRet = true;
4270 id->idAddr()->iiaBBlabel = dst;
4271 id->idjShort = false;
4276 id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
4280 id->idjKeepLong = true;
4283 /* Record the jump's IG and offset within it */
4285 id->idjIG = emitCurIG;
4286 id->idjOffs = emitCurIGsize;
4288 /* Append this jump to this IG's jump list */
4290 id->idjNext = emitCurIGjmpList;
4291 emitCurIGjmpList = id;
4293 // Set the relocation flags - these give hint to zap to perform
4294 // relocation of the specified 32bit address.
4295 id->idSetRelocFlags(attr);
4305 /*****************************************************************************
4307 * Add a data label instruction.
4310 void emitter::emitIns_R_D(instruction ins, emitAttr attr, unsigned offs, regNumber reg)
4312 noway_assert((ins == INS_movw) || (ins == INS_movt));
4314 insFormat fmt = IF_T2_N2;
4315 instrDesc* id = emitNewInstrSC(attr, offs);
4316 insSize isz = emitInsSize(fmt);
4323 if (emitComp->opts.compReloc)
4325 // Set the relocation flags - these give hint to zap to perform
4326 // relocation of the specified 32bit address.
4327 id->idSetRelocFlags(attr);
4334 void emitter::emitIns_J_R(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
4336 assert(dst->bbFlags & BBF_JMP_TARGET);
4338 insFormat fmt = IF_NONE;
4348 assert(fmt == IF_T1_I);
4350 assert(isLowRegister(reg));
4352 instrDescJmp* id = emitNewInstrJmp();
4354 id->idInsFmt(IF_T1_I);
4355 id->idInsSize(emitInsSize(IF_T1_I));
4358 /* This jump better be short or-else! */
4359 id->idjShort = true;
4360 id->idAddr()->iiaBBlabel = dst;
4361 id->idjKeepLong = false;
4363 /* Record the jump's IG and offset within it */
4365 id->idjIG = emitCurIG;
4366 id->idjOffs = emitCurIGsize;
4368 /* Append this jump to this IG's jump list */
4370 id->idjNext = emitCurIGjmpList;
4371 emitCurIGjmpList = id;
4381 /*****************************************************************************
4383 * Add a call instruction (direct or indirect).
4384 * argSize<0 means that the caller will pop the arguments
4386 * The other arguments are interpreted depending on callType as shown:
4387 * Unless otherwise specified, ireg,xreg,xmul,disp should have default values.
4389 * EC_FUNC_TOKEN : addr is the method address
4390 * EC_FUNC_ADDR : addr is the absolute address of the function
4391 * if addr is NULL, it is a recursive call
4393 * If callType is one of these emitCallTypes, addr has to be NULL.
4394 * EC_INDIR_R : "call ireg".
4396 * For ARM xreg, xmul and disp are never used and should always be 0/REG_NA.
4398 * Please consult the "debugger team notification" comment in genFnProlog().
4401 void emitter::emitIns_Call(EmitCallType callType,
4402 CORINFO_METHOD_HANDLE methHnd, // used for pretty printing
4403 INDEBUG_LDISASM_COMMA(CORINFO_SIG_INFO* sigInfo) // used to report call sites to the EE
4407 VARSET_VALARG_TP ptrVars,
4408 regMaskTP gcrefRegs,
4409 regMaskTP byrefRegs,
4410 IL_OFFSETX ilOffset /* = BAD_IL_OFFSET */,
4411 regNumber ireg /* = REG_NA */,
4412 regNumber xreg /* = REG_NA */,
4413 unsigned xmul /* = 0 */,
4415 bool isJump /* = false */,
4416 bool isNoGC /* = false */,
4417 bool isProfLeaveCB /* = false */)
4419 /* Sanity check the arguments depending on callType */
4421 assert(callType < EC_COUNT);
4422 assert((callType != EC_FUNC_TOKEN && callType != EC_FUNC_ADDR) ||
4423 (ireg == REG_NA && xreg == REG_NA && xmul == 0 && disp == 0));
4424 assert(callType < EC_INDIR_R || addr == NULL);
4425 assert(callType != EC_INDIR_R || (ireg < REG_COUNT && xreg == REG_NA && xmul == 0 && disp == 0));
4427 // ARM never uses these
4428 assert(xreg == REG_NA && xmul == 0 && disp == 0);
4430 // Our stack level should be always greater than the bytes of arguments we push. Just
4432 assert((unsigned)abs(argSize) <= codeGen->genStackLevel);
4437 /* This is the saved set of registers after a normal call */
4438 regMaskTP savedSet = RBM_CALLEE_SAVED;
4440 /* some special helper calls have a different saved set registers */
4444 assert(emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
4446 // Get the set of registers that this call kills and remove it from the saved set.
4447 savedSet = RBM_ALLINT & ~emitComp->compNoGCHelperCallKillSet(Compiler::eeGetHelperNum(methHnd));
4449 // In case of Leave profiler callback, we need to preserve liveness of REG_PROFILER_RET_SCRATCH
4452 savedSet |= RBM_PROFILER_RET_SCRATCH;
4456 if (emitComp->verbose)
4458 printf("NOGC Call: savedSet=");
4459 printRegMaskInt(savedSet);
4460 emitDispRegSet(savedSet);
4467 assert(!emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
4470 /* Trim out any callee-trashed registers from the live set */
4472 gcrefRegs &= savedSet;
4473 byrefRegs &= savedSet;
4476 if (EMIT_GC_VERBOSE)
4478 printf("Call: GCvars=%s ", VarSetOps::ToString(emitComp, ptrVars));
4479 dumpConvertedVarSet(emitComp, ptrVars);
4480 printf(", gcrefRegs=");
4481 printRegMaskInt(gcrefRegs);
4482 emitDispRegSet(gcrefRegs);
4483 printf(", byrefRegs=");
4484 printRegMaskInt(byrefRegs);
4485 emitDispRegSet(byrefRegs);
4490 assert(argSize % (int)REGSIZE_BYTES == 0);
4491 argCnt = argSize / (int)REGSIZE_BYTES;
4493 /* Managed RetVal: emit sequence point for the call */
4494 if (emitComp->opts.compDbgInfo && ilOffset != BAD_IL_OFFSET)
4496 codeGen->genIPmappingAdd(ilOffset, false);
4500 We need to allocate the appropriate instruction descriptor based
4501 on whether this is a direct/indirect call, and whether we need to
4502 record an updated set of live GC variables.
4504 The stats for a ton of classes is as follows:
4506 Direct call w/o GC vars 220,216
4507 Indir. call w/o GC vars 144,781
4509 Direct call with GC vars 9,440
4510 Indir. call with GC vars 5,768
4513 if (callType >= EC_INDIR_R)
4515 /* Indirect call, virtual calls */
4517 assert(callType == EC_INDIR_R);
4519 id = emitNewInstrCallInd(argCnt, disp, ptrVars, gcrefRegs, byrefRegs, retSize);
4523 /* Helper/static/nonvirtual/function calls (direct or through handle),
4524 and calls to an absolute addr. */
4526 assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
4528 id = emitNewInstrCallDir(argCnt, ptrVars, gcrefRegs, byrefRegs, retSize);
4531 /* Update the emitter's live GC ref sets */
4533 VarSetOps::Assign(emitComp, emitThisGCrefVars, ptrVars);
4534 emitThisGCrefRegs = gcrefRegs;
4535 emitThisByrefRegs = byrefRegs;
4537 /* Set the instruction - special case jumping a function */
4539 insFormat fmt = IF_NONE;
4541 id->idSetIsNoGC(isNoGC);
4543 /* Record the address: method, indirection, or funcptr */
4545 if (callType > EC_FUNC_ADDR)
4547 /* This is an indirect call (either a virtual call or func ptr call) */
4551 case EC_INDIR_R: // the address is in a register
4553 id->idSetIsCallRegPtr();
4557 ins = INS_bx; // INS_bx Reg
4561 ins = INS_blx; // INS_blx Reg
4567 id->idInsSize(emitInsSize(fmt));
4569 assert(xreg == REG_NA);
4573 NO_WAY("unexpected instruction");
4579 /* This is a simple direct call: "call helper/method/addr" */
4581 assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
4583 // if addr is nullptr then this call is treated as a recursive call.
4584 assert(addr == nullptr || codeGen->arm_Valid_Imm_For_BL((ssize_t)addr));
4588 ins = INS_b; // INS_b imm24
4592 ins = INS_bl; // INS_bl imm24
4599 id->idInsSize(emitInsSize(fmt));
4601 id->idAddr()->iiaAddr = (BYTE*)addr;
4603 if (callType == EC_FUNC_ADDR)
4605 id->idSetIsCallAddr();
4608 if (emitComp->opts.compReloc)
4610 // Since this is an indirect call through a pointer and we don't
4611 // currently pass in emitAttr into this function we have decided
4612 // to always mark the displacement as being relocatable.
4614 id->idSetIsDspReloc();
4619 if (EMIT_GC_VERBOSE)
4621 if (id->idIsLargeCall())
4623 printf("[%02u] Rec call GC vars = %s\n", id->idDebugOnlyInfo()->idNum,
4624 VarSetOps::ToString(emitComp, ((instrDescCGCA*)id)->idcGCvars));
4628 id->idDebugOnlyInfo()->idMemCookie = (size_t)methHnd; // method token
4629 id->idDebugOnlyInfo()->idCallSig = sigInfo;
4633 if (addr != nullptr)
4635 codeGen->getDisAssembler().disSetMethod((size_t)addr, methHnd);
4637 #endif // LATE_DISASM
4643 /*****************************************************************************
4645 * Returns an encoding for the specified register (any-reg) to be used in
4646 * a Thumb-1 encoding in the M4 position
4649 inline unsigned insEncodeRegT1_M4(regNumber reg)
4651 assert(reg < REG_STK);
4656 /*****************************************************************************
4658 * Returns an encoding for the specified register (any-reg) to be used in
4659 * a Thumb-1 encoding in the D4 position
4662 inline unsigned insEncodeRegT1_D4(regNumber reg)
4664 assert(reg < REG_STK);
4666 return (reg & 0x7) | ((reg & 0x8) << 4);
4669 /*****************************************************************************
4671 * Returns an encoding for the specified register (low-only) to be used in
4672 * a Thumb-1 encoding in the M3 position
4675 inline unsigned insEncodeRegT1_M3(regNumber reg)
4677 assert(reg < REG_R8);
4682 /*****************************************************************************
4684 * Returns an encoding for the specified register (low-only) to be used in
4685 * a Thumb-1 encoding in the N3 position
4688 inline unsigned insEncodeRegT1_N3(regNumber reg)
4690 assert(reg < REG_R8);
4695 /*****************************************************************************
4697 * Returns an encoding for the specified register (low-only) to be used in
4698 * a Thumb-1 encoding in the D3 position
4701 inline unsigned insEncodeRegT1_D3(regNumber reg)
4703 assert(reg < REG_R8);
4707 /*****************************************************************************
4709 * Returns an encoding for the specified register (low-only) to be used in
4710 * a Thumb-1 encoding in the DI position
4713 inline unsigned insEncodeRegT1_DI(regNumber reg)
4715 assert(reg < REG_R8);
4720 /*****************************************************************************
4722 * Returns an encoding for the specified register to be used in
4723 * a Thumb-2 encoding in the N position
4726 inline unsigned insEncodeRegT2_N(regNumber reg)
4728 assert(reg < REG_STK);
4733 inline unsigned floatRegIndex(regNumber reg, int size)
4735 // theoretically this could support quad floats as well but for now...
4736 assert(size == EA_8BYTE || size == EA_4BYTE);
4738 if (size == EA_8BYTE)
4739 assert(emitter::isDoubleReg(reg));
4741 assert(emitter::isFloatReg(reg));
4743 unsigned result = reg - REG_F0;
4745 // the assumption here is that the register F8 also refers to D4
4746 if (size == EA_8BYTE)
4754 // variant: SOME arm VFP instructions use the convention that
4755 // for doubles, the split bit holds the msb of the register index
4756 // for singles it holds the lsb
4757 // excerpt : d = if dp_operation then UInt(D:Vd)
4758 // if single UInt(Vd:D);
4760 inline unsigned floatRegEncoding(unsigned index, int size, bool variant = false)
4762 if (!variant || size == EA_8BYTE)
4766 return ((index & 1) << 4) | (index >> 1);
4770 // thumb2 VFP M register encoding
4771 inline unsigned insEncodeRegT2_VectorM(regNumber reg, int size, bool variant)
4773 unsigned enc = floatRegIndex(reg, size);
4774 enc = floatRegEncoding(enc, size, variant);
4775 return ((enc & 0xf) << 0) | ((enc & 0x10) << 1);
4778 // thumb2 VFP N register encoding
4779 inline unsigned insEncodeRegT2_VectorN(regNumber reg, int size, bool variant)
4781 unsigned enc = floatRegIndex(reg, size);
4782 enc = floatRegEncoding(enc, size, variant);
4783 return ((enc & 0xf) << 16) | ((enc & 0x10) << 3);
4786 // thumb2 VFP D register encoding
4787 inline unsigned insEncodeRegT2_VectorD(regNumber reg, int size, bool variant)
4789 unsigned enc = floatRegIndex(reg, size);
4790 enc = floatRegEncoding(enc, size, variant);
4791 return ((enc & 0xf) << 12) | ((enc & 0x10) << 18);
4794 /*****************************************************************************
4796 * Returns an encoding for the specified register to be used in
4797 * a Thumb-2 encoding in the T position
4800 inline unsigned insEncodeRegT2_T(regNumber reg)
4802 assert(reg < REG_STK);
4807 /*****************************************************************************
4809 * Returns an encoding for the specified register to be used in
4810 * a Thumb-2 encoding in the D position
4813 inline unsigned insEncodeRegT2_D(regNumber reg)
4815 assert(reg < REG_STK);
4820 /*****************************************************************************
4822 * Returns an encoding for the specified register to be used in
4823 * a Thumb-2 encoding in the M position
4826 inline unsigned insEncodeRegT2_M(regNumber reg)
4828 assert(reg < REG_STK);
4833 /*****************************************************************************
4835 * Returns the encoding for the Set Flags bit to be used in a Thumb-2 encoding
4838 unsigned emitter::insEncodeSetFlags(insFlags sf)
4840 if (sf == INS_FLAGS_SET)
4846 /*****************************************************************************
4848 * Returns the encoding for the Shift Type bits to be used in a Thumb-2 encoding
4851 unsigned emitter::insEncodeShiftOpts(insOpts opt)
4853 if (opt == INS_OPTS_NONE)
4855 else if (opt == INS_OPTS_LSL)
4857 else if (opt == INS_OPTS_LSR)
4859 else if (opt == INS_OPTS_ASR)
4861 else if (opt == INS_OPTS_ROR)
4863 else if (opt == INS_OPTS_RRX)
4866 assert(!"Invalid insOpts");
4870 /*****************************************************************************
4872 * Returns the encoding for the PUW bits to be used in a T2_G0 Thumb-2 encoding
4875 unsigned emitter::insEncodePUW_G0(insOpts opt, int imm)
4877 unsigned result = 0;
4879 if (opt != INS_OPTS_LDST_POST_INC)
4880 result |= (1 << 24); // The P bit
4883 result |= (1 << 23); // The U bit
4885 if (opt != INS_OPTS_NONE)
4886 result |= (1 << 21); // The W bits
4890 /*****************************************************************************
4892 * Returns the encoding for the PUW bits to be used in a T2_H0 Thumb-2 encoding
4895 unsigned emitter::insEncodePUW_H0(insOpts opt, int imm)
4897 unsigned result = 0;
4899 if (opt != INS_OPTS_LDST_POST_INC)
4900 result |= (1 << 10); // The P bit
4903 result |= (1 << 9); // The U bit
4905 if (opt != INS_OPTS_NONE)
4906 result |= (1 << 8); // The W bits
4911 /*****************************************************************************
4913 * Returns the encoding for the Shift Count bits to be used in a Thumb-2 encoding
4916 inline unsigned insEncodeShiftCount(int imm)
4920 assert((imm & 0x001F) == imm);
4921 result = (imm & 0x03) << 6;
4922 result |= (imm & 0x1C) << 10;
4927 /*****************************************************************************
4929 * Returns the encoding for the immediate use by BFI/BFC Thumb-2 encodings
4932 inline unsigned insEncodeBitFieldImm(int imm)
4936 assert((imm & 0x03FF) == imm);
4937 result = (imm & 0x001f);
4938 result |= (imm & 0x0060) << 1;
4939 result |= (imm & 0x0380) << 5;
4944 /*****************************************************************************
4946 * Returns an encoding for the immediate use by MOV/MOVW Thumb-2 encodings
4949 inline unsigned insEncodeImmT2_Mov(int imm)
4953 assert((imm & 0x0000ffff) == imm);
4954 result = (imm & 0x00ff);
4955 result |= ((imm & 0x0700) << 4);
4956 result |= ((imm & 0x0800) << 15);
4957 result |= ((imm & 0xf000) << 4);
4962 /*****************************************************************************
4964 * Unscales the immediate based on the operand size in 'size'
4966 /*static*/ int emitter::insUnscaleImm(int imm, emitAttr size)
4972 assert((imm & 0x0003) == 0);
4977 assert((imm & 0x0001) == 0);
4986 assert(!"Invalid value in size");
4992 /*****************************************************************************
4994 * Emit a Thumb-1 instruction (a 16-bit integer as code)
4997 /*static*/ unsigned emitter::emitOutput_Thumb1Instr(BYTE* dst, code_t code)
4999 unsigned short word1 = code & 0xffff;
5000 assert(word1 == code);
5003 unsigned short top5bits = (word1 & 0xf800) >> 11;
5004 assert(top5bits < 29);
5007 MISALIGNED_WR_I2(dst, word1);
5009 return sizeof(short);
5011 /*****************************************************************************
5013 * Emit a Thumb-2 instruction (two 16-bit integers as code)
5016 /*static*/ unsigned emitter::emitOutput_Thumb2Instr(BYTE* dst, code_t code)
5018 unsigned short word1 = (code >> 16) & 0xffff;
5019 unsigned short word2 = (code)&0xffff;
5020 assert((code_t)((word1 << 16) | word2) == code);
5023 unsigned short top5bits = (word1 & 0xf800) >> 11;
5024 assert(top5bits >= 29);
5027 MISALIGNED_WR_I2(dst, word1);
5029 MISALIGNED_WR_I2(dst, word2);
5031 return sizeof(short) * 2;
5034 /*****************************************************************************
5036 * Output a local jump instruction.
5037 * Note that this may be invoked to overwrite an existing jump instruction at 'dst'
5038 * to handle forward branch patching.
5041 BYTE* emitter::emitOutputLJ(insGroup* ig, BYTE* dst, instrDesc* i)
5047 instrDescJmp* id = (instrDescJmp*)i;
5048 instruction ins = id->idIns();
5051 bool loadLabel = false;
5052 bool isJump = false;
5053 bool relAddr = true; // does the instruction use relative-addressing?
5060 sdistneg = JCC_DIST_SMALL_MAX_NEG;
5066 // One size fits all!
5072 sdistneg = LBL_DIST_SMALL_MAX_NEG;
5078 sdistneg = LBL_DIST_SMALL_MAX_NEG;
5084 /* Figure out the distance to the target */
5086 srcOffs = emitCurCodeOffs(dst);
5087 if (id->idAddr()->iiaHasInstrCount())
5090 int instrCount = id->idAddr()->iiaGetInstrCount();
5091 unsigned insNum = emitFindInsNum(ig, id);
5094 // Backward branches using instruction count must be within the same instruction group.
5095 assert(insNum + 1 >= (unsigned)(-instrCount));
5097 dstOffs = ig->igOffs + emitFindOffset(ig, (insNum + 1 + instrCount));
5101 dstOffs = id->idAddr()->iiaIGlabel->igOffs;
5108 // for adr, the distance is calculated from 4-byte aligned srcOffs.
5109 distVal = (ssize_t)((emitOffsetToPtr(dstOffs) - (BYTE*)(((size_t)emitOffsetToPtr(srcOffs)) & ~3)) + 1);
5113 distVal = (ssize_t)(emitOffsetToPtr(dstOffs) - emitOffsetToPtr(srcOffs));
5118 assert(ins == INS_movw || ins == INS_movt);
5119 distVal = (ssize_t)emitOffsetToPtr(dstOffs) + 1; // Or in thumb bit
5122 if (dstOffs <= srcOffs)
5124 /* This is a backward jump - distance is known at this point */
5127 if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
5129 size_t blkOffs = id->idjIG->igOffs;
5131 if (INTERESTING_JUMP_NUM == 0)
5132 printf("[3] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
5133 printf("[3] Jump block is at %08X - %02X = %08X\n", blkOffs, emitOffsAdj, blkOffs - emitOffsAdj);
5134 printf("[3] Jump is at %08X - %02X = %08X\n", srcOffs, emitOffsAdj, srcOffs - emitOffsAdj);
5135 printf("[3] Label block is at %08X - %02X = %08X\n", dstOffs, emitOffsAdj, dstOffs - emitOffsAdj);
5139 // This format only supports forward branches
5140 noway_assert(id->idInsFmt() != IF_T1_I);
5142 /* Can we use a short jump? */
5144 if (isJump && ((unsigned)(distVal - 4) >= (unsigned)sdistneg))
5146 emitSetShortJump(id);
5151 /* This is a forward jump - distance will be an upper limit */
5153 emitFwdJumps = true;
5155 /* The target offset will be closer by at least 'emitOffsAdj', but only if this
5156 jump doesn't cross the hot-cold boundary. */
5158 if (!emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
5160 dstOffs -= emitOffsAdj;
5161 distVal -= emitOffsAdj;
5164 /* Record the location of the jump for later patching */
5166 id->idjOffs = dstOffs;
5168 /* Are we overflowing the id->idjOffs bitfield? */
5169 if (id->idjOffs != dstOffs)
5170 IMPL_LIMITATION("Method is too large");
5173 if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
5175 size_t blkOffs = id->idjIG->igOffs;
5177 if (INTERESTING_JUMP_NUM == 0)
5178 printf("[4] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
5179 printf("[4] Jump block is at %08X\n", blkOffs);
5180 printf("[4] Jump is at %08X\n", srcOffs);
5181 printf("[4] Label block is at %08X - %02X = %08X\n", dstOffs + emitOffsAdj, emitOffsAdj, dstOffs);
5186 /* Adjust the offset to emit relative to the end of the instruction */
5192 if (0 && emitComp->verbose)
5194 size_t sz = 4; // Thumb-2 pretends all instructions are 4-bytes long for computing jump offsets?
5195 int distValSize = id->idjShort ? 4 : 8;
5196 printf("; %s jump [%08X/%03u] from %0*X to %0*X: dist = %08XH\n", (dstOffs <= srcOffs) ? "Fwd" : "Bwd",
5197 dspPtr(id), id->idDebugOnlyInfo()->idNum, distValSize, srcOffs + sz, distValSize, dstOffs, distVal);
5201 insFormat fmt = id->idInsFmt();
5205 /* What size jump should we use? */
5211 assert(!id->idjKeepLong);
5212 assert(emitJumpCrossHotColdBoundary(srcOffs, dstOffs) == false);
5214 assert(JMP_SIZE_SMALL == JCC_SIZE_SMALL);
5215 assert(JMP_SIZE_SMALL == 2);
5217 /* For forward jumps, record the address of the distance value */
5218 id->idjTemp.idjAddr = (distVal > 0) ? dst : NULL;
5220 dst = emitOutputShortBranch(dst, ins, fmt, distVal, id);
5226 /* For forward jumps, record the address of the distance value */
5227 id->idjTemp.idjAddr = (dstOffs > srcOffs) ? dst : NULL;
5229 if (fmt == IF_LARGEJMP)
5231 // This is a pseudo-instruction format representing a large conditional branch, to allow
5232 // us to get a greater branch target range than we can get by using a straightforward conditional
5233 // branch. It is encoded as a short conditional branch that branches around a long unconditional
5236 // Conceptually, we have:
5240 // The code we emit is:
5242 // b<!cond> L_not // 2 bytes. Note that we reverse the condition.
5243 // b L_target // 4 bytes
5246 // Note that we don't actually insert any blocks: we simply encode "b <!cond> L_not" as a branch with
5247 // the correct offset. Note also that this works for both integer and floating-point conditions, because
5248 // the condition inversion takes ordered/unordered into account, preserving NaN behavior. For example,
5249 // "GT" (greater than) is inverted to "LE" (less than, equal, or unordered).
5251 // History: previously, we generated:
5254 // but the "it" instruction was deprecated, so we can't use it.
5256 dst = emitOutputShortBranch(dst,
5257 emitJumpKindToIns(emitReverseJumpKind(
5258 emitInsToJumpKind(ins))), // reverse the conditional instruction
5260 6 - 4, /* 6 bytes from start of this large conditional pseudo-instruction to
5261 L_not. Jumps are encoded as offset from instr address + 4. */
5262 NULL /* only used for cbz/cbnz */);
5264 // Now, pretend we've got a normal unconditional branch, and fall through to the code to emit that.
5268 // The distVal was computed based on the beginning of the pseudo-instruction, which is
5269 // the IT. So subtract the size of the IT from the offset, so it is relative to the
5270 // unconditional branch.
5274 code = emitInsCode(ins, fmt);
5276 if (fmt == IF_T2_J1)
5278 // Can't use this form for jumps between the hot and cold regions
5279 assert(!id->idjKeepLong);
5280 assert(emitJumpCrossHotColdBoundary(srcOffs, dstOffs) == false);
5282 assert((distVal & 1) == 0);
5283 assert(distVal >= -1048576);
5284 assert(distVal <= 1048574);
5288 code |= ((distVal >> 1) & 0x0007ff);
5289 code |= (((distVal >> 1) & 0x01f800) << 5);
5290 code |= (((distVal >> 1) & 0x020000) >> 4);
5291 code |= (((distVal >> 1) & 0x040000) >> 7);
5293 else if (fmt == IF_T2_J2)
5295 assert((distVal & 1) == 0);
5296 if (emitComp->opts.compReloc && emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
5298 // dst isn't an actual final target location, just some intermediate
5299 // location. Thus we cannot make any guarantees about distVal (not
5300 // even the direction/sign). Instead we don't encode any offset and
5301 // rely on the relocation to do all the work
5305 assert(distVal >= CALL_DIST_MAX_NEG);
5306 assert(distVal <= CALL_DIST_MAX_POS);
5310 code |= ((distVal >> 1) & 0x0007ff);
5311 code |= (((distVal >> 1) & 0x1ff800) << 5);
5313 bool S = (distVal < 0);
5314 bool I1 = ((distVal & 0x00800000) == 0);
5315 bool I2 = ((distVal & 0x00400000) == 0);
5318 code |= (1 << 13); // J1 bit
5320 code |= (1 << 11); // J2 bit
5325 assert(!"Unknown fmt");
5328 unsigned instrSize = emitOutput_Thumb2Instr(dst, code);
5330 if (emitComp->opts.compReloc)
5332 if (emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
5334 assert(id->idjKeepLong);
5335 if (emitComp->info.compMatchedVM)
5337 void* target = emitOffsetToPtr(dstOffs);
5338 emitRecordRelocation((void*)dst, target, IMAGE_REL_BASED_THUMB_BRANCH24);
5348 /* For forward jumps, record the address of the distance value */
5349 id->idjTemp.idjAddr = (distVal > 0) ? dst : NULL;
5351 code = emitInsCode(ins, fmt);
5353 if (fmt == IF_T1_J3)
5355 assert((dstOffs & 3) == 0); // The target label must be 4-byte aligned
5356 assert(distVal >= 0);
5357 assert(distVal <= 1022);
5358 code |= ((distVal >> 2) & 0xff);
5360 dst += emitOutput_Thumb1Instr(dst, code);
5362 else if (fmt == IF_T2_M1)
5364 assert(distVal >= -4095);
5365 assert(distVal <= +4095);
5368 code |= 0x00A0 << 16;
5371 assert((distVal & 0x0fff) == distVal);
5372 code |= (distVal & 0x00ff);
5373 code |= ((distVal & 0x0700) << 4);
5375 code |= ((distVal & 0x0800) << 15);
5376 code |= id->idReg1() << 8;
5378 dst += emitOutput_Thumb2Instr(dst, code);
5380 else if (fmt == IF_T2_N1)
5382 code |= insEncodeRegT2_D(id->idReg1());
5383 unsigned imm = distVal;
5384 if (ins == INS_movw)
5390 imm = (imm >> 16) & 0xffff;
5392 ((instrDescJmp*)id)->idjTemp.idjAddr = (dstOffs > srcOffs) ? dst : NULL;
5394 assert((imm & 0x0000ffff) == imm);
5395 code |= (imm & 0x00ff);
5396 code |= ((imm & 0x0700) << 4);
5397 code |= ((imm & 0x0800) << 15);
5398 code |= ((imm & 0xf000) << 4);
5399 dst += emitOutput_Thumb2Instr(dst, code);
5401 if (id->idIsCnsReloc() || id->idIsDspReloc())
5403 assert(ins == INS_movt || ins == INS_movw);
5404 if ((ins == INS_movt) && emitComp->info.compMatchedVM)
5405 emitHandlePCRelativeMov32((void*)(dst - 8), (void*)distVal);
5410 assert(!"Unknown fmt");
5417 /*****************************************************************************
5419 * Output a short branch instruction.
5422 BYTE* emitter::emitOutputShortBranch(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, instrDescJmp* id)
5426 code = emitInsCode(ins, fmt);
5430 assert((distVal & 1) == 0);
5431 assert(distVal >= -256);
5432 assert(distVal <= 254);
5436 code |= ((distVal >> 1) & 0x7f);
5438 else if (fmt == IF_T1_M)
5440 assert((distVal & 1) == 0);
5441 assert(distVal >= -2048);
5442 assert(distVal <= 2046);
5446 code |= ((distVal >> 1) & 0x3ff);
5448 else if (fmt == IF_T1_I)
5451 assert(ins == INS_cbz || INS_cbnz);
5452 assert((distVal & 1) == 0);
5453 assert(distVal >= 0);
5454 assert(distVal <= 126);
5456 code |= ((distVal << 3) & 0x0200);
5457 code |= ((distVal << 2) & 0x00F8);
5458 code |= (id->idReg1() & 0x0007);
5462 assert(!"Unknown fmt");
5465 dst += emitOutput_Thumb1Instr(dst, code);
5470 #ifdef FEATURE_ITINSTRUCTION
5472 /*****************************************************************************
5473 * The "IT" instruction is deprecated (with a very few exceptions). Don't generate it!
5474 * Don't delete this code, though, in case we ever want to bring it back.
5475 *****************************************************************************/
5477 /*****************************************************************************
5479 * Output an IT instruction.
5482 BYTE* emitter::emitOutputIT(BYTE* dst, instruction ins, insFormat fmt, code_t condcode)
5485 code_t code, mask, bit;
5487 code = emitInsCode(ins, fmt);
5488 code |= (condcode << 4); // encode firstcond
5489 imm0 = condcode & 1; // this is firstcond[0]
5490 mask = code & 0x0f; // initialize mask encoded in opcode
5491 bit = 0x08; // where in mask we are encoding
5492 while ((mask & (bit - 1)) != 0) // are the remaining bits all zeros?
5493 { // then we are done
5494 // otherwise determine the setting of bit
5495 if ((imm0 == 1) ^ ((bit & mask) != 0))
5497 code |= bit; // set the current bit
5501 code &= ~bit; // clear the current bit
5505 dst += emitOutput_Thumb1Instr(dst, code);
5510 #endif // FEATURE_ITINSTRUCTION
5512 /*****************************************************************************
5514 * Append the machine code corresponding to the given instruction descriptor
5515 * to the code block at '*dp'; the base of the code block is 'bp', and 'ig'
5516 * is the instruction group that contains the instruction. Updates '*dp' to
5517 * point past the generated code, and returns the size of the instruction
5518 * descriptor in bytes.
5521 size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
5527 instruction ins = id->idIns();
5528 insFormat fmt = id->idInsFmt();
5529 emitAttr size = id->idOpSize();
5530 unsigned char callInstrSize = 0;
5533 bool dspOffs = emitComp->opts.dspGCtbls || !emitComp->opts.disDiffable;
5536 assert(REG_NA == (int)REG_NA);
5538 VARSET_TP GCvars(VarSetOps::UninitVal());
5540 /* What instruction format have we got? */
5546 regMaskTP gcrefRegs;
5547 regMaskTP byrefRegs;
5549 case IF_T1_A: // T1_A ................
5550 sz = SMALL_IDSC_SIZE;
5551 code = emitInsCode(ins, fmt);
5552 dst += emitOutput_Thumb1Instr(dst, code);
5555 #ifdef FEATURE_ITINSTRUCTION
5556 case IF_T1_B: // T1_B ........cccc.... cond
5558 assert(id->idGCref() == GCT_NONE);
5559 target_ssize_t condcode = emitGetInsSC(id);
5560 dst = emitOutputIT(dst, ins, fmt, condcode);
5561 sz = SMALL_IDSC_SIZE;
5564 #endif // FEATURE_ITINSTRUCTION
5566 case IF_T1_C: // T1_C .....iiiiinnnddd R1 R2 imm5
5567 sz = SMALL_IDSC_SIZE;
5568 imm = emitGetInsSC(id);
5569 code = emitInsCode(ins, fmt);
5570 code |= insEncodeRegT1_D3(id->idReg1());
5571 code |= insEncodeRegT1_N3(id->idReg2());
5572 if (emitInsIsLoadOrStore(ins))
5574 imm = insUnscaleImm(imm, size);
5576 assert((imm & 0x001f) == imm);
5578 dst += emitOutput_Thumb1Instr(dst, code);
5581 case IF_T1_D0: // T1_D0 ........Dmmmmddd R1* R2*
5582 sz = SMALL_IDSC_SIZE;
5583 code = emitInsCode(ins, fmt);
5584 code |= insEncodeRegT1_D4(id->idReg1());
5585 code |= insEncodeRegT1_M4(id->idReg2());
5586 dst += emitOutput_Thumb1Instr(dst, code);
5589 case IF_T1_E: // T1_E ..........nnnddd R1 R2
5590 sz = SMALL_IDSC_SIZE;
5591 code = emitInsCode(ins, fmt);
5592 code |= insEncodeRegT1_D3(id->idReg1());
5593 code |= insEncodeRegT1_N3(id->idReg2());
5594 dst += emitOutput_Thumb1Instr(dst, code);
5597 case IF_T1_F: // T1_F .........iiiiiii SP imm7
5598 sz = emitGetInstrDescSize(id);
5599 imm = emitGetInsSC(id);
5600 code = emitInsCode(ins, fmt);
5601 imm = insUnscaleImm(imm, size);
5602 assert((imm & 0x007F) == imm);
5604 dst += emitOutput_Thumb1Instr(dst, code);
5607 case IF_T1_G: // T1_G .......iiinnnddd R1 R2 imm3
5608 sz = SMALL_IDSC_SIZE;
5609 imm = emitGetInsSC(id);
5610 code = emitInsCode(ins, fmt);
5611 code |= insEncodeRegT1_D3(id->idReg1());
5612 code |= insEncodeRegT1_N3(id->idReg2());
5613 assert((imm & 0x0007) == imm);
5615 dst += emitOutput_Thumb1Instr(dst, code);
5618 case IF_T1_H: // T1_H .......mmmnnnddd R1 R2 R3
5619 sz = emitGetInstrDescSize(id);
5620 code = emitInsCode(ins, fmt);
5621 code |= insEncodeRegT1_D3(id->idReg1());
5622 code |= insEncodeRegT1_N3(id->idReg2());
5623 code |= insEncodeRegT1_M3(id->idReg3());
5624 dst += emitOutput_Thumb1Instr(dst, code);
5627 case IF_T1_I: // T1_I ......i.iiiiiddd R1 imm6
5628 assert(id->idIsBound());
5630 dst = emitOutputLJ(ig, dst, id);
5631 sz = sizeof(instrDescJmp);
5634 case IF_T1_J0: // T1_J0 .....dddiiiiiiii R1 imm8
5635 case IF_T1_J1: // T1_J1 .....dddiiiiiiii R1 <regmask8>
5636 case IF_T1_J2: // T1_J2 .....dddiiiiiiii R1 SP imm8
5637 sz = emitGetInstrDescSize(id);
5638 imm = emitGetInsSC(id);
5639 code = emitInsCode(ins, fmt);
5640 code |= insEncodeRegT1_DI(id->idReg1());
5641 if (fmt == IF_T1_J2)
5643 imm = insUnscaleImm(imm, size);
5645 assert((imm & 0x00ff) == imm);
5647 dst += emitOutput_Thumb1Instr(dst, code);
5650 case IF_T1_L0: // T1_L0 ........iiiiiiii imm8
5651 case IF_T1_L1: // T1_L1 .......Rrrrrrrrr <regmask8>
5652 sz = emitGetInstrDescSize(id);
5653 imm = emitGetInsSC(id);
5654 code = emitInsCode(ins, fmt);
5655 if (fmt == IF_T1_L1)
5657 assert((imm & 0x3) != 0x3);
5659 code |= 0x0100; // R bit
5662 assert((imm & 0x00ff) == imm);
5664 dst += emitOutput_Thumb1Instr(dst, code);
5667 case IF_T2_A: // T2_A ................ ................
5668 sz = SMALL_IDSC_SIZE;
5669 code = emitInsCode(ins, fmt);
5670 dst += emitOutput_Thumb2Instr(dst, code);
5673 case IF_T2_B: // T2_B ................ ............iiii imm4
5674 sz = SMALL_IDSC_SIZE;
5675 imm = emitGetInsSC(id);
5676 code = emitInsCode(ins, fmt);
5677 assert((imm & 0x000F) == imm);
5679 dst += emitOutput_Thumb2Instr(dst, code);
5682 case IF_T2_C0: // T2_C0 ...........Snnnn .iiiddddiishmmmm R1 R2 R3 S, imm5, sh
5683 case IF_T2_C4: // T2_C4 ...........Snnnn ....dddd....mmmm R1 R2 R3 S
5684 case IF_T2_C5: // T2_C5 ............nnnn ....dddd....mmmm R1 R2 R3
5685 sz = emitGetInstrDescSize(id);
5686 code = emitInsCode(ins, fmt);
5687 code |= insEncodeRegT2_D(id->idReg1());
5688 code |= insEncodeRegT2_N(id->idReg2());
5689 code |= insEncodeRegT2_M(id->idReg3());
5690 if (fmt != IF_T2_C5)
5691 code |= insEncodeSetFlags(id->idInsFlags());
5692 if (fmt == IF_T2_C0)
5694 imm = emitGetInsSC(id);
5695 code |= insEncodeShiftCount(imm);
5696 code |= insEncodeShiftOpts(id->idInsOpt());
5698 dst += emitOutput_Thumb2Instr(dst, code);
5701 case IF_T2_C1: // T2_C1 ...........S.... .iiiddddiishmmmm R1 R2 S, imm5, sh
5702 case IF_T2_C2: // T2_C2 ...........S.... .iiiddddii..mmmm R1 R2 S, imm5
5703 case IF_T2_C6: // T2_C6 ................ ....dddd..iimmmm R1 R2 imm2
5704 sz = SMALL_IDSC_SIZE;
5705 imm = emitGetInsSC(id);
5706 code = emitInsCode(ins, fmt);
5707 code |= insEncodeRegT2_D(id->idReg1());
5708 code |= insEncodeRegT2_M(id->idReg2());
5709 if (fmt == IF_T2_C6)
5711 assert((imm & 0x0018) == imm);
5716 code |= insEncodeSetFlags(id->idInsFlags());
5717 code |= insEncodeShiftCount(imm);
5718 if (fmt == IF_T2_C1)
5719 code |= insEncodeShiftOpts(id->idInsOpt());
5721 dst += emitOutput_Thumb2Instr(dst, code);
5724 case IF_T2_C3: // T2_C3 ...........S.... ....dddd....mmmm R1 R2 S
5725 sz = SMALL_IDSC_SIZE;
5726 code = emitInsCode(ins, fmt);
5727 code |= insEncodeRegT2_D(id->idReg1());
5728 code |= insEncodeRegT2_M(id->idReg2());
5729 code |= insEncodeSetFlags(id->idInsFlags());
5730 dst += emitOutput_Thumb2Instr(dst, code);
5733 case IF_T2_C7: // T2_C7 ............nnnn ..........shmmmm R1 R2 imm2
5734 case IF_T2_C8: // T2_C8 ............nnnn .iii....iishmmmm R1 R2 imm5, sh
5735 sz = SMALL_IDSC_SIZE;
5736 imm = emitGetInsSC(id);
5737 code = emitInsCode(ins, fmt);
5738 code |= insEncodeRegT2_N(id->idReg1());
5739 code |= insEncodeRegT2_M(id->idReg2());
5740 if (fmt == IF_T2_C7)
5742 assert((imm & 0x0003) == imm);
5745 else if (fmt == IF_T2_C8)
5747 code |= insEncodeShiftCount(imm);
5748 code |= insEncodeShiftOpts(id->idInsOpt());
5750 dst += emitOutput_Thumb2Instr(dst, code);
5753 case IF_T2_C9: // T2_C9 ............nnnn ............mmmm R1 R2
5754 sz = SMALL_IDSC_SIZE;
5755 code = emitInsCode(ins, fmt);
5756 code |= insEncodeRegT2_N(id->idReg1());
5757 code |= insEncodeRegT2_M(id->idReg2());
5758 dst += emitOutput_Thumb2Instr(dst, code);
5761 case IF_T2_C10: // T2_C10 ............mmmm ....dddd....mmmm R1 R2
5762 sz = SMALL_IDSC_SIZE;
5763 code = emitInsCode(ins, fmt);
5764 code |= insEncodeRegT2_D(id->idReg1());
5765 code |= insEncodeRegT2_M(id->idReg2());
5766 code |= insEncodeRegT2_N(id->idReg2());
5767 dst += emitOutput_Thumb2Instr(dst, code);
5770 case IF_T2_D0: // T2_D0 ............nnnn .iiiddddii.wwwww R1 R2 imm5, imm5
5771 case IF_T2_D1: // T2_D1 ................ .iiiddddii.wwwww R1 imm5, imm5
5772 sz = SMALL_IDSC_SIZE;
5773 imm = emitGetInsSC(id);
5774 code = emitInsCode(ins, fmt);
5775 code |= insEncodeRegT2_D(id->idReg1());
5776 if (fmt == IF_T2_D0)
5777 code |= insEncodeRegT2_N(id->idReg2());
5778 code |= insEncodeBitFieldImm(imm);
5779 dst += emitOutput_Thumb2Instr(dst, code);
5782 case IF_T2_E0: // T2_E0 ............nnnn tttt......shmmmm R1 R2 R3 imm2
5783 case IF_T2_E1: // T2_E1 ............nnnn tttt............ R1 R2
5784 case IF_T2_E2: // T2_E2 ................ tttt............ R1
5785 code = emitInsCode(ins, fmt);
5786 code |= insEncodeRegT2_T(id->idReg1());
5787 if (fmt == IF_T2_E0)
5789 sz = emitGetInstrDescSize(id);
5790 code |= insEncodeRegT2_N(id->idReg2());
5791 if (id->idIsLclVar())
5793 code |= insEncodeRegT2_M(codeGen->rsGetRsvdReg());
5798 code |= insEncodeRegT2_M(id->idReg3());
5799 imm = emitGetInsSC(id);
5800 assert((imm & 0x0003) == imm);
5806 sz = SMALL_IDSC_SIZE;
5807 if (fmt != IF_T2_E2)
5809 code |= insEncodeRegT2_N(id->idReg2());
5812 dst += emitOutput_Thumb2Instr(dst, code);
5815 case IF_T2_F1: // T2_F1 ............nnnn ttttdddd....mmmm R1 R2 R3 R4
5816 sz = emitGetInstrDescSize(id);
5818 code = emitInsCode(ins, fmt);
5819 code |= insEncodeRegT2_T(id->idReg1());
5820 code |= insEncodeRegT2_D(id->idReg2());
5821 code |= insEncodeRegT2_N(id->idReg3());
5822 code |= insEncodeRegT2_M(id->idReg4());
5823 dst += emitOutput_Thumb2Instr(dst, code);
5826 case IF_T2_F2: // T2_F2 ............nnnn aaaadddd....mmmm R1 R2 R3 R4
5827 sz = emitGetInstrDescSize(id);
5828 code = emitInsCode(ins, fmt);
5829 code |= insEncodeRegT2_D(id->idReg1());
5830 code |= insEncodeRegT2_N(id->idReg2());
5831 code |= insEncodeRegT2_M(id->idReg3());
5832 code |= insEncodeRegT2_T(id->idReg4());
5833 dst += emitOutput_Thumb2Instr(dst, code);
5836 case IF_T2_G0: // T2_G0 .......PU.W.nnnn ttttTTTTiiiiiiii R1 R2 R3 imm8, PUW
5837 case IF_T2_G1: // T2_G1 ............nnnn ttttTTTT........ R1 R2 R3
5838 code = emitInsCode(ins, fmt);
5839 code |= insEncodeRegT2_T(id->idReg1());
5840 code |= insEncodeRegT2_D(id->idReg2());
5841 code |= insEncodeRegT2_N(id->idReg3());
5842 if (fmt == IF_T2_G0)
5844 sz = emitGetInstrDescSizeSC(id);
5845 imm = emitGetInsSC(id);
5846 assert(unsigned_abs(imm) <= 0x00ff);
5848 code |= insEncodePUW_G0(id->idInsOpt(), imm);
5852 sz = emitGetInstrDescSize(id);
5854 dst += emitOutput_Thumb2Instr(dst, code);
5857 case IF_T2_H0: // T2_H0 ............nnnn tttt.PUWiiiiiiii R1 R2 imm8, PUW
5858 case IF_T2_H1: // T2_H1 ............nnnn tttt....iiiiiiii R1 R2 imm8
5859 case IF_T2_H2: // T2_H2 ............nnnn ........iiiiiiii R1 imm8
5860 sz = emitGetInstrDescSizeSC(id);
5861 imm = emitGetInsSC(id);
5862 code = emitInsCode(ins, fmt);
5863 code |= insEncodeRegT2_T(id->idReg1());
5865 if (fmt != IF_T2_H2)
5866 code |= insEncodeRegT2_N(id->idReg2());
5868 if (fmt == IF_T2_H0)
5870 assert(unsigned_abs(imm) <= 0x00ff);
5871 code |= insEncodePUW_H0(id->idInsOpt(), imm);
5872 code |= unsigned_abs(imm);
5876 assert((imm & 0x00ff) == imm);
5879 dst += emitOutput_Thumb2Instr(dst, code);
5882 case IF_T2_I0: // T2_I0 ..........W.nnnn rrrrrrrrrrrrrrrr R1 W, imm16
5883 case IF_T2_I1: // T2_I1 ................ rrrrrrrrrrrrrrrr imm16
5884 sz = emitGetInstrDescSizeSC(id);
5885 code = emitInsCode(ins, fmt);
5886 if (fmt == IF_T2_I0)
5888 code |= insEncodeRegT2_N(id->idReg1());
5889 code |= (1 << 21); // W bit
5891 imm = emitGetInsSC(id);
5892 assert((imm & 0x3) != 0x3);
5894 code |= 0x8000; // PC bit
5896 code |= 0x4000; // LR bit
5898 assert(imm <= 0x1fff); // 13 bits
5900 dst += emitOutput_Thumb2Instr(dst, code);
5903 case IF_T2_K1: // T2_K1 ............nnnn ttttiiiiiiiiiiii R1 R2 imm12
5904 case IF_T2_K4: // T2_K4 ........U....... ttttiiiiiiiiiiii R1 PC U, imm12
5905 case IF_T2_K3: // T2_K3 ........U....... ....iiiiiiiiiiii PC U, imm12
5906 sz = emitGetInstrDescSize(id);
5907 imm = emitGetInsSC(id);
5908 code = emitInsCode(ins, fmt);
5909 if (fmt != IF_T2_K3)
5911 code |= insEncodeRegT2_T(id->idReg1());
5913 if (fmt == IF_T2_K1)
5915 code |= insEncodeRegT2_N(id->idReg2());
5916 assert(imm <= 0xfff); // 12 bits
5921 assert(unsigned_abs(imm) <= 0xfff); // 12 bits (signed)
5924 code |= (1 << 23); // U bit
5926 dst += emitOutput_Thumb2Instr(dst, code);
5929 case IF_T2_K2: // T2_K2 ............nnnn ....iiiiiiiiiiii R1 imm12
5930 sz = emitGetInstrDescSizeSC(id);
5931 imm = emitGetInsSC(id);
5932 code = emitInsCode(ins, fmt);
5933 code |= insEncodeRegT2_N(id->idReg1());
5934 assert(imm <= 0xfff); // 12 bits
5936 dst += emitOutput_Thumb2Instr(dst, code);
5939 case IF_T2_L0: // T2_L0 .....i.....Snnnn .iiiddddiiiiiiii R1 R2 S, imm8<<imm4
5940 case IF_T2_L1: // T2_L1 .....i.....S.... .iiiddddiiiiiiii R1 S, imm8<<imm4
5941 case IF_T2_L2: // T2_L2 .....i......nnnn .iii....iiiiiiii R1 imm8<<imm4
5942 sz = emitGetInstrDescSize(id);
5943 imm = emitGetInsSC(id);
5944 code = emitInsCode(ins, fmt);
5946 if (fmt == IF_T2_L2)
5947 code |= insEncodeRegT2_N(id->idReg1());
5950 code |= insEncodeSetFlags(id->idInsFlags());
5951 code |= insEncodeRegT2_D(id->idReg1());
5952 if (fmt == IF_T2_L0)
5953 code |= insEncodeRegT2_N(id->idReg2());
5955 assert(isModImmConst(imm)); // Funky ARM imm encoding
5956 imm = encodeModImmConst(imm);
5957 assert(imm <= 0xfff); // 12 bits
5958 code |= (imm & 0x00ff);
5959 code |= (imm & 0x0700) << 4;
5960 code |= (imm & 0x0800) << 15;
5961 dst += emitOutput_Thumb2Instr(dst, code);
5964 case IF_T2_M0: // T2_M0 .....i......nnnn .iiiddddiiiiiiii R1 R2 imm12
5965 sz = emitGetInstrDescSizeSC(id);
5966 imm = emitGetInsSC(id);
5967 code = emitInsCode(ins, fmt);
5968 code |= insEncodeRegT2_D(id->idReg1());
5969 if (fmt == IF_T2_M0)
5970 code |= insEncodeRegT2_N(id->idReg2());
5971 imm = emitGetInsSC(id);
5972 assert(imm <= 0xfff); // 12 bits
5973 code |= (imm & 0x00ff);
5974 code |= (imm & 0x0700) << 4;
5975 code |= (imm & 0x0800) << 15;
5976 dst += emitOutput_Thumb2Instr(dst, code);
5979 case IF_T2_N: // T2_N .....i......iiii .iiiddddiiiiiiii R1 imm16
5980 sz = emitGetInstrDescSizeSC(id);
5981 code = emitInsCode(ins, fmt);
5982 code |= insEncodeRegT2_D(id->idReg1());
5983 imm = emitGetInsSC(id);
5984 if (id->idIsLclVar())
5986 if (ins == INS_movw)
5992 assert(ins == INS_movt);
5993 imm = (imm >> 16) & 0xffff;
5997 assert(!id->idIsReloc());
5998 code |= insEncodeImmT2_Mov(imm);
5999 dst += emitOutput_Thumb2Instr(dst, code);
6002 case IF_T2_N2: // T2_N2 .....i......iiii .iiiddddiiiiiiii R1 imm16
6003 sz = emitGetInstrDescSizeSC(id);
6004 code = emitInsCode(ins, fmt);
6005 code |= insEncodeRegT2_D(id->idReg1());
6006 imm = emitGetInsSC(id);
6007 addr = emitConsBlock + imm;
6008 if (!id->idIsReloc())
6010 assert(sizeof(size_t) == sizeof(target_size_t));
6011 imm = (target_size_t)addr;
6012 if (ins == INS_movw)
6018 assert(ins == INS_movt);
6019 imm = (imm >> 16) & 0xffff;
6021 code |= insEncodeImmT2_Mov(imm);
6022 dst += emitOutput_Thumb2Instr(dst, code);
6026 assert((ins == INS_movt) || (ins == INS_movw));
6027 dst += emitOutput_Thumb2Instr(dst, code);
6028 if ((ins == INS_movt) && emitComp->info.compMatchedVM)
6029 emitHandlePCRelativeMov32((void*)(dst - 8), addr);
6033 case IF_T2_N3: // T2_N3 .....i......iiii .iiiddddiiiiiiii R1 imm16
6034 sz = sizeof(instrDescReloc);
6035 code = emitInsCode(ins, fmt);
6036 code |= insEncodeRegT2_D(id->idReg1());
6038 assert((ins == INS_movt) || (ins == INS_movw));
6039 assert(id->idIsReloc());
6041 addr = emitGetInsRelocValue(id);
6042 dst += emitOutput_Thumb2Instr(dst, code);
6043 if ((ins == INS_movt) && emitComp->info.compMatchedVM)
6044 emitHandlePCRelativeMov32((void*)(dst - 8), addr);
6048 // these are the binary operators
6050 sz = emitGetInstrDescSize(id);
6051 code = emitInsCode(ins, fmt);
6052 code |= insEncodeRegT2_VectorN(id->idReg2(), size, true);
6053 code |= insEncodeRegT2_VectorM(id->idReg3(), size, true);
6054 code |= insEncodeRegT2_VectorD(id->idReg1(), size, true);
6055 if (size == EA_8BYTE)
6057 dst += emitOutput_Thumb2Instr(dst, code);
6087 if (id->idOpSize() == EA_8BYTE)
6092 srcSize = dstSize = id->idOpSize();
6096 sz = emitGetInstrDescSize(id);
6097 code = emitInsCode(ins, fmt);
6099 code |= insEncodeRegT2_VectorD(id->idReg1(), dstSize, true);
6100 code |= insEncodeRegT2_VectorM(id->idReg2(), srcSize, true);
6102 dst += emitOutput_Thumb2Instr(dst, code);
6107 sz = emitGetInstrDescSizeSC(id);
6108 code = emitInsCode(ins, fmt);
6109 code |= insEncodeRegT2_N(id->idReg2());
6110 code |= insEncodeRegT2_VectorD(id->idReg1(), size, true);
6112 imm = emitGetInsSC(id);
6114 imm = -imm; // bit 23 at 0 means negate
6116 code |= 1 << 23; // set the positive bit
6118 // offset is +/- 1020
6120 assert(imm >> 10 == 0);
6122 // bit 8 is set for doubles
6123 if (id->idOpSize() == EA_8BYTE)
6125 dst += emitOutput_Thumb2Instr(dst, code);
6129 // 3op assemble a double from two int regs (or back)
6130 sz = emitGetInstrDescSize(id);
6131 code = emitInsCode(ins, fmt);
6132 if (ins == INS_vmov_i2d)
6134 code |= insEncodeRegT2_VectorM(id->idReg1(), size, true);
6135 code |= id->idReg2() << 12;
6136 code |= id->idReg3() << 16;
6140 assert(ins == INS_vmov_d2i);
6141 code |= id->idReg1() << 12;
6142 code |= id->idReg2() << 16;
6143 code |= insEncodeRegT2_VectorM(id->idReg3(), size, true);
6145 dst += emitOutput_Thumb2Instr(dst, code);
6149 // 2op assemble a float from one int reg (or back)
6150 sz = emitGetInstrDescSize(id);
6151 code = emitInsCode(ins, fmt);
6152 if (ins == INS_vmov_f2i)
6154 code |= insEncodeRegT2_VectorN(id->idReg2(), EA_4BYTE, true);
6155 code |= id->idReg1() << 12;
6159 assert(ins == INS_vmov_i2f);
6160 code |= insEncodeRegT2_VectorN(id->idReg1(), EA_4BYTE, true);
6161 code |= id->idReg2() << 12;
6164 dst += emitOutput_Thumb2Instr(dst, code);
6167 case IF_T1_J3: // T1_J3 .....dddiiiiiiii R1 PC imm8
6168 case IF_T2_M1: // T2_M1 .....i.......... .iiiddddiiiiiiii R1 PC imm12
6169 assert(id->idGCref() == GCT_NONE);
6170 assert(id->idIsBound());
6172 dst = emitOutputLJ(ig, dst, id);
6173 sz = sizeof(instrDescLbl);
6176 case IF_T1_K: // T1_K ....cccciiiiiiii Branch imm8, cond4
6177 case IF_T1_M: // T1_M .....iiiiiiiiiii Branch imm11
6178 case IF_T2_J1: // T2_J1 .....Scccciiiiii ..j.jiiiiiiiiiii Branch imm20, cond4
6179 case IF_T2_J2: // T2_J2 .....Siiiiiiiiii ..j.jiiiiiiiiii. Branch imm24
6180 case IF_T2_N1: // T2_N .....i......iiii .iiiddddiiiiiiii R1 imm16
6182 assert(id->idGCref() == GCT_NONE);
6183 assert(id->idIsBound());
6185 dst = emitOutputLJ(ig, dst, id);
6186 sz = sizeof(instrDescJmp);
6189 case IF_T1_D1: // T1_D1 .........mmmm... R1*
6191 code = emitInsCode(ins, fmt);
6192 code |= insEncodeRegT1_M4(id->idReg1());
6193 dst += emitOutput_Thumb1Instr(dst, code);
6194 sz = SMALL_IDSC_SIZE;
6197 case IF_T1_D2: // T1_D2 .........mmmm... R3*
6199 /* Is this a "fat" call descriptor? */
6201 if (id->idIsLargeCall())
6203 instrDescCGCA* idCall = (instrDescCGCA*)id;
6204 gcrefRegs = idCall->idcGcrefRegs;
6205 byrefRegs = idCall->idcByrefRegs;
6206 VarSetOps::Assign(emitComp, GCvars, idCall->idcGCvars);
6207 sz = sizeof(instrDescCGCA);
6211 assert(!id->idIsLargeDsp());
6212 assert(!id->idIsLargeCns());
6214 gcrefRegs = emitDecodeCallGCregs(id);
6216 VarSetOps::AssignNoCopy(emitComp, GCvars, VarSetOps::MakeEmpty(emitComp));
6217 sz = sizeof(instrDesc);
6220 code = emitInsCode(ins, fmt);
6221 code |= insEncodeRegT1_M4(id->idReg3());
6222 callInstrSize = SafeCvtAssert<unsigned char>(emitOutput_Thumb1Instr(dst, code));
6223 dst += callInstrSize;
6226 case IF_T2_J3: // T2_J3 .....Siiiiiiiiii ..j.jiiiiiiiiii. Call imm24
6228 /* Is this a "fat" call descriptor? */
6230 if (id->idIsLargeCall())
6232 instrDescCGCA* idCall = (instrDescCGCA*)id;
6233 gcrefRegs = idCall->idcGcrefRegs;
6234 byrefRegs = idCall->idcByrefRegs;
6235 VarSetOps::Assign(emitComp, GCvars, idCall->idcGCvars);
6236 sz = sizeof(instrDescCGCA);
6240 assert(!id->idIsLargeDsp());
6241 assert(!id->idIsLargeCns());
6243 gcrefRegs = emitDecodeCallGCregs(id);
6245 VarSetOps::AssignNoCopy(emitComp, GCvars, VarSetOps::MakeEmpty(emitComp));
6246 sz = sizeof(instrDesc);
6249 if (id->idAddr()->iiaAddr == NULL) /* a recursive call */
6251 addr = emitCodeBlock;
6255 addr = id->idAddr()->iiaAddr;
6257 code = emitInsCode(ins, fmt);
6259 if (id->idIsDspReloc())
6261 callInstrSize = SafeCvtAssert<unsigned char>(emitOutput_Thumb2Instr(dst, code));
6262 dst += callInstrSize;
6263 if (emitComp->info.compMatchedVM)
6264 emitRecordRelocation((void*)(dst - 4), addr, IMAGE_REL_BASED_THUMB_BRANCH24);
6268 addr = (BYTE*)((size_t)addr & ~1); // Clear the lowest bit from target address
6270 /* Calculate PC relative displacement */
6271 int disp = addr - (dst + 4);
6272 bool S = (disp < 0);
6273 bool I1 = ((disp & 0x00800000) == 0);
6274 bool I2 = ((disp & 0x00400000) == 0);
6277 code |= (1 << 26); // S bit
6279 code |= (1 << 13); // J1 bit
6281 code |= (1 << 11); // J2 bit
6283 int immLo = (disp & 0x00000ffe) >> 1;
6284 int immHi = (disp & 0x003ff000) >> 12;
6286 code |= (immHi << 16);
6290 assert((disp & 0x00fffffe) == disp);
6292 callInstrSize = SafeCvtAssert<unsigned char>(emitOutput_Thumb2Instr(dst, code));
6293 dst += callInstrSize;
6298 /* We update the GC info before the call as the variables cannot be
6299 used by the call. Killing variables before the call helps with
6300 boundary conditions if the call is CORINFO_HELP_THROW - see bug 50029.
6301 If we ever track aliased variables (which could be used by the
6302 call), we would have to keep them alive past the call. */
6304 emitUpdateLiveGCvars(GCvars, *dp);
6306 // If the method returns a GC ref, mark R0 appropriately.
6307 if (id->idGCref() == GCT_GCREF)
6308 gcrefRegs |= RBM_R0;
6309 else if (id->idGCref() == GCT_BYREF)
6310 byrefRegs |= RBM_R0;
6312 // If the GC register set has changed, report the new set.
6313 if (gcrefRegs != emitThisGCrefRegs)
6314 emitUpdateLiveGCregs(GCT_GCREF, gcrefRegs, dst);
6316 if (byrefRegs != emitThisByrefRegs)
6317 emitUpdateLiveGCregs(GCT_BYREF, byrefRegs, dst);
6319 // Some helper calls may be marked as not requiring GC info to be recorded.
6320 if ((!id->idIsNoGC()))
6322 // On ARM, as on AMD64, we don't change the stack pointer to push/pop args.
6323 // So we're not really doing a "stack pop" here (note that "args" is 0), but we use this mechanism
6324 // to record the call for GC info purposes. (It might be best to use an alternate call,
6325 // and protect "emitStackPop" under the EMIT_TRACK_STACK_DEPTH preprocessor variable.)
6326 emitStackPop(dst, /*isCall*/ true, callInstrSize, /*args*/ 0);
6328 /* Do we need to record a call location for GC purposes? */
6330 if (!emitFullGCinfo)
6332 emitRecordGCcall(dst, callInstrSize);
6338 /********************************************************************/
6340 /********************************************************************/
6345 printf("unexpected format %s\n", emitIfName(id->idInsFmt()));
6346 assert(!"don't know how to encode this instruction");
6351 // Determine if any registers now hold GC refs, or whether a register that was overwritten held a GC ref.
6352 // We assume here that "id->idGCref()" is not GC_NONE only if the instruction described by "id" writes a
6353 // GC ref to register "id->idReg1()". (It may, apparently, also not be GC_NONE in other cases, such as
6354 // for stores, but we ignore those cases here.)
6355 if (emitInsMayWriteToGCReg(id)) // True if "id->idIns()" writes to a register than can hold GC ref.
6357 // If we ever generate instructions that write to multiple registers (LDM, or POP),
6358 // then we'd need to more work here to ensure that changes in the status of GC refs are
6359 // tracked properly.
6360 if (emitInsMayWriteMultipleRegs(id))
6362 // We explicitly list the multiple-destination-target instruction that we expect to
6363 // be emitted outside of the prolog and epilog here.
6371 // For each of these, idReg1() and idReg2() are the destination registers.
6372 emitGCregDeadUpd(id->idReg1(), dst);
6373 emitGCregDeadUpd(id->idReg2(), dst);
6376 assert(false); // We need to recognize this multi-target instruction...
6381 if (id->idGCref() != GCT_NONE)
6383 emitGCregLiveUpd(id->idGCref(), id->idReg1(), dst);
6387 // I also assume that "idReg1" is the destination register of all instructions that write to registers.
6388 emitGCregDeadUpd(id->idReg1(), dst);
6393 // Now we determine if the instruction has written to a (local variable) stack location, and either written a GC
6394 // ref or overwritten one.
6395 if (emitInsWritesToLclVarStackLoc(id))
6397 int varNum = id->idAddr()->iiaLclVar.lvaVarNum();
6398 unsigned ofs = AlignDown(id->idAddr()->iiaLclVar.lvaOffset(), TARGET_POINTER_SIZE);
6400 int adr = emitComp->lvaFrameAddress(varNum, true, ®Base, ofs);
6401 if (id->idGCref() != GCT_NONE)
6403 emitGCvarLiveUpd(adr + ofs, varNum, id->idGCref(), dst);
6407 // If the type of the local is a gc ref type, update the liveness.
6411 // "Regular" (non-spill-temp) local.
6412 vt = var_types(emitComp->lvaTable[varNum].lvType);
6416 TempDsc* tmpDsc = codeGen->regSet.tmpFindNum(varNum);
6417 vt = tmpDsc->tdTempType();
6419 if (vt == TYP_REF || vt == TYP_BYREF)
6420 emitGCvarDeadUpd(adr + ofs, dst);
6425 /* Make sure we set the instruction descriptor size correctly */
6427 size_t expected = emitSizeOfInsDsc(id);
6428 assert(sz == expected);
6430 if (emitComp->opts.disAsm || emitComp->opts.dspEmit || emitComp->verbose)
6432 emitDispIns(id, false, dspOffs, true, emitCurCodeOffs(odst), *dp, (dst - *dp), ig);
6435 if (emitComp->compDebugBreak)
6437 // set JitEmitPrintRefRegs=1 will print out emitThisGCrefRegs and emitThisByrefRegs
6438 // at the beginning of this method.
6439 if (JitConfig.JitEmitPrintRefRegs() != 0)
6441 printf("Before emitOutputInstr for id->idDebugOnlyInfo()->idNum=0x%02x\n", id->idDebugOnlyInfo()->idNum);
6442 printf(" emitThisGCrefRegs(0x%p)=", dspPtr(&emitThisGCrefRegs));
6443 printRegMaskInt(emitThisGCrefRegs);
6444 emitDispRegSet(emitThisGCrefRegs);
6446 printf(" emitThisByrefRegs(0x%p)=", dspPtr(&emitThisByrefRegs));
6447 printRegMaskInt(emitThisByrefRegs);
6448 emitDispRegSet(emitThisByrefRegs);
6452 // For example, set JitBreakEmitOutputInstr=a6 will break when this method is called for
6453 // emitting instruction a6, (i.e. IN00a6 in jitdump).
6454 if ((unsigned)JitConfig.JitBreakEmitOutputInstr() == id->idDebugOnlyInfo()->idNum)
6456 assert(!"JitBreakEmitOutputInstr reached");
6461 /* All instructions are expected to generate code */
6470 /*****************************************************************************/
6471 /*****************************************************************************/
6475 static bool insAlwaysSetFlags(instruction ins)
6477 bool result = false;
6493 /*****************************************************************************
6495 * Display the instruction name, optionally the instruction
6496 * can add the "s" suffix if it must set the flags.
6498 void emitter::emitDispInst(instruction ins, insFlags flags)
6500 const char* insstr = codeGen->genInsName(ins);
6501 int len = strlen(insstr);
6503 /* Display the instruction name */
6505 printf("%s", insstr);
6506 if (insSetsFlags(flags) && !insAlwaysSetFlags(ins))
6513 // Add at least one space after the instruction name
6514 // and add spaces until we have reach the normal size of 8
6522 #define STRICT_ARM_ASM 0
6524 /*****************************************************************************
6526 * Display an immediate value
6528 void emitter::emitDispImm(int imm, bool addComma, bool alwaysHex /* =false */)
6530 if (!alwaysHex && (imm > -1000) && (imm < 1000))
6532 else if ((imm > 0) ||
6533 (imm == -imm) || // -0x80000000 == 0x80000000. So we don't want to add an extra "-" at the beginning.
6534 (emitComp->opts.disDiffable && (imm == 0xD1FFAB1E))) // Don't display this as negative
6535 printf("0x%02x", imm);
6536 else // val <= -1000
6537 printf("-0x%02x", -imm);
6543 /*****************************************************************************
6545 * Display a relocatable immediate value
6547 void emitter::emitDispReloc(BYTE* addr)
6549 printf("0x%p", dspPtr(addr));
6552 /*****************************************************************************
6554 * Display an arm condition for the IT instructions
6556 void emitter::emitDispCond(int cond)
6558 const static char* armCond[16] = {"eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc",
6559 "hi", "ls", "ge", "lt", "gt", "le", "AL", "NV"}; // The last two are invalid
6560 assert(0 <= cond && (unsigned)cond < ArrLen(armCond));
6561 printf(armCond[cond]);
6564 /*****************************************************************************
6566 * Display a register range in a range format
6568 void emitter::emitDispRegRange(regNumber reg, int len, emitAttr attr)
6571 emitDispReg(reg, attr, false);
6575 emitDispReg((regNumber)(reg + len - 1), attr, false);
6580 /*****************************************************************************
6582 * Display an register mask in a list format
6584 void emitter::emitDispRegmask(int imm, bool encodedPC_LR)
6586 bool printedOne = false;
6592 hasPC = (imm & 2) != 0;
6593 hasLR = (imm & 1) != 0;
6598 hasPC = (imm & RBM_PC) != 0;
6599 hasLR = (imm & RBM_LR) != 0;
6600 imm &= ~(RBM_PC | RBM_LR);
6603 regNumber reg = REG_R0;
6613 printf("%s", emitRegName(reg));
6618 reg = regNumber(reg + 1);
6626 printf("%s", emitRegName(REG_LR));
6634 printf("%s", emitRegName(REG_PC));
6640 /*****************************************************************************
6642 * Returns the encoding for the Shift Type bits to be used in a Thumb-2 encoding
6645 void emitter::emitDispShiftOpts(insOpts opt)
6647 if (opt == INS_OPTS_LSL)
6649 else if (opt == INS_OPTS_LSR)
6651 else if (opt == INS_OPTS_ASR)
6653 else if (opt == INS_OPTS_ROR)
6655 else if (opt == INS_OPTS_RRX)
6659 /*****************************************************************************
6661 * Display a register
6663 void emitter::emitDispReg(regNumber reg, emitAttr attr, bool addComma)
6665 if (isFloatReg(reg))
6667 const char* size = attr == EA_8BYTE ? "d" : "s";
6668 printf("%s%s", size, emitFloatRegName(reg, attr) + 1);
6672 printf("%s", emitRegName(reg, attr));
6679 /*****************************************************************************
6681 * Display an addressing operand [reg]
6683 void emitter::emitDispAddrR(regNumber reg, emitAttr attr)
6686 emitDispReg(reg, attr, false);
6691 /*****************************************************************************
6693 * Display an addressing operand [reg + imm]
6695 void emitter::emitDispAddrRI(regNumber reg, int imm, emitAttr attr)
6697 bool regIsSPorFP = (reg == REG_SP) || (reg == REG_FP);
6700 emitDispReg(reg, attr, false);
6711 emitDispImm(imm, false, regIsSPorFP);
6717 /*****************************************************************************
6719 * Display an addressing operand [reg + reg]
6721 void emitter::emitDispAddrRR(regNumber reg1, regNumber reg2, emitAttr attr)
6724 emitDispReg(reg1, attr, false);
6730 emitDispReg(reg2, attr, false);
6735 /*****************************************************************************
6737 * Display an addressing operand [reg + reg * imm]
6739 void emitter::emitDispAddrRRI(regNumber reg1, regNumber reg2, int imm, emitAttr attr)
6742 emitDispReg(reg1, attr, false);
6745 emitDispReg(reg2, attr, false);
6749 emitDispImm(1 << imm, false);
6755 emitDispImm(1 << imm, false);
6758 emitDispReg(reg2, attr, false);
6764 /*****************************************************************************
6766 * Display an addressing operand [reg + imm]
6768 void emitter::emitDispAddrPUW(regNumber reg, int imm, insOpts opt, emitAttr attr)
6770 bool regIsSPorFP = (reg == REG_SP) || (reg == REG_FP);
6773 emitDispReg(reg, attr, false);
6774 if (insOptAnyInc(opt))
6787 emitDispImm(imm, false, regIsSPorFP);
6794 /*****************************************************************************
6796 * Display the gc-ness of the operand
6798 void emitter::emitDispGC(emitAttr attr)
6801 // TODO-ARM-Cleanup: Fix or delete.
6802 if (attr == EA_GCREF)
6804 else if (attr == EA_BYREF)
6809 /*****************************************************************************
6811 * Display (optionally) the instruction encoding in hex
6814 void emitter::emitDispInsHex(BYTE* code, size_t sz)
6816 // We do not display the instruction hex if we want diff-able disassembly
6817 if (!emitComp->opts.disDiffable)
6821 printf(" %04X ", (*((unsigned short*)code)));
6825 printf(" %04X %04X", (*((unsigned short*)(code + 0))), (*((unsigned short*)(code + 2))));
6830 /****************************************************************************
6832 * Display the given instruction.
6835 void emitter::emitDispInsHelp(
6836 instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* code, size_t sz, insGroup* ig)
6840 unsigned idNum = id->idDebugOnlyInfo()->idNum; // Do not remove this! It is needed for VisualStudio
6841 // conditional breakpoints
6843 printf("IN%04x: ", idNum);
6849 if (!emitComp->opts.dspEmit && !isNew && !asmfm && sz)
6852 /* Display the instruction offset */
6854 emitDispInsOffs(offset, doffs);
6856 /* Display the instruction hex code */
6858 emitDispInsHex(code, sz);
6862 /* Get the instruction and format */
6864 instruction ins = id->idIns();
6865 insFormat fmt = id->idInsFmt();
6867 emitDispInst(ins, id->idInsFlags());
6869 /* If this instruction has just been added, check its size */
6871 assert(isNew == false || (int)emitSizeOfInsDsc(id) == emitCurIGfreeNext - (BYTE*)id);
6873 /* Figure out the operand size */
6875 if (id->idGCref() == GCT_GCREF)
6877 else if (id->idGCref() == GCT_BYREF)
6880 attr = id->idOpSize();
6886 const char* methodName;
6888 case IF_T1_A: // None
6892 case IF_T1_L0: // Imm
6894 emitDispImm(emitGetInsSC(id), false);
6897 case IF_T1_B: // <cond>
6898 emitDispCond(emitGetInsSC(id));
6901 case IF_T1_L1: // <regmask8>
6902 case IF_T2_I1: // <regmask16>
6903 emitDispRegmask(emitGetInsSC(id), true);
6906 case IF_T2_E2: // Reg
6907 if (id->idIns() == INS_vmrs)
6909 if (id->idReg1() != REG_R15)
6911 emitDispReg(id->idReg1(), attr, true);
6916 printf("APSR, FPSCR");
6921 emitDispReg(id->idReg1(), attr, false);
6926 emitDispReg(id->idReg1(), attr, false);
6930 emitDispReg(id->idReg3(), attr, false);
6932 CORINFO_METHOD_HANDLE handle = (CORINFO_METHOD_HANDLE)id->idDebugOnlyInfo()->idMemCookie;
6935 methodName = emitComp->eeGetMethodFullName(handle);
6936 printf("\t\t// %s", methodName);
6941 case IF_T1_F: // SP, Imm
6942 emitDispReg(REG_SP, attr, true);
6943 emitDispImm(emitGetInsSC(id), false);
6946 case IF_T1_J0: // Reg, Imm
6949 emitDispReg(id->idReg1(), attr, true);
6950 imm = emitGetInsSC(id);
6951 emitDispImm(imm, false, false);
6955 emitDispReg(id->idReg1(), attr, true);
6956 imm = emitGetInsSC(id);
6957 if (emitComp->opts.disDiffable)
6959 emitDispImm(imm, false, true);
6963 emitDispReg(id->idReg1(), attr, true);
6964 printf("%s RELOC ", (id->idIns() == INS_movw) ? "LOW" : "HIGH");
6965 emitDispReloc(emitGetInsRelocValue(id));
6969 emitDispReg(id->idReg1(), attr, true);
6970 imm = emitGetInsSC(id);
6972 dataSection* jdsc = 0;
6973 NATIVE_OFFSET offs = 0;
6975 /* Find the appropriate entry in the data section list */
6977 for (jdsc = emitConsDsc.dsdList; jdsc; jdsc = jdsc->dsNext)
6979 UNATIVE_OFFSET size = jdsc->dsSize;
6981 /* Is this a label table? */
6983 if (jdsc->dsType == dataSection::blockAbsoluteAddr)
6992 assert(jdsc != NULL);
6994 if (id->idIsDspReloc())
6998 printf("%s ADDRESS J_M%03u_DS%02u", (id->idIns() == INS_movw) ? "LOW" : "HIGH",
6999 Compiler::s_compMethodsCount, imm);
7001 // After the MOVT, dump the table
7002 if (id->idIns() == INS_movt)
7004 unsigned cnt = jdsc->dsSize / TARGET_POINTER_SIZE;
7005 BasicBlock** bbp = (BasicBlock**)jdsc->dsCont;
7007 bool isBound = (emitCodeGetCookie(*bbp) != NULL);
7011 printf("\n\n J_M%03u_DS%02u LABEL DWORD", Compiler::s_compMethodsCount, imm);
7013 /* Display the label table (it's stored as "BasicBlock*" values) */
7019 /* Convert the BasicBlock* value to an IG address */
7021 lab = (insGroup*)emitCodeGetCookie(*bbp++);
7024 printf("\n DD G_M%03u_IG%02u", Compiler::s_compMethodsCount, lab->igNum);
7031 case IF_T2_H2: // [Reg+imm]
7033 emitDispAddrRI(id->idReg1(), emitGetInsSC(id), attr);
7036 case IF_T2_K3: // [PC+imm]
7037 emitDispAddrRI(REG_PC, emitGetInsSC(id), attr);
7040 case IF_T1_J1: // reg, <regmask8>
7041 case IF_T2_I0: // reg, <regmask16>
7042 emitDispReg(id->idReg1(), attr, false);
7044 emitDispRegmask(emitGetInsSC(id), false);
7047 case IF_T1_D0: // Reg, Reg
7052 emitDispReg(id->idReg1(), attr, true);
7053 emitDispReg(id->idReg2(), attr, false);
7054 if (fmt == IF_T1_E && id->idIns() == INS_rsb)
7060 case IF_T2_E1: // Reg, [Reg]
7061 emitDispReg(id->idReg1(), attr, true);
7062 emitDispAddrR(id->idReg2(), attr);
7065 case IF_T2_D1: // Reg, Imm, Imm
7066 emitDispReg(id->idReg1(), attr, true);
7067 imm = emitGetInsSC(id);
7069 int lsb = (imm >> 5) & 0x1f;
7070 int msb = imm & 0x1f;
7072 int imm2 = msb + 1 - lsb;
7073 emitDispImm(imm1, true);
7074 emitDispImm(imm2, false);
7078 case IF_T1_C: // Reg, Reg, Imm
7085 emitDispReg(id->idReg1(), attr, true);
7086 imm = emitGetInsSC(id);
7087 if (emitInsIsLoadOrStore(ins))
7089 emitDispAddrRI(id->idReg2(), imm, attr);
7093 emitDispReg(id->idReg2(), attr, true);
7094 emitDispImm(imm, false);
7099 emitDispReg(id->idReg1(), attr, true);
7100 imm = emitGetInsSC(id);
7101 if (emitInsIsLoadOrStore(ins))
7103 emitDispAddrRI(REG_SP, imm, attr);
7107 emitDispReg(REG_SP, attr, true);
7108 emitDispImm(imm, false);
7113 emitDispReg(id->idReg1(), attr, true);
7114 emitDispAddrRI(REG_PC, emitGetInsSC(id), attr);
7119 emitDispReg(id->idReg1(), attr, true);
7120 emitDispReg(id->idReg2(), attr, false);
7121 imm = emitGetInsSC(id);
7122 if (id->idInsOpt() == INS_OPTS_RRX)
7124 emitDispShiftOpts(id->idInsOpt());
7129 emitDispShiftOpts(id->idInsOpt());
7130 emitDispImm(imm, false);
7135 imm = emitGetInsSC(id);
7136 emitDispReg(id->idReg1(), attr, true);
7137 emitDispReg(id->idReg2(), attr, (imm != 0));
7140 emitDispImm(imm, false);
7145 emitDispAddrRRI(id->idReg1(), id->idReg2(), emitGetInsSC(id), attr);
7149 emitDispReg(id->idReg1(), attr, true);
7150 emitDispAddrPUW(id->idReg2(), emitGetInsSC(id), id->idInsOpt(), attr);
7153 case IF_T1_H: // Reg, Reg, Reg
7154 emitDispReg(id->idReg1(), attr, true);
7155 if (emitInsIsLoadOrStore(ins))
7157 emitDispAddrRR(id->idReg2(), id->idReg3(), attr);
7161 emitDispReg(id->idReg2(), attr, true);
7162 emitDispReg(id->idReg3(), attr, false);
7168 emitDispReg(id->idReg1(), attr, true);
7169 emitDispReg(id->idReg2(), attr, true);
7170 emitDispReg(id->idReg3(), attr, false);
7174 emitDispReg(id->idReg1(), attr, true);
7175 emitDispReg(id->idReg2(), attr, true);
7176 emitDispReg(id->idReg3(), attr, false);
7180 switch (id->idIns())
7185 emitDispReg(id->idReg1(), EA_4BYTE, true);
7186 emitDispReg(id->idReg2(), EA_8BYTE, false);
7192 emitDispReg(id->idReg1(), EA_8BYTE, true);
7193 emitDispReg(id->idReg2(), EA_4BYTE, false);
7196 // we just use the type on the instruction
7197 // unless it is an asymmetrical one like the converts
7199 emitDispReg(id->idReg1(), attr, true);
7200 emitDispReg(id->idReg2(), attr, false);
7206 imm = emitGetInsSC(id);
7207 switch (id->idIns())
7211 emitDispReg(id->idReg1(), attr, true);
7212 emitDispAddrPUW(id->idReg2(), imm, id->idInsOpt(), attr);
7217 emitDispReg(id->idReg2(), attr, false);
7218 if (insOptAnyInc(id->idInsOpt()))
7221 emitDispRegRange(id->idReg1(), abs(imm) >> 2, attr);
7226 emitDispRegRange(id->idReg1(), abs(imm) >> 2, attr);
7235 switch (id->idIns())
7238 emitDispReg(id->idReg1(), attr, true); // EA_8BYTE
7239 emitDispReg(id->idReg2(), EA_4BYTE, true);
7240 emitDispReg(id->idReg3(), EA_4BYTE, false);
7243 emitDispReg(id->idReg1(), EA_4BYTE, true);
7244 emitDispReg(id->idReg2(), EA_4BYTE, true);
7245 emitDispReg(id->idReg3(), attr, false); // EA_8BYTE
7253 emitDispReg(id->idReg1(), attr, true);
7254 emitDispReg(id->idReg2(), attr, false);
7258 emitDispReg(id->idReg1(), attr, true);
7259 emitDispAddrRR(id->idReg2(), id->idReg3(), attr);
7262 case IF_T2_D0: // Reg, Reg, Imm, Imm
7263 emitDispReg(id->idReg1(), attr, true);
7264 emitDispReg(id->idReg2(), attr, true);
7265 imm = emitGetInsSC(id);
7268 int lsb = (imm >> 5) & 0x1f;
7269 int msb = imm & 0x1f;
7271 int imm2 = msb + 1 - lsb;
7272 emitDispImm(imm1, true);
7273 emitDispImm(imm2, false);
7277 int lsb = (imm >> 5) & 0x1f;
7278 int widthm1 = imm & 0x1f;
7280 int imm2 = widthm1 + 1;
7281 emitDispImm(imm1, true);
7282 emitDispImm(imm2, false);
7286 case IF_T2_C0: // Reg, Reg, Reg, Imm
7287 emitDispReg(id->idReg1(), attr, true);
7288 emitDispReg(id->idReg2(), attr, true);
7289 emitDispReg(id->idReg3(), attr, false);
7290 imm = emitGetInsSC(id);
7291 if (id->idInsOpt() == INS_OPTS_RRX)
7293 emitDispShiftOpts(id->idInsOpt());
7298 emitDispShiftOpts(id->idInsOpt());
7299 emitDispImm(imm, false);
7304 emitDispReg(id->idReg1(), attr, true);
7305 if (id->idIsLclVar())
7307 emitDispAddrRRI(id->idReg2(), codeGen->rsGetRsvdReg(), 0, attr);
7311 emitDispAddrRRI(id->idReg2(), id->idReg3(), emitGetInsSC(id), attr);
7316 emitDispReg(id->idReg1(), attr, true);
7317 emitDispReg(id->idReg2(), attr, true);
7318 emitDispAddrPUW(id->idReg3(), emitGetInsSC(id), id->idInsOpt(), attr);
7321 case IF_T2_F1: // Reg, Reg, Reg, Reg
7323 emitDispReg(id->idReg1(), attr, true);
7324 emitDispReg(id->idReg2(), attr, true);
7325 emitDispReg(id->idReg3(), attr, true);
7326 emitDispReg(id->idReg4(), attr, false);
7330 case IF_T2_M1: // Load Label
7331 emitDispReg(id->idReg1(), attr, true);
7332 if (id->idIsBound())
7333 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
7335 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
7338 case IF_T1_I: // Special Compare-and-branch
7339 emitDispReg(id->idReg1(), attr, true);
7342 case IF_T1_K: // Special Branch, conditional
7344 assert(((instrDescJmp*)id)->idjShort);
7349 if (fmt == IF_T2_N1)
7351 emitDispReg(id->idReg1(), attr, true);
7352 printf("%s ADDRESS ", (id->idIns() == INS_movw) ? "LOW" : "HIGH");
7360 if (id->idAddr()->iiaHasInstrCount())
7362 int instrCount = id->idAddr()->iiaGetInstrCount();
7366 printf("pc%s%d instructions", (instrCount >= 0) ? "+" : "", instrCount);
7370 unsigned insNum = emitFindInsNum(ig, id);
7371 UNATIVE_OFFSET srcOffs = ig->igOffs + emitFindOffset(ig, insNum + 1);
7372 UNATIVE_OFFSET dstOffs = ig->igOffs + emitFindOffset(ig, insNum + 1 + instrCount);
7373 ssize_t relOffs = (ssize_t)(emitOffsetToPtr(dstOffs) - emitOffsetToPtr(srcOffs));
7374 printf("pc%s%d (%d instructions)", (relOffs >= 0) ? "+" : "", relOffs, instrCount);
7377 else if (id->idIsBound())
7378 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
7380 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
7385 if (id->idIsCallAddr())
7387 offs = (ssize_t)id->idAddr()->iiaAddr;
7393 methodName = emitComp->eeGetMethodFullName((CORINFO_METHOD_HANDLE)id->idDebugOnlyInfo()->idMemCookie);
7398 if (id->idIsDspReloc())
7400 printf("%08X", offs);
7404 printf("%s", methodName);
7410 printf("unexpected format %s", emitIfName(id->idInsFmt()));
7411 assert(!"unexpectedFormat");
7415 if (id->idDebugOnlyInfo()->idVarRefOffs)
7418 emitDispFrameRef(id->idAddr()->iiaLclVar.lvaVarNum(), id->idAddr()->iiaLclVar.lvaOffset(),
7419 id->idDebugOnlyInfo()->idVarRefOffs, asmfm);
7425 void emitter::emitDispIns(
7426 instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* code, size_t sz, insGroup* ig)
7428 insFormat fmt = id->idInsFmt();
7430 /* Special-case IF_LARGEJMP */
7432 if ((fmt == IF_LARGEJMP) && id->idIsBound())
7434 // This is a pseudo-instruction format representing a large conditional branch. See the comment
7435 // in emitter::emitOutputLJ() for the full description.
7437 // For this pseudo-instruction, we will actually generate:
7439 // b<!cond> L_not // 2 bytes. Note that we reverse the condition.
7440 // b L_target // 4 bytes
7443 // These instructions don't exist in the actual instruction stream, so we need to fake them
7444 // up to display them.
7446 // Note: don't touch the actual instrDesc. If we accidentally messed it up, it would create a very
7447 // difficult to find bug.
7450 instrDescJmp* pidJmp = &idJmp;
7452 memset(&idJmp, 0, sizeof(idJmp));
7454 pidJmp->idIns(emitJumpKindToIns(emitReverseJumpKind(emitInsToJumpKind(id->idIns())))); // reverse the
7457 pidJmp->idInsFmt(IF_T1_K);
7458 pidJmp->idInsSize(emitInsSize(IF_T1_K));
7459 pidJmp->idjShort = 1;
7460 pidJmp->idAddr()->iiaSetInstrCount(1);
7461 pidJmp->idDebugOnlyInfo(id->idDebugOnlyInfo()); // share the idDebugOnlyInfo() field
7463 size_t bcondSizeOrZero = (code == NULL) ? 0 : 2; // branch is 2 bytes
7464 emitDispInsHelp(pidJmp, false, doffs, asmfm, offset, code, bcondSizeOrZero,
7465 NULL /* force display of pc-relative branch */);
7467 code += bcondSizeOrZero;
7470 // Next, display the unconditional branch
7472 // Reset the local instrDesc
7473 memset(&idJmp, 0, sizeof(idJmp));
7475 pidJmp->idIns(INS_b);
7476 pidJmp->idInsFmt(IF_T2_J2);
7477 pidJmp->idInsSize(emitInsSize(IF_T2_J2));
7478 pidJmp->idjShort = 0;
7479 if (id->idIsBound())
7481 pidJmp->idSetIsBound();
7482 pidJmp->idAddr()->iiaIGlabel = id->idAddr()->iiaIGlabel;
7486 pidJmp->idAddr()->iiaBBlabel = id->idAddr()->iiaBBlabel;
7488 pidJmp->idDebugOnlyInfo(id->idDebugOnlyInfo()); // share the idDebugOnlyInfo() field
7490 size_t brSizeOrZero = (code == NULL) ? 0 : 4; // unconditional branch is 4 bytes
7491 emitDispInsHelp(pidJmp, isNew, doffs, asmfm, offset, code, brSizeOrZero, ig);
7495 emitDispInsHelp(id, isNew, doffs, asmfm, offset, code, sz, ig);
7499 /*****************************************************************************
7501 * Display a stack frame reference.
7504 void emitter::emitDispFrameRef(int varx, int disp, int offs, bool asmfm)
7509 printf("TEMP_%02u", -varx);
7511 emitComp->gtDispLclVar(+varx, false);
7514 printf("-0x%02x", -disp);
7516 printf("+0x%02x", +disp);
7520 if (varx >= 0 && emitComp->opts.varNames)
7523 const char* varName;
7525 assert((unsigned)varx < emitComp->lvaCount);
7526 varDsc = emitComp->lvaTable + varx;
7527 varName = emitComp->compLocalVarName(varx, offs);
7531 printf("'%s", varName);
7534 printf("-%d", -disp);
7536 printf("+%d", +disp);
7545 void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataReg, GenTreeIndir* indir)
7547 // Handle unaligned floating point loads/stores
7548 if ((indir->gtFlags & GTF_IND_UNALIGNED))
7550 if (indir->OperGet() == GT_STOREIND)
7552 var_types type = indir->AsStoreInd()->Data()->TypeGet();
7553 if (type == TYP_FLOAT)
7555 regNumber tmpReg = indir->GetSingleTempReg();
7556 emitIns_R_R(INS_vmov_f2i, EA_4BYTE, tmpReg, dataReg);
7557 emitInsLoadStoreOp(INS_str, EA_4BYTE, tmpReg, indir, 0);
7560 else if (type == TYP_DOUBLE)
7562 regNumber tmpReg1 = indir->ExtractTempReg();
7563 regNumber tmpReg2 = indir->GetSingleTempReg();
7564 emitIns_R_R_R(INS_vmov_d2i, EA_8BYTE, tmpReg1, tmpReg2, dataReg);
7565 emitInsLoadStoreOp(INS_str, EA_4BYTE, tmpReg1, indir, 0);
7566 emitInsLoadStoreOp(INS_str, EA_4BYTE, tmpReg2, indir, 4);
7570 else if (indir->OperGet() == GT_IND)
7572 var_types type = indir->TypeGet();
7573 if (type == TYP_FLOAT)
7575 regNumber tmpReg = indir->GetSingleTempReg();
7576 emitInsLoadStoreOp(INS_ldr, EA_4BYTE, tmpReg, indir, 0);
7577 emitIns_R_R(INS_vmov_i2f, EA_4BYTE, dataReg, tmpReg);
7580 else if (type == TYP_DOUBLE)
7582 regNumber tmpReg1 = indir->ExtractTempReg();
7583 regNumber tmpReg2 = indir->GetSingleTempReg();
7584 emitInsLoadStoreOp(INS_ldr, EA_4BYTE, tmpReg1, indir, 0);
7585 emitInsLoadStoreOp(INS_ldr, EA_4BYTE, tmpReg2, indir, 4);
7586 emitIns_R_R_R(INS_vmov_i2d, EA_8BYTE, dataReg, tmpReg1, tmpReg2);
7592 // Proceed with ordinary loads/stores
7593 emitInsLoadStoreOp(ins, attr, dataReg, indir, 0);
7596 void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataReg, GenTreeIndir* indir, int offset)
7598 GenTree* addr = indir->Addr();
7600 if (addr->isContained())
7602 assert(addr->OperGet() == GT_LCL_VAR_ADDR || addr->OperGet() == GT_LEA);
7606 if (addr->OperGet() == GT_LEA)
7608 offset += addr->AsAddrMode()->Offset();
7609 if (addr->AsAddrMode()->gtScale > 0)
7611 assert(isPow2(addr->AsAddrMode()->gtScale));
7612 BitScanForward(&lsl, addr->AsAddrMode()->gtScale);
7616 GenTree* memBase = indir->Base();
7618 if (indir->HasIndex())
7620 assert(addr->OperGet() == GT_LEA);
7622 GenTree* index = indir->Index();
7626 regNumber tmpReg = indir->GetSingleTempReg();
7628 // If the LEA produces a GCREF or BYREF, we need to be careful to mark any temp register
7629 // computed with the base register as a BYREF.
7630 GenTreeAddrMode* lea = addr->AsAddrMode();
7631 emitAttr leaAttr = emitTypeSize(lea);
7632 emitAttr leaBasePartialAddrAttr = EA_IS_GCREF_OR_BYREF(leaAttr) ? EA_BYREF : EA_PTRSIZE;
7634 if (emitIns_valid_imm_for_add(offset, INS_FLAGS_DONT_CARE))
7638 // Generate code to set tmpReg = base + index*scale
7639 emitIns_R_R_R_I(INS_add, leaBasePartialAddrAttr, tmpReg, memBase->gtRegNum, index->gtRegNum,
7640 lsl, INS_FLAGS_DONT_CARE, INS_OPTS_LSL);
7644 // Generate code to set tmpReg = base + index
7645 emitIns_R_R_R(INS_add, leaBasePartialAddrAttr, tmpReg, memBase->gtRegNum, index->gtRegNum);
7648 noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
7650 // Then load/store dataReg from/to [tmpReg + offset]
7651 emitIns_R_R_I(ins, attr, dataReg, tmpReg, offset);
7653 else // large offset
7655 // First load/store tmpReg with the large offset constant
7656 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
7657 // Then add the base register
7659 emitIns_R_R_R(INS_add, leaBasePartialAddrAttr, tmpReg, tmpReg, memBase->gtRegNum);
7661 noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
7662 noway_assert(tmpReg != index->gtRegNum);
7664 // Then load/store dataReg from/to [tmpReg + index*scale]
7665 emitIns_R_R_R_I(ins, attr, dataReg, tmpReg, index->gtRegNum, lsl, INS_FLAGS_DONT_CARE,
7669 else // (offset == 0)
7673 // Then load/store dataReg from/to [memBase + index*scale]
7674 emitIns_R_R_R_I(ins, attr, dataReg, memBase->gtRegNum, index->gtRegNum, lsl, INS_FLAGS_DONT_CARE,
7679 // Then load/store dataReg from/to [memBase + index]
7680 emitIns_R_R_R(ins, attr, dataReg, memBase->gtRegNum, index->gtRegNum);
7686 if (emitIns_valid_imm_for_ldst_offset(offset, attr))
7688 // Then load/store dataReg from/to [memBase + offset]
7689 emitIns_R_R_I(ins, attr, dataReg, memBase->gtRegNum, offset);
7693 // We require a tmpReg to hold the offset
7694 regNumber tmpReg = indir->GetSingleTempReg();
7696 // First load/store tmpReg with the large offset constant
7697 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
7699 // Then load/store dataReg from/to [memBase + tmpReg]
7700 emitIns_R_R_R(ins, attr, dataReg, memBase->gtRegNum, tmpReg);
7708 assert(emitIns_valid_imm_for_add(offset, INS_FLAGS_DONT_CARE));
7709 emitIns_R_R_I(ins, attr, dataReg, addr->gtRegNum, offset);
7713 emitIns_R_R(ins, attr, dataReg, addr->gtRegNum);
7718 // The callee must call genConsumeReg() for any non-contained srcs
7719 // and genProduceReg() for any non-contained dsts.
7721 regNumber emitter::emitInsBinary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src)
7723 regNumber result = REG_NA;
7725 // dst can only be a reg
7726 assert(!dst->isContained());
7728 // src can be immed or reg
7729 assert(!src->isContained() || src->isContainedIntOrIImmed());
7731 // find immed (if any) - it cannot be a dst
7732 GenTreeIntConCommon* intConst = nullptr;
7733 if (src->isContainedIntOrIImmed())
7735 intConst = src->AsIntConCommon();
7740 emitIns_R_I(ins, attr, dst->gtRegNum, (target_ssize_t)intConst->IconValue());
7741 return dst->gtRegNum;
7745 emitIns_R_R(ins, attr, dst->gtRegNum, src->gtRegNum);
7746 return dst->gtRegNum;
7750 regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src1, GenTree* src2)
7752 // dst can only be a reg
7753 assert(!dst->isContained());
7755 // find immed (if any) - it cannot be a dst
7756 // Only one src can be an int.
7757 GenTreeIntConCommon* intConst = nullptr;
7758 GenTree* nonIntReg = nullptr;
7760 if (varTypeIsFloating(dst))
7762 // src1 can only be a reg
7763 assert(!src1->isContained());
7764 // src2 can only be a reg
7765 assert(!src2->isContained());
7767 else // not floating point
7769 // src2 can be immed or reg
7770 assert(!src2->isContained() || src2->isContainedIntOrIImmed());
7772 // Check src2 first as we can always allow it to be a contained immediate
7773 if (src2->isContainedIntOrIImmed())
7775 intConst = src2->AsIntConCommon();
7778 // Only for commutative operations do we check src1 and allow it to be a contained immediate
7779 else if (dst->OperIsCommutative())
7781 // src1 can be immed or reg
7782 assert(!src1->isContained() || src1->isContainedIntOrIImmed());
7784 // Check src1 and allow it to be a contained immediate
7785 if (src1->isContainedIntOrIImmed())
7787 assert(!src2->isContainedIntOrIImmed());
7788 intConst = src1->AsIntConCommon();
7794 // src1 can only be a reg
7795 assert(!src1->isContained());
7799 insFlags flags = INS_FLAGS_DONT_CARE;
7800 bool isMulOverflow = false;
7801 if (dst->gtOverflowEx())
7803 if ((ins == INS_add) || (ins == INS_adc) || (ins == INS_sub) || (ins == INS_sbc))
7805 flags = INS_FLAGS_SET;
7807 else if (ins == INS_mul)
7809 isMulOverflow = true;
7810 assert(intConst == nullptr); // overflow format doesn't support an int constant operand
7814 assert(!"Invalid ins for overflow check");
7818 if (dst->gtSetFlags())
7820 assert((ins == INS_add) || (ins == INS_adc) || (ins == INS_sub) || (ins == INS_sbc) || (ins == INS_and) ||
7821 (ins == INS_orr) || (ins == INS_eor) || (ins == INS_orn));
7822 flags = INS_FLAGS_SET;
7825 if (intConst != nullptr)
7827 emitIns_R_R_I(ins, attr, dst->gtRegNum, nonIntReg->gtRegNum, (target_ssize_t)intConst->IconValue(), flags);
7833 regNumber extraReg = dst->GetSingleTempReg();
7834 assert(extraReg != dst->gtRegNum);
7836 if ((dst->gtFlags & GTF_UNSIGNED) != 0)
7838 // Compute 8 byte result from 4 byte by 4 byte multiplication.
7839 emitIns_R_R_R_R(INS_umull, EA_4BYTE, dst->gtRegNum, extraReg, src1->gtRegNum, src2->gtRegNum);
7841 // Overflow exists if the result's high word is non-zero.
7842 emitIns_R_I(INS_cmp, attr, extraReg, 0);
7846 // Compute 8 byte result from 4 byte by 4 byte multiplication.
7847 emitIns_R_R_R_R(INS_smull, EA_4BYTE, dst->gtRegNum, extraReg, src1->gtRegNum, src2->gtRegNum);
7849 // Overflow exists if the result's high word is not merely a sign bit.
7850 emitIns_R_R_I(INS_cmp, attr, extraReg, dst->gtRegNum, 31, INS_FLAGS_DONT_CARE, INS_OPTS_ASR);
7855 // We can just do the arithmetic, setting the flags if needed.
7856 emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum, flags);
7860 if (dst->gtOverflowEx())
7862 assert(!varTypeIsFloating(dst));
7864 emitJumpKind jumpKind;
7866 if (dst->OperGet() == GT_MUL)
7872 bool isUnsignedOverflow = ((dst->gtFlags & GTF_UNSIGNED) != 0);
7873 jumpKind = isUnsignedOverflow ? EJ_lo : EJ_vs;
7874 if (jumpKind == EJ_lo)
7876 if ((dst->OperGet() != GT_SUB) && (dst->OperGet() != GT_SUB_HI))
7883 // Jump to the block which will throw the exception.
7884 codeGen->genJumpToThrowHlpBlk(jumpKind, SCK_OVERFLOW);
7887 return dst->gtRegNum;
7890 #endif // defined(_TARGET_ARM_)