Handle MovRelocatableImmediate on ARM32 as a special case (IF_T2_N3) (#19013)
[platform/upstream/coreclr.git] / src / jit / emitarm.cpp
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.
4
5 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
6 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
7 XX                                                                           XX
8 XX                             emitArm.cpp                                   XX
9 XX                                                                           XX
10 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
11 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
12 */
13 #include "jitpch.h"
14 #ifdef _MSC_VER
15 #pragma hdrstop
16 #endif
17
18 #if defined(_TARGET_ARM_)
19
20 /*****************************************************************************/
21 /*****************************************************************************/
22
23 #include "instr.h"
24 #include "emit.h"
25 #include "codegen.h"
26
27 /*****************************************************************************/
28
29 const instruction emitJumpKindInstructions[] = {
30     INS_nop,
31
32 #define JMP_SMALL(en, rev, ins) INS_##ins,
33 #include "emitjmps.h"
34 };
35
36 const emitJumpKind emitReverseJumpKinds[] = {
37     EJ_NONE,
38
39 #define JMP_SMALL(en, rev, ins) EJ_##rev,
40 #include "emitjmps.h"
41 };
42
43 /*****************************************************************************
44  * Look up the instruction for a jump kind
45  */
46
47 /*static*/ instruction emitter::emitJumpKindToIns(emitJumpKind jumpKind)
48 {
49     assert((unsigned)jumpKind < ArrLen(emitJumpKindInstructions));
50     return emitJumpKindInstructions[jumpKind];
51 }
52
53 /*****************************************************************************
54  * Look up the jump kind for an instruction. It better be a conditional
55  * branch instruction with a jump kind!
56  */
57
58 /*static*/ emitJumpKind emitter::emitInsToJumpKind(instruction ins)
59 {
60     for (unsigned i = 0; i < ArrLen(emitJumpKindInstructions); i++)
61     {
62         if (ins == emitJumpKindInstructions[i])
63         {
64             emitJumpKind ret = (emitJumpKind)i;
65             assert(EJ_NONE < ret && ret < EJ_COUNT);
66             return ret;
67         }
68     }
69     unreached();
70 }
71
72 /*****************************************************************************
73  * Reverse the conditional jump
74  */
75
76 /*static*/ emitJumpKind emitter::emitReverseJumpKind(emitJumpKind jumpKind)
77 {
78     assert(jumpKind < EJ_COUNT);
79     return emitReverseJumpKinds[jumpKind];
80 }
81
82 /*****************************************************************************
83  *
84  *  Return the allocated size (in bytes) of the given instruction descriptor.
85  */
86
87 size_t emitter::emitSizeOfInsDsc(instrDesc* id)
88 {
89     if (emitIsScnsInsDsc(id))
90         return SMALL_IDSC_SIZE;
91
92     assert((unsigned)id->idInsFmt() < emitFmtCount);
93
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);
97
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.
102
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
107
108     switch (idOp)
109     {
110         case ID_OP_NONE:
111             break;
112
113         case ID_OP_JMP:
114             return sizeof(instrDescJmp);
115
116         case ID_OP_LBL:
117             return sizeof(instrDescLbl);
118
119         case ID_OP_CALL:
120         case ID_OP_SPEC:
121             assert(isCallIns || maybeCallIns);
122             if (id->idIsLargeCall())
123             {
124                 /* Must be a "fat" indirect call descriptor */
125                 return sizeof(instrDescCGCA);
126             }
127             else
128             {
129                 assert(!id->idIsLargeDsp());
130                 assert(!id->idIsLargeCns());
131                 return sizeof(instrDesc);
132             }
133             break;
134
135         default:
136             NO_WAY("unexpected instruction descriptor format");
137             break;
138     }
139
140     if (id->idInsFmt() == IF_T2_N3)
141     {
142         assert((id->idIns() == INS_movw) || (id->idIns() == INS_movt));
143         return sizeof(instrDescReloc);
144     }
145
146     if (id->idIsLargeCns())
147     {
148         if (id->idIsLargeDsp())
149             return sizeof(instrDescCnsDsp);
150         else
151             return sizeof(instrDescCns);
152     }
153     else
154     {
155         if (id->idIsLargeDsp())
156             return sizeof(instrDescDsp);
157         else
158             return sizeof(instrDesc);
159     }
160 }
161
162 bool offsetFitsInVectorMem(int disp)
163 {
164     unsigned imm = unsigned_abs(disp);
165     return ((imm & 0x03fc) == imm);
166 }
167
168 #ifdef DEBUG
169 /*****************************************************************************
170  *
171  *  The following called for each recorded instruction -- use for debugging.
172  */
173 void emitter::emitInsSanityCheck(instrDesc* id)
174 {
175     /* What instruction format have we got? */
176
177     switch (id->idInsFmt())
178     {
179         case IF_T1_A: // T1_A    ................
180         case IF_T2_A: // T2_A    ................ ................
181             break;
182
183         case IF_T1_B: // T1_B    ........cccc....                                           cond
184         case IF_T2_B: // T2_B    ................ ............iiii                          imm4
185             assert(emitGetInsSC(id) < 0x10);
186             break;
187
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()))
192             {
193                 emitAttr size = id->idOpSize();
194                 int      imm  = emitGetInsSC(id);
195
196                 imm = insUnscaleImm(imm, size);
197                 assert(imm < 0x20);
198             }
199             else
200             {
201                 assert(id->idSmallCns() < 0x20);
202             }
203             break;
204
205         case IF_T1_D0: // T1_D0   ........Dmmmmddd                       R1* R2*
206             assert(isGeneralRegister(id->idReg1()));
207             assert(isGeneralRegister(id->idReg2()));
208             break;
209
210         case IF_T1_D1: // T1_D1   .........mmmm...                       R1*
211             assert(isGeneralRegister(id->idReg1()));
212             break;
213
214         case IF_T1_D2: // T1_D2   .........mmmm...                               R3*
215             assert(isGeneralRegister(id->idReg3()));
216             break;
217
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);
222             break;
223
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);
228             break;
229
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);
234             break;
235
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()));
240             break;
241
242         case IF_T1_I: // T1_I    ......i.iiiiiddd                       R1                  imm6
243             assert(isLowRegister(id->idReg1()));
244             break;
245
246         case IF_T1_J0: // T1_J0   .....dddiiiiiiii                       R1                  imm8
247             assert(isLowRegister(id->idReg1()));
248             assert(emitGetInsSC(id) < 0x100);
249             break;
250
251         case IF_T1_J1: // T1_J1   .....dddiiiiiiii                       R1                  <regmask8>
252             assert(isLowRegister(id->idReg1()));
253             assert(emitGetInsSC(id) < 0x100);
254             break;
255
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);
261             break;
262
263         case IF_T1_L0: // T1_L0   ........iiiiiiii                                           imm8
264             assert(emitGetInsSC(id) < 0x100);
265             break;
266
267         case IF_T1_L1: // T1_L1   .......Rrrrrrrrr                                           <regmask8+2>
268             assert(emitGetInsSC(id) < 0x400);
269             break;
270
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);
276             break;
277
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()));
284             break;
285
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);
292             break;
293
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);
299             break;
300
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()));
306             break;
307
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);
312             break;
313
314         case IF_T2_D1: // T2_D1   ................ .iiiddddii.wwwww       R1                 imm5, imm5
315             assert(isGeneralRegister(id->idReg1()));
316             assert(emitGetInsSC(id) < 0x400);
317             break;
318
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())
323             {
324                 assert(isGeneralRegister(codeGen->rsGetRsvdReg()));
325             }
326             else
327             {
328                 assert(isGeneralRegister(id->idReg3()));
329                 assert(emitGetInsSC(id) < 0x4);
330             }
331             break;
332
333         case IF_T2_E1: // T2_E1   ............nnnn tttt............       R1  R2
334             assert(isGeneralRegister(id->idReg1()));
335             assert(isGeneralRegister(id->idReg2()));
336             break;
337
338         case IF_T2_E2: // T2_E2   ................ tttt............       R1
339             assert(isGeneralRegister(id->idReg1()));
340             break;
341
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()));
348             break;
349
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);
355             break;
356
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);
361             break;
362
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);
367             break;
368
369         case IF_T2_H2: // T2_H2   ............nnnn ........iiiiiiii       R1                 imm8
370             assert(isGeneralRegister(id->idReg1()));
371             assert(emitGetInsSC(id) < 0x100);
372             break;
373
374         case IF_T2_I0: // T2_I0   ..........W.nnnn rrrrrrrrrrrrrrrr       R1              W, imm16
375             assert(isGeneralRegister(id->idReg1()));
376             assert(emitGetInsSC(id) < 0x10000);
377             break;
378
379         case IF_T2_N: // T2_N    .....i......iiii .iiiddddiiiiiiii       R1                 imm16
380             assert(isGeneralRegister(id->idReg1()));
381             assert(!id->idIsReloc());
382             break;
383
384         case IF_T2_N2: // T2_N2   .....i......iiii .iiiddddiiiiiiii       R1                 imm16
385             assert(isGeneralRegister(id->idReg1()));
386             assert((size_t)emitGetInsSC(id) < emitDataSize());
387             break;
388
389         case IF_T2_N3: // T2_N3   .....i......iiii .iiiddddiiiiiiii       R1                 imm16
390             assert(isGeneralRegister(id->idReg1()));
391             assert(id->idIsReloc());
392             break;
393
394         case IF_T2_I1: // T2_I1   ................ rrrrrrrrrrrrrrrr                          imm16
395             assert(emitGetInsSC(id) < 0x10000);
396             break;
397
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);
403             break;
404
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)));
409             break;
410
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);
416             break;
417
418         case IF_T2_K3: // T2_K3   ........U....... ....iiiiiiiiiiii       PC              U, imm12
419             assert(id->idReg1() == REG_PC);
420             assert(emitGetInsSC(id) < 0x1000);
421             break;
422
423         case IF_T2_K2: // T2_K2   ............nnnn ....iiiiiiiiiiii       R1                 imm12
424             assert(isGeneralRegister(id->idReg1()));
425             assert(emitGetInsSC(id) < 0x1000);
426             break;
427
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)));
432             break;
433
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);
438             break;
439
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
446         case IF_LARGEJMP:
447             break;
448
449         case IF_T2_VFP3:
450             if (id->idOpSize() == EA_8BYTE)
451             {
452                 assert(isDoubleReg(id->idReg1()));
453                 assert(isDoubleReg(id->idReg2()));
454                 assert(isDoubleReg(id->idReg3()));
455             }
456             else
457             {
458                 assert(id->idOpSize() == EA_4BYTE);
459                 assert(isFloatReg(id->idReg1()));
460                 assert(isFloatReg(id->idReg2()));
461                 assert(isFloatReg(id->idReg3()));
462             }
463             break;
464
465         case IF_T2_VFP2:
466             assert(isFloatReg(id->idReg1()));
467             assert(isFloatReg(id->idReg2()));
468             break;
469
470         case IF_T2_VLDST:
471             if (id->idOpSize() == EA_8BYTE)
472                 assert(isDoubleReg(id->idReg1()));
473             else
474                 assert(isFloatReg(id->idReg1()));
475             assert(isGeneralRegister(id->idReg2()));
476             assert(offsetFitsInVectorMem(emitGetInsSC(id)));
477             break;
478
479         case IF_T2_VMOVD:
480             assert(id->idOpSize() == EA_8BYTE);
481             if (id->idIns() == INS_vmov_d2i)
482             {
483                 assert(isGeneralRegister(id->idReg1()));
484                 assert(isGeneralRegister(id->idReg2()));
485                 assert(isDoubleReg(id->idReg3()));
486             }
487             else
488             {
489                 assert(id->idIns() == INS_vmov_i2d);
490                 assert(isDoubleReg(id->idReg1()));
491                 assert(isGeneralRegister(id->idReg2()));
492                 assert(isGeneralRegister(id->idReg3()));
493             }
494             break;
495
496         case IF_T2_VMOVS:
497             assert(id->idOpSize() == EA_4BYTE);
498             if (id->idIns() == INS_vmov_i2f)
499             {
500                 assert(isFloatReg(id->idReg1()));
501                 assert(isGeneralRegister(id->idReg2()));
502             }
503             else
504             {
505                 assert(id->idIns() == INS_vmov_f2i);
506                 assert(isGeneralRegister(id->idReg1()));
507                 assert(isFloatReg(id->idReg2()));
508             }
509             break;
510
511         default:
512             printf("unexpected format %s\n", emitIfName(id->idInsFmt()));
513             assert(!"Unexpected format");
514             break;
515     }
516 }
517 #endif // DEBUG
518
519 bool emitter::emitInsMayWriteToGCReg(instrDesc* id)
520 {
521     instruction ins = id->idIns();
522     insFormat   fmt = id->idInsFmt();
523
524     switch (fmt)
525     {
526
527         // These are the formats with "destination" or "target" registers:
528         case IF_T1_C:
529         case IF_T1_D0:
530         case IF_T1_E:
531         case IF_T1_G:
532         case IF_T1_H:
533         case IF_T1_J0:
534         case IF_T1_J1:
535         case IF_T1_J2:
536         case IF_T1_J3:
537         case IF_T2_C0:
538         case IF_T2_C1:
539         case IF_T2_C2:
540         case IF_T2_C3:
541         case IF_T2_C4:
542         case IF_T2_C5:
543         case IF_T2_C6:
544         case IF_T2_C10:
545         case IF_T2_D0:
546         case IF_T2_D1:
547         case IF_T2_F1:
548         case IF_T2_F2:
549         case IF_T2_L0:
550         case IF_T2_L1:
551         case IF_T2_M0:
552         case IF_T2_M1:
553         case IF_T2_N:
554         case IF_T2_N1:
555         case IF_T2_N2:
556         case IF_T2_N3:
557         case IF_T2_VFP3:
558         case IF_T2_VFP2:
559         case IF_T2_VLDST:
560         case IF_T2_E0:
561         case IF_T2_E1:
562         case IF_T2_E2:
563         case IF_T2_G0:
564         case IF_T2_G1:
565         case IF_T2_H0:
566         case IF_T2_H1:
567         case IF_T2_K1:
568         case IF_T2_K4:
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
574             // be
575             // be in this list because it has no forms matched above, but I'm putting it here for completeness.
576             switch (ins)
577             {
578                 case INS_str:
579                 case INS_strb:
580                 case INS_strh:
581                 case INS_strd:
582                 case INS_strex:
583                 case INS_strexb:
584                 case INS_strexd:
585                 case INS_strexh:
586                 case INS_push:
587                 case INS_cmp:
588                 case INS_cmn:
589                 case INS_tst:
590                 case INS_teq:
591                     return false;
592                 default:
593                     return true;
594             }
595         case IF_T2_VMOVS:
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);
600
601         case IF_T2_VMOVD:
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);
606
607         default:
608             return false;
609     }
610 }
611
612 bool emitter::emitInsWritesToLclVarStackLoc(instrDesc* id)
613 {
614     if (!id->idIsLclVar())
615         return false;
616
617     instruction ins = id->idIns();
618
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.
621
622     switch (ins)
623     {
624         case INS_strb:
625         case INS_strh:
626         case INS_str:
627             return true;
628         default:
629             return false;
630     }
631 }
632
633 bool emitter::emitInsMayWriteMultipleRegs(instrDesc* id)
634 {
635     instruction ins = id->idIns();
636
637     switch (ins)
638     {
639         case INS_ldm:
640         case INS_ldmdb:
641         case INS_pop:
642         case INS_smlal:
643         case INS_smull:
644         case INS_umlal:
645         case INS_umull:
646         case INS_vmov_d2i:
647             return true;
648         default:
649             return false;
650     }
651 }
652
653 /*****************************************************************************/
654 #ifdef DEBUG
655 /*****************************************************************************
656  *
657  *  Return a string that represents the given register.
658  */
659
660 const char* emitter::emitRegName(regNumber reg, emitAttr attr, bool varName)
661 {
662     assert(reg < REG_COUNT);
663
664     const char* rn = emitComp->compRegVarName(reg, varName, false);
665
666     assert(strlen(rn) >= 1);
667
668     return rn;
669 }
670
671 const char* emitter::emitFloatRegName(regNumber reg, emitAttr attr, bool varName)
672 {
673     assert(reg < REG_COUNT);
674
675     const char* rn = emitComp->compRegVarName(reg, varName, true);
676
677     assert(strlen(rn) >= 1);
678
679     return rn;
680 }
681 #endif // DEBUG
682
683 /*****************************************************************************
684  *
685  *  Returns the base encoding of the given CPU instruction.
686  */
687
688 emitter::insFormat emitter::emitInsFormat(instruction ins)
689 {
690     // clang-format off
691     const static insFormat insFormats[] =
692     {
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,
701         #include "instrs.h"
702     };
703     // clang-format on
704
705     assert(ins < ArrLen(insFormats));
706     assert((insFormats[ins] != IF_NONE));
707
708     return insFormats[ins];
709 }
710
711 // INST_FP is 1
712 #define LD 2
713 #define ST 4
714 #define CMP 8
715
716 // clang-format off
717 /*static*/ const BYTE CodeGenInterface::instInfo[] =
718 {
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,
727     #include "instrs.h"
728 };
729 // clang-format on
730
731 /*****************************************************************************
732  *
733  *  Returns true if the instruction is some kind of load instruction
734  */
735
736 bool emitter::emitInsIsLoad(instruction ins)
737 {
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;
741     else
742         return false;
743 }
744
745 /*****************************************************************************
746  *
747  *  Returns true if the instruction is some kind of compare or test instruction
748  */
749
750 bool emitter::emitInsIsCompare(instruction ins)
751 {
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;
755     else
756         return false;
757 }
758
759 /*****************************************************************************
760  *
761  *  Returns true if the instruction is some kind of store instruction
762  */
763
764 bool emitter::emitInsIsStore(instruction ins)
765 {
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;
769     else
770         return false;
771 }
772
773 /*****************************************************************************
774  *
775  *  Returns true if the instruction is some kind of load/store instruction
776  */
777
778 bool emitter::emitInsIsLoadOrStore(instruction ins)
779 {
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;
783     else
784         return false;
785 }
786
787 #undef LD
788 #undef ST
789 #undef CMP
790
791 /*****************************************************************************
792  *
793  *  Returns the specific encoding of the given CPU instruction and format
794  */
795
796 emitter::code_t emitter::emitInsCode(instruction ins, insFormat fmt)
797 {
798     // clang-format off
799     const static code_t insCodes1[] =
800     {
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,
809         #include "instrs.h"
810     };
811     const static code_t insCodes2[] =
812     {
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,
821         #include "instrs.h"
822     };
823     const static code_t insCodes3[] =
824     {
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,
833         #include "instrs.h"
834     };
835     const static code_t insCodes4[] =
836     {
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,
845         #include "instrs.h"
846     };
847     const static code_t insCodes5[] =
848     {
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,
857         #include "instrs.h"
858     };
859     const static code_t insCodes6[] =
860     {
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,
869         #include "instrs.h"
870     };
871     const static code_t insCodes7[] =
872     {
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,
881         #include "instrs.h"
882     };
883     const static code_t insCodes8[] =
884     {
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,
893         #include "instrs.h"
894     };
895     const static code_t insCodes9[] =
896     {
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,
905         #include "instrs.h"
906     };
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 };
928     // clang-format on
929
930     code_t    code   = BAD_CODE;
931     insFormat insFmt = emitInsFormat(ins);
932     bool      found  = false;
933     int       index  = 0;
934
935     switch (insFmt)
936     {
937         case IF_EN9:
938             for (index = 0; index < 9; index++)
939             {
940                 if (fmt == formatEncode9[index])
941                 {
942                     found = true;
943                     break;
944                 }
945             }
946             break;
947
948         case IF_EN8:
949             for (index = 0; index < 8; index++)
950             {
951                 if (fmt == formatEncode8[index])
952                 {
953                     found = true;
954                     break;
955                 }
956             }
957             break;
958
959         case IF_EN6A:
960             for (index = 0; index < 6; index++)
961             {
962                 if (fmt == formatEncode6A[index])
963                 {
964                     found = true;
965                     break;
966                 }
967             }
968             break;
969
970         case IF_EN6B:
971             for (index = 0; index < 6; index++)
972             {
973                 if (fmt == formatEncode6B[index])
974                 {
975                     found = true;
976                     break;
977                 }
978             }
979             break;
980
981         case IF_EN5A:
982             for (index = 0; index < 5; index++)
983             {
984                 if (fmt == formatEncode5A[index])
985                 {
986                     found = true;
987                     break;
988                 }
989             }
990             break;
991
992         case IF_EN5B:
993             for (index = 0; index < 5; index++)
994             {
995                 if (fmt == formatEncode5B[index])
996                 {
997                     found = true;
998                     break;
999                 }
1000             }
1001             break;
1002
1003         case IF_EN4A:
1004             for (index = 0; index < 4; index++)
1005             {
1006                 if (fmt == formatEncode4A[index])
1007                 {
1008                     found = true;
1009                     break;
1010                 }
1011             }
1012             break;
1013
1014         case IF_EN4B:
1015             for (index = 0; index < 4; index++)
1016             {
1017                 if (fmt == formatEncode4B[index])
1018                 {
1019                     found = true;
1020                     break;
1021                 }
1022             }
1023             break;
1024
1025         case IF_EN4C:
1026             for (index = 0; index < 4; index++)
1027             {
1028                 if (fmt == formatEncode4C[index])
1029                 {
1030                     found = true;
1031                     break;
1032                 }
1033             }
1034             break;
1035
1036         case IF_EN3A:
1037             for (index = 0; index < 3; index++)
1038             {
1039                 if (fmt == formatEncode3A[index])
1040                 {
1041                     found = true;
1042                     break;
1043                 }
1044             }
1045             break;
1046
1047         case IF_EN3B:
1048             for (index = 0; index < 3; index++)
1049             {
1050                 if (fmt == formatEncode3B[index])
1051                 {
1052                     found = true;
1053                     break;
1054                 }
1055             }
1056             break;
1057         case IF_EN3C:
1058             for (index = 0; index < 3; index++)
1059             {
1060                 if (fmt == formatEncode3C[index])
1061                 {
1062                     found = true;
1063                     break;
1064                 }
1065             }
1066             break;
1067         case IF_EN3D:
1068             for (index = 0; index < 3; index++)
1069             {
1070                 if (fmt == formatEncode3D[index])
1071                 {
1072                     found = true;
1073                     break;
1074                 }
1075             }
1076             break;
1077         case IF_EN3E:
1078             for (index = 0; index < 3; index++)
1079             {
1080                 if (fmt == formatEncode3E[index])
1081                 {
1082                     found = true;
1083                     break;
1084                 }
1085             }
1086             break;
1087
1088         case IF_EN2A:
1089             for (index = 0; index < 2; index++)
1090             {
1091                 if (fmt == formatEncode2A[index])
1092                 {
1093                     found = true;
1094                     break;
1095                 }
1096             }
1097             break;
1098         case IF_EN2B:
1099             for (index = 0; index < 2; index++)
1100             {
1101                 if (fmt == formatEncode2B[index])
1102                 {
1103                     found = true;
1104                     break;
1105                 }
1106             }
1107             break;
1108         case IF_EN2C:
1109             for (index = 0; index < 2; index++)
1110             {
1111                 if (fmt == formatEncode2C[index])
1112                 {
1113                     found = true;
1114                     break;
1115                 }
1116             }
1117             break;
1118         case IF_EN2D:
1119             for (index = 0; index < 2; index++)
1120             {
1121                 if (fmt == formatEncode2D[index])
1122                 {
1123                     found = true;
1124                     break;
1125                 }
1126             }
1127             break;
1128         case IF_EN2E:
1129             for (index = 0; index < 2; index++)
1130             {
1131                 if (fmt == formatEncode2E[index])
1132                 {
1133                     found = true;
1134                     break;
1135                 }
1136             }
1137             break;
1138         case IF_EN2F:
1139             for (index = 0; index < 2; index++)
1140             {
1141                 if (fmt == formatEncode2F[index])
1142                 {
1143                     found = true;
1144                     break;
1145                 }
1146             }
1147             break;
1148
1149         case IF_EN2G:
1150             for (index = 0; index < 2; index++)
1151             {
1152                 if (fmt == formatEncode2G[index])
1153                 {
1154                     found = true;
1155                     break;
1156                 }
1157             }
1158             break;
1159
1160         default:
1161             index = 0;
1162             found = true;
1163             break;
1164     }
1165
1166     assert(found);
1167
1168     switch (index)
1169     {
1170         case 0:
1171             assert(ins < ArrLen(insCodes1));
1172             code = insCodes1[ins];
1173             break;
1174         case 1:
1175             assert(ins < ArrLen(insCodes2));
1176             code = insCodes2[ins];
1177             break;
1178         case 2:
1179             assert(ins < ArrLen(insCodes3));
1180             code = insCodes3[ins];
1181             break;
1182         case 3:
1183             assert(ins < ArrLen(insCodes4));
1184             code = insCodes4[ins];
1185             break;
1186         case 4:
1187             assert(ins < ArrLen(insCodes5));
1188             code = insCodes5[ins];
1189             break;
1190         case 5:
1191             assert(ins < ArrLen(insCodes6));
1192             code = insCodes6[ins];
1193             break;
1194         case 6:
1195             assert(ins < ArrLen(insCodes7));
1196             code = insCodes7[ins];
1197             break;
1198         case 7:
1199             assert(ins < ArrLen(insCodes8));
1200             code = insCodes8[ins];
1201             break;
1202         case 8:
1203             assert(ins < ArrLen(insCodes9));
1204             code = insCodes9[ins];
1205             break;
1206     }
1207
1208     assert((code != BAD_CODE));
1209
1210     return code;
1211 }
1212
1213 /*****************************************************************************
1214  *
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.
1217  */
1218
1219 emitter::insSize emitter::emitInsSize(insFormat insFmt)
1220 {
1221     if ((insFmt >= IF_T1_A) && (insFmt < IF_T2_A))
1222         return ISZ_16BIT;
1223
1224     if ((insFmt >= IF_T2_A) && (insFmt < IF_INVALID))
1225         return ISZ_32BIT;
1226
1227     if (insFmt == IF_LARGEJMP)
1228         return ISZ_48BIT;
1229
1230     assert(!"Invalid insFormat");
1231     return ISZ_48BIT;
1232 }
1233
1234 /*****************************************************************************
1235  *
1236  *  isModImmConst() returns true when immediate 'val32' can be encoded
1237  *   using the special modified immediate constant available in Thumb
1238  */
1239
1240 /*static*/ bool emitter::isModImmConst(int val32)
1241 {
1242     unsigned uval32 = (unsigned)val32;
1243     unsigned imm8   = uval32 & 0xff;
1244
1245     /* encode = 0000x */
1246     if (imm8 == uval32)
1247         return true;
1248
1249     unsigned imm32a = (imm8 << 16) | imm8;
1250     /* encode = 0001x */
1251     if (imm32a == uval32)
1252         return true;
1253
1254     unsigned imm32b = (imm32a << 8);
1255     /* encode = 0010x */
1256     if (imm32b == uval32)
1257         return true;
1258
1259     unsigned imm32c = (imm32a | imm32b);
1260     /* encode = 0011x */
1261     if (imm32c == uval32)
1262         return true;
1263
1264     unsigned mask32 = 0x00000ff;
1265
1266     unsigned encode = 31; /* 11111 */
1267     unsigned temp;
1268
1269     do
1270     {
1271         mask32 <<= 1;
1272         temp = uval32 & ~mask32;
1273         if (temp == 0)
1274             return true;
1275         encode--;
1276     } while (encode >= 8);
1277
1278     return false;
1279 }
1280
1281 /*****************************************************************************
1282  *
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.
1286  */
1287
1288 /*static*/ int emitter::encodeModImmConst(int val32)
1289 {
1290     unsigned uval32 = (unsigned)val32;
1291     unsigned imm8   = uval32 & 0xff;
1292     unsigned encode = imm8 >> 7;
1293     unsigned imm32a;
1294     unsigned imm32b;
1295     unsigned imm32c;
1296     unsigned mask32;
1297     unsigned temp;
1298
1299     /* encode = 0000x */
1300     if (imm8 == uval32)
1301     {
1302         goto DONE;
1303     }
1304
1305     imm32a = (imm8 << 16) | imm8;
1306     /* encode = 0001x */
1307     if (imm32a == uval32)
1308     {
1309         encode += 2;
1310         goto DONE;
1311     }
1312
1313     imm32b = (imm32a << 8);
1314     /* encode = 0010x */
1315     if (imm32b == uval32)
1316     {
1317         encode += 4;
1318         goto DONE;
1319     }
1320
1321     imm32c = (imm32a | imm32b);
1322     /* encode = 0011x */
1323     if (imm32c == uval32)
1324     {
1325         encode += 6;
1326         goto DONE;
1327     }
1328
1329     mask32 = 0x00000ff;
1330
1331     encode = 31; /* 11111 */
1332     do
1333     {
1334         mask32 <<= 1;
1335         temp = uval32 & ~mask32;
1336         if (temp == 0)
1337         {
1338             imm8 = (uval32 & mask32) >> (32 - encode);
1339             assert((imm8 & 0x80) != 0);
1340             goto DONE;
1341         }
1342         encode--;
1343     } while (encode >= 8);
1344
1345     assert(!"encodeModImmConst failed!");
1346     return BAD_CODE;
1347
1348 DONE:
1349     unsigned result = (encode << 7) | (imm8 & 0x7f);
1350     assert(result <= 0x0fff);
1351     assert(result >= 0);
1352     return (int)result;
1353 }
1354
1355 /*****************************************************************************
1356  *
1357  *  emitIns_valid_imm_for_alu() returns true when the immediate 'imm'
1358  *   can be encoded using the 12-bit funky Arm immediate encoding
1359  */
1360 /*static*/ bool emitter::emitIns_valid_imm_for_alu(int imm)
1361 {
1362     if (isModImmConst(imm))
1363         return true;
1364     return false;
1365 }
1366
1367 /*****************************************************************************
1368  *
1369  *  emitIns_valid_imm_for_mov() returns true when the immediate 'imm'
1370  *   can be encoded using a single mov or mvn instruction.
1371  */
1372 /*static*/ bool emitter::emitIns_valid_imm_for_mov(int imm)
1373 {
1374     if ((imm & 0x0000ffff) == imm) // 16-bit immediate
1375         return true;
1376     if (isModImmConst(imm)) // funky arm immediate
1377         return true;
1378     if (isModImmConst(~imm)) // funky arm immediate via mvn
1379         return true;
1380     return false;
1381 }
1382
1383 /*****************************************************************************
1384  *
1385  *  emitIns_valid_imm_for_small_mov() returns true when the immediate 'imm'
1386  *   can be encoded using a single 2-byte mov instruction.
1387  */
1388 /*static*/ bool emitter::emitIns_valid_imm_for_small_mov(regNumber reg, int imm, insFlags flags)
1389 {
1390     return isLowRegister(reg) && insSetsFlags(flags) && ((imm & 0x00ff) == imm);
1391 }
1392
1393 /*****************************************************************************
1394  *
1395  *  emitins_valid_imm_for_add() returns true when the immediate 'imm'
1396  *   can be encoded using a single add or sub instruction.
1397  */
1398 /*static*/ bool emitter::emitIns_valid_imm_for_add(int imm, insFlags flags)
1399 {
1400     if ((unsigned_abs(imm) <= 0x00000fff) && (flags != INS_FLAGS_SET)) // 12-bit immediate via add/sub
1401         return true;
1402     if (isModImmConst(imm)) // funky arm immediate
1403         return true;
1404     if (isModImmConst(-imm)) // funky arm immediate via sub
1405         return true;
1406     return false;
1407 }
1408
1409 /*****************************************************************************
1410  *
1411  *  emitins_valid_imm_for_cmp() returns true if this 'imm'
1412  *   can be encoded as a input operand to an cmp instruction.
1413  */
1414 /*static*/ bool emitter::emitIns_valid_imm_for_cmp(int imm, insFlags flags)
1415 {
1416     if (isModImmConst(imm)) // funky arm immediate
1417         return true;
1418     if (isModImmConst(-imm)) // funky arm immediate via sub
1419         return true;
1420     return false;
1421 }
1422
1423 /*****************************************************************************
1424  *
1425  *  emitIns_valid_imm_for_add_sp() returns true when the immediate 'imm'
1426  *   can be encoded in "add Rd,SP,i10".
1427  */
1428 /*static*/ bool emitter::emitIns_valid_imm_for_add_sp(int imm)
1429 {
1430     if ((imm & 0x03fc) == imm)
1431         return true;
1432     return false;
1433 }
1434
1435 /*****************************************************************************
1436  *
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.
1439  */
1440 /*static*/ bool emitter::emitIns_valid_imm_for_ldst_offset(int imm, emitAttr size)
1441 {
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
1446     return false;
1447 }
1448
1449 /*****************************************************************************
1450  *
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.
1454  */
1455 /*static*/ bool emitter::emitIns_valid_imm_for_vldst_offset(int imm)
1456 {
1457     if ((imm & 0x3fc) == imm)
1458         return true;
1459     return false;
1460 }
1461
1462 /*****************************************************************************
1463  *
1464  *  Add an instruction with no operands.
1465  */
1466
1467 void emitter::emitIns(instruction ins)
1468 {
1469     instrDesc* id  = emitNewInstrSmall(EA_4BYTE);
1470     insFormat  fmt = emitInsFormat(ins);
1471     insSize    isz = emitInsSize(fmt);
1472
1473     assert((fmt == IF_T1_A) || (fmt == IF_T2_A));
1474
1475     id->idIns(ins);
1476     id->idInsFmt(fmt);
1477     id->idInsSize(isz);
1478
1479     dispIns(id);
1480     appendToCurIG(id);
1481 }
1482
1483 /*****************************************************************************
1484  *
1485  *  Add an instruction with a single immediate value.
1486  */
1487
1488 void emitter::emitIns_I(instruction ins, emitAttr attr, target_ssize_t imm)
1489 {
1490     insFormat fmt    = IF_NONE;
1491     bool      hasLR  = false;
1492     bool      hasPC  = false;
1493     bool      useT2  = false;
1494     bool      onlyT1 = false;
1495
1496     /* Figure out the encoding format of the instruction */
1497     switch (ins)
1498     {
1499 #ifdef FEATURE_ITINSTRUCTION
1500         case INS_it:
1501         case INS_itt:
1502         case INS_ite:
1503         case INS_ittt:
1504         case INS_itte:
1505         case INS_itet:
1506         case INS_itee:
1507         case INS_itttt:
1508         case INS_ittte:
1509         case INS_ittet:
1510         case INS_ittee:
1511         case INS_itett:
1512         case INS_itete:
1513         case INS_iteet:
1514         case INS_iteee:
1515             assert((imm & 0x0F) == imm);
1516             fmt  = IF_T1_B;
1517             attr = EA_4BYTE;
1518             break;
1519 #endif // FEATURE_ITINSTRUCTION
1520
1521         case INS_push:
1522             assert((imm & 0xA000) == 0); // Cannot push PC or SP
1523
1524             if (imm & 0x4000) // Is the LR being pushed?
1525                 hasLR = true;
1526
1527             goto COMMON_PUSH_POP;
1528
1529         case INS_pop:
1530             assert((imm & 0x2000) == 0);      // Cannot pop SP
1531             assert((imm & 0xC000) != 0xC000); // Cannot pop both PC and LR
1532
1533             if (imm & 0x8000) // Is the PC being popped?
1534                 hasPC = true;
1535             if (imm & 0x4000) // Is the LR being popped?
1536             {
1537                 hasLR = true;
1538                 useT2 = true;
1539             }
1540
1541         COMMON_PUSH_POP:
1542
1543             if (((imm - 1) & imm) == 0) // Is only one or zero bits set in imm?
1544             {
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
1547                 {
1548                     onlyT1 = true; // if only one bit is set we must use the T1 encoding
1549                 }
1550             }
1551
1552             imm &= ~0xE000; // ensure that PC, LR and SP bits are removed from imm
1553
1554             if (((imm & 0x00ff) == imm) && !useT2)
1555             {
1556                 fmt = IF_T1_L1;
1557             }
1558             else if (!onlyT1)
1559             {
1560                 fmt = IF_T2_I1;
1561             }
1562             else
1563             {
1564                 // We have to use the Thumb-2 push single register encoding
1565                 regNumber reg = genRegNumFromMask(imm);
1566                 emitIns_R(ins, attr, reg);
1567                 return;
1568             }
1569
1570             //
1571             // Encode the PC and LR bits as the lowest two bits
1572             //
1573             imm <<= 2;
1574             if (hasPC)
1575                 imm |= 2;
1576             if (hasLR)
1577                 imm |= 1;
1578
1579             assert(imm != 0);
1580
1581             break;
1582
1583 #if 0
1584     // TODO-ARM-Cleanup: Enable or delete.
1585     case INS_bkpt:   // Windows uses a different encoding
1586         if ((imm & 0x0000ffff) == imm)
1587         {
1588             fmt = IF_T1_L0;
1589         }
1590         else
1591         {
1592             assert(!"Instruction cannot be encoded");
1593         }
1594         break;
1595 #endif
1596
1597         case INS_dmb:
1598         case INS_ism:
1599             if ((imm & 0x000f) == imm)
1600             {
1601                 fmt  = IF_T2_B;
1602                 attr = EA_4BYTE;
1603             }
1604             else
1605             {
1606                 assert(!"Instruction cannot be encoded");
1607             }
1608             break;
1609
1610         default:
1611             unreached();
1612     }
1613     assert((fmt == IF_T1_B) || (fmt == IF_T1_L0) || (fmt == IF_T1_L1) || (fmt == IF_T2_I1) || (fmt == IF_T2_B));
1614
1615     instrDesc* id  = emitNewInstrSC(attr, imm);
1616     insSize    isz = emitInsSize(fmt);
1617
1618     id->idIns(ins);
1619     id->idInsFmt(fmt);
1620     id->idInsSize(isz);
1621
1622     dispIns(id);
1623     appendToCurIG(id);
1624 }
1625
1626 /*****************************************************************************
1627  *
1628  *  Add an instruction referencing a single register.
1629  */
1630
1631 void emitter::emitIns_R(instruction ins, emitAttr attr, regNumber reg)
1632 {
1633     emitAttr  size = EA_SIZE(attr);
1634     insFormat fmt  = IF_NONE;
1635
1636     /* Figure out the encoding format of the instruction */
1637     switch (ins)
1638     {
1639         case INS_pop:
1640         case INS_push:
1641             if (isLowRegister(reg))
1642             {
1643                 int regmask = 1 << ((int)reg);
1644                 emitIns_I(ins, attr, regmask);
1645                 return;
1646             }
1647             assert(size == EA_PTRSIZE);
1648             fmt = IF_T2_E2;
1649             break;
1650
1651         case INS_vmrs:
1652             assert(size == EA_PTRSIZE);
1653             fmt = IF_T2_E2;
1654             break;
1655
1656         case INS_bx:
1657             assert(size == EA_PTRSIZE);
1658             fmt = IF_T1_D1;
1659             break;
1660         case INS_rsb:
1661         case INS_mvn:
1662             emitIns_R_R_I(ins, attr, reg, reg, 0);
1663             return;
1664
1665         default:
1666             unreached();
1667     }
1668     assert((fmt == IF_T1_D1) || (fmt == IF_T2_E2));
1669
1670     instrDesc* id  = emitNewInstrSmall(attr);
1671     insSize    isz = emitInsSize(fmt);
1672
1673     id->idIns(ins);
1674     id->idInsFmt(fmt);
1675     id->idInsSize(isz);
1676     id->idReg1(reg);
1677
1678     dispIns(id);
1679     appendToCurIG(id);
1680 }
1681
1682 /*****************************************************************************
1683  *
1684  *  Add an instruction referencing a register and a constant.
1685  */
1686
1687 void emitter::emitIns_R_I(
1688     instruction ins, emitAttr attr, regNumber reg, target_ssize_t imm, insFlags flags /* = INS_FLAGS_DONT_CARE */)
1689
1690 {
1691     insFormat fmt = IF_NONE;
1692     insFlags  sf  = INS_FLAGS_DONT_CARE;
1693
1694     /* Figure out the encoding format of the instruction */
1695     switch (ins)
1696     {
1697         case INS_add:
1698         case INS_sub:
1699             if ((reg == REG_SP) && insDoesNotSetFlags(flags) && ((imm & 0x01fc) == imm))
1700             {
1701                 fmt = IF_T1_F;
1702                 sf  = INS_FLAGS_NOT_SET;
1703             }
1704             else if (isLowRegister(reg) && insSetsFlags(flags) && (unsigned_abs(imm) <= 0x00ff))
1705             {
1706                 if (imm < 0)
1707                 {
1708                     assert((ins == INS_add) || (ins == INS_sub));
1709                     if (ins == INS_add)
1710                         ins = INS_sub;
1711                     else // ins == INS_sub
1712                         ins = INS_add;
1713                     imm     = -imm;
1714                 }
1715                 fmt = IF_T1_J0;
1716                 sf  = INS_FLAGS_SET;
1717             }
1718             else
1719             {
1720                 // otherwise we have to use a Thumb-2 encoding
1721                 emitIns_R_R_I(ins, attr, reg, reg, imm, flags);
1722                 return;
1723             }
1724             break;
1725
1726         case INS_adc:
1727             emitIns_R_R_I(ins, attr, reg, reg, imm, flags);
1728             return;
1729
1730         case INS_vpush:
1731         case INS_vpop:
1732             assert(imm > 0);
1733             if (attr == EA_8BYTE)
1734             {
1735                 assert(isDoubleReg(reg));
1736                 assert(imm <= 16);
1737                 imm *= 2;
1738             }
1739             else
1740             {
1741                 assert(attr == EA_4BYTE);
1742                 assert(isFloatReg(reg));
1743                 assert(imm <= 16);
1744             }
1745             assert(((reg - REG_F0) + imm) <= 32);
1746             imm *= 4;
1747
1748             if (ins == INS_vpush)
1749                 imm = -imm;
1750
1751             sf  = INS_FLAGS_NOT_SET;
1752             fmt = IF_T2_VLDST;
1753             break;
1754
1755         case INS_stm:
1756         {
1757             sf = INS_FLAGS_NOT_SET;
1758
1759             bool hasLR  = false;
1760             bool hasPC  = false;
1761             bool useT2  = false;
1762             bool onlyT1 = false;
1763
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
1767
1768             if (imm & 0x8000) // Is the PC being popped?
1769                 hasPC = true;
1770
1771             if (imm & 0x4000) // Is the LR being pushed?
1772             {
1773                 hasLR = true;
1774                 useT2 = true;
1775             }
1776
1777             if (!isLowRegister(reg))
1778                 useT2 = true;
1779
1780             if (((imm - 1) & imm) == 0) // Is only one or zero bits set in imm?
1781             {
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
1784                 {
1785                     onlyT1 = true; // if only one bit is set we must use the T1 encoding
1786                 }
1787             }
1788
1789             imm &= ~0xE000; // ensure that PC, LR and SP bits are removed from imm
1790
1791             if (((imm & 0x00ff) == imm) && !useT2)
1792             {
1793                 fmt = IF_T1_J1;
1794             }
1795             else if (!onlyT1)
1796             {
1797                 fmt = IF_T2_I0;
1798             }
1799             else
1800             {
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);
1805                 return;
1806             }
1807
1808             //
1809             // Encode the PC and LR bits as the lowest two bits
1810             //
1811             if (fmt == IF_T2_I0)
1812             {
1813                 imm <<= 2;
1814                 if (hasPC)
1815                     imm |= 2;
1816                 if (hasLR)
1817                     imm |= 1;
1818             }
1819             assert(imm != 0);
1820         }
1821         break;
1822
1823         case INS_and:
1824         case INS_bic:
1825         case INS_eor:
1826         case INS_orr:
1827         case INS_orn:
1828         case INS_rsb:
1829         case INS_sbc:
1830
1831         case INS_ror:
1832         case INS_asr:
1833         case INS_lsl:
1834         case INS_lsr:
1835             // use the Reg, Reg, Imm encoding
1836             emitIns_R_R_I(ins, attr, reg, reg, imm, flags);
1837             return;
1838
1839         case INS_mov:
1840             assert(!EA_IS_CNS_RELOC(attr));
1841
1842             if (isLowRegister(reg) && insSetsFlags(flags) && ((imm & 0x00ff) == imm))
1843             {
1844                 fmt = IF_T1_J0;
1845                 sf  = INS_FLAGS_SET;
1846             }
1847             else if (isModImmConst(imm))
1848             {
1849                 fmt = IF_T2_L1;
1850                 sf  = insMustSetFlags(flags);
1851             }
1852             else if (isModImmConst(~imm)) // See if we can use move negated instruction instead
1853             {
1854                 ins = INS_mvn;
1855                 imm = ~imm;
1856                 fmt = IF_T2_L1;
1857                 sf  = insMustSetFlags(flags);
1858             }
1859             else if (insDoesNotSetFlags(flags) && ((imm & 0x0000ffff) == imm))
1860             {
1861                 // mov => movw instruction
1862                 ins = INS_movw;
1863                 fmt = IF_T2_N;
1864                 sf  = INS_FLAGS_NOT_SET;
1865             }
1866             else
1867             {
1868                 assert(!"Instruction cannot be encoded");
1869             }
1870             break;
1871
1872         case INS_movw:
1873         case INS_movt:
1874             assert(!EA_IS_RELOC(attr));
1875             assert(insDoesNotSetFlags(flags));
1876
1877             if ((imm & 0x0000ffff) == imm)
1878             {
1879                 fmt = IF_T2_N;
1880                 sf  = INS_FLAGS_NOT_SET;
1881             }
1882             else
1883             {
1884                 assert(!"Instruction cannot be encoded");
1885             }
1886             break;
1887
1888         case INS_mvn:
1889             if (isModImmConst(imm))
1890             {
1891                 fmt = IF_T2_L1;
1892                 sf  = insMustSetFlags(flags);
1893             }
1894             else
1895             {
1896                 assert(!"Instruction cannot be encoded");
1897             }
1898             break;
1899
1900         case INS_cmp:
1901             assert(!EA_IS_CNS_RELOC(attr));
1902             assert(insSetsFlags(flags));
1903             sf = INS_FLAGS_SET;
1904             if (isLowRegister(reg) && ((imm & 0x0ff) == imm))
1905             {
1906                 fmt = IF_T1_J0;
1907             }
1908             else if (isModImmConst(imm))
1909             {
1910                 fmt = IF_T2_L2;
1911             }
1912             else if (isModImmConst(-imm))
1913             {
1914                 ins = INS_cmn;
1915                 fmt = IF_T2_L2;
1916                 imm = -imm;
1917             }
1918             else
1919             {
1920                 assert(!"emitIns_R_I: immediate doesn't fit into the instruction");
1921                 return;
1922             }
1923             break;
1924
1925         case INS_cmn:
1926         case INS_tst:
1927         case INS_teq:
1928             assert(insSetsFlags(flags));
1929             sf = INS_FLAGS_SET;
1930             if (isModImmConst(imm))
1931             {
1932                 fmt = IF_T2_L2;
1933             }
1934             else
1935             {
1936                 assert(!"Instruction cannot be encoded");
1937             }
1938             break;
1939
1940 #ifdef FEATURE_PLI_INSTRUCTION
1941         case INS_pli:
1942             assert(insDoesNotSetFlags(flags));
1943             if ((reg == REG_SP) && (unsigned_abs(imm) <= 0x0fff))
1944             {
1945                 fmt = IF_T2_K3;
1946                 sf  = INS_FLAGS_NOT_SET;
1947             }
1948             __fallthrough;
1949 #endif // FEATURE_PLI_INSTRUCTION
1950
1951         case INS_pld:
1952         case INS_pldw:
1953             assert(insDoesNotSetFlags(flags));
1954             sf = INS_FLAGS_NOT_SET;
1955             if ((imm >= 0) && (imm <= 0x0fff))
1956             {
1957                 fmt = IF_T2_K2;
1958             }
1959             else if ((imm < 0) && (-imm <= 0x00ff))
1960             {
1961                 imm = -imm;
1962                 fmt = IF_T2_H2;
1963             }
1964             else
1965             {
1966                 assert(!"Instruction cannot be encoded");
1967             }
1968             break;
1969
1970         default:
1971             unreached();
1972     }
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));
1976
1977     assert(sf != INS_FLAGS_DONT_CARE);
1978
1979     instrDesc* id  = emitNewInstrSC(attr, imm);
1980     insSize    isz = emitInsSize(fmt);
1981
1982     id->idIns(ins);
1983     id->idInsFmt(fmt);
1984     id->idInsSize(isz);
1985     id->idInsFlags(sf);
1986     id->idReg1(reg);
1987
1988     dispIns(id);
1989     appendToCurIG(id);
1990 }
1991
1992 void emitter::emitIns_MovRelocatableImmediate(instruction ins, emitAttr attr, regNumber reg, BYTE* addr)
1993 {
1994     assert(EA_IS_RELOC(attr));
1995     assert((ins == INS_movw) || (ins == INS_movt));
1996
1997     insFormat fmt = IF_T2_N3;
1998     insFlags  sf  = INS_FLAGS_NOT_SET;
1999
2000     instrDesc* id  = emitNewInstrReloc(attr, addr);
2001     insSize    isz = emitInsSize(fmt);
2002
2003     id->idIns(ins);
2004     id->idInsFmt(fmt);
2005     id->idInsSize(isz);
2006     id->idInsFlags(sf);
2007     id->idReg1(reg);
2008
2009     dispIns(id);
2010     appendToCurIG(id);
2011 }
2012
2013 /*****************************************************************************
2014  *
2015  *  Add an instruction referencing two registers
2016  */
2017
2018 void emitter::emitIns_R_R(
2019     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insFlags flags /* = INS_FLAGS_DONT_CARE */)
2020
2021 {
2022     emitAttr  size = EA_SIZE(attr);
2023     insFormat fmt  = IF_NONE;
2024     insFlags  sf   = INS_FLAGS_DONT_CARE;
2025
2026     /* Figure out the encoding format of the instruction */
2027     switch (ins)
2028     {
2029         case INS_add:
2030             if (insDoesNotSetFlags(flags))
2031             {
2032                 fmt = IF_T1_D0;
2033                 sf  = INS_FLAGS_NOT_SET;
2034                 break;
2035             }
2036             __fallthrough;
2037
2038         case INS_sub:
2039             // Use the Thumb-1 reg,reg,reg encoding
2040             emitIns_R_R_R(ins, attr, reg1, reg1, reg2, flags);
2041             return;
2042
2043         case INS_mov:
2044             if (insDoesNotSetFlags(flags))
2045             {
2046                 assert(reg1 != reg2);
2047                 fmt = IF_T1_D0;
2048                 sf  = INS_FLAGS_NOT_SET;
2049             }
2050             else // insSetsFlags(flags)
2051             {
2052                 sf = INS_FLAGS_SET;
2053                 if (isLowRegister(reg1) && isLowRegister(reg2))
2054                 {
2055                     fmt = IF_T1_E;
2056                 }
2057                 else
2058                 {
2059                     fmt = IF_T2_C3;
2060                 }
2061             }
2062             break;
2063
2064         case INS_cmp:
2065             assert(insSetsFlags(flags));
2066             sf = INS_FLAGS_SET;
2067             if (isLowRegister(reg1) && isLowRegister(reg2))
2068             {
2069                 fmt = IF_T1_E; // both are low registers
2070             }
2071             else
2072             {
2073                 fmt = IF_T1_D0; // one or both are high registers
2074             }
2075             break;
2076
2077         case INS_vmov_f2i:
2078             assert(isGeneralRegister(reg1));
2079             assert(isFloatReg(reg2));
2080             fmt = IF_T2_VMOVS;
2081             sf  = INS_FLAGS_NOT_SET;
2082             break;
2083
2084         case INS_vmov_i2f:
2085             assert(isFloatReg(reg1));
2086             assert(isGeneralRegister(reg2));
2087             fmt = IF_T2_VMOVS;
2088             sf  = INS_FLAGS_NOT_SET;
2089             break;
2090
2091         case INS_vcvt_d2i:
2092         case INS_vcvt_d2u:
2093         case INS_vcvt_d2f:
2094             assert(isFloatReg(reg1));
2095             assert(isDoubleReg(reg2));
2096             goto VCVT_COMMON;
2097
2098         case INS_vcvt_f2d:
2099         case INS_vcvt_u2d:
2100         case INS_vcvt_i2d:
2101             assert(isDoubleReg(reg1));
2102             assert(isFloatReg(reg2));
2103             goto VCVT_COMMON;
2104
2105         case INS_vcvt_u2f:
2106         case INS_vcvt_i2f:
2107         case INS_vcvt_f2i:
2108         case INS_vcvt_f2u:
2109             assert(size == EA_4BYTE);
2110             assert(isFloatReg(reg1));
2111             assert(isFloatReg(reg2));
2112             goto VCVT_COMMON;
2113
2114         case INS_vmov:
2115             assert(reg1 != reg2);
2116             __fallthrough;
2117
2118         case INS_vabs:
2119         case INS_vsqrt:
2120         case INS_vcmp:
2121         case INS_vneg:
2122             if (size == EA_8BYTE)
2123             {
2124                 assert(isDoubleReg(reg1));
2125                 assert(isDoubleReg(reg2));
2126             }
2127             else
2128             {
2129                 assert(isFloatReg(reg1));
2130                 assert(isFloatReg(reg2));
2131             }
2132             __fallthrough;
2133
2134         VCVT_COMMON:
2135             fmt = IF_T2_VFP2;
2136             sf  = INS_FLAGS_NOT_SET;
2137             break;
2138
2139         case INS_vadd:
2140         case INS_vmul:
2141         case INS_vsub:
2142         case INS_vdiv:
2143             emitIns_R_R_R(ins, attr, reg1, reg1, reg2);
2144             return;
2145
2146         case INS_vldr:
2147         case INS_vstr:
2148         case INS_ldr:
2149         case INS_ldrb:
2150         case INS_ldrsb:
2151         case INS_ldrh:
2152         case INS_ldrsh:
2153
2154         case INS_str:
2155         case INS_strb:
2156         case INS_strh:
2157             emitIns_R_R_I(ins, attr, reg1, reg2, 0);
2158             return;
2159
2160         case INS_adc:
2161         case INS_and:
2162         case INS_bic:
2163         case INS_eor:
2164         case INS_orr:
2165         case INS_sbc:
2166             if (insSetsFlags(flags) && isLowRegister(reg1) && isLowRegister(reg2))
2167             {
2168                 fmt = IF_T1_E;
2169                 sf  = INS_FLAGS_SET;
2170                 break;
2171             }
2172             __fallthrough;
2173
2174         case INS_orn:
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);
2181             return;
2182
2183         case INS_asr:
2184         case INS_lsl:
2185         case INS_lsr:
2186         case INS_ror:
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))
2192             {
2193                 fmt = IF_T1_E;
2194                 sf  = INS_FLAGS_SET;
2195             }
2196             else
2197             {
2198                 // Use the Thumb-2 three register encoding
2199                 emitIns_R_R_R(ins, attr, reg1, reg1, reg2, flags);
2200                 return;
2201             }
2202             break;
2203
2204         case INS_mul:
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
2207             //
2208             if (insMustSetFlags(flags) && isLowRegister(reg1) && isLowRegister(reg2))
2209             {
2210                 fmt = IF_T1_E;
2211                 sf  = INS_FLAGS_SET;
2212             }
2213             else
2214             {
2215                 // Use the Thumb-2 three register encoding
2216                 emitIns_R_R_R(ins, attr, reg1, reg2, reg1, flags);
2217                 return;
2218             }
2219             break;
2220
2221         case INS_mvn:
2222         case INS_cmn:
2223         case INS_tst:
2224             if (insSetsFlags(flags) && isLowRegister(reg1) && isLowRegister(reg2))
2225             {
2226                 fmt = IF_T1_E;
2227                 sf  = INS_FLAGS_SET;
2228             }
2229             else
2230             {
2231                 // Use the Thumb-2 register with shift encoding
2232                 emitIns_R_R_I(ins, attr, reg1, reg2, 0, flags);
2233                 return;
2234             }
2235             break;
2236
2237         case INS_sxtb:
2238         case INS_uxtb:
2239             assert(size == EA_4BYTE);
2240             goto EXTEND_COMMON;
2241
2242         case INS_sxth:
2243         case INS_uxth:
2244             assert(size == EA_4BYTE);
2245         EXTEND_COMMON:
2246             assert(insDoesNotSetFlags(flags));
2247             if (isLowRegister(reg1) && isLowRegister(reg2))
2248             {
2249                 fmt = IF_T1_E;
2250                 sf  = INS_FLAGS_NOT_SET;
2251             }
2252             else
2253             {
2254                 // Use the Thumb-2 reg,reg with rotation encoding
2255                 emitIns_R_R_I(ins, attr, reg1, reg2, 0, INS_FLAGS_NOT_SET);
2256                 return;
2257             }
2258             break;
2259
2260         case INS_tbb:
2261             assert(size == EA_1BYTE);
2262             assert(insDoesNotSetFlags(flags));
2263             fmt = IF_T2_C9;
2264             sf  = INS_FLAGS_NOT_SET;
2265             break;
2266
2267         case INS_tbh:
2268             assert(size == EA_2BYTE);
2269             assert(insDoesNotSetFlags(flags));
2270             fmt = IF_T2_C9;
2271             sf  = INS_FLAGS_NOT_SET;
2272             break;
2273
2274         case INS_clz:
2275             assert(insDoesNotSetFlags(flags));
2276             fmt = IF_T2_C10;
2277             sf  = INS_FLAGS_NOT_SET;
2278             break;
2279
2280         case INS_ldrexb:
2281         case INS_strexb:
2282             assert(size == EA_1BYTE);
2283             assert(insDoesNotSetFlags(flags));
2284             fmt = IF_T2_E1;
2285             sf  = INS_FLAGS_NOT_SET;
2286             break;
2287
2288         case INS_ldrexh:
2289         case INS_strexh:
2290             assert(size == EA_2BYTE);
2291             assert(insDoesNotSetFlags(flags));
2292             fmt = IF_T2_E1;
2293             sf  = INS_FLAGS_NOT_SET;
2294             break;
2295         default:
2296 #ifdef DEBUG
2297             printf("did not expect instruction %s\n", codeGen->genInsName(ins));
2298 #endif
2299             unreached();
2300     }
2301
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));
2304
2305     assert(sf != INS_FLAGS_DONT_CARE);
2306
2307     instrDesc* id  = emitNewInstrSmall(attr);
2308     insSize    isz = emitInsSize(fmt);
2309
2310     id->idIns(ins);
2311     id->idInsFmt(fmt);
2312     id->idInsSize(isz);
2313     id->idInsFlags(sf);
2314     id->idReg1(reg1);
2315     id->idReg2(reg2);
2316
2317     dispIns(id);
2318     appendToCurIG(id);
2319 }
2320
2321 /*****************************************************************************
2322  *
2323  *  Add an instruction referencing a register and two constants.
2324  */
2325
2326 void emitter::emitIns_R_I_I(
2327     instruction ins, emitAttr attr, regNumber reg, int imm1, int imm2, insFlags flags /* = INS_FLAGS_DONT_CARE */)
2328
2329 {
2330     insFormat fmt = IF_NONE;
2331     insFlags  sf  = INS_FLAGS_DONT_CARE;
2332     int       imm = 0; // combined immediates
2333
2334     /* Figure out the encoding format of the instruction */
2335     switch (ins)
2336     {
2337         case INS_bfc:
2338         {
2339             int lsb = imm1;
2340             int msb = lsb + imm2 - 1;
2341
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
2345
2346             imm = (lsb << 5) | msb;
2347
2348             assert(insDoesNotSetFlags(flags));
2349             fmt = IF_T2_D1;
2350             sf  = INS_FLAGS_NOT_SET;
2351         }
2352         break;
2353
2354         default:
2355             unreached();
2356     }
2357     assert(fmt == IF_T2_D1);
2358     assert(sf != INS_FLAGS_DONT_CARE);
2359
2360     instrDesc* id  = emitNewInstrSC(attr, imm);
2361     insSize    isz = emitInsSize(fmt);
2362
2363     id->idIns(ins);
2364     id->idInsFmt(fmt);
2365     id->idInsSize(isz);
2366     id->idInsFlags(sf);
2367     id->idReg1(reg);
2368
2369     dispIns(id);
2370     appendToCurIG(id);
2371 }
2372
2373 /*****************************************************************************
2374  *
2375  *  Add an instruction referencing two registers and a constant.
2376  */
2377
2378 void emitter::emitIns_R_R_I(instruction ins,
2379                             emitAttr    attr,
2380                             regNumber   reg1,
2381                             regNumber   reg2,
2382                             int         imm,
2383                             insFlags    flags /* = INS_FLAGS_DONT_CARE */,
2384                             insOpts     opt /* = INS_OPTS_NONE */)
2385 {
2386     emitAttr  size = EA_SIZE(attr);
2387     insFormat fmt  = IF_NONE;
2388     insFlags  sf   = INS_FLAGS_DONT_CARE;
2389
2390     if (ins == INS_lea)
2391     {
2392         ins = INS_add;
2393     }
2394
2395     /* Figure out the encoding format of the instruction */
2396     switch (ins)
2397     {
2398         case INS_add:
2399             assert(insOptsNone(opt));
2400
2401             // Can we possibly encode the immediate 'imm' using a Thumb-1 encoding?
2402             if ((reg2 == REG_SP) && insDoesNotSetFlags(flags) && ((imm & 0x03fc) == imm))
2403             {
2404                 if ((reg1 == REG_SP) && ((imm & 0x01fc) == imm))
2405                 {
2406                     // Use Thumb-1 encoding
2407                     emitIns_R_I(ins, attr, reg1, imm, flags);
2408                     return;
2409                 }
2410                 else if (isLowRegister(reg1))
2411                 {
2412                     fmt = IF_T1_J2;
2413                     sf  = INS_FLAGS_NOT_SET;
2414                     break;
2415                 }
2416             }
2417             __fallthrough;
2418
2419         case INS_sub:
2420             assert(insOptsNone(opt));
2421
2422             // Is it just a mov?
2423             if ((imm == 0) && insDoesNotSetFlags(flags))
2424             {
2425                 // Is the mov even necessary?
2426                 // Fix 383915 ARM ILGEN
2427                 if (reg1 != reg2)
2428                 {
2429                     emitIns_R_R(INS_mov, attr, reg1, reg2, flags);
2430                 }
2431                 return;
2432             }
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))
2435             {
2436                 if (imm < 0)
2437                 {
2438                     assert((ins == INS_add) || (ins == INS_sub));
2439                     if (ins == INS_add)
2440                         ins = INS_sub;
2441                     else
2442                         ins = INS_add;
2443                     imm     = -imm;
2444                 }
2445                 fmt = IF_T1_G;
2446                 sf  = INS_FLAGS_SET;
2447             }
2448             else if ((reg1 == reg2) && isLowRegister(reg1) && insSetsFlags(flags) && (unsigned_abs(imm) <= 0x00ff))
2449             {
2450                 if (imm < 0)
2451                 {
2452                     assert((ins == INS_add) || (ins == INS_sub));
2453                     if (ins == INS_add)
2454                         ins = INS_sub;
2455                     else
2456                         ins = INS_add;
2457                     imm     = -imm;
2458                 }
2459                 // Use Thumb-1 encoding
2460                 emitIns_R_I(ins, attr, reg1, imm, flags);
2461                 return;
2462             }
2463             else if (isModImmConst(imm))
2464             {
2465                 fmt = IF_T2_L0;
2466                 sf  = insMustSetFlags(flags);
2467             }
2468             else if (isModImmConst(-imm))
2469             {
2470                 assert((ins == INS_add) || (ins == INS_sub));
2471                 ins = (ins == INS_add) ? INS_sub : INS_add;
2472                 imm = -imm;
2473                 fmt = IF_T2_L0;
2474                 sf  = insMustSetFlags(flags);
2475             }
2476             else if (insDoesNotSetFlags(flags) && (unsigned_abs(imm) <= 0x0fff))
2477             {
2478                 if (imm < 0)
2479                 {
2480                     assert((ins == INS_add) || (ins == INS_sub));
2481                     ins = (ins == INS_add) ? INS_sub : INS_add;
2482                     imm = -imm;
2483                 }
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;
2487                 fmt = IF_T2_M0;
2488                 sf  = INS_FLAGS_NOT_SET;
2489             }
2490             else if (insDoesNotSetFlags(flags) && (reg1 != REG_SP) && (reg1 != REG_PC))
2491             {
2492                 // movw,movt reg1, imm
2493                 codeGen->instGen_Set_Reg_To_Imm(attr, reg1, (ins == INS_sub ? -1 : 1) * imm);
2494
2495                 // ins reg1, reg2
2496                 emitIns_R_R(INS_add, attr, reg1, reg2);
2497
2498                 return;
2499             }
2500             else
2501             {
2502                 assert(!"Instruction cannot be encoded");
2503             }
2504             break;
2505
2506         case INS_and:
2507         case INS_bic:
2508         case INS_orr:
2509         case INS_orn:
2510             assert(insOptsNone(opt));
2511             if (isModImmConst(imm))
2512             {
2513                 fmt = IF_T2_L0;
2514                 sf  = insMustSetFlags(flags);
2515             }
2516             else if (isModImmConst(~imm))
2517             {
2518                 fmt = IF_T2_L0;
2519                 sf  = insMustSetFlags(flags);
2520                 imm = ~imm;
2521
2522                 if (ins == INS_and)
2523                     ins = INS_bic;
2524                 else if (ins == INS_bic)
2525                     ins = INS_and;
2526                 else if (ins == INS_orr)
2527                     ins = INS_orn;
2528                 else if (ins == INS_orn)
2529                     ins = INS_orr;
2530                 else
2531                     assert(!"Instruction cannot be encoded");
2532             }
2533             else
2534             {
2535                 assert(!"Instruction cannot be encoded");
2536             }
2537             break;
2538
2539         case INS_rsb:
2540             assert(insOptsNone(opt));
2541             if (imm == 0 && isLowRegister(reg1) && isLowRegister(reg2) && insSetsFlags(flags))
2542             {
2543                 fmt = IF_T1_E;
2544                 sf  = INS_FLAGS_SET;
2545                 break;
2546             }
2547             __fallthrough;
2548
2549         case INS_adc:
2550         case INS_eor:
2551         case INS_sbc:
2552             assert(insOptsNone(opt));
2553             if (isModImmConst(imm))
2554             {
2555                 fmt = IF_T2_L0;
2556                 sf  = insMustSetFlags(flags);
2557             }
2558             else
2559             {
2560                 assert(!"Instruction cannot be encoded");
2561             }
2562             break;
2563
2564         case INS_adr:
2565             assert(insOptsNone(opt));
2566             assert(insDoesNotSetFlags(flags));
2567             assert(reg2 == REG_PC);
2568             sf = INS_FLAGS_NOT_SET;
2569
2570             if (isLowRegister(reg1) && ((imm & 0x00ff) == imm))
2571             {
2572                 fmt = IF_T1_J3;
2573             }
2574             else if ((imm & 0x0fff) == imm)
2575             {
2576                 fmt = IF_T2_M1;
2577             }
2578             else
2579             {
2580                 assert(!"Instruction cannot be encoded");
2581             }
2582             break;
2583
2584         case INS_mvn:
2585             assert((imm >= 0) && (imm <= 31)); // required for encoding
2586             assert(!insOptAnyInc(opt));
2587             if (imm == 0)
2588             {
2589                 assert(insOptsNone(opt));
2590                 if (isLowRegister(reg1) && isLowRegister(reg2) && insSetsFlags(flags))
2591                 {
2592                     // Use the Thumb-1 reg,reg encoding
2593                     emitIns_R_R(ins, attr, reg1, reg2, flags);
2594                     return;
2595                 }
2596             }
2597             else // imm > 0  &&  imm <= 31
2598             {
2599                 assert(insOptAnyShift(opt));
2600             }
2601             fmt = IF_T2_C1;
2602             sf  = insMustSetFlags(flags);
2603             break;
2604
2605         case INS_cmp:
2606         case INS_cmn:
2607         case INS_teq:
2608         case INS_tst:
2609             assert(insSetsFlags(flags));
2610             assert((imm >= 0) && (imm <= 31)); // required for encoding
2611             assert(!insOptAnyInc(opt));
2612             if (imm == 0)
2613             {
2614                 assert(insOptsNone(opt));
2615                 if (ins == INS_cmp)
2616                 {
2617                     // Use the Thumb-1 reg,reg encoding
2618                     emitIns_R_R(ins, attr, reg1, reg2, flags);
2619                     return;
2620                 }
2621                 if (((ins == INS_cmn) || (ins == INS_tst)) && isLowRegister(reg1) && isLowRegister(reg2))
2622                 {
2623                     // Use the Thumb-1 reg,reg encoding
2624                     emitIns_R_R(ins, attr, reg1, reg2, flags);
2625                     return;
2626                 }
2627             }
2628             else // imm > 0  &&  imm <= 31)
2629             {
2630                 assert(insOptAnyShift(opt));
2631                 if (insOptsRRX(opt))
2632                     assert(imm == 1);
2633             }
2634
2635             fmt = IF_T2_C8;
2636             sf  = INS_FLAGS_SET;
2637             break;
2638
2639         case INS_ror:
2640         case INS_asr:
2641         case INS_lsl:
2642         case INS_lsr:
2643             assert(insOptsNone(opt));
2644
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.
2651             imm &= 0x1f;
2652
2653             if (imm == 0)
2654             {
2655                 // Additional Fix 383915 ARM ILGEN
2656                 if ((reg1 != reg2) || insMustSetFlags(flags))
2657                 {
2658                     // Use MOV/MOVS instriction
2659                     emitIns_R_R(INS_mov, attr, reg1, reg2, flags);
2660                 }
2661                 return;
2662             }
2663
2664             if (insSetsFlags(flags) && (ins != INS_ror) && isLowRegister(reg1) && isLowRegister(reg2))
2665             {
2666                 fmt = IF_T1_C;
2667                 sf  = INS_FLAGS_SET;
2668             }
2669             else
2670             {
2671                 fmt = IF_T2_C2;
2672                 sf  = insMustSetFlags(flags);
2673             }
2674             break;
2675
2676         case INS_sxtb:
2677         case INS_uxtb:
2678             assert(size == EA_4BYTE);
2679             goto EXTEND_COMMON;
2680
2681         case INS_sxth:
2682         case INS_uxth:
2683             assert(size == EA_4BYTE);
2684         EXTEND_COMMON:
2685             assert(insOptsNone(opt));
2686             assert(insDoesNotSetFlags(flags));
2687             assert((imm & 0x018) == imm); // required for encoding
2688
2689             if ((imm == 0) && isLowRegister(reg1) && isLowRegister(reg2))
2690             {
2691                 // Use Thumb-1 encoding
2692                 emitIns_R_R(ins, attr, reg1, reg2, INS_FLAGS_NOT_SET);
2693                 return;
2694             }
2695
2696             fmt = IF_T2_C6;
2697             sf  = INS_FLAGS_NOT_SET;
2698             break;
2699
2700         case INS_pld:
2701         case INS_pldw:
2702 #ifdef FEATURE_PLI_INSTRUCTION
2703         case INS_pli:
2704 #endif // FEATURE_PLI_INSTRUCTION
2705             assert(insOptsNone(opt));
2706             assert(insDoesNotSetFlags(flags));
2707             assert((imm & 0x003) == imm); // required for encoding
2708
2709             fmt = IF_T2_C7;
2710             sf  = INS_FLAGS_NOT_SET;
2711             break;
2712
2713         case INS_ldrb:
2714         case INS_strb:
2715             assert(size == EA_1BYTE);
2716             assert(insDoesNotSetFlags(flags));
2717
2718             if (isLowRegister(reg1) && isLowRegister(reg2) && insOptsNone(opt) && ((imm & 0x001f) == imm))
2719             {
2720                 fmt = IF_T1_C;
2721                 sf  = INS_FLAGS_NOT_SET;
2722                 break;
2723             }
2724             goto COMMON_THUMB2_LDST;
2725
2726         case INS_ldrsb:
2727             assert(size == EA_1BYTE);
2728             goto COMMON_THUMB2_LDST;
2729
2730         case INS_ldrh:
2731         case INS_strh:
2732             assert(size == EA_2BYTE);
2733             assert(insDoesNotSetFlags(flags));
2734
2735             if (isLowRegister(reg1) && isLowRegister(reg2) && insOptsNone(opt) && ((imm & 0x003e) == imm))
2736             {
2737                 fmt = IF_T1_C;
2738                 sf  = INS_FLAGS_NOT_SET;
2739                 break;
2740             }
2741             goto COMMON_THUMB2_LDST;
2742
2743         case INS_ldrsh:
2744             assert(size == EA_2BYTE);
2745             goto COMMON_THUMB2_LDST;
2746
2747         case INS_vldr:
2748         case INS_vstr:
2749         case INS_vldm:
2750         case INS_vstm:
2751             assert(fmt == IF_NONE);
2752             assert(insDoesNotSetFlags(flags));
2753             assert(offsetFitsInVectorMem(imm)); // required for encoding
2754             if (insOptAnyInc(opt))
2755             {
2756                 if (insOptsPostInc(opt))
2757                 {
2758                     assert(imm > 0);
2759                 }
2760                 else // insOptsPreDec(opt)
2761                 {
2762                     assert(imm < 0);
2763                 }
2764             }
2765             else
2766             {
2767                 assert(insOptsNone(opt));
2768             }
2769
2770             sf  = INS_FLAGS_NOT_SET;
2771             fmt = IF_T2_VLDST;
2772             break;
2773
2774         case INS_ldr:
2775         case INS_str:
2776             assert(size == EA_4BYTE);
2777             assert(insDoesNotSetFlags(flags));
2778
2779             // Can we possibly encode the immediate 'imm' using a Thumb-1 encoding?
2780             if (isLowRegister(reg1) && insOptsNone(opt) && ((imm & 0x03fc) == imm))
2781             {
2782                 if (reg2 == REG_SP)
2783                 {
2784                     fmt = IF_T1_J2;
2785                     sf  = INS_FLAGS_NOT_SET;
2786                     break;
2787                 }
2788                 else if (reg2 == REG_PC)
2789                 {
2790                     if (ins == INS_ldr)
2791                     {
2792                         fmt = IF_T1_J3;
2793                         sf  = INS_FLAGS_NOT_SET;
2794                         break;
2795                     }
2796                 }
2797                 else if (isLowRegister(reg2))
2798                 {
2799                     // Only the smaller range 'imm' can be encoded
2800                     if ((imm & 0x07c) == imm)
2801                     {
2802                         fmt = IF_T1_C;
2803                         sf  = INS_FLAGS_NOT_SET;
2804                         break;
2805                     }
2806                 }
2807             }
2808             //
2809             // If we did not find a thumb-1 encoding above
2810             //
2811             __fallthrough;
2812
2813         COMMON_THUMB2_LDST:
2814             assert(fmt == IF_NONE);
2815             assert(insDoesNotSetFlags(flags));
2816             sf = INS_FLAGS_NOT_SET;
2817
2818             if (insOptAnyInc(opt))
2819             {
2820                 if (insOptsPostInc(opt))
2821                     assert(imm > 0);
2822                 else // insOptsPreDec(opt)
2823                     assert(imm < 0);
2824
2825                 if (unsigned_abs(imm) <= 0x00ff)
2826                 {
2827                     fmt = IF_T2_H0;
2828                 }
2829                 else
2830                 {
2831                     assert(!"Instruction cannot be encoded");
2832                 }
2833             }
2834             else
2835             {
2836                 assert(insOptsNone(opt));
2837                 if ((reg2 == REG_PC) && (unsigned_abs(imm) <= 0x0fff))
2838                 {
2839                     fmt = IF_T2_K4;
2840                 }
2841                 else if ((imm & 0x0fff) == imm)
2842                 {
2843                     fmt = IF_T2_K1;
2844                 }
2845                 else if (unsigned_abs(imm) <= 0x0ff)
2846                 {
2847                     fmt = IF_T2_H0;
2848                 }
2849                 else
2850                 {
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);
2855                     return;
2856                 }
2857             }
2858             break;
2859
2860         case INS_ldrex:
2861         case INS_strex:
2862             assert(insOptsNone(opt));
2863             assert(insDoesNotSetFlags(flags));
2864             sf = INS_FLAGS_NOT_SET;
2865
2866             if ((imm & 0x03fc) == imm)
2867             {
2868                 fmt = IF_T2_H0;
2869             }
2870             else
2871             {
2872                 assert(!"Instruction cannot be encoded");
2873             }
2874             break;
2875
2876         default:
2877             assert(!"Unexpected instruction");
2878     }
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);
2884
2885     instrDesc* id  = emitNewInstrSC(attr, imm);
2886     insSize    isz = emitInsSize(fmt);
2887
2888     id->idIns(ins);
2889     id->idInsFmt(fmt);
2890     id->idInsSize(isz);
2891     id->idInsFlags(sf);
2892     id->idInsOpt(opt);
2893     id->idReg1(reg1);
2894     id->idReg2(reg2);
2895
2896     dispIns(id);
2897     appendToCurIG(id);
2898 }
2899
2900 /*****************************************************************************
2901  *
2902  *  Add an instruction referencing three registers.
2903  */
2904
2905 void emitter::emitIns_R_R_R(instruction ins,
2906                             emitAttr    attr,
2907                             regNumber   reg1,
2908                             regNumber   reg2,
2909                             regNumber   reg3,
2910                             insFlags    flags /* = INS_FLAGS_DONT_CARE */)
2911 {
2912     emitAttr  size = EA_SIZE(attr);
2913     insFormat fmt  = IF_NONE;
2914     insFlags  sf   = INS_FLAGS_DONT_CARE;
2915
2916     /* Figure out the encoding format of the instruction */
2917     switch (ins)
2918     {
2919         case INS_add:
2920             // Encodings do not support SP in the reg3 slot
2921             if (reg3 == REG_SP)
2922             {
2923                 // Swap reg2 and reg3
2924                 reg3 = reg2;
2925                 reg2 = REG_SP;
2926             }
2927             __fallthrough;
2928
2929         case INS_sub:
2930             assert(reg3 != REG_SP);
2931
2932             if (isLowRegister(reg1) && isLowRegister(reg2) && isLowRegister(reg3) && insSetsFlags(flags))
2933             {
2934                 fmt = IF_T1_H;
2935                 sf  = INS_FLAGS_SET;
2936                 break;
2937             }
2938
2939             if ((ins == INS_add) && insDoesNotSetFlags(flags))
2940             {
2941                 if (reg1 == reg2)
2942                 {
2943                     // Use the Thumb-1 regdest,reg encoding
2944                     emitIns_R_R(ins, attr, reg1, reg3, flags);
2945                     return;
2946                 }
2947                 if (reg1 == reg3)
2948                 {
2949                     // Use the Thumb-1 regdest,reg encoding
2950                     emitIns_R_R(ins, attr, reg1, reg2, flags);
2951                     return;
2952                 }
2953             }
2954
2955             // Use the Thumb-2 reg,reg,reg with shift encoding
2956             emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, flags);
2957             return;
2958
2959         case INS_adc:
2960         case INS_and:
2961         case INS_bic:
2962         case INS_eor:
2963         case INS_orr:
2964         case INS_sbc:
2965             if (reg1 == reg2)
2966             {
2967                 // Try to encode as a Thumb-1 instruction
2968                 emitIns_R_R(ins, attr, reg1, reg3, flags);
2969                 return;
2970             }
2971             __fallthrough;
2972
2973         case INS_orn:
2974             // Use the Thumb-2 three register encoding, with imm=0
2975             emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, flags);
2976             return;
2977
2978         case INS_asr:
2979         case INS_lsl:
2980         case INS_lsr:
2981             if (reg1 == reg2 && insSetsFlags(flags) && isLowRegister(reg1) && isLowRegister(reg3))
2982             {
2983                 // Use the Thumb-1 regdest,reg encoding
2984                 emitIns_R_R(ins, attr, reg1, reg3, flags);
2985                 return;
2986             }
2987             __fallthrough;
2988
2989         case INS_ror:
2990             fmt = IF_T2_C4;
2991             sf  = insMustSetFlags(flags);
2992             break;
2993
2994         case INS_mul:
2995             if (insMustSetFlags(flags))
2996             {
2997                 if ((reg1 == reg2) && isLowRegister(reg1))
2998                 {
2999                     // Use the Thumb-1 regdest,reg encoding
3000                     emitIns_R_R(ins, attr, reg1, reg3, flags);
3001                     return;
3002                 }
3003                 if ((reg1 == reg3) && isLowRegister(reg1))
3004                 {
3005                     // Use the Thumb-1 regdest,reg encoding
3006                     emitIns_R_R(ins, attr, reg1, reg2, flags);
3007                     return;
3008                 }
3009                 else
3010                 {
3011                     assert(!"Instruction cannot be encoded");
3012                 }
3013             }
3014             __fallthrough;
3015
3016 #if !defined(USE_HELPERS_FOR_INT_DIV)
3017         case INS_sdiv:
3018         case INS_udiv:
3019 #endif // !USE_HELPERS_FOR_INT_DIV
3020
3021             assert(insDoesNotSetFlags(flags));
3022             fmt = IF_T2_C5;
3023             sf  = INS_FLAGS_NOT_SET;
3024             break;
3025
3026         case INS_ldrb:
3027         case INS_strb:
3028         case INS_ldrsb:
3029             assert(size == EA_1BYTE);
3030             goto COMMON_THUMB1_LDST;
3031
3032         case INS_ldrsh:
3033         case INS_ldrh:
3034         case INS_strh:
3035             assert(size == EA_2BYTE);
3036             goto COMMON_THUMB1_LDST;
3037
3038         case INS_ldr:
3039         case INS_str:
3040             assert(size == EA_4BYTE);
3041
3042         COMMON_THUMB1_LDST:
3043             assert(insDoesNotSetFlags(flags));
3044
3045             if (isLowRegister(reg1) && isLowRegister(reg2) && isLowRegister(reg3))
3046             {
3047                 fmt = IF_T1_H;
3048                 sf  = INS_FLAGS_NOT_SET;
3049             }
3050             else
3051             {
3052                 // Use the Thumb-2 reg,reg,reg with shift encoding
3053                 emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, flags);
3054                 return;
3055             }
3056             break;
3057
3058         case INS_vadd:
3059         case INS_vmul:
3060         case INS_vsub:
3061         case INS_vdiv:
3062             if (size == EA_8BYTE)
3063             {
3064                 assert(isDoubleReg(reg1));
3065                 assert(isDoubleReg(reg2));
3066                 assert(isDoubleReg(reg3));
3067             }
3068             else
3069             {
3070                 assert(isFloatReg(reg1));
3071                 assert(isFloatReg(reg2));
3072                 assert(isFloatReg(reg3));
3073             }
3074             fmt = IF_T2_VFP3;
3075             sf  = INS_FLAGS_NOT_SET;
3076             break;
3077
3078         case INS_vmov_i2d:
3079             assert(isDoubleReg(reg1));
3080             assert(isGeneralRegister(reg2));
3081             assert(isGeneralRegister(reg3));
3082             fmt = IF_T2_VMOVD;
3083             sf  = INS_FLAGS_NOT_SET;
3084             break;
3085
3086         case INS_vmov_d2i:
3087             assert(isGeneralRegister(reg1));
3088             assert(isGeneralRegister(reg2));
3089             assert(isDoubleReg(reg3));
3090             fmt = IF_T2_VMOVD;
3091             sf  = INS_FLAGS_NOT_SET;
3092             break;
3093
3094         case INS_ldrexd:
3095         case INS_strexd:
3096             assert(insDoesNotSetFlags(flags));
3097             fmt = IF_T2_G1;
3098             sf  = INS_FLAGS_NOT_SET;
3099             break;
3100
3101         default:
3102             unreached();
3103     }
3104     assert((fmt == IF_T1_H) || (fmt == IF_T2_C4) || (fmt == IF_T2_C5) || (fmt == IF_T2_VFP3) || (fmt == IF_T2_VMOVD) ||
3105            (fmt == IF_T2_G1));
3106     assert(sf != INS_FLAGS_DONT_CARE);
3107
3108     instrDesc* id  = emitNewInstr(attr);
3109     insSize    isz = emitInsSize(fmt);
3110
3111     id->idIns(ins);
3112     id->idInsFmt(fmt);
3113     id->idInsSize(isz);
3114     id->idInsFlags(sf);
3115     id->idReg1(reg1);
3116     id->idReg2(reg2);
3117     id->idReg3(reg3);
3118
3119     dispIns(id);
3120     appendToCurIG(id);
3121 }
3122
3123 /*****************************************************************************
3124  *
3125  *  Add an instruction referencing two registers and two constants.
3126  */
3127
3128 void emitter::emitIns_R_R_I_I(instruction ins,
3129                               emitAttr    attr,
3130                               regNumber   reg1,
3131                               regNumber   reg2,
3132                               int         imm1,
3133                               int         imm2,
3134                               insFlags    flags /* = INS_FLAGS_DONT_CARE */)
3135 {
3136     insFormat fmt = IF_NONE;
3137     insFlags  sf  = INS_FLAGS_DONT_CARE;
3138
3139     int lsb   = imm1;
3140     int width = imm2;
3141     int msb   = lsb + width - 1;
3142     int imm   = 0; /* combined immediate */
3143
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
3148
3149     /* Figure out the encoding format of the instruction */
3150     switch (ins)
3151     {
3152         case INS_bfi:
3153             assert(insDoesNotSetFlags(flags));
3154             imm = (lsb << 5) | msb;
3155
3156             fmt = IF_T2_D0;
3157             sf  = INS_FLAGS_NOT_SET;
3158             break;
3159
3160         case INS_sbfx:
3161         case INS_ubfx:
3162             assert(insDoesNotSetFlags(flags));
3163             imm = (lsb << 5) | (width - 1);
3164
3165             fmt = IF_T2_D0;
3166             sf  = INS_FLAGS_NOT_SET;
3167             break;
3168
3169         default:
3170             unreached();
3171     }
3172     assert((fmt == IF_T2_D0));
3173     assert(sf != INS_FLAGS_DONT_CARE);
3174
3175     instrDesc* id  = emitNewInstrSC(attr, imm);
3176     insSize    isz = emitInsSize(fmt);
3177
3178     id->idIns(ins);
3179     id->idInsFmt(fmt);
3180     id->idInsSize(isz);
3181     id->idInsFlags(sf);
3182     id->idReg1(reg1);
3183     id->idReg2(reg2);
3184
3185     dispIns(id);
3186     appendToCurIG(id);
3187 }
3188
3189 /*****************************************************************************
3190  *
3191  *  Add an instruction referencing three registers and a constant.
3192  */
3193
3194 void emitter::emitIns_R_R_R_I(instruction ins,
3195                               emitAttr    attr,
3196                               regNumber   reg1,
3197                               regNumber   reg2,
3198                               regNumber   reg3,
3199                               int         imm,
3200                               insFlags    flags /* = INS_FLAGS_DONT_CARE */,
3201                               insOpts     opt /* = INS_OPTS_NONE */)
3202 {
3203     emitAttr  size = EA_SIZE(attr);
3204     insFormat fmt  = IF_NONE;
3205     insFlags  sf   = INS_FLAGS_DONT_CARE;
3206
3207     /* Figure out the encoding format of the instruction */
3208     switch (ins)
3209     {
3210
3211         case INS_add:
3212         case INS_sub:
3213             if (imm == 0)
3214             {
3215                 if (isLowRegister(reg1) && isLowRegister(reg2) && isLowRegister(reg3) && insSetsFlags(flags))
3216                 {
3217                     // Use the Thumb-1 reg,reg,reg encoding
3218                     emitIns_R_R_R(ins, attr, reg1, reg2, reg3, flags);
3219                     return;
3220                 }
3221                 if ((ins == INS_add) && insDoesNotSetFlags(flags))
3222                 {
3223                     if (reg1 == reg2)
3224                     {
3225                         // Use the Thumb-1 regdest,reg encoding
3226                         emitIns_R_R(ins, attr, reg1, reg3, flags);
3227                         return;
3228                     }
3229                     if (reg1 == reg3)
3230                     {
3231                         // Use the Thumb-1 regdest,reg encoding
3232                         emitIns_R_R(ins, attr, reg1, reg2, flags);
3233                         return;
3234                     }
3235                 }
3236             }
3237             __fallthrough;
3238
3239         case INS_adc:
3240         case INS_and:
3241         case INS_bic:
3242         case INS_eor:
3243         case INS_orn:
3244         case INS_orr:
3245         case INS_sbc:
3246             assert((imm >= 0) && (imm <= 31)); // required for encoding
3247             assert(!insOptAnyInc(opt));
3248             if (imm == 0)
3249             {
3250                 if (opt == INS_OPTS_LSL) // left shift of zero
3251                     opt = INS_OPTS_NONE; //           is a nop
3252
3253                 assert(insOptsNone(opt));
3254                 if (isLowRegister(reg1) && isLowRegister(reg2) && isLowRegister(reg3) && insSetsFlags(flags))
3255                 {
3256                     if (reg1 == reg2)
3257                     {
3258                         // Use the Thumb-1 regdest,reg encoding
3259                         emitIns_R_R(ins, attr, reg1, reg3, flags);
3260                         return;
3261                     }
3262                     if ((reg1 == reg3) && (ins != INS_bic) && (ins != INS_orn) && (ins != INS_sbc))
3263                     {
3264                         // Use the Thumb-1 regdest,reg encoding
3265                         emitIns_R_R(ins, attr, reg1, reg2, flags);
3266                         return;
3267                     }
3268                 }
3269             }
3270             else // imm > 0  &&  imm <= 31)
3271             {
3272                 assert(insOptAnyShift(opt));
3273                 if (insOptsRRX(opt))
3274                     assert(imm == 1);
3275             }
3276             fmt = IF_T2_C0;
3277             sf  = insMustSetFlags(flags);
3278             break;
3279
3280         case INS_ldrb:
3281         case INS_ldrsb:
3282         case INS_strb:
3283             assert(size == EA_1BYTE);
3284             goto COMMON_THUMB2_LDST;
3285
3286         case INS_ldrh:
3287         case INS_ldrsh:
3288         case INS_strh:
3289             assert(size == EA_2BYTE);
3290             goto COMMON_THUMB2_LDST;
3291
3292         case INS_ldr:
3293         case INS_str:
3294             assert(size == EA_4BYTE);
3295
3296         COMMON_THUMB2_LDST:
3297             assert(insDoesNotSetFlags(flags));
3298             assert((imm & 0x0003) == imm); // required for encoding
3299
3300             if ((imm == 0) && insOptsNone(opt) && isLowRegister(reg1) && isLowRegister(reg2) && isLowRegister(reg3))
3301             {
3302                 // Use the Thumb-1 reg,reg,reg encoding
3303                 emitIns_R_R_R(ins, attr, reg1, reg2, reg3, flags);
3304                 return;
3305             }
3306             assert(insOptsNone(opt) || insOptsLSL(opt));
3307             fmt = IF_T2_E0;
3308             sf  = INS_FLAGS_NOT_SET;
3309             break;
3310
3311         case INS_ldrd:
3312         case INS_strd:
3313             assert(insDoesNotSetFlags(flags));
3314             assert((imm & 0x03) == 0);
3315             sf = INS_FLAGS_NOT_SET;
3316
3317             if (insOptAnyInc(opt))
3318             {
3319                 if (insOptsPostInc(opt))
3320                     assert(imm > 0);
3321                 else // insOptsPreDec(opt)
3322                     assert(imm < 0);
3323             }
3324             else
3325             {
3326                 assert(insOptsNone(opt));
3327             }
3328
3329             if (unsigned_abs(imm) <= 0x03fc)
3330             {
3331                 imm >>= 2;
3332                 fmt = IF_T2_G0;
3333             }
3334             else
3335             {
3336                 assert(!"Instruction cannot be encoded");
3337             }
3338             break;
3339
3340         default:
3341             unreached();
3342     }
3343     assert((fmt == IF_T2_C0) || (fmt == IF_T2_E0) || (fmt == IF_T2_G0));
3344     assert(sf != INS_FLAGS_DONT_CARE);
3345
3346     // 3-reg ops can't use the small instrdesc
3347     instrDescCns* id = emitAllocInstrCns(attr);
3348     id->idSetIsLargeCns();
3349     id->idcCnsVal = imm;
3350
3351     id->idIns(ins);
3352     id->idInsFmt(fmt);
3353     id->idInsSize(emitInsSize(fmt));
3354
3355     id->idInsFlags(sf);
3356     id->idInsOpt(opt);
3357     id->idReg1(reg1);
3358     id->idReg2(reg2);
3359     id->idReg3(reg3);
3360
3361     dispIns(id);
3362     appendToCurIG(id);
3363 }
3364
3365 /*****************************************************************************
3366  *
3367  *  Add an instruction referencing four registers.
3368  */
3369
3370 void emitter::emitIns_R_R_R_R(
3371     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, regNumber reg4)
3372 {
3373     insFormat fmt = IF_NONE;
3374     insFlags  sf  = INS_FLAGS_NOT_SET;
3375
3376     /* Figure out the encoding format of the instruction */
3377     switch (ins)
3378     {
3379
3380         case INS_smull:
3381         case INS_umull:
3382         case INS_smlal:
3383         case INS_umlal:
3384             assert(reg1 != reg2); // Illegal encoding
3385             fmt = IF_T2_F1;
3386             break;
3387         case INS_mla:
3388         case INS_mls:
3389             fmt = IF_T2_F2;
3390             break;
3391         default:
3392             unreached();
3393     }
3394     assert((fmt == IF_T2_F1) || (fmt == IF_T2_F2));
3395
3396     instrDesc* id  = emitNewInstr(attr);
3397     insSize    isz = emitInsSize(fmt);
3398
3399     id->idIns(ins);
3400     id->idInsFmt(fmt);
3401     id->idInsSize(isz);
3402     id->idInsFlags(sf);
3403     id->idReg1(reg1);
3404     id->idReg2(reg2);
3405     id->idReg3(reg3);
3406     id->idReg4(reg4);
3407
3408     dispIns(id);
3409     appendToCurIG(id);
3410 }
3411
3412 /*****************************************************************************
3413  *
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]").
3417  */
3418
3419 void emitter::emitIns_C(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, int offs)
3420 {
3421     NYI("emitIns_C");
3422 }
3423
3424 /*****************************************************************************
3425  *
3426  *  Add an instruction referencing stack-based local variable.
3427  */
3428
3429 void emitter::emitIns_S(instruction ins, emitAttr attr, int varx, int offs)
3430 {
3431     NYI("emitIns_S");
3432 }
3433
3434 /*****************************************************************************
3435  *
3436  *  Add an instruction referencing a register and a stack-based local variable.
3437  */
3438 void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
3439 {
3440     if (ins == INS_mov)
3441     {
3442         assert(!"Please use ins_Load() to select the correct instruction");
3443     }
3444
3445     switch (ins)
3446     {
3447         case INS_add:
3448         case INS_ldr:
3449         case INS_ldrh:
3450         case INS_ldrb:
3451         case INS_ldrsh:
3452         case INS_ldrsb:
3453         case INS_vldr:
3454         case INS_vmov:
3455         case INS_movw:
3456         case INS_movt:
3457             break;
3458
3459         case INS_lea:
3460             ins = INS_add;
3461             break;
3462
3463         default:
3464             NYI("emitIns_R_S");
3465             return;
3466     }
3467
3468     insFormat fmt = IF_NONE;
3469     insFlags  sf  = INS_FLAGS_NOT_SET;
3470     regNumber reg2;
3471
3472     /* Figure out the variable's frame position */
3473     int      base;
3474     int      disp;
3475     unsigned undisp;
3476
3477     base = emitComp->lvaFrameAddress(varx, emitComp->funCurrentFunc()->funKind != FUNC_ROOT, &reg2, offs);
3478
3479     disp   = base + offs;
3480     undisp = unsigned_abs(disp);
3481
3482     if (CodeGen::instIsFP(ins))
3483     {
3484         // all fp mem ops take 8 bit immediate, multiplied by 4, plus sign
3485         //
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
3490         //
3491         if (undisp <= 0x03fc)
3492         {
3493             fmt = IF_T2_VLDST;
3494         }
3495         else
3496         {
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);
3501             return;
3502         }
3503     }
3504     else if (emitInsIsLoadOrStore(ins))
3505     {
3506         if (isLowRegister(reg1) && (reg2 == REG_SP) && (ins == INS_ldr) && ((disp & 0x03fc) == disp))
3507         {
3508             fmt = IF_T1_J2;
3509         }
3510         else if (disp >= 0 && disp <= 0x0fff)
3511         {
3512             fmt = IF_T2_K1;
3513         }
3514         else if (undisp <= 0x0ff)
3515         {
3516             fmt = IF_T2_H0;
3517         }
3518         else
3519         {
3520             // Load disp into a register
3521             regNumber rsvdReg = codeGen->rsGetRsvdReg();
3522             emitIns_genStackOffset(rsvdReg, varx, offs);
3523             fmt = IF_T2_E0;
3524         }
3525     }
3526     else if (ins == INS_add)
3527     {
3528         if (isLowRegister(reg1) && (reg2 == REG_SP) && ((disp & 0x03fc) == disp))
3529         {
3530             fmt = IF_T1_J2;
3531         }
3532         else if (undisp <= 0x0fff)
3533         {
3534             if (disp < 0)
3535             {
3536                 ins  = INS_sub;
3537                 disp = -disp;
3538             }
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;
3542             fmt = IF_T2_M0;
3543         }
3544         else
3545         {
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);
3550             return;
3551         }
3552     }
3553     else if (ins == INS_movw || ins == INS_movt)
3554     {
3555         fmt = IF_T2_N;
3556     }
3557
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);
3561
3562     instrDesc* id  = emitNewInstrCns(attr, disp);
3563     insSize    isz = emitInsSize(fmt);
3564
3565     id->idIns(ins);
3566     id->idInsFmt(fmt);
3567     id->idInsSize(isz);
3568     id->idInsFlags(sf);
3569     id->idInsOpt(INS_OPTS_NONE);
3570     id->idReg1(reg1);
3571     id->idReg2(reg2);
3572     id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
3573     id->idSetIsLclVar();
3574     if (reg2 == REG_FP)
3575         id->idSetIsLclFPBase();
3576
3577 #ifdef DEBUG
3578     id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
3579 #endif
3580
3581     dispIns(id);
3582     appendToCurIG(id);
3583 }
3584
3585 // generate the offset of &varx + offs into a register
3586 void emitter::emitIns_genStackOffset(regNumber r, int varx, int offs)
3587 {
3588     regNumber regBase;
3589     int       base;
3590     int       disp;
3591
3592     base = emitComp->lvaFrameAddress(varx, emitComp->funCurrentFunc()->funKind != FUNC_ROOT, &regBase, offs);
3593     disp = base + offs;
3594
3595     emitIns_R_S(INS_movw, EA_4BYTE, r, varx, offs);
3596
3597     if ((disp & 0xffff) != disp)
3598     {
3599         emitIns_R_S(INS_movt, EA_4BYTE, r, varx, offs);
3600     }
3601 }
3602
3603 /*****************************************************************************
3604  *
3605  *  Add an instruction referencing a stack-based local variable and a register
3606  */
3607 void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
3608 {
3609     if (ins == INS_mov)
3610     {
3611         assert(!"Please use ins_Store() to select the correct instruction");
3612     }
3613
3614     switch (ins)
3615     {
3616         case INS_str:
3617         case INS_strh:
3618         case INS_strb:
3619         case INS_vstr:
3620             break;
3621
3622         default:
3623             NYI("emitIns_R_S");
3624             return;
3625     }
3626
3627     insFormat fmt = IF_NONE;
3628     insFlags  sf  = INS_FLAGS_NOT_SET;
3629     regNumber reg2;
3630
3631     /* Figure out the variable's frame position */
3632     int      base;
3633     int      disp;
3634     unsigned undisp;
3635
3636     base = emitComp->lvaFrameAddress(varx, emitComp->funCurrentFunc()->funKind != FUNC_ROOT, &reg2, offs);
3637
3638     disp   = base + offs;
3639     undisp = unsigned_abs(disp);
3640
3641     if (CodeGen::instIsFP(ins))
3642     {
3643         // all fp mem ops take 8 bit immediate, multiplied by 4, plus sign
3644         //
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
3649         //
3650         if (undisp <= 0x03fc)
3651         {
3652             fmt = IF_T2_VLDST;
3653         }
3654         else
3655         {
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);
3660             return;
3661         }
3662     }
3663     else if (isLowRegister(reg1) && (reg2 == REG_SP) && (ins == INS_str) && ((disp & 0x03fc) == disp))
3664     {
3665         fmt = IF_T1_J2;
3666     }
3667     else if (disp >= 0 && disp <= 0x0fff)
3668     {
3669         fmt = IF_T2_K1;
3670     }
3671     else if (undisp <= 0x0ff)
3672     {
3673         fmt = IF_T2_H0;
3674     }
3675     else
3676     {
3677         // Load disp into a register
3678         regNumber rsvdReg = codeGen->rsGetRsvdReg();
3679         emitIns_genStackOffset(rsvdReg, varx, offs);
3680         fmt = IF_T2_E0;
3681     }
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);
3684
3685     instrDesc* id  = emitNewInstrCns(attr, disp);
3686     insSize    isz = emitInsSize(fmt);
3687
3688     id->idIns(ins);
3689     id->idInsFmt(fmt);
3690     id->idInsSize(isz);
3691     id->idInsFlags(sf);
3692     id->idInsOpt(INS_OPTS_NONE);
3693     id->idReg1(reg1);
3694     id->idReg2(reg2);
3695     id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
3696     id->idSetIsLclVar();
3697     if (reg2 == REG_FP)
3698         id->idSetIsLclFPBase();
3699 #ifdef DEBUG
3700     id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
3701 #endif
3702
3703     dispIns(id);
3704     appendToCurIG(id);
3705 }
3706
3707 /*****************************************************************************
3708  *
3709  *  Add an instruction referencing stack-based local variable and an immediate
3710  */
3711 void emitter::emitIns_S_I(instruction ins, emitAttr attr, int varx, int offs, int val)
3712 {
3713     NYI("emitIns_S_I");
3714 }
3715
3716 /*****************************************************************************
3717  *
3718  *  Add an instruction with a register + static member operands.
3719  */
3720 void emitter::emitIns_R_C(instruction ins, emitAttr attr, regNumber reg, CORINFO_FIELD_HANDLE fldHnd, int offs)
3721 {
3722     if (ins == INS_mov)
3723     {
3724         assert(!"Please use ins_Load() to select the correct instruction");
3725     }
3726     assert(emitInsIsLoad(ins) || (ins == INS_lea));
3727     if (ins == INS_lea)
3728     {
3729         ins = INS_add;
3730     }
3731
3732     int     doff = Compiler::eeGetJitDataOffs(fldHnd);
3733     ssize_t addr = NULL;
3734
3735     if (doff >= 0)
3736     {
3737         NYI_ARM("JitDataOffset static fields");
3738     }
3739     else if (fldHnd == FLD_GLOBAL_FS)
3740     {
3741         NYI_ARM("Thread-Local-Storage static fields");
3742     }
3743     else if (fldHnd == FLD_GLOBAL_DS)
3744     {
3745         addr = (ssize_t)offs;
3746         offs = 0;
3747     }
3748     else
3749     {
3750         assert(!jitStaticFldIsGlobAddr(fldHnd));
3751         addr = (ssize_t)emitComp->info.compCompHnd->getFieldAddress(fldHnd, NULL);
3752         if (addr == NULL)
3753             NO_WAY("could not obtain address of static field");
3754     }
3755
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;
3759
3760     if (isFloatReg(regTmp))
3761     {
3762         assert(!"emitIns_R_C() cannot be called with floating point target");
3763         return;
3764     }
3765
3766     // Load address of CLS_VAR into a register
3767     codeGen->instGen_Set_Reg_To_Imm(EA_HANDLE_CNS_RELOC, regTmp, addr);
3768
3769     if ((ins != INS_add) || (offs != 0) || (reg != regTmp))
3770     {
3771         emitIns_R_R_I(ins, attr, reg, regTmp, offs);
3772     }
3773 }
3774
3775 /*****************************************************************************
3776  *
3777  *  Add an instruction with a static member + register operands.
3778  */
3779
3780 void emitter::emitIns_C_R(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, regNumber reg, int offs)
3781 {
3782     assert(!"emitIns_C_R not supported");
3783 }
3784
3785 /*****************************************************************************
3786  *
3787  *  Add an instruction with a static member + constant.
3788  */
3789
3790 void emitter::emitIns_C_I(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, int offs, ssize_t val)
3791 {
3792     NYI("emitIns_C_I");
3793 }
3794
3795 /*****************************************************************************
3796  *
3797  *  The following adds instructions referencing address modes.
3798  */
3799
3800 void emitter::emitIns_I_AR(instruction ins, emitAttr attr, int val, regNumber reg, int offs)
3801 {
3802     NYI("emitIns_I_AR");
3803 }
3804
3805 void emitter::emitIns_R_AR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
3806 {
3807     if (ins == INS_mov)
3808     {
3809         assert(!"Please use ins_Load() to select the correct instruction");
3810     }
3811
3812     if (ins == INS_lea)
3813     {
3814         if (emitter::emitIns_valid_imm_for_add(offs, INS_FLAGS_DONT_CARE))
3815         {
3816             emitIns_R_R_I(INS_add, attr, ireg, reg, offs);
3817         }
3818         else
3819         {
3820             assert(!"emitIns_R_AR: immediate doesn't fit in the instruction");
3821         }
3822         return;
3823     }
3824     else if (emitInsIsLoad(ins))
3825     {
3826         emitIns_R_R_I(ins, attr, ireg, reg, offs);
3827         return;
3828     }
3829     else if ((ins == INS_mov) || (ins == INS_ldr))
3830     {
3831         if (EA_SIZE(attr) == EA_4BYTE)
3832         {
3833             emitIns_R_R_I(INS_ldr, attr, ireg, reg, offs);
3834             return;
3835         }
3836     }
3837     else if (ins == INS_vldr)
3838     {
3839         emitIns_R_R_I(ins, attr, ireg, reg, offs);
3840     }
3841     NYI("emitIns_R_AR");
3842 }
3843
3844 void emitter::emitIns_R_AI(instruction ins, emitAttr attr, regNumber ireg, ssize_t disp)
3845 {
3846     if (emitInsIsLoad(ins))
3847     {
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;
3851
3852         if (isFloatReg(regTmp))
3853         {
3854             assert(!"emitIns_R_AI with floating point reg");
3855             return;
3856         }
3857
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);
3860         return;
3861     }
3862     NYI("emitIns_R_AI");
3863 }
3864
3865 void emitter::emitIns_AR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
3866 {
3867     if (ins == INS_mov)
3868     {
3869         assert(!"Please use ins_Store() to select the correct instruction");
3870     }
3871     emitIns_R_R_I(ins, attr, ireg, reg, offs);
3872 }
3873
3874 void emitter::emitIns_R_ARR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
3875 {
3876     if (ins == INS_mov)
3877     {
3878         assert(!"Please use ins_Load() to select the correct instruction");
3879     }
3880
3881     if (ins == INS_lea)
3882     {
3883         emitIns_R_R_R(INS_add, attr, ireg, reg, rg2);
3884         if (disp != 0)
3885         {
3886             emitIns_R_R_I(INS_add, attr, ireg, ireg, disp);
3887         }
3888         return;
3889     }
3890     else if (emitInsIsLoad(ins))
3891     {
3892         if (disp == 0)
3893         {
3894             emitIns_R_R_R_I(ins, attr, ireg, reg, rg2, 0, INS_FLAGS_DONT_CARE, INS_OPTS_NONE);
3895             return;
3896         }
3897     }
3898     assert(!"emitIns_R_ARR: Unexpected instruction");
3899 }
3900
3901 void emitter::emitIns_ARR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
3902 {
3903     if (ins == INS_mov)
3904     {
3905         assert(!"Please use ins_Store() to select the correct instruction");
3906     }
3907     if (emitInsIsStore(ins))
3908     {
3909         if (disp == 0)
3910         {
3911             emitIns_R_R_R(ins, attr, ireg, reg, rg2);
3912         }
3913         else
3914         {
3915             emitIns_R_R_R(INS_add, attr, ireg, reg, rg2);
3916             emitIns_R_R_I(ins, attr, ireg, ireg, disp);
3917         }
3918         return;
3919     }
3920     assert(!"emitIns_ARR_R: Unexpected instruction");
3921 }
3922
3923 void emitter::emitIns_R_ARX(
3924     instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, unsigned mul, int disp)
3925 {
3926     if (ins == INS_mov)
3927     {
3928         assert(!"Please use ins_Load() to select the correct instruction");
3929     }
3930
3931     unsigned shift = genLog2((unsigned)mul);
3932
3933     if ((ins == INS_lea) || emitInsIsLoad(ins))
3934     {
3935         if (ins == INS_lea)
3936         {
3937             ins = INS_add;
3938         }
3939         if (disp == 0)
3940         {
3941             emitIns_R_R_R_I(ins, attr, ireg, reg, rg2, (int)shift, INS_FLAGS_DONT_CARE, INS_OPTS_LSL);
3942             return;
3943         }
3944         else
3945         {
3946             bool useForm2     = false;
3947             bool mustUseForm1 = ((disp % mul) != 0) || (reg == ireg);
3948             if (!mustUseForm1)
3949             {
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
3954                 //
3955                 if ((reg >= REG_R8) && (ireg < REG_R8) && (rg2 < REG_R8) && ((disp >> shift) <= 7))
3956                 {
3957                     useForm2 = true;
3958                 }
3959             }
3960
3961             if (useForm2)
3962             {
3963                 // Form2:
3964                 //     Thumb-1   instruction    add     Rd, Rx, disp>>shift
3965                 //     Thumb-2   instructions   ldr     Rd, Rb, Rd LSL shift
3966                 //
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);
3969             }
3970             else
3971             {
3972                 // Form1:
3973                 //     Thumb-2   instruction    add     Rd, Rb, Rx LSL shift
3974                 //     Thumb-1/2 instructions   ldr     Rd, Rd, disp
3975                 //
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);
3978             }
3979             return;
3980         }
3981     }
3982
3983     assert(!"emitIns_R_ARX: Unexpected instruction");
3984 }
3985
3986 /*****************************************************************************
3987  *
3988  *  Record that a jump instruction uses the short encoding
3989  *
3990  */
3991 void emitter::emitSetShortJump(instrDescJmp* id)
3992 {
3993     if (id->idjKeepLong)
3994         return;
3995
3996     if (emitIsCondJump(id))
3997     {
3998         id->idInsFmt(IF_T1_K);
3999     }
4000     else if (emitIsCmpJump(id))
4001     {
4002         // These are always only ever short!
4003         assert(id->idjShort);
4004         return;
4005     }
4006     else if (emitIsUncondJump(id))
4007     {
4008         id->idInsFmt(IF_T1_M);
4009     }
4010     else if (emitIsLoadLabel(id))
4011     {
4012         return; // Keep long - we don't know the alignment of the target
4013     }
4014     else
4015     {
4016         assert(!"Unknown instruction in emitSetShortJump()");
4017     }
4018
4019     id->idjShort = true;
4020
4021 #if DEBUG_EMIT
4022     if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
4023     {
4024         printf("[8] Converting jump %u to short\n", id->idDebugOnlyInfo()->idNum);
4025     }
4026 #endif // DEBUG_EMIT
4027
4028     insSize isz = emitInsSize(id->idInsFmt());
4029     id->idInsSize(isz);
4030 }
4031
4032 /*****************************************************************************
4033  *
4034  *  Record that a jump instruction uses the medium encoding
4035  *
4036  */
4037 void emitter::emitSetMediumJump(instrDescJmp* id)
4038 {
4039     if (id->idjKeepLong)
4040         return;
4041
4042 #if DEBUG_EMIT
4043     if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
4044     {
4045         printf("[9] Converting jump %u to medium\n", id->idDebugOnlyInfo()->idNum);
4046     }
4047 #endif // DEBUG_EMIT
4048
4049     assert(emitIsCondJump(id));
4050     id->idInsFmt(IF_T2_J1);
4051     id->idjShort = false;
4052
4053     insSize isz = emitInsSize(id->idInsFmt());
4054     id->idInsSize(isz);
4055 }
4056
4057 /*****************************************************************************
4058  *
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.
4067  */
4068
4069 void emitter::emitIns_J(instruction ins, BasicBlock* dst, int instrCount /* = 0 */)
4070 {
4071     insFormat fmt = IF_NONE;
4072
4073     if (dst != NULL)
4074     {
4075         assert(dst->bbFlags & BBF_JMP_TARGET);
4076     }
4077     else
4078     {
4079         assert(instrCount != 0);
4080     }
4081
4082     /* Figure out the encoding format of the instruction */
4083     switch (ins)
4084     {
4085         case INS_b:
4086             fmt = IF_T2_J2; /* Assume the jump will be long */
4087             break;
4088
4089         case INS_beq:
4090         case INS_bne:
4091         case INS_bhs:
4092         case INS_blo:
4093         case INS_bmi:
4094         case INS_bpl:
4095         case INS_bvs:
4096         case INS_bvc:
4097         case INS_bhi:
4098         case INS_bls:
4099         case INS_bge:
4100         case INS_blt:
4101         case INS_bgt:
4102         case INS_ble:
4103             fmt = IF_LARGEJMP; /* Assume the jump will be long */
4104             break;
4105
4106         default:
4107             unreached();
4108     }
4109     assert((fmt == IF_LARGEJMP) || (fmt == IF_T2_J2));
4110
4111     instrDescJmp* id  = emitNewInstrJmp();
4112     insSize       isz = emitInsSize(fmt);
4113
4114     id->idIns(ins);
4115     id->idInsFmt(fmt);
4116     id->idInsSize(isz);
4117
4118 #ifdef DEBUG
4119     // Mark the finally call
4120     if (ins == INS_b && emitComp->compCurBB->bbJumpKind == BBJ_CALLFINALLY)
4121     {
4122         id->idDebugOnlyInfo()->idFinallyCall = true;
4123     }
4124 #endif // DEBUG
4125
4126     /* Assume the jump will be long */
4127
4128     id->idjShort = 0;
4129     if (dst != NULL)
4130     {
4131         id->idAddr()->iiaBBlabel = dst;
4132         id->idjKeepLong          = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
4133
4134 #ifdef DEBUG
4135         if (emitComp->opts.compLongAddress) // Force long branches
4136             id->idjKeepLong = 1;
4137 #endif // DEBUG
4138     }
4139     else
4140     {
4141         id->idAddr()->iiaSetInstrCount(instrCount);
4142         id->idjKeepLong = false;
4143         /* This jump must be short */
4144         emitSetShortJump(id);
4145         id->idSetIsBound();
4146     }
4147
4148     /* Record the jump's IG and offset within it */
4149
4150     id->idjIG   = emitCurIG;
4151     id->idjOffs = emitCurIGsize;
4152
4153     /* Append this jump to this IG's jump list */
4154
4155     id->idjNext      = emitCurIGjmpList;
4156     emitCurIGjmpList = id;
4157
4158 #if EMITTER_STATS
4159     emitTotalIGjmps++;
4160 #endif
4161
4162     /* Figure out the max. size of the jump/call instruction */
4163
4164     if (!id->idjKeepLong)
4165     {
4166         insGroup* tgt = NULL;
4167
4168         /* Can we guess at the jump distance? */
4169
4170         if (dst != NULL)
4171         {
4172             tgt = (insGroup*)emitCodeGetCookie(dst);
4173         }
4174
4175         if (tgt)
4176         {
4177             UNATIVE_OFFSET srcOffs;
4178             int            jmpDist;
4179
4180             assert(JMP_SIZE_SMALL == JCC_SIZE_SMALL);
4181
4182             /* This is a backward jump - figure out the distance */
4183
4184             srcOffs = emitCurCodeOffset + emitCurIGsize;
4185
4186             /* Compute the distance estimate */
4187
4188             jmpDist = srcOffs - tgt->igOffs;
4189             assert(jmpDist >= 0);
4190             jmpDist += 4; // Adjustment for ARM PC
4191
4192             switch (fmt)
4193             {
4194                 case IF_T2_J2:
4195                     if (JMP_DIST_SMALL_MAX_NEG <= -jmpDist)
4196                     {
4197                         /* This jump surely will be short */
4198                         emitSetShortJump(id);
4199                     }
4200                     break;
4201
4202                 case IF_LARGEJMP:
4203                     if (JCC_DIST_SMALL_MAX_NEG <= -jmpDist)
4204                     {
4205                         /* This jump surely will be short */
4206                         emitSetShortJump(id);
4207                     }
4208                     else if (JCC_DIST_MEDIUM_MAX_NEG <= -jmpDist)
4209                     {
4210                         /* This jump surely will be medium */
4211                         emitSetMediumJump(id);
4212                     }
4213                     break;
4214
4215                 default:
4216                     unreached();
4217                     break;
4218             }
4219         }
4220     }
4221
4222     dispIns(id);
4223     appendToCurIG(id);
4224 }
4225
4226 /*****************************************************************************
4227  *
4228  *  Add a label instruction.
4229  */
4230
4231 void emitter::emitIns_R_L(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
4232 {
4233     assert(dst->bbFlags & BBF_JMP_TARGET);
4234
4235     insFormat     fmt = IF_NONE;
4236     instrDescJmp* id;
4237
4238     /* Figure out the encoding format of the instruction */
4239     switch (ins)
4240     {
4241         case INS_adr:
4242             id  = emitNewInstrLbl();
4243             fmt = IF_T2_M1;
4244             break;
4245         case INS_movt:
4246         case INS_movw:
4247             id  = emitNewInstrJmp();
4248             fmt = IF_T2_N1;
4249             break;
4250         default:
4251             unreached();
4252     }
4253     assert((fmt == IF_T2_M1) || (fmt == IF_T2_N1));
4254
4255     insSize isz = emitInsSize(fmt);
4256
4257     id->idIns(ins);
4258     id->idReg1(reg);
4259     id->idInsFmt(fmt);
4260     id->idInsSize(isz);
4261
4262 #ifdef DEBUG
4263     // Mark the catch return
4264     if (emitComp->compCurBB->bbJumpKind == BBJ_EHCATCHRET)
4265     {
4266         id->idDebugOnlyInfo()->idCatchRet = true;
4267     }
4268 #endif // DEBUG
4269
4270     id->idAddr()->iiaBBlabel = dst;
4271     id->idjShort             = false;
4272
4273     if (ins == INS_adr)
4274     {
4275         id->idReg2(REG_PC);
4276         id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
4277     }
4278     else
4279     {
4280         id->idjKeepLong = true;
4281     }
4282
4283     /* Record the jump's IG and offset within it */
4284
4285     id->idjIG   = emitCurIG;
4286     id->idjOffs = emitCurIGsize;
4287
4288     /* Append this jump to this IG's jump list */
4289
4290     id->idjNext      = emitCurIGjmpList;
4291     emitCurIGjmpList = id;
4292
4293     // Set the relocation flags - these give hint to zap to perform
4294     // relocation of the specified 32bit address.
4295     id->idSetRelocFlags(attr);
4296
4297 #if EMITTER_STATS
4298     emitTotalIGjmps++;
4299 #endif
4300
4301     dispIns(id);
4302     appendToCurIG(id);
4303 }
4304
4305 /*****************************************************************************
4306  *
4307  *  Add a data label instruction.
4308  */
4309
4310 void emitter::emitIns_R_D(instruction ins, emitAttr attr, unsigned offs, regNumber reg)
4311 {
4312     noway_assert((ins == INS_movw) || (ins == INS_movt));
4313
4314     insFormat  fmt = IF_T2_N2;
4315     instrDesc* id  = emitNewInstrSC(attr, offs);
4316     insSize    isz = emitInsSize(fmt);
4317
4318     id->idIns(ins);
4319     id->idReg1(reg);
4320     id->idInsFmt(fmt);
4321     id->idInsSize(isz);
4322
4323     if (emitComp->opts.compReloc)
4324     {
4325         // Set the relocation flags - these give hint to zap to perform
4326         // relocation of the specified 32bit address.
4327         id->idSetRelocFlags(attr);
4328     }
4329
4330     dispIns(id);
4331     appendToCurIG(id);
4332 }
4333
4334 void emitter::emitIns_J_R(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
4335 {
4336     assert(dst->bbFlags & BBF_JMP_TARGET);
4337
4338     insFormat fmt = IF_NONE;
4339     switch (ins)
4340     {
4341         case INS_cbz:
4342         case INS_cbnz:
4343             fmt = IF_T1_I;
4344             break;
4345         default:
4346             unreached();
4347     }
4348     assert(fmt == IF_T1_I);
4349
4350     assert(isLowRegister(reg));
4351
4352     instrDescJmp* id = emitNewInstrJmp();
4353     id->idIns(ins);
4354     id->idInsFmt(IF_T1_I);
4355     id->idInsSize(emitInsSize(IF_T1_I));
4356     id->idReg1(reg);
4357
4358     /* This jump better be short or-else! */
4359     id->idjShort             = true;
4360     id->idAddr()->iiaBBlabel = dst;
4361     id->idjKeepLong          = false;
4362
4363     /* Record the jump's IG and offset within it */
4364
4365     id->idjIG   = emitCurIG;
4366     id->idjOffs = emitCurIGsize;
4367
4368     /* Append this jump to this IG's jump list */
4369
4370     id->idjNext      = emitCurIGjmpList;
4371     emitCurIGjmpList = id;
4372
4373 #if EMITTER_STATS
4374     emitTotalIGjmps++;
4375 #endif
4376
4377     dispIns(id);
4378     appendToCurIG(id);
4379 }
4380
4381 /*****************************************************************************
4382  *
4383  *  Add a call instruction (direct or indirect).
4384  *      argSize<0 means that the caller will pop the arguments
4385  *
4386  * The other arguments are interpreted depending on callType as shown:
4387  * Unless otherwise specified, ireg,xreg,xmul,disp should have default values.
4388  *
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
4392  *
4393  * If callType is one of these emitCallTypes, addr has to be NULL.
4394  * EC_INDIR_R          : "call ireg".
4395  *
4396  * For ARM xreg, xmul and disp are never used and should always be 0/REG_NA.
4397  *
4398  *  Please consult the "debugger team notification" comment in genFnProlog().
4399  */
4400
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
4404                            void*            addr,
4405                            ssize_t          argSize,
4406                            emitAttr         retSize,
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     */,
4414                            int              disp /* = 0     */,
4415                            bool             isJump /* = false */,
4416                            bool             isNoGC /* = false */,
4417                            bool             isProfLeaveCB /* = false */)
4418 {
4419     /* Sanity check the arguments depending on callType */
4420
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));
4426
4427     // ARM never uses these
4428     assert(xreg == REG_NA && xmul == 0 && disp == 0);
4429
4430     // Our stack level should be always greater than the bytes of arguments we push. Just
4431     // a sanity test.
4432     assert((unsigned)abs(argSize) <= codeGen->genStackLevel);
4433
4434     int        argCnt;
4435     instrDesc* id;
4436
4437     /* This is the saved set of registers after a normal call */
4438     regMaskTP savedSet = RBM_CALLEE_SAVED;
4439
4440     /* some special helper calls have a different saved set registers */
4441
4442     if (isNoGC)
4443     {
4444         assert(emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
4445
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));
4448
4449         // In case of Leave profiler callback, we need to preserve liveness of REG_PROFILER_RET_SCRATCH
4450         if (isProfLeaveCB)
4451         {
4452             savedSet |= RBM_PROFILER_RET_SCRATCH;
4453         }
4454
4455 #ifdef DEBUG
4456         if (emitComp->verbose)
4457         {
4458             printf("NOGC Call: savedSet=");
4459             printRegMaskInt(savedSet);
4460             emitDispRegSet(savedSet);
4461             printf("\n");
4462         }
4463 #endif
4464     }
4465     else
4466     {
4467         assert(!emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
4468     }
4469
4470     /* Trim out any callee-trashed registers from the live set */
4471
4472     gcrefRegs &= savedSet;
4473     byrefRegs &= savedSet;
4474
4475 #ifdef DEBUG
4476     if (EMIT_GC_VERBOSE)
4477     {
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);
4486         printf("\n");
4487     }
4488 #endif
4489
4490     assert(argSize % (int)REGSIZE_BYTES == 0);
4491     argCnt = argSize / (int)REGSIZE_BYTES;
4492
4493     /* Managed RetVal: emit sequence point for the call */
4494     if (emitComp->opts.compDbgInfo && ilOffset != BAD_IL_OFFSET)
4495     {
4496         codeGen->genIPmappingAdd(ilOffset, false);
4497     }
4498
4499     /*
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.
4503
4504         The stats for a ton of classes is as follows:
4505
4506             Direct call w/o  GC vars        220,216
4507             Indir. call w/o  GC vars        144,781
4508
4509             Direct call with GC vars          9,440
4510             Indir. call with GC vars          5,768
4511      */
4512
4513     if (callType >= EC_INDIR_R)
4514     {
4515         /* Indirect call, virtual calls */
4516
4517         assert(callType == EC_INDIR_R);
4518
4519         id = emitNewInstrCallInd(argCnt, disp, ptrVars, gcrefRegs, byrefRegs, retSize);
4520     }
4521     else
4522     {
4523         /* Helper/static/nonvirtual/function calls (direct or through handle),
4524            and calls to an absolute addr. */
4525
4526         assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
4527
4528         id = emitNewInstrCallDir(argCnt, ptrVars, gcrefRegs, byrefRegs, retSize);
4529     }
4530
4531     /* Update the emitter's live GC ref sets */
4532
4533     VarSetOps::Assign(emitComp, emitThisGCrefVars, ptrVars);
4534     emitThisGCrefRegs = gcrefRegs;
4535     emitThisByrefRegs = byrefRegs;
4536
4537     /* Set the instruction - special case jumping a function */
4538     instruction ins;
4539     insFormat   fmt = IF_NONE;
4540
4541     id->idSetIsNoGC(isNoGC);
4542
4543     /* Record the address: method, indirection, or funcptr */
4544
4545     if (callType > EC_FUNC_ADDR)
4546     {
4547         /* This is an indirect call (either a virtual call or func ptr call) */
4548
4549         switch (callType)
4550         {
4551             case EC_INDIR_R: // the address is in a register
4552
4553                 id->idSetIsCallRegPtr();
4554
4555                 if (isJump)
4556                 {
4557                     ins = INS_bx; // INS_bx  Reg
4558                 }
4559                 else
4560                 {
4561                     ins = INS_blx; // INS_blx Reg
4562                 }
4563                 fmt = IF_T1_D2;
4564
4565                 id->idIns(ins);
4566                 id->idInsFmt(fmt);
4567                 id->idInsSize(emitInsSize(fmt));
4568                 id->idReg3(ireg);
4569                 assert(xreg == REG_NA);
4570                 break;
4571
4572             default:
4573                 NO_WAY("unexpected instruction");
4574                 break;
4575         }
4576     }
4577     else
4578     {
4579         /* This is a simple direct call: "call helper/method/addr" */
4580
4581         assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
4582
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));
4585
4586         if (isJump)
4587         {
4588             ins = INS_b; // INS_b imm24
4589         }
4590         else
4591         {
4592             ins = INS_bl; // INS_bl imm24
4593         }
4594
4595         fmt = IF_T2_J3;
4596
4597         id->idIns(ins);
4598         id->idInsFmt(fmt);
4599         id->idInsSize(emitInsSize(fmt));
4600
4601         id->idAddr()->iiaAddr = (BYTE*)addr;
4602
4603         if (callType == EC_FUNC_ADDR)
4604         {
4605             id->idSetIsCallAddr();
4606         }
4607
4608         if (emitComp->opts.compReloc)
4609         {
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.
4613
4614             id->idSetIsDspReloc();
4615         }
4616     }
4617
4618 #ifdef DEBUG
4619     if (EMIT_GC_VERBOSE)
4620     {
4621         if (id->idIsLargeCall())
4622         {
4623             printf("[%02u] Rec call GC vars = %s\n", id->idDebugOnlyInfo()->idNum,
4624                    VarSetOps::ToString(emitComp, ((instrDescCGCA*)id)->idcGCvars));
4625         }
4626     }
4627
4628     id->idDebugOnlyInfo()->idMemCookie = (size_t)methHnd; // method token
4629     id->idDebugOnlyInfo()->idCallSig   = sigInfo;
4630 #endif // DEBUG
4631
4632 #ifdef LATE_DISASM
4633     if (addr != nullptr)
4634     {
4635         codeGen->getDisAssembler().disSetMethod((size_t)addr, methHnd);
4636     }
4637 #endif // LATE_DISASM
4638
4639     dispIns(id);
4640     appendToCurIG(id);
4641 }
4642
4643 /*****************************************************************************
4644  *
4645  *  Returns an encoding for the specified register (any-reg) to be used in
4646  *   a Thumb-1 encoding in the M4 position
4647  */
4648
4649 inline unsigned insEncodeRegT1_M4(regNumber reg)
4650 {
4651     assert(reg < REG_STK);
4652
4653     return reg << 3;
4654 }
4655
4656 /*****************************************************************************
4657  *
4658  *  Returns an encoding for the specified register (any-reg) to be used in
4659  *   a Thumb-1 encoding in the D4 position
4660  */
4661
4662 inline unsigned insEncodeRegT1_D4(regNumber reg)
4663 {
4664     assert(reg < REG_STK);
4665
4666     return (reg & 0x7) | ((reg & 0x8) << 4);
4667 }
4668
4669 /*****************************************************************************
4670  *
4671  *  Returns an encoding for the specified register (low-only) to be used in
4672  *   a Thumb-1 encoding in the M3 position
4673  */
4674
4675 inline unsigned insEncodeRegT1_M3(regNumber reg)
4676 {
4677     assert(reg < REG_R8);
4678
4679     return reg << 6;
4680 }
4681
4682 /*****************************************************************************
4683  *
4684  *  Returns an encoding for the specified register (low-only) to be used in
4685  *   a Thumb-1 encoding in the N3 position
4686  */
4687
4688 inline unsigned insEncodeRegT1_N3(regNumber reg)
4689 {
4690     assert(reg < REG_R8);
4691
4692     return reg << 3;
4693 }
4694
4695 /*****************************************************************************
4696  *
4697  *  Returns an encoding for the specified register (low-only) to be used in
4698  *   a Thumb-1 encoding in the D3 position
4699  */
4700
4701 inline unsigned insEncodeRegT1_D3(regNumber reg)
4702 {
4703     assert(reg < REG_R8);
4704
4705     return reg;
4706 }
4707 /*****************************************************************************
4708  *
4709  *  Returns an encoding for the specified register (low-only) to be used in
4710  *   a Thumb-1 encoding in the DI position
4711  */
4712
4713 inline unsigned insEncodeRegT1_DI(regNumber reg)
4714 {
4715     assert(reg < REG_R8);
4716
4717     return reg << 8;
4718 }
4719
4720 /*****************************************************************************
4721  *
4722  *  Returns an encoding for the specified register to be used in
4723  *   a Thumb-2 encoding in the N position
4724  */
4725
4726 inline unsigned insEncodeRegT2_N(regNumber reg)
4727 {
4728     assert(reg < REG_STK);
4729
4730     return reg << 16;
4731 }
4732
4733 inline unsigned floatRegIndex(regNumber reg, int size)
4734 {
4735     // theoretically this could support quad floats as well but for now...
4736     assert(size == EA_8BYTE || size == EA_4BYTE);
4737
4738     if (size == EA_8BYTE)
4739         assert(emitter::isDoubleReg(reg));
4740     else
4741         assert(emitter::isFloatReg(reg));
4742
4743     unsigned result = reg - REG_F0;
4744
4745     // the assumption here is that the register F8 also refers to D4
4746     if (size == EA_8BYTE)
4747     {
4748         result >>= 1;
4749     }
4750
4751     return result;
4752 }
4753
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);
4759
4760 inline unsigned floatRegEncoding(unsigned index, int size, bool variant = false)
4761 {
4762     if (!variant || size == EA_8BYTE)
4763         return index;
4764     else
4765     {
4766         return ((index & 1) << 4) | (index >> 1);
4767     }
4768 }
4769
4770 // thumb2 VFP M register encoding
4771 inline unsigned insEncodeRegT2_VectorM(regNumber reg, int size, bool variant)
4772 {
4773     unsigned enc = floatRegIndex(reg, size);
4774     enc          = floatRegEncoding(enc, size, variant);
4775     return ((enc & 0xf) << 0) | ((enc & 0x10) << 1);
4776 }
4777
4778 // thumb2 VFP N register encoding
4779 inline unsigned insEncodeRegT2_VectorN(regNumber reg, int size, bool variant)
4780 {
4781     unsigned enc = floatRegIndex(reg, size);
4782     enc          = floatRegEncoding(enc, size, variant);
4783     return ((enc & 0xf) << 16) | ((enc & 0x10) << 3);
4784 }
4785
4786 // thumb2 VFP D register encoding
4787 inline unsigned insEncodeRegT2_VectorD(regNumber reg, int size, bool variant)
4788 {
4789     unsigned enc = floatRegIndex(reg, size);
4790     enc          = floatRegEncoding(enc, size, variant);
4791     return ((enc & 0xf) << 12) | ((enc & 0x10) << 18);
4792 }
4793
4794 /*****************************************************************************
4795  *
4796  *  Returns an encoding for the specified register to be used in
4797  *   a Thumb-2 encoding in the T position
4798  */
4799
4800 inline unsigned insEncodeRegT2_T(regNumber reg)
4801 {
4802     assert(reg < REG_STK);
4803
4804     return reg << 12;
4805 }
4806
4807 /*****************************************************************************
4808  *
4809  *  Returns an encoding for the specified register to be used in
4810  *   a Thumb-2 encoding in the D position
4811  */
4812
4813 inline unsigned insEncodeRegT2_D(regNumber reg)
4814 {
4815     assert(reg < REG_STK);
4816
4817     return reg << 8;
4818 }
4819
4820 /*****************************************************************************
4821  *
4822  *  Returns an encoding for the specified register to be used in
4823  *   a Thumb-2 encoding in the M position
4824  */
4825
4826 inline unsigned insEncodeRegT2_M(regNumber reg)
4827 {
4828     assert(reg < REG_STK);
4829
4830     return reg;
4831 }
4832
4833 /*****************************************************************************
4834  *
4835  *  Returns the encoding for the Set Flags bit to be used in a Thumb-2 encoding
4836  */
4837
4838 unsigned emitter::insEncodeSetFlags(insFlags sf)
4839 {
4840     if (sf == INS_FLAGS_SET)
4841         return (1 << 20);
4842     else
4843         return 0;
4844 }
4845
4846 /*****************************************************************************
4847  *
4848  *  Returns the encoding for the Shift Type bits to be used in a Thumb-2 encoding
4849  */
4850
4851 unsigned emitter::insEncodeShiftOpts(insOpts opt)
4852 {
4853     if (opt == INS_OPTS_NONE)
4854         return 0;
4855     else if (opt == INS_OPTS_LSL)
4856         return 0x00;
4857     else if (opt == INS_OPTS_LSR)
4858         return 0x10;
4859     else if (opt == INS_OPTS_ASR)
4860         return 0x20;
4861     else if (opt == INS_OPTS_ROR)
4862         return 0x30;
4863     else if (opt == INS_OPTS_RRX)
4864         return 0x30;
4865
4866     assert(!"Invalid insOpts");
4867     return 0;
4868 }
4869
4870 /*****************************************************************************
4871  *
4872  *  Returns the encoding for the PUW bits to be used in a T2_G0 Thumb-2 encoding
4873  */
4874
4875 unsigned emitter::insEncodePUW_G0(insOpts opt, int imm)
4876 {
4877     unsigned result = 0;
4878
4879     if (opt != INS_OPTS_LDST_POST_INC)
4880         result |= (1 << 24); // The P bit
4881
4882     if (imm >= 0)
4883         result |= (1 << 23); // The U bit
4884
4885     if (opt != INS_OPTS_NONE)
4886         result |= (1 << 21); // The W bits
4887     return result;
4888 }
4889
4890 /*****************************************************************************
4891  *
4892  *  Returns the encoding for the PUW bits to be used in a T2_H0 Thumb-2 encoding
4893  */
4894
4895 unsigned emitter::insEncodePUW_H0(insOpts opt, int imm)
4896 {
4897     unsigned result = 0;
4898
4899     if (opt != INS_OPTS_LDST_POST_INC)
4900         result |= (1 << 10); // The P bit
4901
4902     if (imm >= 0)
4903         result |= (1 << 9); // The U bit
4904
4905     if (opt != INS_OPTS_NONE)
4906         result |= (1 << 8); // The W bits
4907
4908     return result;
4909 }
4910
4911 /*****************************************************************************
4912  *
4913  *  Returns the encoding for the Shift Count bits to be used in a Thumb-2 encoding
4914  */
4915
4916 inline unsigned insEncodeShiftCount(int imm)
4917 {
4918     unsigned result;
4919
4920     assert((imm & 0x001F) == imm);
4921     result = (imm & 0x03) << 6;
4922     result |= (imm & 0x1C) << 10;
4923
4924     return result;
4925 }
4926
4927 /*****************************************************************************
4928  *
4929  *  Returns the encoding for the immediate use by BFI/BFC Thumb-2 encodings
4930  */
4931
4932 inline unsigned insEncodeBitFieldImm(int imm)
4933 {
4934     unsigned result;
4935
4936     assert((imm & 0x03FF) == imm);
4937     result = (imm & 0x001f);
4938     result |= (imm & 0x0060) << 1;
4939     result |= (imm & 0x0380) << 5;
4940
4941     return result;
4942 }
4943
4944 /*****************************************************************************
4945  *
4946  *  Returns an encoding for the immediate use by MOV/MOVW Thumb-2 encodings
4947  */
4948
4949 inline unsigned insEncodeImmT2_Mov(int imm)
4950 {
4951     unsigned result;
4952
4953     assert((imm & 0x0000ffff) == imm);
4954     result = (imm & 0x00ff);
4955     result |= ((imm & 0x0700) << 4);
4956     result |= ((imm & 0x0800) << 15);
4957     result |= ((imm & 0xf000) << 4);
4958
4959     return result;
4960 }
4961
4962 /*****************************************************************************
4963  *
4964  *  Unscales the immediate based on the operand size in 'size'
4965  */
4966 /*static*/ int emitter::insUnscaleImm(int imm, emitAttr size)
4967 {
4968     switch (size)
4969     {
4970         case EA_8BYTE:
4971         case EA_4BYTE:
4972             assert((imm & 0x0003) == 0);
4973             imm >>= 2;
4974             break;
4975
4976         case EA_2BYTE:
4977             assert((imm & 0x0001) == 0);
4978             imm >>= 1;
4979             break;
4980
4981         case EA_1BYTE:
4982             // Do nothing
4983             break;
4984
4985         default:
4986             assert(!"Invalid value in size");
4987             break;
4988     }
4989     return imm;
4990 }
4991
4992 /*****************************************************************************
4993  *
4994  *  Emit a Thumb-1 instruction (a 16-bit integer as code)
4995  */
4996
4997 /*static*/ unsigned emitter::emitOutput_Thumb1Instr(BYTE* dst, code_t code)
4998 {
4999     unsigned short word1 = code & 0xffff;
5000     assert(word1 == code);
5001
5002 #ifdef DEBUG
5003     unsigned short top5bits = (word1 & 0xf800) >> 11;
5004     assert(top5bits < 29);
5005 #endif
5006
5007     MISALIGNED_WR_I2(dst, word1);
5008
5009     return sizeof(short);
5010 }
5011 /*****************************************************************************
5012  *
5013  *  Emit a Thumb-2 instruction (two 16-bit integers as code)
5014  */
5015
5016 /*static*/ unsigned emitter::emitOutput_Thumb2Instr(BYTE* dst, code_t code)
5017 {
5018     unsigned short word1 = (code >> 16) & 0xffff;
5019     unsigned short word2 = (code)&0xffff;
5020     assert((code_t)((word1 << 16) | word2) == code);
5021
5022 #ifdef DEBUG
5023     unsigned short top5bits = (word1 & 0xf800) >> 11;
5024     assert(top5bits >= 29);
5025 #endif
5026
5027     MISALIGNED_WR_I2(dst, word1);
5028     dst += 2;
5029     MISALIGNED_WR_I2(dst, word2);
5030
5031     return sizeof(short) * 2;
5032 }
5033
5034 /*****************************************************************************
5035  *
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.
5039  */
5040
5041 BYTE* emitter::emitOutputLJ(insGroup* ig, BYTE* dst, instrDesc* i)
5042 {
5043     unsigned srcOffs;
5044     unsigned dstOffs;
5045     ssize_t  distVal;
5046
5047     instrDescJmp* id  = (instrDescJmp*)i;
5048     instruction   ins = id->idIns();
5049     code_t        code;
5050
5051     bool loadLabel = false;
5052     bool isJump    = false;
5053     bool relAddr   = true; // does the instruction use relative-addressing?
5054
5055     size_t sdistneg;
5056
5057     switch (ins)
5058     {
5059         default:
5060             sdistneg = JCC_DIST_SMALL_MAX_NEG;
5061             isJump   = true;
5062             break;
5063
5064         case INS_cbz:
5065         case INS_cbnz:
5066             // One size fits all!
5067             sdistneg = 0;
5068             isJump   = true;
5069             break;
5070
5071         case INS_adr:
5072             sdistneg  = LBL_DIST_SMALL_MAX_NEG;
5073             loadLabel = true;
5074             break;
5075
5076         case INS_movw:
5077         case INS_movt:
5078             sdistneg  = LBL_DIST_SMALL_MAX_NEG;
5079             relAddr   = false;
5080             loadLabel = true;
5081             break;
5082     }
5083
5084     /* Figure out the distance to the target */
5085
5086     srcOffs = emitCurCodeOffs(dst);
5087     if (id->idAddr()->iiaHasInstrCount())
5088     {
5089         assert(ig != NULL);
5090         int      instrCount = id->idAddr()->iiaGetInstrCount();
5091         unsigned insNum     = emitFindInsNum(ig, id);
5092         if (instrCount < 0)
5093         {
5094             // Backward branches using instruction count must be within the same instruction group.
5095             assert(insNum + 1 >= (unsigned)(-instrCount));
5096         }
5097         dstOffs = ig->igOffs + emitFindOffset(ig, (insNum + 1 + instrCount));
5098     }
5099     else
5100     {
5101         dstOffs = id->idAddr()->iiaIGlabel->igOffs;
5102     }
5103
5104     if (relAddr)
5105     {
5106         if (ins == INS_adr)
5107         {
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);
5110         }
5111         else
5112         {
5113             distVal = (ssize_t)(emitOffsetToPtr(dstOffs) - emitOffsetToPtr(srcOffs));
5114         }
5115     }
5116     else
5117     {
5118         assert(ins == INS_movw || ins == INS_movt);
5119         distVal = (ssize_t)emitOffsetToPtr(dstOffs) + 1; // Or in thumb bit
5120     }
5121
5122     if (dstOffs <= srcOffs)
5123     {
5124 /* This is a backward jump - distance is known at this point */
5125
5126 #if DEBUG_EMIT
5127         if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
5128         {
5129             size_t blkOffs = id->idjIG->igOffs;
5130
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);
5136         }
5137 #endif
5138
5139         // This format only supports forward branches
5140         noway_assert(id->idInsFmt() != IF_T1_I);
5141
5142         /* Can we use a short jump? */
5143
5144         if (isJump && ((unsigned)(distVal - 4) >= (unsigned)sdistneg))
5145         {
5146             emitSetShortJump(id);
5147         }
5148     }
5149     else
5150     {
5151         /* This is a  forward jump - distance will be an upper limit */
5152
5153         emitFwdJumps = true;
5154
5155         /* The target offset will be closer by at least 'emitOffsAdj', but only if this
5156            jump doesn't cross the hot-cold boundary. */
5157
5158         if (!emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
5159         {
5160             dstOffs -= emitOffsAdj;
5161             distVal -= emitOffsAdj;
5162         }
5163
5164         /* Record the location of the jump for later patching */
5165
5166         id->idjOffs = dstOffs;
5167
5168         /* Are we overflowing the id->idjOffs bitfield? */
5169         if (id->idjOffs != dstOffs)
5170             IMPL_LIMITATION("Method is too large");
5171
5172 #if DEBUG_EMIT
5173         if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
5174         {
5175             size_t blkOffs = id->idjIG->igOffs;
5176
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);
5182         }
5183 #endif
5184     }
5185
5186     /* Adjust the offset to emit relative to the end of the instruction */
5187
5188     if (relAddr)
5189         distVal -= 4;
5190
5191 #ifdef DEBUG
5192     if (0 && emitComp->verbose)
5193     {
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);
5198     }
5199 #endif
5200
5201     insFormat fmt = id->idInsFmt();
5202
5203     if (isJump)
5204     {
5205         /* What size jump should we use? */
5206
5207         if (id->idjShort)
5208         {
5209             /* Short jump */
5210
5211             assert(!id->idjKeepLong);
5212             assert(emitJumpCrossHotColdBoundary(srcOffs, dstOffs) == false);
5213
5214             assert(JMP_SIZE_SMALL == JCC_SIZE_SMALL);
5215             assert(JMP_SIZE_SMALL == 2);
5216
5217             /* For forward jumps, record the address of the distance value */
5218             id->idjTemp.idjAddr = (distVal > 0) ? dst : NULL;
5219
5220             dst = emitOutputShortBranch(dst, ins, fmt, distVal, id);
5221         }
5222         else
5223         {
5224             /* Long  jump */
5225
5226             /* For forward jumps, record the address of the distance value */
5227             id->idjTemp.idjAddr = (dstOffs > srcOffs) ? dst : NULL;
5228
5229             if (fmt == IF_LARGEJMP)
5230             {
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
5234                 // branch.
5235                 //
5236                 // Conceptually, we have:
5237                 //
5238                 //      b<cond> L_target
5239                 //
5240                 // The code we emit is:
5241                 //
5242                 //      b<!cond> L_not  // 2 bytes. Note that we reverse the condition.
5243                 //      b L_target      // 4 bytes
5244                 //   L_not:
5245                 //
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).
5250                 //
5251                 // History: previously, we generated:
5252                 //      it<cond>
5253                 //      b L_target
5254                 // but the "it" instruction was deprecated, so we can't use it.
5255
5256                 dst = emitOutputShortBranch(dst,
5257                                             emitJumpKindToIns(emitReverseJumpKind(
5258                                                 emitInsToJumpKind(ins))), // reverse the conditional instruction
5259                                             IF_T1_K,
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 */);
5263
5264                 // Now, pretend we've got a normal unconditional branch, and fall through to the code to emit that.
5265                 ins = INS_b;
5266                 fmt = IF_T2_J2;
5267
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.
5271                 distVal -= 2;
5272             }
5273
5274             code = emitInsCode(ins, fmt);
5275
5276             if (fmt == IF_T2_J1)
5277             {
5278                 // Can't use this form for jumps between the hot and cold regions
5279                 assert(!id->idjKeepLong);
5280                 assert(emitJumpCrossHotColdBoundary(srcOffs, dstOffs) == false);
5281
5282                 assert((distVal & 1) == 0);
5283                 assert(distVal >= -1048576);
5284                 assert(distVal <= 1048574);
5285
5286                 if (distVal < 0)
5287                     code |= 1 << 26;
5288                 code |= ((distVal >> 1) & 0x0007ff);
5289                 code |= (((distVal >> 1) & 0x01f800) << 5);
5290                 code |= (((distVal >> 1) & 0x020000) >> 4);
5291                 code |= (((distVal >> 1) & 0x040000) >> 7);
5292             }
5293             else if (fmt == IF_T2_J2)
5294             {
5295                 assert((distVal & 1) == 0);
5296                 if (emitComp->opts.compReloc && emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
5297                 {
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
5302                 }
5303                 else
5304                 {
5305                     assert(distVal >= CALL_DIST_MAX_NEG);
5306                     assert(distVal <= CALL_DIST_MAX_POS);
5307
5308                     if (distVal < 0)
5309                         code |= 1 << 26;
5310                     code |= ((distVal >> 1) & 0x0007ff);
5311                     code |= (((distVal >> 1) & 0x1ff800) << 5);
5312
5313                     bool S  = (distVal < 0);
5314                     bool I1 = ((distVal & 0x00800000) == 0);
5315                     bool I2 = ((distVal & 0x00400000) == 0);
5316
5317                     if (S ^ I1)
5318                         code |= (1 << 13); // J1 bit
5319                     if (S ^ I2)
5320                         code |= (1 << 11); // J2 bit
5321                 }
5322             }
5323             else
5324             {
5325                 assert(!"Unknown fmt");
5326             }
5327
5328             unsigned instrSize = emitOutput_Thumb2Instr(dst, code);
5329
5330             if (emitComp->opts.compReloc)
5331             {
5332                 if (emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
5333                 {
5334                     assert(id->idjKeepLong);
5335                     if (emitComp->info.compMatchedVM)
5336                     {
5337                         void* target = emitOffsetToPtr(dstOffs);
5338                         emitRecordRelocation((void*)dst, target, IMAGE_REL_BASED_THUMB_BRANCH24);
5339                     }
5340                 }
5341             }
5342
5343             dst += instrSize;
5344         }
5345     }
5346     else if (loadLabel)
5347     {
5348         /* For forward jumps, record the address of the distance value */
5349         id->idjTemp.idjAddr = (distVal > 0) ? dst : NULL;
5350
5351         code = emitInsCode(ins, fmt);
5352
5353         if (fmt == IF_T1_J3)
5354         {
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);
5359
5360             dst += emitOutput_Thumb1Instr(dst, code);
5361         }
5362         else if (fmt == IF_T2_M1)
5363         {
5364             assert(distVal >= -4095);
5365             assert(distVal <= +4095);
5366             if (distVal < 0)
5367             {
5368                 code |= 0x00A0 << 16;
5369                 distVal = -distVal;
5370             }
5371             assert((distVal & 0x0fff) == distVal);
5372             code |= (distVal & 0x00ff);
5373             code |= ((distVal & 0x0700) << 4);
5374
5375             code |= ((distVal & 0x0800) << 15);
5376             code |= id->idReg1() << 8;
5377
5378             dst += emitOutput_Thumb2Instr(dst, code);
5379         }
5380         else if (fmt == IF_T2_N1)
5381         {
5382             code |= insEncodeRegT2_D(id->idReg1());
5383             unsigned imm = distVal;
5384             if (ins == INS_movw)
5385             {
5386                 imm &= 0xffff;
5387             }
5388             else
5389             {
5390                 imm = (imm >> 16) & 0xffff;
5391             }
5392             ((instrDescJmp*)id)->idjTemp.idjAddr = (dstOffs > srcOffs) ? dst : NULL;
5393
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);
5400
5401             if (id->idIsCnsReloc() || id->idIsDspReloc())
5402             {
5403                 assert(ins == INS_movt || ins == INS_movw);
5404                 if ((ins == INS_movt) && emitComp->info.compMatchedVM)
5405                     emitHandlePCRelativeMov32((void*)(dst - 8), (void*)distVal);
5406             }
5407         }
5408         else
5409         {
5410             assert(!"Unknown fmt");
5411         }
5412     }
5413
5414     return dst;
5415 }
5416
5417 /*****************************************************************************
5418  *
5419  *  Output a short branch instruction.
5420  */
5421
5422 BYTE* emitter::emitOutputShortBranch(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, instrDescJmp* id)
5423 {
5424     code_t code;
5425
5426     code = emitInsCode(ins, fmt);
5427
5428     if (fmt == IF_T1_K)
5429     {
5430         assert((distVal & 1) == 0);
5431         assert(distVal >= -256);
5432         assert(distVal <= 254);
5433
5434         if (distVal < 0)
5435             code |= 1 << 7;
5436         code |= ((distVal >> 1) & 0x7f);
5437     }
5438     else if (fmt == IF_T1_M)
5439     {
5440         assert((distVal & 1) == 0);
5441         assert(distVal >= -2048);
5442         assert(distVal <= 2046);
5443
5444         if (distVal < 0)
5445             code |= 1 << 10;
5446         code |= ((distVal >> 1) & 0x3ff);
5447     }
5448     else if (fmt == IF_T1_I)
5449     {
5450         assert(id != NULL);
5451         assert(ins == INS_cbz || INS_cbnz);
5452         assert((distVal & 1) == 0);
5453         assert(distVal >= 0);
5454         assert(distVal <= 126);
5455
5456         code |= ((distVal << 3) & 0x0200);
5457         code |= ((distVal << 2) & 0x00F8);
5458         code |= (id->idReg1() & 0x0007);
5459     }
5460     else
5461     {
5462         assert(!"Unknown fmt");
5463     }
5464
5465     dst += emitOutput_Thumb1Instr(dst, code);
5466
5467     return dst;
5468 }
5469
5470 #ifdef FEATURE_ITINSTRUCTION
5471
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  *****************************************************************************/
5476
5477 /*****************************************************************************
5478  *
5479  *  Output an IT instruction.
5480  */
5481
5482 BYTE* emitter::emitOutputIT(BYTE* dst, instruction ins, insFormat fmt, code_t condcode)
5483 {
5484     code_t imm0;
5485     code_t code, mask, bit;
5486
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))
5496         {
5497             code |= bit; // set the current bit
5498         }
5499         else
5500         {
5501             code &= ~bit; // clear the current bit
5502         }
5503         bit >>= 1;
5504     }
5505     dst += emitOutput_Thumb1Instr(dst, code);
5506
5507     return dst;
5508 }
5509
5510 #endif // FEATURE_ITINSTRUCTION
5511
5512 /*****************************************************************************
5513 *
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.
5519  */
5520
5521 size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
5522 {
5523     BYTE*         dst           = *dp;
5524     BYTE*         odst          = dst;
5525     code_t        code          = 0;
5526     size_t        sz            = 0;
5527     instruction   ins           = id->idIns();
5528     insFormat     fmt           = id->idInsFmt();
5529     emitAttr      size          = id->idOpSize();
5530     unsigned char callInstrSize = 0;
5531
5532 #ifdef DEBUG
5533     bool dspOffs = emitComp->opts.dspGCtbls || !emitComp->opts.disDiffable;
5534 #endif // DEBUG
5535
5536     assert(REG_NA == (int)REG_NA);
5537
5538     VARSET_TP GCvars(VarSetOps::UninitVal());
5539
5540     /* What instruction format have we got? */
5541
5542     switch (fmt)
5543     {
5544         int       imm;
5545         BYTE*     addr;
5546         regMaskTP gcrefRegs;
5547         regMaskTP byrefRegs;
5548
5549         case IF_T1_A: // T1_A    ................
5550             sz   = SMALL_IDSC_SIZE;
5551             code = emitInsCode(ins, fmt);
5552             dst += emitOutput_Thumb1Instr(dst, code);
5553             break;
5554
5555 #ifdef FEATURE_ITINSTRUCTION
5556         case IF_T1_B: // T1_B    ........cccc....                                           cond
5557         {
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;
5562         }
5563         break;
5564 #endif // FEATURE_ITINSTRUCTION
5565
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))
5573             {
5574                 imm = insUnscaleImm(imm, size);
5575             }
5576             assert((imm & 0x001f) == imm);
5577             code |= (imm << 6);
5578             dst += emitOutput_Thumb1Instr(dst, code);
5579             break;
5580
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);
5587             break;
5588
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);
5595             break;
5596
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);
5603             code |= imm;
5604             dst += emitOutput_Thumb1Instr(dst, code);
5605             break;
5606
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);
5614             code |= (imm << 6);
5615             dst += emitOutput_Thumb1Instr(dst, code);
5616             break;
5617
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);
5625             break;
5626
5627         case IF_T1_I: // T1_I    ......i.iiiiiddd                       R1                  imm6
5628             assert(id->idIsBound());
5629
5630             dst = emitOutputLJ(ig, dst, id);
5631             sz  = sizeof(instrDescJmp);
5632             break;
5633
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)
5642             {
5643                 imm = insUnscaleImm(imm, size);
5644             }
5645             assert((imm & 0x00ff) == imm);
5646             code |= imm;
5647             dst += emitOutput_Thumb1Instr(dst, code);
5648             break;
5649
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)
5656             {
5657                 assert((imm & 0x3) != 0x3);
5658                 if (imm & 0x3)
5659                     code |= 0x0100; //  R bit
5660                 imm >>= 2;
5661             }
5662             assert((imm & 0x00ff) == imm);
5663             code |= imm;
5664             dst += emitOutput_Thumb1Instr(dst, code);
5665             break;
5666
5667         case IF_T2_A: // T2_A    ................ ................
5668             sz   = SMALL_IDSC_SIZE;
5669             code = emitInsCode(ins, fmt);
5670             dst += emitOutput_Thumb2Instr(dst, code);
5671             break;
5672
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);
5678             code |= imm;
5679             dst += emitOutput_Thumb2Instr(dst, code);
5680             break;
5681
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)
5693             {
5694                 imm = emitGetInsSC(id);
5695                 code |= insEncodeShiftCount(imm);
5696                 code |= insEncodeShiftOpts(id->idInsOpt());
5697             }
5698             dst += emitOutput_Thumb2Instr(dst, code);
5699             break;
5700
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)
5710             {
5711                 assert((imm & 0x0018) == imm);
5712                 code |= (imm << 1);
5713             }
5714             else
5715             {
5716                 code |= insEncodeSetFlags(id->idInsFlags());
5717                 code |= insEncodeShiftCount(imm);
5718                 if (fmt == IF_T2_C1)
5719                     code |= insEncodeShiftOpts(id->idInsOpt());
5720             }
5721             dst += emitOutput_Thumb2Instr(dst, code);
5722             break;
5723
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);
5731             break;
5732
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)
5741             {
5742                 assert((imm & 0x0003) == imm);
5743                 code |= (imm << 4);
5744             }
5745             else if (fmt == IF_T2_C8)
5746             {
5747                 code |= insEncodeShiftCount(imm);
5748                 code |= insEncodeShiftOpts(id->idInsOpt());
5749             }
5750             dst += emitOutput_Thumb2Instr(dst, code);
5751             break;
5752
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);
5759             break;
5760
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);
5768             break;
5769
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);
5780             break;
5781
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)
5788             {
5789                 sz = emitGetInstrDescSize(id);
5790                 code |= insEncodeRegT2_N(id->idReg2());
5791                 if (id->idIsLclVar())
5792                 {
5793                     code |= insEncodeRegT2_M(codeGen->rsGetRsvdReg());
5794                     imm = 0;
5795                 }
5796                 else
5797                 {
5798                     code |= insEncodeRegT2_M(id->idReg3());
5799                     imm = emitGetInsSC(id);
5800                     assert((imm & 0x0003) == imm);
5801                     code |= (imm << 4);
5802                 }
5803             }
5804             else
5805             {
5806                 sz = SMALL_IDSC_SIZE;
5807                 if (fmt != IF_T2_E2)
5808                 {
5809                     code |= insEncodeRegT2_N(id->idReg2());
5810                 }
5811             }
5812             dst += emitOutput_Thumb2Instr(dst, code);
5813             break;
5814
5815         case IF_T2_F1: // T2_F1    ............nnnn ttttdddd....mmmm       R1  R2  R3  R4
5816             sz = emitGetInstrDescSize(id);
5817             ;
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);
5824             break;
5825
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);
5834             break;
5835
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)
5843             {
5844                 sz  = emitGetInstrDescSizeSC(id);
5845                 imm = emitGetInsSC(id);
5846                 assert(unsigned_abs(imm) <= 0x00ff);
5847                 code |= abs(imm);
5848                 code |= insEncodePUW_G0(id->idInsOpt(), imm);
5849             }
5850             else
5851             {
5852                 sz = emitGetInstrDescSize(id);
5853             }
5854             dst += emitOutput_Thumb2Instr(dst, code);
5855             break;
5856
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());
5864
5865             if (fmt != IF_T2_H2)
5866                 code |= insEncodeRegT2_N(id->idReg2());
5867
5868             if (fmt == IF_T2_H0)
5869             {
5870                 assert(unsigned_abs(imm) <= 0x00ff);
5871                 code |= insEncodePUW_H0(id->idInsOpt(), imm);
5872                 code |= unsigned_abs(imm);
5873             }
5874             else
5875             {
5876                 assert((imm & 0x00ff) == imm);
5877                 code |= imm;
5878             }
5879             dst += emitOutput_Thumb2Instr(dst, code);
5880             break;
5881
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)
5887             {
5888                 code |= insEncodeRegT2_N(id->idReg1());
5889                 code |= (1 << 21); //  W bit
5890             }
5891             imm = emitGetInsSC(id);
5892             assert((imm & 0x3) != 0x3);
5893             if (imm & 0x2)
5894                 code |= 0x8000; //  PC bit
5895             if (imm & 0x1)
5896                 code |= 0x4000; //  LR bit
5897             imm >>= 2;
5898             assert(imm <= 0x1fff); //  13 bits
5899             code |= imm;
5900             dst += emitOutput_Thumb2Instr(dst, code);
5901             break;
5902
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)
5910             {
5911                 code |= insEncodeRegT2_T(id->idReg1());
5912             }
5913             if (fmt == IF_T2_K1)
5914             {
5915                 code |= insEncodeRegT2_N(id->idReg2());
5916                 assert(imm <= 0xfff); //  12 bits
5917                 code |= imm;
5918             }
5919             else
5920             {
5921                 assert(unsigned_abs(imm) <= 0xfff); //  12 bits (signed)
5922                 code |= abs(imm);
5923                 if (imm >= 0)
5924                     code |= (1 << 23); //  U bit
5925             }
5926             dst += emitOutput_Thumb2Instr(dst, code);
5927             break;
5928
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
5935             code |= imm;
5936             dst += emitOutput_Thumb2Instr(dst, code);
5937             break;
5938
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);
5945
5946             if (fmt == IF_T2_L2)
5947                 code |= insEncodeRegT2_N(id->idReg1());
5948             else
5949             {
5950                 code |= insEncodeSetFlags(id->idInsFlags());
5951                 code |= insEncodeRegT2_D(id->idReg1());
5952                 if (fmt == IF_T2_L0)
5953                     code |= insEncodeRegT2_N(id->idReg2());
5954             }
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);
5962             break;
5963
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);
5977             break;
5978
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())
5985             {
5986                 if (ins == INS_movw)
5987                 {
5988                     imm &= 0xffff;
5989                 }
5990                 else
5991                 {
5992                     assert(ins == INS_movt);
5993                     imm = (imm >> 16) & 0xffff;
5994                 }
5995             }
5996
5997             assert(!id->idIsReloc());
5998             code |= insEncodeImmT2_Mov(imm);
5999             dst += emitOutput_Thumb2Instr(dst, code);
6000             break;
6001
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())
6009             {
6010                 assert(sizeof(size_t) == sizeof(target_size_t));
6011                 imm = (target_size_t)addr;
6012                 if (ins == INS_movw)
6013                 {
6014                     imm &= 0xffff;
6015                 }
6016                 else
6017                 {
6018                     assert(ins == INS_movt);
6019                     imm = (imm >> 16) & 0xffff;
6020                 }
6021                 code |= insEncodeImmT2_Mov(imm);
6022                 dst += emitOutput_Thumb2Instr(dst, code);
6023             }
6024             else
6025             {
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);
6030             }
6031             break;
6032
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());
6037
6038             assert((ins == INS_movt) || (ins == INS_movw));
6039             assert(id->idIsReloc());
6040
6041             addr = emitGetInsRelocValue(id);
6042             dst += emitOutput_Thumb2Instr(dst, code);
6043             if ((ins == INS_movt) && emitComp->info.compMatchedVM)
6044                 emitHandlePCRelativeMov32((void*)(dst - 8), addr);
6045             break;
6046
6047         case IF_T2_VFP3:
6048             // these are the binary operators
6049             // d = n - m
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)
6056                 code |= 1 << 8;
6057             dst += emitOutput_Thumb2Instr(dst, code);
6058             break;
6059
6060         case IF_T2_VFP2:
6061         {
6062             emitAttr srcSize;
6063             emitAttr dstSize;
6064             size_t   szCode = 0;
6065
6066             switch (ins)
6067             {
6068                 case INS_vcvt_i2d:
6069                 case INS_vcvt_u2d:
6070                 case INS_vcvt_f2d:
6071                     srcSize = EA_4BYTE;
6072                     dstSize = EA_8BYTE;
6073                     break;
6074
6075                 case INS_vcvt_d2i:
6076                 case INS_vcvt_d2u:
6077                 case INS_vcvt_d2f:
6078                     srcSize = EA_8BYTE;
6079                     dstSize = EA_4BYTE;
6080                     break;
6081
6082                 case INS_vmov:
6083                 case INS_vabs:
6084                 case INS_vsqrt:
6085                 case INS_vcmp:
6086                 case INS_vneg:
6087                     if (id->idOpSize() == EA_8BYTE)
6088                         szCode |= (1 << 8);
6089                     __fallthrough;
6090
6091                 default:
6092                     srcSize = dstSize = id->idOpSize();
6093                     break;
6094             }
6095
6096             sz   = emitGetInstrDescSize(id);
6097             code = emitInsCode(ins, fmt);
6098             code |= szCode;
6099             code |= insEncodeRegT2_VectorD(id->idReg1(), dstSize, true);
6100             code |= insEncodeRegT2_VectorM(id->idReg2(), srcSize, true);
6101
6102             dst += emitOutput_Thumb2Instr(dst, code);
6103             break;
6104         }
6105
6106         case IF_T2_VLDST:
6107             sz   = emitGetInstrDescSizeSC(id);
6108             code = emitInsCode(ins, fmt);
6109             code |= insEncodeRegT2_N(id->idReg2());
6110             code |= insEncodeRegT2_VectorD(id->idReg1(), size, true);
6111
6112             imm = emitGetInsSC(id);
6113             if (imm < 0)
6114                 imm = -imm; // bit 23 at 0 means negate
6115             else
6116                 code |= 1 << 23; // set the positive bit
6117
6118             // offset is +/- 1020
6119             assert(!(imm % 4));
6120             assert(imm >> 10 == 0);
6121             code |= imm >> 2;
6122             // bit 8 is set for doubles
6123             if (id->idOpSize() == EA_8BYTE)
6124                 code |= (1 << 8);
6125             dst += emitOutput_Thumb2Instr(dst, code);
6126             break;
6127
6128         case IF_T2_VMOVD:
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)
6133             {
6134                 code |= insEncodeRegT2_VectorM(id->idReg1(), size, true);
6135                 code |= id->idReg2() << 12;
6136                 code |= id->idReg3() << 16;
6137             }
6138             else
6139             {
6140                 assert(ins == INS_vmov_d2i);
6141                 code |= id->idReg1() << 12;
6142                 code |= id->idReg2() << 16;
6143                 code |= insEncodeRegT2_VectorM(id->idReg3(), size, true);
6144             }
6145             dst += emitOutput_Thumb2Instr(dst, code);
6146             break;
6147
6148         case IF_T2_VMOVS:
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)
6153             {
6154                 code |= insEncodeRegT2_VectorN(id->idReg2(), EA_4BYTE, true);
6155                 code |= id->idReg1() << 12;
6156             }
6157             else
6158             {
6159                 assert(ins == INS_vmov_i2f);
6160                 code |= insEncodeRegT2_VectorN(id->idReg1(), EA_4BYTE, true);
6161                 code |= id->idReg2() << 12;
6162             }
6163
6164             dst += emitOutput_Thumb2Instr(dst, code);
6165             break;
6166
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());
6171
6172             dst = emitOutputLJ(ig, dst, id);
6173             sz  = sizeof(instrDescLbl);
6174             break;
6175
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
6181         case IF_LARGEJMP:
6182             assert(id->idGCref() == GCT_NONE);
6183             assert(id->idIsBound());
6184
6185             dst = emitOutputLJ(ig, dst, id);
6186             sz  = sizeof(instrDescJmp);
6187             break;
6188
6189         case IF_T1_D1: // T1_D1   .........mmmm...                       R1*
6190
6191             code = emitInsCode(ins, fmt);
6192             code |= insEncodeRegT1_M4(id->idReg1());
6193             dst += emitOutput_Thumb1Instr(dst, code);
6194             sz = SMALL_IDSC_SIZE;
6195             break;
6196
6197         case IF_T1_D2: // T1_D2   .........mmmm...                                R3*
6198
6199             /* Is this a "fat" call descriptor? */
6200
6201             if (id->idIsLargeCall())
6202             {
6203                 instrDescCGCA* idCall = (instrDescCGCA*)id;
6204                 gcrefRegs             = idCall->idcGcrefRegs;
6205                 byrefRegs             = idCall->idcByrefRegs;
6206                 VarSetOps::Assign(emitComp, GCvars, idCall->idcGCvars);
6207                 sz = sizeof(instrDescCGCA);
6208             }
6209             else
6210             {
6211                 assert(!id->idIsLargeDsp());
6212                 assert(!id->idIsLargeCns());
6213
6214                 gcrefRegs = emitDecodeCallGCregs(id);
6215                 byrefRegs = 0;
6216                 VarSetOps::AssignNoCopy(emitComp, GCvars, VarSetOps::MakeEmpty(emitComp));
6217                 sz = sizeof(instrDesc);
6218             }
6219
6220             code = emitInsCode(ins, fmt);
6221             code |= insEncodeRegT1_M4(id->idReg3());
6222             callInstrSize = SafeCvtAssert<unsigned char>(emitOutput_Thumb1Instr(dst, code));
6223             dst += callInstrSize;
6224             goto DONE_CALL;
6225
6226         case IF_T2_J3: // T2_J3   .....Siiiiiiiiii ..j.jiiiiiiiiii.      Call                imm24
6227
6228             /* Is this a "fat" call descriptor? */
6229
6230             if (id->idIsLargeCall())
6231             {
6232                 instrDescCGCA* idCall = (instrDescCGCA*)id;
6233                 gcrefRegs             = idCall->idcGcrefRegs;
6234                 byrefRegs             = idCall->idcByrefRegs;
6235                 VarSetOps::Assign(emitComp, GCvars, idCall->idcGCvars);
6236                 sz = sizeof(instrDescCGCA);
6237             }
6238             else
6239             {
6240                 assert(!id->idIsLargeDsp());
6241                 assert(!id->idIsLargeCns());
6242
6243                 gcrefRegs = emitDecodeCallGCregs(id);
6244                 byrefRegs = 0;
6245                 VarSetOps::AssignNoCopy(emitComp, GCvars, VarSetOps::MakeEmpty(emitComp));
6246                 sz = sizeof(instrDesc);
6247             }
6248
6249             if (id->idAddr()->iiaAddr == NULL) /* a recursive call */
6250             {
6251                 addr = emitCodeBlock;
6252             }
6253             else
6254             {
6255                 addr = id->idAddr()->iiaAddr;
6256             }
6257             code = emitInsCode(ins, fmt);
6258
6259             if (id->idIsDspReloc())
6260             {
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);
6265             }
6266             else
6267             {
6268                 addr = (BYTE*)((size_t)addr & ~1); // Clear the lowest bit from target address
6269
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);
6275
6276                 if (S)
6277                     code |= (1 << 26); // S bit
6278                 if (S ^ I1)
6279                     code |= (1 << 13); // J1 bit
6280                 if (S ^ I2)
6281                     code |= (1 << 11); // J2 bit
6282
6283                 int immLo = (disp & 0x00000ffe) >> 1;
6284                 int immHi = (disp & 0x003ff000) >> 12;
6285
6286                 code |= (immHi << 16);
6287                 code |= immLo;
6288
6289                 disp = abs(disp);
6290                 assert((disp & 0x00fffffe) == disp);
6291
6292                 callInstrSize = SafeCvtAssert<unsigned char>(emitOutput_Thumb2Instr(dst, code));
6293                 dst += callInstrSize;
6294             }
6295
6296         DONE_CALL:
6297
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. */
6303
6304             emitUpdateLiveGCvars(GCvars, *dp);
6305
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;
6311
6312             // If the GC register set has changed, report the new set.
6313             if (gcrefRegs != emitThisGCrefRegs)
6314                 emitUpdateLiveGCregs(GCT_GCREF, gcrefRegs, dst);
6315
6316             if (byrefRegs != emitThisByrefRegs)
6317                 emitUpdateLiveGCregs(GCT_BYREF, byrefRegs, dst);
6318
6319             // Some helper calls may be marked as not requiring GC info to be recorded.
6320             if ((!id->idIsNoGC()))
6321             {
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);
6327
6328                 /* Do we need to record a call location for GC purposes? */
6329
6330                 if (!emitFullGCinfo)
6331                 {
6332                     emitRecordGCcall(dst, callInstrSize);
6333                 }
6334             }
6335
6336             break;
6337
6338         /********************************************************************/
6339         /*                            oops                                  */
6340         /********************************************************************/
6341
6342         default:
6343
6344 #ifdef DEBUG
6345             printf("unexpected format %s\n", emitIfName(id->idInsFmt()));
6346             assert(!"don't know how to encode this instruction");
6347 #endif
6348             break;
6349     }
6350
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.
6356     {
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))
6361         {
6362             // We explicitly list the multiple-destination-target instruction that we expect to
6363             // be emitted outside of the prolog and epilog here.
6364             switch (ins)
6365             {
6366                 case INS_smull:
6367                 case INS_umull:
6368                 case INS_smlal:
6369                 case INS_umlal:
6370                 case INS_vmov_d2i:
6371                     // For each of these, idReg1() and idReg2() are the destination registers.
6372                     emitGCregDeadUpd(id->idReg1(), dst);
6373                     emitGCregDeadUpd(id->idReg2(), dst);
6374                     break;
6375                 default:
6376                     assert(false); // We need to recognize this multi-target instruction...
6377             }
6378         }
6379         else
6380         {
6381             if (id->idGCref() != GCT_NONE)
6382             {
6383                 emitGCregLiveUpd(id->idGCref(), id->idReg1(), dst);
6384             }
6385             else
6386             {
6387                 // I also assume that "idReg1" is the destination register of all instructions that write to registers.
6388                 emitGCregDeadUpd(id->idReg1(), dst);
6389             }
6390         }
6391     }
6392
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))
6396     {
6397         int       varNum = id->idAddr()->iiaLclVar.lvaVarNum();
6398         unsigned  ofs    = AlignDown(id->idAddr()->iiaLclVar.lvaOffset(), TARGET_POINTER_SIZE);
6399         regNumber regBase;
6400         int       adr = emitComp->lvaFrameAddress(varNum, true, &regBase, ofs);
6401         if (id->idGCref() != GCT_NONE)
6402         {
6403             emitGCvarLiveUpd(adr + ofs, varNum, id->idGCref(), dst);
6404         }
6405         else
6406         {
6407             // If the type of the local is a gc ref type, update the liveness.
6408             var_types vt;
6409             if (varNum >= 0)
6410             {
6411                 // "Regular" (non-spill-temp) local.
6412                 vt = var_types(emitComp->lvaTable[varNum].lvType);
6413             }
6414             else
6415             {
6416                 TempDsc* tmpDsc = codeGen->regSet.tmpFindNum(varNum);
6417                 vt              = tmpDsc->tdTempType();
6418             }
6419             if (vt == TYP_REF || vt == TYP_BYREF)
6420                 emitGCvarDeadUpd(adr + ofs, dst);
6421         }
6422     }
6423
6424 #ifdef DEBUG
6425     /* Make sure we set the instruction descriptor size correctly */
6426
6427     size_t expected = emitSizeOfInsDsc(id);
6428     assert(sz == expected);
6429
6430     if (emitComp->opts.disAsm || emitComp->opts.dspEmit || emitComp->verbose)
6431     {
6432         emitDispIns(id, false, dspOffs, true, emitCurCodeOffs(odst), *dp, (dst - *dp), ig);
6433     }
6434
6435     if (emitComp->compDebugBreak)
6436     {
6437         // set JitEmitPrintRefRegs=1 will print out emitThisGCrefRegs and emitThisByrefRegs
6438         // at the beginning of this method.
6439         if (JitConfig.JitEmitPrintRefRegs() != 0)
6440         {
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);
6445             printf("\n");
6446             printf("  emitThisByrefRegs(0x%p)=", dspPtr(&emitThisByrefRegs));
6447             printRegMaskInt(emitThisByrefRegs);
6448             emitDispRegSet(emitThisByrefRegs);
6449             printf("\n");
6450         }
6451
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)
6455         {
6456             assert(!"JitBreakEmitOutputInstr reached");
6457         }
6458     }
6459 #endif
6460
6461     /* All instructions are expected to generate code */
6462
6463     assert(*dp != dst);
6464
6465     *dp = dst;
6466
6467     return sz;
6468 }
6469
6470 /*****************************************************************************/
6471 /*****************************************************************************/
6472
6473 #ifdef DEBUG
6474
6475 static bool insAlwaysSetFlags(instruction ins)
6476 {
6477     bool result = false;
6478     switch (ins)
6479     {
6480         case INS_cmp:
6481         case INS_cmn:
6482         case INS_teq:
6483         case INS_tst:
6484             result = true;
6485             break;
6486
6487         default:
6488             break;
6489     }
6490     return result;
6491 }
6492
6493 /*****************************************************************************
6494  *
6495  *  Display the instruction name, optionally the instruction
6496  *   can add the "s" suffix if it must set the flags.
6497  */
6498 void emitter::emitDispInst(instruction ins, insFlags flags)
6499 {
6500     const char* insstr = codeGen->genInsName(ins);
6501     int         len    = strlen(insstr);
6502
6503     /* Display the instruction name */
6504
6505     printf("%s", insstr);
6506     if (insSetsFlags(flags) && !insAlwaysSetFlags(ins))
6507     {
6508         printf("s");
6509         len++;
6510     }
6511
6512     //
6513     // Add at least one space after the instruction name
6514     // and add spaces until we have reach the normal size of 8
6515     do
6516     {
6517         printf(" ");
6518         len++;
6519     } while (len < 8);
6520 }
6521
6522 #define STRICT_ARM_ASM 0
6523
6524 /*****************************************************************************
6525  *
6526  *  Display an immediate value
6527  */
6528 void emitter::emitDispImm(int imm, bool addComma, bool alwaysHex /* =false */)
6529 {
6530     if (!alwaysHex && (imm > -1000) && (imm < 1000))
6531         printf("%d", imm);
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);
6538
6539     if (addComma)
6540         printf(", ");
6541 }
6542
6543 /*****************************************************************************
6544  *
6545  *  Display a relocatable immediate value
6546  */
6547 void emitter::emitDispReloc(BYTE* addr)
6548 {
6549     printf("0x%p", dspPtr(addr));
6550 }
6551
6552 /*****************************************************************************
6553  *
6554  *  Display an arm condition for the IT instructions
6555  */
6556 void emitter::emitDispCond(int cond)
6557 {
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]);
6562 }
6563
6564 /*****************************************************************************
6565  *
6566  *  Display a register range in a range format
6567  */
6568 void emitter::emitDispRegRange(regNumber reg, int len, emitAttr attr)
6569 {
6570     printf("{");
6571     emitDispReg(reg, attr, false);
6572     if (len > 1)
6573     {
6574         printf("-");
6575         emitDispReg((regNumber)(reg + len - 1), attr, false);
6576     }
6577     printf("}");
6578 }
6579
6580 /*****************************************************************************
6581  *
6582  *  Display an register mask in a list format
6583  */
6584 void emitter::emitDispRegmask(int imm, bool encodedPC_LR)
6585 {
6586     bool printedOne = false;
6587     bool hasPC;
6588     bool hasLR;
6589
6590     if (encodedPC_LR)
6591     {
6592         hasPC = (imm & 2) != 0;
6593         hasLR = (imm & 1) != 0;
6594         imm >>= 2;
6595     }
6596     else
6597     {
6598         hasPC = (imm & RBM_PC) != 0;
6599         hasLR = (imm & RBM_LR) != 0;
6600         imm &= ~(RBM_PC | RBM_LR);
6601     }
6602
6603     regNumber reg = REG_R0;
6604     unsigned  bit = 1;
6605
6606     printf("{");
6607     while (imm != 0)
6608     {
6609         if (bit & imm)
6610         {
6611             if (printedOne)
6612                 printf(",");
6613             printf("%s", emitRegName(reg));
6614             printedOne = true;
6615             imm -= bit;
6616         }
6617
6618         reg = regNumber(reg + 1);
6619         bit <<= 1;
6620     }
6621
6622     if (hasLR)
6623     {
6624         if (printedOne)
6625             printf(",");
6626         printf("%s", emitRegName(REG_LR));
6627         printedOne = true;
6628     }
6629
6630     if (hasPC)
6631     {
6632         if (printedOne)
6633             printf(",");
6634         printf("%s", emitRegName(REG_PC));
6635         printedOne = true;
6636     }
6637     printf("}");
6638 }
6639
6640 /*****************************************************************************
6641  *
6642  *  Returns the encoding for the Shift Type bits to be used in a Thumb-2 encoding
6643  */
6644
6645 void emitter::emitDispShiftOpts(insOpts opt)
6646 {
6647     if (opt == INS_OPTS_LSL)
6648         printf(" LSL ");
6649     else if (opt == INS_OPTS_LSR)
6650         printf(" LSR ");
6651     else if (opt == INS_OPTS_ASR)
6652         printf(" ASR ");
6653     else if (opt == INS_OPTS_ROR)
6654         printf(" ROR ");
6655     else if (opt == INS_OPTS_RRX)
6656         printf(" RRX ");
6657 }
6658
6659 /*****************************************************************************
6660  *
6661  *  Display a register
6662  */
6663 void emitter::emitDispReg(regNumber reg, emitAttr attr, bool addComma)
6664 {
6665     if (isFloatReg(reg))
6666     {
6667         const char* size = attr == EA_8BYTE ? "d" : "s";
6668         printf("%s%s", size, emitFloatRegName(reg, attr) + 1);
6669     }
6670     else
6671     {
6672         printf("%s", emitRegName(reg, attr));
6673     }
6674
6675     if (addComma)
6676         printf(", ");
6677 }
6678
6679 /*****************************************************************************
6680  *
6681  *  Display an addressing operand [reg]
6682  */
6683 void emitter::emitDispAddrR(regNumber reg, emitAttr attr)
6684 {
6685     printf("[");
6686     emitDispReg(reg, attr, false);
6687     printf("]");
6688     emitDispGC(attr);
6689 }
6690
6691 /*****************************************************************************
6692  *
6693  *  Display an addressing operand [reg + imm]
6694  */
6695 void emitter::emitDispAddrRI(regNumber reg, int imm, emitAttr attr)
6696 {
6697     bool regIsSPorFP = (reg == REG_SP) || (reg == REG_FP);
6698
6699     printf("[");
6700     emitDispReg(reg, attr, false);
6701     if (imm != 0)
6702     {
6703         if (imm >= 0)
6704         {
6705 #if STRICT_ARM_ASM
6706             printf(", ");
6707 #else
6708             printf("+");
6709 #endif
6710         }
6711         emitDispImm(imm, false, regIsSPorFP);
6712     }
6713     printf("]");
6714     emitDispGC(attr);
6715 }
6716
6717 /*****************************************************************************
6718  *
6719  *  Display an addressing operand [reg + reg]
6720  */
6721 void emitter::emitDispAddrRR(regNumber reg1, regNumber reg2, emitAttr attr)
6722 {
6723     printf("[");
6724     emitDispReg(reg1, attr, false);
6725 #if STRICT_ARM_ASM
6726     printf(", ");
6727 #else
6728     printf("+");
6729 #endif
6730     emitDispReg(reg2, attr, false);
6731     printf("]");
6732     emitDispGC(attr);
6733 }
6734
6735 /*****************************************************************************
6736  *
6737  *  Display an addressing operand [reg + reg * imm]
6738  */
6739 void emitter::emitDispAddrRRI(regNumber reg1, regNumber reg2, int imm, emitAttr attr)
6740 {
6741     printf("[");
6742     emitDispReg(reg1, attr, false);
6743 #if STRICT_ARM_ASM
6744     printf(", ");
6745     emitDispReg(reg2, attr, false);
6746     if (imm > 0)
6747     {
6748         printf(" LSL ");
6749         emitDispImm(1 << imm, false);
6750     }
6751 #else
6752     printf("+");
6753     if (imm > 0)
6754     {
6755         emitDispImm(1 << imm, false);
6756         printf("*");
6757     }
6758     emitDispReg(reg2, attr, false);
6759 #endif
6760     printf("]");
6761     emitDispGC(attr);
6762 }
6763
6764 /*****************************************************************************
6765  *
6766  *  Display an addressing operand [reg + imm]
6767  */
6768 void emitter::emitDispAddrPUW(regNumber reg, int imm, insOpts opt, emitAttr attr)
6769 {
6770     bool regIsSPorFP = (reg == REG_SP) || (reg == REG_FP);
6771
6772     printf("[");
6773     emitDispReg(reg, attr, false);
6774     if (insOptAnyInc(opt))
6775         printf("!");
6776
6777     if (imm != 0)
6778     {
6779         if (imm >= 0)
6780         {
6781 #if STRICT_ARM_ASM
6782             printf(", ");
6783 #else
6784             printf("+");
6785 #endif
6786         }
6787         emitDispImm(imm, false, regIsSPorFP);
6788     }
6789     printf("]");
6790
6791     emitDispGC(attr);
6792 }
6793
6794 /*****************************************************************************
6795  *
6796  *  Display the gc-ness of the operand
6797  */
6798 void emitter::emitDispGC(emitAttr attr)
6799 {
6800 #if 0
6801     // TODO-ARM-Cleanup: Fix or delete.
6802     if (attr == EA_GCREF)
6803         printf(" @gc");
6804     else if (attr == EA_BYREF)
6805         printf(" @byref");
6806 #endif
6807 }
6808
6809 /*****************************************************************************
6810  *
6811  *  Display (optionally) the instruction encoding in hex
6812  */
6813
6814 void emitter::emitDispInsHex(BYTE* code, size_t sz)
6815 {
6816     // We do not display the instruction hex if we want diff-able disassembly
6817     if (!emitComp->opts.disDiffable)
6818     {
6819         if (sz == 2)
6820         {
6821             printf("  %04X     ", (*((unsigned short*)code)));
6822         }
6823         else if (sz == 4)
6824         {
6825             printf("  %04X %04X", (*((unsigned short*)(code + 0))), (*((unsigned short*)(code + 2))));
6826         }
6827     }
6828 }
6829
6830 /****************************************************************************
6831  *
6832  *  Display the given instruction.
6833  */
6834
6835 void emitter::emitDispInsHelp(
6836     instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* code, size_t sz, insGroup* ig)
6837 {
6838     if (EMITVERBOSE)
6839     {
6840         unsigned idNum = id->idDebugOnlyInfo()->idNum; // Do not remove this!  It is needed for VisualStudio
6841                                                        // conditional breakpoints
6842
6843         printf("IN%04x: ", idNum);
6844     }
6845
6846     if (code == NULL)
6847         sz = 0;
6848
6849     if (!emitComp->opts.dspEmit && !isNew && !asmfm && sz)
6850         doffs = true;
6851
6852     /* Display the instruction offset */
6853
6854     emitDispInsOffs(offset, doffs);
6855
6856     /* Display the instruction hex code */
6857
6858     emitDispInsHex(code, sz);
6859
6860     printf("      ");
6861
6862     /* Get the instruction and format */
6863
6864     instruction ins = id->idIns();
6865     insFormat   fmt = id->idInsFmt();
6866
6867     emitDispInst(ins, id->idInsFlags());
6868
6869     /* If this instruction has just been added, check its size */
6870
6871     assert(isNew == false || (int)emitSizeOfInsDsc(id) == emitCurIGfreeNext - (BYTE*)id);
6872
6873     /* Figure out the operand size */
6874     emitAttr attr;
6875     if (id->idGCref() == GCT_GCREF)
6876         attr = EA_GCREF;
6877     else if (id->idGCref() == GCT_BYREF)
6878         attr = EA_BYREF;
6879     else
6880         attr = id->idOpSize();
6881
6882     switch (fmt)
6883     {
6884         int         imm;
6885         int         offs;
6886         const char* methodName;
6887
6888         case IF_T1_A: // None
6889         case IF_T2_A:
6890             break;
6891
6892         case IF_T1_L0: // Imm
6893         case IF_T2_B:
6894             emitDispImm(emitGetInsSC(id), false);
6895             break;
6896
6897         case IF_T1_B: // <cond>
6898             emitDispCond(emitGetInsSC(id));
6899             break;
6900
6901         case IF_T1_L1: // <regmask8>
6902         case IF_T2_I1: // <regmask16>
6903             emitDispRegmask(emitGetInsSC(id), true);
6904             break;
6905
6906         case IF_T2_E2: // Reg
6907             if (id->idIns() == INS_vmrs)
6908             {
6909                 if (id->idReg1() != REG_R15)
6910                 {
6911                     emitDispReg(id->idReg1(), attr, true);
6912                     printf("FPSCR");
6913                 }
6914                 else
6915                 {
6916                     printf("APSR, FPSCR");
6917                 }
6918             }
6919             else
6920             {
6921                 emitDispReg(id->idReg1(), attr, false);
6922             }
6923             break;
6924
6925         case IF_T1_D1:
6926             emitDispReg(id->idReg1(), attr, false);
6927             break;
6928
6929         case IF_T1_D2:
6930             emitDispReg(id->idReg3(), attr, false);
6931             {
6932                 CORINFO_METHOD_HANDLE handle = (CORINFO_METHOD_HANDLE)id->idDebugOnlyInfo()->idMemCookie;
6933                 if (handle != 0)
6934                 {
6935                     methodName = emitComp->eeGetMethodFullName(handle);
6936                     printf("\t\t// %s", methodName);
6937                 }
6938             }
6939             break;
6940
6941         case IF_T1_F: // SP, Imm
6942             emitDispReg(REG_SP, attr, true);
6943             emitDispImm(emitGetInsSC(id), false);
6944             break;
6945
6946         case IF_T1_J0: // Reg, Imm
6947         case IF_T2_L1:
6948         case IF_T2_L2:
6949             emitDispReg(id->idReg1(), attr, true);
6950             imm = emitGetInsSC(id);
6951             emitDispImm(imm, false, false);
6952             break;
6953
6954         case IF_T2_N:
6955             emitDispReg(id->idReg1(), attr, true);
6956             imm = emitGetInsSC(id);
6957             if (emitComp->opts.disDiffable)
6958                 imm = 0xD1FF;
6959             emitDispImm(imm, false, true);
6960             break;
6961
6962         case IF_T2_N3:
6963             emitDispReg(id->idReg1(), attr, true);
6964             printf("%s RELOC ", (id->idIns() == INS_movw) ? "LOW" : "HIGH");
6965             emitDispReloc(emitGetInsRelocValue(id));
6966             break;
6967
6968         case IF_T2_N2:
6969             emitDispReg(id->idReg1(), attr, true);
6970             imm = emitGetInsSC(id);
6971             {
6972                 dataSection*  jdsc = 0;
6973                 NATIVE_OFFSET offs = 0;
6974
6975                 /* Find the appropriate entry in the data section list */
6976
6977                 for (jdsc = emitConsDsc.dsdList; jdsc; jdsc = jdsc->dsNext)
6978                 {
6979                     UNATIVE_OFFSET size = jdsc->dsSize;
6980
6981                     /* Is this a label table? */
6982
6983                     if (jdsc->dsType == dataSection::blockAbsoluteAddr)
6984                     {
6985                         if (offs == imm)
6986                             break;
6987                     }
6988
6989                     offs += size;
6990                 }
6991
6992                 assert(jdsc != NULL);
6993
6994                 if (id->idIsDspReloc())
6995                 {
6996                     printf("reloc ");
6997                 }
6998                 printf("%s ADDRESS J_M%03u_DS%02u", (id->idIns() == INS_movw) ? "LOW" : "HIGH",
6999                        Compiler::s_compMethodsCount, imm);
7000
7001                 // After the MOVT, dump the table
7002                 if (id->idIns() == INS_movt)
7003                 {
7004                     unsigned     cnt = jdsc->dsSize / TARGET_POINTER_SIZE;
7005                     BasicBlock** bbp = (BasicBlock**)jdsc->dsCont;
7006
7007                     bool isBound = (emitCodeGetCookie(*bbp) != NULL);
7008
7009                     if (isBound)
7010                     {
7011                         printf("\n\n    J_M%03u_DS%02u LABEL   DWORD", Compiler::s_compMethodsCount, imm);
7012
7013                         /* Display the label table (it's stored as "BasicBlock*" values) */
7014
7015                         do
7016                         {
7017                             insGroup* lab;
7018
7019                             /* Convert the BasicBlock* value to an IG address */
7020
7021                             lab = (insGroup*)emitCodeGetCookie(*bbp++);
7022                             assert(lab);
7023
7024                             printf("\n            DD      G_M%03u_IG%02u", Compiler::s_compMethodsCount, lab->igNum);
7025                         } while (--cnt);
7026                     }
7027                 }
7028             }
7029             break;
7030
7031         case IF_T2_H2: // [Reg+imm]
7032         case IF_T2_K2:
7033             emitDispAddrRI(id->idReg1(), emitGetInsSC(id), attr);
7034             break;
7035
7036         case IF_T2_K3: // [PC+imm]
7037             emitDispAddrRI(REG_PC, emitGetInsSC(id), attr);
7038             break;
7039
7040         case IF_T1_J1: // reg, <regmask8>
7041         case IF_T2_I0: // reg, <regmask16>
7042             emitDispReg(id->idReg1(), attr, false);
7043             printf("!, ");
7044             emitDispRegmask(emitGetInsSC(id), false);
7045             break;
7046
7047         case IF_T1_D0: // Reg, Reg
7048         case IF_T1_E:
7049         case IF_T2_C3:
7050         case IF_T2_C9:
7051         case IF_T2_C10:
7052             emitDispReg(id->idReg1(), attr, true);
7053             emitDispReg(id->idReg2(), attr, false);
7054             if (fmt == IF_T1_E && id->idIns() == INS_rsb)
7055             {
7056                 printf(", 0");
7057             }
7058             break;
7059
7060         case IF_T2_E1: // Reg, [Reg]
7061             emitDispReg(id->idReg1(), attr, true);
7062             emitDispAddrR(id->idReg2(), attr);
7063             break;
7064
7065         case IF_T2_D1: // Reg, Imm, Imm
7066             emitDispReg(id->idReg1(), attr, true);
7067             imm = emitGetInsSC(id);
7068             {
7069                 int lsb  = (imm >> 5) & 0x1f;
7070                 int msb  = imm & 0x1f;
7071                 int imm1 = lsb;
7072                 int imm2 = msb + 1 - lsb;
7073                 emitDispImm(imm1, true);
7074                 emitDispImm(imm2, false);
7075             }
7076             break;
7077
7078         case IF_T1_C: // Reg, Reg, Imm
7079         case IF_T1_G:
7080         case IF_T2_C2:
7081         case IF_T2_H1:
7082         case IF_T2_K1:
7083         case IF_T2_L0:
7084         case IF_T2_M0:
7085             emitDispReg(id->idReg1(), attr, true);
7086             imm = emitGetInsSC(id);
7087             if (emitInsIsLoadOrStore(ins))
7088             {
7089                 emitDispAddrRI(id->idReg2(), imm, attr);
7090             }
7091             else
7092             {
7093                 emitDispReg(id->idReg2(), attr, true);
7094                 emitDispImm(imm, false);
7095             }
7096             break;
7097
7098         case IF_T1_J2:
7099             emitDispReg(id->idReg1(), attr, true);
7100             imm = emitGetInsSC(id);
7101             if (emitInsIsLoadOrStore(ins))
7102             {
7103                 emitDispAddrRI(REG_SP, imm, attr);
7104             }
7105             else
7106             {
7107                 emitDispReg(REG_SP, attr, true);
7108                 emitDispImm(imm, false);
7109             }
7110             break;
7111
7112         case IF_T2_K4:
7113             emitDispReg(id->idReg1(), attr, true);
7114             emitDispAddrRI(REG_PC, emitGetInsSC(id), attr);
7115             break;
7116
7117         case IF_T2_C1:
7118         case IF_T2_C8:
7119             emitDispReg(id->idReg1(), attr, true);
7120             emitDispReg(id->idReg2(), attr, false);
7121             imm = emitGetInsSC(id);
7122             if (id->idInsOpt() == INS_OPTS_RRX)
7123             {
7124                 emitDispShiftOpts(id->idInsOpt());
7125                 assert(imm == 1);
7126             }
7127             else if (imm > 0)
7128             {
7129                 emitDispShiftOpts(id->idInsOpt());
7130                 emitDispImm(imm, false);
7131             }
7132             break;
7133
7134         case IF_T2_C6:
7135             imm = emitGetInsSC(id);
7136             emitDispReg(id->idReg1(), attr, true);
7137             emitDispReg(id->idReg2(), attr, (imm != 0));
7138             if (imm != 0)
7139             {
7140                 emitDispImm(imm, false);
7141             }
7142             break;
7143
7144         case IF_T2_C7:
7145             emitDispAddrRRI(id->idReg1(), id->idReg2(), emitGetInsSC(id), attr);
7146             break;
7147
7148         case IF_T2_H0:
7149             emitDispReg(id->idReg1(), attr, true);
7150             emitDispAddrPUW(id->idReg2(), emitGetInsSC(id), id->idInsOpt(), attr);
7151             break;
7152
7153         case IF_T1_H: // Reg, Reg, Reg
7154             emitDispReg(id->idReg1(), attr, true);
7155             if (emitInsIsLoadOrStore(ins))
7156             {
7157                 emitDispAddrRR(id->idReg2(), id->idReg3(), attr);
7158             }
7159             else
7160             {
7161                 emitDispReg(id->idReg2(), attr, true);
7162                 emitDispReg(id->idReg3(), attr, false);
7163             }
7164             break;
7165
7166         case IF_T2_C4:
7167         case IF_T2_C5:
7168             emitDispReg(id->idReg1(), attr, true);
7169             emitDispReg(id->idReg2(), attr, true);
7170             emitDispReg(id->idReg3(), attr, false);
7171             break;
7172
7173         case IF_T2_VFP3:
7174             emitDispReg(id->idReg1(), attr, true);
7175             emitDispReg(id->idReg2(), attr, true);
7176             emitDispReg(id->idReg3(), attr, false);
7177             break;
7178
7179         case IF_T2_VFP2:
7180             switch (id->idIns())
7181             {
7182                 case INS_vcvt_d2i:
7183                 case INS_vcvt_d2u:
7184                 case INS_vcvt_d2f:
7185                     emitDispReg(id->idReg1(), EA_4BYTE, true);
7186                     emitDispReg(id->idReg2(), EA_8BYTE, false);
7187                     break;
7188
7189                 case INS_vcvt_i2d:
7190                 case INS_vcvt_u2d:
7191                 case INS_vcvt_f2d:
7192                     emitDispReg(id->idReg1(), EA_8BYTE, true);
7193                     emitDispReg(id->idReg2(), EA_4BYTE, false);
7194                     break;
7195
7196                 // we just use the type on the instruction
7197                 // unless it is an asymmetrical one like the converts
7198                 default:
7199                     emitDispReg(id->idReg1(), attr, true);
7200                     emitDispReg(id->idReg2(), attr, false);
7201                     break;
7202             }
7203             break;
7204
7205         case IF_T2_VLDST:
7206             imm = emitGetInsSC(id);
7207             switch (id->idIns())
7208             {
7209                 case INS_vldr:
7210                 case INS_vstr:
7211                     emitDispReg(id->idReg1(), attr, true);
7212                     emitDispAddrPUW(id->idReg2(), imm, id->idInsOpt(), attr);
7213                     break;
7214
7215                 case INS_vldm:
7216                 case INS_vstm:
7217                     emitDispReg(id->idReg2(), attr, false);
7218                     if (insOptAnyInc(id->idInsOpt()))
7219                         printf("!");
7220                     printf(", ");
7221                     emitDispRegRange(id->idReg1(), abs(imm) >> 2, attr);
7222                     break;
7223
7224                 case INS_vpush:
7225                 case INS_vpop:
7226                     emitDispRegRange(id->idReg1(), abs(imm) >> 2, attr);
7227                     break;
7228
7229                 default:
7230                     unreached();
7231             }
7232             break;
7233
7234         case IF_T2_VMOVD:
7235             switch (id->idIns())
7236             {
7237                 case INS_vmov_i2d:
7238                     emitDispReg(id->idReg1(), attr, true); // EA_8BYTE
7239                     emitDispReg(id->idReg2(), EA_4BYTE, true);
7240                     emitDispReg(id->idReg3(), EA_4BYTE, false);
7241                     break;
7242                 case INS_vmov_d2i:
7243                     emitDispReg(id->idReg1(), EA_4BYTE, true);
7244                     emitDispReg(id->idReg2(), EA_4BYTE, true);
7245                     emitDispReg(id->idReg3(), attr, false); // EA_8BYTE
7246                     break;
7247                 default:
7248                     unreached();
7249             }
7250             break;
7251
7252         case IF_T2_VMOVS:
7253             emitDispReg(id->idReg1(), attr, true);
7254             emitDispReg(id->idReg2(), attr, false);
7255             break;
7256
7257         case IF_T2_G1:
7258             emitDispReg(id->idReg1(), attr, true);
7259             emitDispAddrRR(id->idReg2(), id->idReg3(), attr);
7260             break;
7261
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);
7266             if (ins == INS_bfi)
7267             {
7268                 int lsb  = (imm >> 5) & 0x1f;
7269                 int msb  = imm & 0x1f;
7270                 int imm1 = lsb;
7271                 int imm2 = msb + 1 - lsb;
7272                 emitDispImm(imm1, true);
7273                 emitDispImm(imm2, false);
7274             }
7275             else
7276             {
7277                 int lsb     = (imm >> 5) & 0x1f;
7278                 int widthm1 = imm & 0x1f;
7279                 int imm1    = lsb;
7280                 int imm2    = widthm1 + 1;
7281                 emitDispImm(imm1, true);
7282                 emitDispImm(imm2, false);
7283             }
7284             break;
7285
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)
7292             {
7293                 emitDispShiftOpts(id->idInsOpt());
7294                 assert(imm == 1);
7295             }
7296             else if (imm > 0)
7297             {
7298                 emitDispShiftOpts(id->idInsOpt());
7299                 emitDispImm(imm, false);
7300             }
7301             break;
7302
7303         case IF_T2_E0:
7304             emitDispReg(id->idReg1(), attr, true);
7305             if (id->idIsLclVar())
7306             {
7307                 emitDispAddrRRI(id->idReg2(), codeGen->rsGetRsvdReg(), 0, attr);
7308             }
7309             else
7310             {
7311                 emitDispAddrRRI(id->idReg2(), id->idReg3(), emitGetInsSC(id), attr);
7312             }
7313             break;
7314
7315         case IF_T2_G0:
7316             emitDispReg(id->idReg1(), attr, true);
7317             emitDispReg(id->idReg2(), attr, true);
7318             emitDispAddrPUW(id->idReg3(), emitGetInsSC(id), id->idInsOpt(), attr);
7319             break;
7320
7321         case IF_T2_F1: // Reg, Reg, Reg, Reg
7322         case IF_T2_F2:
7323             emitDispReg(id->idReg1(), attr, true);
7324             emitDispReg(id->idReg2(), attr, true);
7325             emitDispReg(id->idReg3(), attr, true);
7326             emitDispReg(id->idReg4(), attr, false);
7327             break;
7328
7329         case IF_T1_J3:
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);
7334             else
7335                 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
7336             break;
7337
7338         case IF_T1_I: // Special Compare-and-branch
7339             emitDispReg(id->idReg1(), attr, true);
7340             __fallthrough;
7341
7342         case IF_T1_K: // Special Branch, conditional
7343         case IF_T1_M:
7344             assert(((instrDescJmp*)id)->idjShort);
7345             printf("SHORT ");
7346             __fallthrough;
7347
7348         case IF_T2_N1:
7349             if (fmt == IF_T2_N1)
7350             {
7351                 emitDispReg(id->idReg1(), attr, true);
7352                 printf("%s ADDRESS ", (id->idIns() == INS_movw) ? "LOW" : "HIGH");
7353             }
7354             __fallthrough;
7355
7356         case IF_T2_J1:
7357         case IF_T2_J2:
7358         case IF_LARGEJMP:
7359         {
7360             if (id->idAddr()->iiaHasInstrCount())
7361             {
7362                 int instrCount = id->idAddr()->iiaGetInstrCount();
7363
7364                 if (ig == NULL)
7365                 {
7366                     printf("pc%s%d instructions", (instrCount >= 0) ? "+" : "", instrCount);
7367                 }
7368                 else
7369                 {
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);
7375                 }
7376             }
7377             else if (id->idIsBound())
7378                 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
7379             else
7380                 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
7381         }
7382         break;
7383
7384         case IF_T2_J3:
7385             if (id->idIsCallAddr())
7386             {
7387                 offs       = (ssize_t)id->idAddr()->iiaAddr;
7388                 methodName = "";
7389             }
7390             else
7391             {
7392                 offs       = 0;
7393                 methodName = emitComp->eeGetMethodFullName((CORINFO_METHOD_HANDLE)id->idDebugOnlyInfo()->idMemCookie);
7394             }
7395
7396             if (offs)
7397             {
7398                 if (id->idIsDspReloc())
7399                     printf("reloc ");
7400                 printf("%08X", offs);
7401             }
7402             else
7403             {
7404                 printf("%s", methodName);
7405             }
7406
7407             break;
7408
7409         default:
7410             printf("unexpected format %s", emitIfName(id->idInsFmt()));
7411             assert(!"unexpectedFormat");
7412             break;
7413     }
7414
7415     if (id->idDebugOnlyInfo()->idVarRefOffs)
7416     {
7417         printf("\t// ");
7418         emitDispFrameRef(id->idAddr()->iiaLclVar.lvaVarNum(), id->idAddr()->iiaLclVar.lvaOffset(),
7419                          id->idDebugOnlyInfo()->idVarRefOffs, asmfm);
7420     }
7421
7422     printf("\n");
7423 }
7424
7425 void emitter::emitDispIns(
7426     instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* code, size_t sz, insGroup* ig)
7427 {
7428     insFormat fmt = id->idInsFmt();
7429
7430     /* Special-case IF_LARGEJMP */
7431
7432     if ((fmt == IF_LARGEJMP) && id->idIsBound())
7433     {
7434         // This is a pseudo-instruction format representing a large conditional branch. See the comment
7435         // in emitter::emitOutputLJ() for the full description.
7436         //
7437         // For this pseudo-instruction, we will actually generate:
7438         //
7439         //      b<!cond> L_not  // 2 bytes. Note that we reverse the condition.
7440         //      b L_target      // 4 bytes
7441         //   L_not:
7442         //
7443         // These instructions don't exist in the actual instruction stream, so we need to fake them
7444         // up to display them.
7445         //
7446         // Note: don't touch the actual instrDesc. If we accidentally messed it up, it would create a very
7447         // difficult to find bug.
7448
7449         instrDescJmp  idJmp;
7450         instrDescJmp* pidJmp = &idJmp;
7451
7452         memset(&idJmp, 0, sizeof(idJmp));
7453
7454         pidJmp->idIns(emitJumpKindToIns(emitReverseJumpKind(emitInsToJumpKind(id->idIns())))); // reverse the
7455                                                                                                // conditional
7456                                                                                                // instruction
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
7462
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 */);
7466
7467         code += bcondSizeOrZero;
7468         offset += 2;
7469
7470         // Next, display the unconditional branch
7471
7472         // Reset the local instrDesc
7473         memset(&idJmp, 0, sizeof(idJmp));
7474
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())
7480         {
7481             pidJmp->idSetIsBound();
7482             pidJmp->idAddr()->iiaIGlabel = id->idAddr()->iiaIGlabel;
7483         }
7484         else
7485         {
7486             pidJmp->idAddr()->iiaBBlabel = id->idAddr()->iiaBBlabel;
7487         }
7488         pidJmp->idDebugOnlyInfo(id->idDebugOnlyInfo()); // share the idDebugOnlyInfo() field
7489
7490         size_t brSizeOrZero = (code == NULL) ? 0 : 4; // unconditional branch is 4 bytes
7491         emitDispInsHelp(pidJmp, isNew, doffs, asmfm, offset, code, brSizeOrZero, ig);
7492     }
7493     else
7494     {
7495         emitDispInsHelp(id, isNew, doffs, asmfm, offset, code, sz, ig);
7496     }
7497 }
7498
7499 /*****************************************************************************
7500  *
7501  *  Display a stack frame reference.
7502  */
7503
7504 void emitter::emitDispFrameRef(int varx, int disp, int offs, bool asmfm)
7505 {
7506     printf("[");
7507
7508     if (varx < 0)
7509         printf("TEMP_%02u", -varx);
7510     else
7511         emitComp->gtDispLclVar(+varx, false);
7512
7513     if (disp < 0)
7514         printf("-0x%02x", -disp);
7515     else if (disp > 0)
7516         printf("+0x%02x", +disp);
7517
7518     printf("]");
7519
7520     if (varx >= 0 && emitComp->opts.varNames)
7521     {
7522         LclVarDsc*  varDsc;
7523         const char* varName;
7524
7525         assert((unsigned)varx < emitComp->lvaCount);
7526         varDsc  = emitComp->lvaTable + varx;
7527         varName = emitComp->compLocalVarName(varx, offs);
7528
7529         if (varName)
7530         {
7531             printf("'%s", varName);
7532
7533             if (disp < 0)
7534                 printf("-%d", -disp);
7535             else if (disp > 0)
7536                 printf("+%d", +disp);
7537
7538             printf("'");
7539         }
7540     }
7541 }
7542
7543 #endif // DEBUG
7544
7545 void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataReg, GenTreeIndir* indir)
7546 {
7547     // Handle unaligned floating point loads/stores
7548     if ((indir->gtFlags & GTF_IND_UNALIGNED))
7549     {
7550         if (indir->OperGet() == GT_STOREIND)
7551         {
7552             var_types type = indir->AsStoreInd()->Data()->TypeGet();
7553             if (type == TYP_FLOAT)
7554             {
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);
7558                 return;
7559             }
7560             else if (type == TYP_DOUBLE)
7561             {
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);
7567                 return;
7568             }
7569         }
7570         else if (indir->OperGet() == GT_IND)
7571         {
7572             var_types type = indir->TypeGet();
7573             if (type == TYP_FLOAT)
7574             {
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);
7578                 return;
7579             }
7580             else if (type == TYP_DOUBLE)
7581             {
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);
7587                 return;
7588             }
7589         }
7590     }
7591
7592     // Proceed with ordinary loads/stores
7593     emitInsLoadStoreOp(ins, attr, dataReg, indir, 0);
7594 }
7595
7596 void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataReg, GenTreeIndir* indir, int offset)
7597 {
7598     GenTree* addr = indir->Addr();
7599
7600     if (addr->isContained())
7601     {
7602         assert(addr->OperGet() == GT_LCL_VAR_ADDR || addr->OperGet() == GT_LEA);
7603
7604         DWORD lsl = 0;
7605
7606         if (addr->OperGet() == GT_LEA)
7607         {
7608             offset += addr->AsAddrMode()->Offset();
7609             if (addr->AsAddrMode()->gtScale > 0)
7610             {
7611                 assert(isPow2(addr->AsAddrMode()->gtScale));
7612                 BitScanForward(&lsl, addr->AsAddrMode()->gtScale);
7613             }
7614         }
7615
7616         GenTree* memBase = indir->Base();
7617
7618         if (indir->HasIndex())
7619         {
7620             assert(addr->OperGet() == GT_LEA);
7621
7622             GenTree* index = indir->Index();
7623
7624             if (offset != 0)
7625             {
7626                 regNumber tmpReg = indir->GetSingleTempReg();
7627
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;
7633
7634                 if (emitIns_valid_imm_for_add(offset, INS_FLAGS_DONT_CARE))
7635                 {
7636                     if (lsl > 0)
7637                     {
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);
7641                     }
7642                     else // no scale
7643                     {
7644                         // Generate code to set tmpReg = base + index
7645                         emitIns_R_R_R(INS_add, leaBasePartialAddrAttr, tmpReg, memBase->gtRegNum, index->gtRegNum);
7646                     }
7647
7648                     noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
7649
7650                     // Then load/store dataReg from/to [tmpReg + offset]
7651                     emitIns_R_R_I(ins, attr, dataReg, tmpReg, offset);
7652                 }
7653                 else // large offset
7654                 {
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
7658                     //      rd = rd + base
7659                     emitIns_R_R_R(INS_add, leaBasePartialAddrAttr, tmpReg, tmpReg, memBase->gtRegNum);
7660
7661                     noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
7662                     noway_assert(tmpReg != index->gtRegNum);
7663
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,
7666                                     INS_OPTS_LSL);
7667                 }
7668             }
7669             else // (offset == 0)
7670             {
7671                 if (lsl > 0)
7672                 {
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,
7675                                     INS_OPTS_LSL);
7676                 }
7677                 else // no scale
7678                 {
7679                     // Then load/store dataReg from/to [memBase + index]
7680                     emitIns_R_R_R(ins, attr, dataReg, memBase->gtRegNum, index->gtRegNum);
7681                 }
7682             }
7683         }
7684         else // no Index
7685         {
7686             if (emitIns_valid_imm_for_ldst_offset(offset, attr))
7687             {
7688                 // Then load/store dataReg from/to [memBase + offset]
7689                 emitIns_R_R_I(ins, attr, dataReg, memBase->gtRegNum, offset);
7690             }
7691             else
7692             {
7693                 // We require a tmpReg to hold the offset
7694                 regNumber tmpReg = indir->GetSingleTempReg();
7695
7696                 // First load/store tmpReg with the large offset constant
7697                 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
7698
7699                 // Then load/store dataReg from/to [memBase + tmpReg]
7700                 emitIns_R_R_R(ins, attr, dataReg, memBase->gtRegNum, tmpReg);
7701             }
7702         }
7703     }
7704     else
7705     {
7706         if (offset != 0)
7707         {
7708             assert(emitIns_valid_imm_for_add(offset, INS_FLAGS_DONT_CARE));
7709             emitIns_R_R_I(ins, attr, dataReg, addr->gtRegNum, offset);
7710         }
7711         else
7712         {
7713             emitIns_R_R(ins, attr, dataReg, addr->gtRegNum);
7714         }
7715     }
7716 }
7717
7718 // The callee must call genConsumeReg() for any non-contained srcs
7719 // and genProduceReg() for any non-contained dsts.
7720
7721 regNumber emitter::emitInsBinary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src)
7722 {
7723     regNumber result = REG_NA;
7724
7725     // dst can only be a reg
7726     assert(!dst->isContained());
7727
7728     // src can be immed or reg
7729     assert(!src->isContained() || src->isContainedIntOrIImmed());
7730
7731     // find immed (if any) - it cannot be a dst
7732     GenTreeIntConCommon* intConst = nullptr;
7733     if (src->isContainedIntOrIImmed())
7734     {
7735         intConst = src->AsIntConCommon();
7736     }
7737
7738     if (intConst)
7739     {
7740         emitIns_R_I(ins, attr, dst->gtRegNum, (target_ssize_t)intConst->IconValue());
7741         return dst->gtRegNum;
7742     }
7743     else
7744     {
7745         emitIns_R_R(ins, attr, dst->gtRegNum, src->gtRegNum);
7746         return dst->gtRegNum;
7747     }
7748 }
7749
7750 regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src1, GenTree* src2)
7751 {
7752     // dst can only be a reg
7753     assert(!dst->isContained());
7754
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;
7759
7760     if (varTypeIsFloating(dst))
7761     {
7762         // src1 can only be a reg
7763         assert(!src1->isContained());
7764         // src2 can only be a reg
7765         assert(!src2->isContained());
7766     }
7767     else // not floating point
7768     {
7769         // src2 can be immed or reg
7770         assert(!src2->isContained() || src2->isContainedIntOrIImmed());
7771
7772         // Check src2 first as we can always allow it to be a contained immediate
7773         if (src2->isContainedIntOrIImmed())
7774         {
7775             intConst  = src2->AsIntConCommon();
7776             nonIntReg = src1;
7777         }
7778         // Only for commutative operations do we check src1 and allow it to be a contained immediate
7779         else if (dst->OperIsCommutative())
7780         {
7781             // src1 can be immed or reg
7782             assert(!src1->isContained() || src1->isContainedIntOrIImmed());
7783
7784             // Check src1 and allow it to be a contained immediate
7785             if (src1->isContainedIntOrIImmed())
7786             {
7787                 assert(!src2->isContainedIntOrIImmed());
7788                 intConst  = src1->AsIntConCommon();
7789                 nonIntReg = src2;
7790             }
7791         }
7792         else
7793         {
7794             // src1 can only be a reg
7795             assert(!src1->isContained());
7796         }
7797     }
7798
7799     insFlags flags         = INS_FLAGS_DONT_CARE;
7800     bool     isMulOverflow = false;
7801     if (dst->gtOverflowEx())
7802     {
7803         if ((ins == INS_add) || (ins == INS_adc) || (ins == INS_sub) || (ins == INS_sbc))
7804         {
7805             flags = INS_FLAGS_SET;
7806         }
7807         else if (ins == INS_mul)
7808         {
7809             isMulOverflow = true;
7810             assert(intConst == nullptr); // overflow format doesn't support an int constant operand
7811         }
7812         else
7813         {
7814             assert(!"Invalid ins for overflow check");
7815         }
7816     }
7817
7818     if (dst->gtSetFlags())
7819     {
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;
7823     }
7824
7825     if (intConst != nullptr)
7826     {
7827         emitIns_R_R_I(ins, attr, dst->gtRegNum, nonIntReg->gtRegNum, (target_ssize_t)intConst->IconValue(), flags);
7828     }
7829     else
7830     {
7831         if (isMulOverflow)
7832         {
7833             regNumber extraReg = dst->GetSingleTempReg();
7834             assert(extraReg != dst->gtRegNum);
7835
7836             if ((dst->gtFlags & GTF_UNSIGNED) != 0)
7837             {
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);
7840
7841                 // Overflow exists if the result's high word is non-zero.
7842                 emitIns_R_I(INS_cmp, attr, extraReg, 0);
7843             }
7844             else
7845             {
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);
7848
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);
7851             }
7852         }
7853         else
7854         {
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);
7857         }
7858     }
7859
7860     if (dst->gtOverflowEx())
7861     {
7862         assert(!varTypeIsFloating(dst));
7863
7864         emitJumpKind jumpKind;
7865
7866         if (dst->OperGet() == GT_MUL)
7867         {
7868             jumpKind = EJ_ne;
7869         }
7870         else
7871         {
7872             bool isUnsignedOverflow = ((dst->gtFlags & GTF_UNSIGNED) != 0);
7873             jumpKind                = isUnsignedOverflow ? EJ_lo : EJ_vs;
7874             if (jumpKind == EJ_lo)
7875             {
7876                 if ((dst->OperGet() != GT_SUB) && (dst->OperGet() != GT_SUB_HI))
7877                 {
7878                     jumpKind = EJ_hs;
7879                 }
7880             }
7881         }
7882
7883         // Jump to the block which will throw the exception.
7884         codeGen->genJumpToThrowHlpBlk(jumpKind, SCK_OVERFLOW);
7885     }
7886
7887     return dst->gtRegNum;
7888 }
7889
7890 #endif // defined(_TARGET_ARM_)