Use insEncodeImmT2_Mov to encode imm in IF_T2_N1 in src/jit/emitarm.cpp
[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             code |= insEncodeImmT2_Mov(imm);
5395             dst += emitOutput_Thumb2Instr(dst, code);
5396
5397             if (id->idIsCnsReloc() || id->idIsDspReloc())
5398             {
5399                 assert(ins == INS_movt || ins == INS_movw);
5400                 if ((ins == INS_movt) && emitComp->info.compMatchedVM)
5401                     emitHandlePCRelativeMov32((void*)(dst - 8), (void*)distVal);
5402             }
5403         }
5404         else
5405         {
5406             assert(!"Unknown fmt");
5407         }
5408     }
5409
5410     return dst;
5411 }
5412
5413 /*****************************************************************************
5414  *
5415  *  Output a short branch instruction.
5416  */
5417
5418 BYTE* emitter::emitOutputShortBranch(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, instrDescJmp* id)
5419 {
5420     code_t code;
5421
5422     code = emitInsCode(ins, fmt);
5423
5424     if (fmt == IF_T1_K)
5425     {
5426         assert((distVal & 1) == 0);
5427         assert(distVal >= -256);
5428         assert(distVal <= 254);
5429
5430         if (distVal < 0)
5431             code |= 1 << 7;
5432         code |= ((distVal >> 1) & 0x7f);
5433     }
5434     else if (fmt == IF_T1_M)
5435     {
5436         assert((distVal & 1) == 0);
5437         assert(distVal >= -2048);
5438         assert(distVal <= 2046);
5439
5440         if (distVal < 0)
5441             code |= 1 << 10;
5442         code |= ((distVal >> 1) & 0x3ff);
5443     }
5444     else if (fmt == IF_T1_I)
5445     {
5446         assert(id != NULL);
5447         assert(ins == INS_cbz || INS_cbnz);
5448         assert((distVal & 1) == 0);
5449         assert(distVal >= 0);
5450         assert(distVal <= 126);
5451
5452         code |= ((distVal << 3) & 0x0200);
5453         code |= ((distVal << 2) & 0x00F8);
5454         code |= (id->idReg1() & 0x0007);
5455     }
5456     else
5457     {
5458         assert(!"Unknown fmt");
5459     }
5460
5461     dst += emitOutput_Thumb1Instr(dst, code);
5462
5463     return dst;
5464 }
5465
5466 #ifdef FEATURE_ITINSTRUCTION
5467
5468 /*****************************************************************************
5469  * The "IT" instruction is deprecated (with a very few exceptions). Don't generate it!
5470  * Don't delete this code, though, in case we ever want to bring it back.
5471  *****************************************************************************/
5472
5473 /*****************************************************************************
5474  *
5475  *  Output an IT instruction.
5476  */
5477
5478 BYTE* emitter::emitOutputIT(BYTE* dst, instruction ins, insFormat fmt, code_t condcode)
5479 {
5480     code_t imm0;
5481     code_t code, mask, bit;
5482
5483     code = emitInsCode(ins, fmt);
5484     code |= (condcode << 4);        // encode firstcond
5485     imm0 = condcode & 1;            // this is firstcond[0]
5486     mask = code & 0x0f;             // initialize mask encoded in opcode
5487     bit  = 0x08;                    // where in mask we are encoding
5488     while ((mask & (bit - 1)) != 0) // are the remaining bits all zeros?
5489     {                               //  then we are done
5490         // otherwise determine the setting of bit
5491         if ((imm0 == 1) ^ ((bit & mask) != 0))
5492         {
5493             code |= bit; // set the current bit
5494         }
5495         else
5496         {
5497             code &= ~bit; // clear the current bit
5498         }
5499         bit >>= 1;
5500     }
5501     dst += emitOutput_Thumb1Instr(dst, code);
5502
5503     return dst;
5504 }
5505
5506 #endif // FEATURE_ITINSTRUCTION
5507
5508 /*****************************************************************************
5509 *
5510  *  Append the machine code corresponding to the given instruction descriptor
5511  *  to the code block at '*dp'; the base of the code block is 'bp', and 'ig'
5512  *  is the instruction group that contains the instruction. Updates '*dp' to
5513  *  point past the generated code, and returns the size of the instruction
5514  *  descriptor in bytes.
5515  */
5516
5517 size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
5518 {
5519     BYTE*         dst           = *dp;
5520     BYTE*         odst          = dst;
5521     code_t        code          = 0;
5522     size_t        sz            = 0;
5523     instruction   ins           = id->idIns();
5524     insFormat     fmt           = id->idInsFmt();
5525     emitAttr      size          = id->idOpSize();
5526     unsigned char callInstrSize = 0;
5527
5528 #ifdef DEBUG
5529     bool dspOffs = emitComp->opts.dspGCtbls || !emitComp->opts.disDiffable;
5530 #endif // DEBUG
5531
5532     assert(REG_NA == (int)REG_NA);
5533
5534     VARSET_TP GCvars(VarSetOps::UninitVal());
5535
5536     /* What instruction format have we got? */
5537
5538     switch (fmt)
5539     {
5540         int       imm;
5541         BYTE*     addr;
5542         regMaskTP gcrefRegs;
5543         regMaskTP byrefRegs;
5544
5545         case IF_T1_A: // T1_A    ................
5546             sz   = SMALL_IDSC_SIZE;
5547             code = emitInsCode(ins, fmt);
5548             dst += emitOutput_Thumb1Instr(dst, code);
5549             break;
5550
5551 #ifdef FEATURE_ITINSTRUCTION
5552         case IF_T1_B: // T1_B    ........cccc....                                           cond
5553         {
5554             assert(id->idGCref() == GCT_NONE);
5555             target_ssize_t condcode = emitGetInsSC(id);
5556             dst                     = emitOutputIT(dst, ins, fmt, condcode);
5557             sz                      = SMALL_IDSC_SIZE;
5558         }
5559         break;
5560 #endif // FEATURE_ITINSTRUCTION
5561
5562         case IF_T1_C: // T1_C    .....iiiiinnnddd                       R1  R2              imm5
5563             sz   = SMALL_IDSC_SIZE;
5564             imm  = emitGetInsSC(id);
5565             code = emitInsCode(ins, fmt);
5566             code |= insEncodeRegT1_D3(id->idReg1());
5567             code |= insEncodeRegT1_N3(id->idReg2());
5568             if (emitInsIsLoadOrStore(ins))
5569             {
5570                 imm = insUnscaleImm(imm, size);
5571             }
5572             assert((imm & 0x001f) == imm);
5573             code |= (imm << 6);
5574             dst += emitOutput_Thumb1Instr(dst, code);
5575             break;
5576
5577         case IF_T1_D0: // T1_D0   ........Dmmmmddd                       R1* R2*
5578             sz   = SMALL_IDSC_SIZE;
5579             code = emitInsCode(ins, fmt);
5580             code |= insEncodeRegT1_D4(id->idReg1());
5581             code |= insEncodeRegT1_M4(id->idReg2());
5582             dst += emitOutput_Thumb1Instr(dst, code);
5583             break;
5584
5585         case IF_T1_E: // T1_E    ..........nnnddd                       R1  R2
5586             sz   = SMALL_IDSC_SIZE;
5587             code = emitInsCode(ins, fmt);
5588             code |= insEncodeRegT1_D3(id->idReg1());
5589             code |= insEncodeRegT1_N3(id->idReg2());
5590             dst += emitOutput_Thumb1Instr(dst, code);
5591             break;
5592
5593         case IF_T1_F: // T1_F    .........iiiiiii                       SP                  imm7
5594             sz   = emitGetInstrDescSize(id);
5595             imm  = emitGetInsSC(id);
5596             code = emitInsCode(ins, fmt);
5597             imm  = insUnscaleImm(imm, size);
5598             assert((imm & 0x007F) == imm);
5599             code |= imm;
5600             dst += emitOutput_Thumb1Instr(dst, code);
5601             break;
5602
5603         case IF_T1_G: // T1_G    .......iiinnnddd                       R1  R2              imm3
5604             sz   = SMALL_IDSC_SIZE;
5605             imm  = emitGetInsSC(id);
5606             code = emitInsCode(ins, fmt);
5607             code |= insEncodeRegT1_D3(id->idReg1());
5608             code |= insEncodeRegT1_N3(id->idReg2());
5609             assert((imm & 0x0007) == imm);
5610             code |= (imm << 6);
5611             dst += emitOutput_Thumb1Instr(dst, code);
5612             break;
5613
5614         case IF_T1_H: // T1_H    .......mmmnnnddd                       R1  R2  R3
5615             sz   = emitGetInstrDescSize(id);
5616             code = emitInsCode(ins, fmt);
5617             code |= insEncodeRegT1_D3(id->idReg1());
5618             code |= insEncodeRegT1_N3(id->idReg2());
5619             code |= insEncodeRegT1_M3(id->idReg3());
5620             dst += emitOutput_Thumb1Instr(dst, code);
5621             break;
5622
5623         case IF_T1_I: // T1_I    ......i.iiiiiddd                       R1                  imm6
5624             assert(id->idIsBound());
5625
5626             dst = emitOutputLJ(ig, dst, id);
5627             sz  = sizeof(instrDescJmp);
5628             break;
5629
5630         case IF_T1_J0: // T1_J0   .....dddiiiiiiii                       R1                  imm8
5631         case IF_T1_J1: // T1_J1   .....dddiiiiiiii                       R1                  <regmask8>
5632         case IF_T1_J2: // T1_J2   .....dddiiiiiiii                       R1  SP              imm8
5633             sz   = emitGetInstrDescSize(id);
5634             imm  = emitGetInsSC(id);
5635             code = emitInsCode(ins, fmt);
5636             code |= insEncodeRegT1_DI(id->idReg1());
5637             if (fmt == IF_T1_J2)
5638             {
5639                 imm = insUnscaleImm(imm, size);
5640             }
5641             assert((imm & 0x00ff) == imm);
5642             code |= imm;
5643             dst += emitOutput_Thumb1Instr(dst, code);
5644             break;
5645
5646         case IF_T1_L0: // T1_L0   ........iiiiiiii                                           imm8
5647         case IF_T1_L1: // T1_L1   .......Rrrrrrrrr                                           <regmask8>
5648             sz   = emitGetInstrDescSize(id);
5649             imm  = emitGetInsSC(id);
5650             code = emitInsCode(ins, fmt);
5651             if (fmt == IF_T1_L1)
5652             {
5653                 assert((imm & 0x3) != 0x3);
5654                 if (imm & 0x3)
5655                     code |= 0x0100; //  R bit
5656                 imm >>= 2;
5657             }
5658             assert((imm & 0x00ff) == imm);
5659             code |= imm;
5660             dst += emitOutput_Thumb1Instr(dst, code);
5661             break;
5662
5663         case IF_T2_A: // T2_A    ................ ................
5664             sz   = SMALL_IDSC_SIZE;
5665             code = emitInsCode(ins, fmt);
5666             dst += emitOutput_Thumb2Instr(dst, code);
5667             break;
5668
5669         case IF_T2_B: // T2_B    ................ ............iiii                          imm4
5670             sz   = SMALL_IDSC_SIZE;
5671             imm  = emitGetInsSC(id);
5672             code = emitInsCode(ins, fmt);
5673             assert((imm & 0x000F) == imm);
5674             code |= imm;
5675             dst += emitOutput_Thumb2Instr(dst, code);
5676             break;
5677
5678         case IF_T2_C0: // T2_C0   ...........Snnnn .iiiddddiishmmmm       R1  R2  R3      S, imm5, sh
5679         case IF_T2_C4: // T2_C4   ...........Snnnn ....dddd....mmmm       R1  R2  R3      S
5680         case IF_T2_C5: // T2_C5   ............nnnn ....dddd....mmmm       R1  R2  R3
5681             sz   = emitGetInstrDescSize(id);
5682             code = emitInsCode(ins, fmt);
5683             code |= insEncodeRegT2_D(id->idReg1());
5684             code |= insEncodeRegT2_N(id->idReg2());
5685             code |= insEncodeRegT2_M(id->idReg3());
5686             if (fmt != IF_T2_C5)
5687                 code |= insEncodeSetFlags(id->idInsFlags());
5688             if (fmt == IF_T2_C0)
5689             {
5690                 imm = emitGetInsSC(id);
5691                 code |= insEncodeShiftCount(imm);
5692                 code |= insEncodeShiftOpts(id->idInsOpt());
5693             }
5694             dst += emitOutput_Thumb2Instr(dst, code);
5695             break;
5696
5697         case IF_T2_C1: // T2_C1   ...........S.... .iiiddddiishmmmm       R1  R2          S, imm5, sh
5698         case IF_T2_C2: // T2_C2   ...........S.... .iiiddddii..mmmm       R1  R2          S, imm5
5699         case IF_T2_C6: // T2_C6   ................ ....dddd..iimmmm       R1  R2                   imm2
5700             sz   = SMALL_IDSC_SIZE;
5701             imm  = emitGetInsSC(id);
5702             code = emitInsCode(ins, fmt);
5703             code |= insEncodeRegT2_D(id->idReg1());
5704             code |= insEncodeRegT2_M(id->idReg2());
5705             if (fmt == IF_T2_C6)
5706             {
5707                 assert((imm & 0x0018) == imm);
5708                 code |= (imm << 1);
5709             }
5710             else
5711             {
5712                 code |= insEncodeSetFlags(id->idInsFlags());
5713                 code |= insEncodeShiftCount(imm);
5714                 if (fmt == IF_T2_C1)
5715                     code |= insEncodeShiftOpts(id->idInsOpt());
5716             }
5717             dst += emitOutput_Thumb2Instr(dst, code);
5718             break;
5719
5720         case IF_T2_C3: // T2_C3   ...........S.... ....dddd....mmmm       R1  R2          S
5721             sz   = SMALL_IDSC_SIZE;
5722             code = emitInsCode(ins, fmt);
5723             code |= insEncodeRegT2_D(id->idReg1());
5724             code |= insEncodeRegT2_M(id->idReg2());
5725             code |= insEncodeSetFlags(id->idInsFlags());
5726             dst += emitOutput_Thumb2Instr(dst, code);
5727             break;
5728
5729         case IF_T2_C7: // T2_C7   ............nnnn ..........shmmmm       R1  R2                   imm2
5730         case IF_T2_C8: // T2_C8   ............nnnn .iii....iishmmmm       R1  R2             imm5, sh
5731             sz   = SMALL_IDSC_SIZE;
5732             imm  = emitGetInsSC(id);
5733             code = emitInsCode(ins, fmt);
5734             code |= insEncodeRegT2_N(id->idReg1());
5735             code |= insEncodeRegT2_M(id->idReg2());
5736             if (fmt == IF_T2_C7)
5737             {
5738                 assert((imm & 0x0003) == imm);
5739                 code |= (imm << 4);
5740             }
5741             else if (fmt == IF_T2_C8)
5742             {
5743                 code |= insEncodeShiftCount(imm);
5744                 code |= insEncodeShiftOpts(id->idInsOpt());
5745             }
5746             dst += emitOutput_Thumb2Instr(dst, code);
5747             break;
5748
5749         case IF_T2_C9: // T2_C9   ............nnnn ............mmmm       R1  R2
5750             sz   = SMALL_IDSC_SIZE;
5751             code = emitInsCode(ins, fmt);
5752             code |= insEncodeRegT2_N(id->idReg1());
5753             code |= insEncodeRegT2_M(id->idReg2());
5754             dst += emitOutput_Thumb2Instr(dst, code);
5755             break;
5756
5757         case IF_T2_C10: // T2_C10  ............mmmm ....dddd....mmmm       R1  R2
5758             sz   = SMALL_IDSC_SIZE;
5759             code = emitInsCode(ins, fmt);
5760             code |= insEncodeRegT2_D(id->idReg1());
5761             code |= insEncodeRegT2_M(id->idReg2());
5762             code |= insEncodeRegT2_N(id->idReg2());
5763             dst += emitOutput_Thumb2Instr(dst, code);
5764             break;
5765
5766         case IF_T2_D0: // T2_D0   ............nnnn .iiiddddii.wwwww       R1  R2             imm5, imm5
5767         case IF_T2_D1: // T2_D1   ................ .iiiddddii.wwwww       R1                 imm5, imm5
5768             sz   = SMALL_IDSC_SIZE;
5769             imm  = emitGetInsSC(id);
5770             code = emitInsCode(ins, fmt);
5771             code |= insEncodeRegT2_D(id->idReg1());
5772             if (fmt == IF_T2_D0)
5773                 code |= insEncodeRegT2_N(id->idReg2());
5774             code |= insEncodeBitFieldImm(imm);
5775             dst += emitOutput_Thumb2Instr(dst, code);
5776             break;
5777
5778         case IF_T2_E0: // T2_E0   ............nnnn tttt......shmmmm       R1  R2  R3               imm2
5779         case IF_T2_E1: // T2_E1   ............nnnn tttt............       R1  R2
5780         case IF_T2_E2: // T2_E2   ................ tttt............       R1
5781             code = emitInsCode(ins, fmt);
5782             code |= insEncodeRegT2_T(id->idReg1());
5783             if (fmt == IF_T2_E0)
5784             {
5785                 sz = emitGetInstrDescSize(id);
5786                 code |= insEncodeRegT2_N(id->idReg2());
5787                 if (id->idIsLclVar())
5788                 {
5789                     code |= insEncodeRegT2_M(codeGen->rsGetRsvdReg());
5790                     imm = 0;
5791                 }
5792                 else
5793                 {
5794                     code |= insEncodeRegT2_M(id->idReg3());
5795                     imm = emitGetInsSC(id);
5796                     assert((imm & 0x0003) == imm);
5797                     code |= (imm << 4);
5798                 }
5799             }
5800             else
5801             {
5802                 sz = SMALL_IDSC_SIZE;
5803                 if (fmt != IF_T2_E2)
5804                 {
5805                     code |= insEncodeRegT2_N(id->idReg2());
5806                 }
5807             }
5808             dst += emitOutput_Thumb2Instr(dst, code);
5809             break;
5810
5811         case IF_T2_F1: // T2_F1    ............nnnn ttttdddd....mmmm       R1  R2  R3  R4
5812             sz = emitGetInstrDescSize(id);
5813             ;
5814             code = emitInsCode(ins, fmt);
5815             code |= insEncodeRegT2_T(id->idReg1());
5816             code |= insEncodeRegT2_D(id->idReg2());
5817             code |= insEncodeRegT2_N(id->idReg3());
5818             code |= insEncodeRegT2_M(id->idReg4());
5819             dst += emitOutput_Thumb2Instr(dst, code);
5820             break;
5821
5822         case IF_T2_F2: // T2_F2    ............nnnn aaaadddd....mmmm       R1  R2  R3  R4
5823             sz   = emitGetInstrDescSize(id);
5824             code = emitInsCode(ins, fmt);
5825             code |= insEncodeRegT2_D(id->idReg1());
5826             code |= insEncodeRegT2_N(id->idReg2());
5827             code |= insEncodeRegT2_M(id->idReg3());
5828             code |= insEncodeRegT2_T(id->idReg4());
5829             dst += emitOutput_Thumb2Instr(dst, code);
5830             break;
5831
5832         case IF_T2_G0: // T2_G0   .......PU.W.nnnn ttttTTTTiiiiiiii       R1  R2  R3         imm8, PUW
5833         case IF_T2_G1: // T2_G1   ............nnnn ttttTTTT........       R1  R2  R3
5834             code = emitInsCode(ins, fmt);
5835             code |= insEncodeRegT2_T(id->idReg1());
5836             code |= insEncodeRegT2_D(id->idReg2());
5837             code |= insEncodeRegT2_N(id->idReg3());
5838             if (fmt == IF_T2_G0)
5839             {
5840                 sz  = emitGetInstrDescSizeSC(id);
5841                 imm = emitGetInsSC(id);
5842                 assert(unsigned_abs(imm) <= 0x00ff);
5843                 code |= abs(imm);
5844                 code |= insEncodePUW_G0(id->idInsOpt(), imm);
5845             }
5846             else
5847             {
5848                 sz = emitGetInstrDescSize(id);
5849             }
5850             dst += emitOutput_Thumb2Instr(dst, code);
5851             break;
5852
5853         case IF_T2_H0: // T2_H0   ............nnnn tttt.PUWiiiiiiii       R1  R2             imm8, PUW
5854         case IF_T2_H1: // T2_H1   ............nnnn tttt....iiiiiiii       R1  R2             imm8
5855         case IF_T2_H2: // T2_H2   ............nnnn ........iiiiiiii       R1                 imm8
5856             sz   = emitGetInstrDescSizeSC(id);
5857             imm  = emitGetInsSC(id);
5858             code = emitInsCode(ins, fmt);
5859             code |= insEncodeRegT2_T(id->idReg1());
5860
5861             if (fmt != IF_T2_H2)
5862                 code |= insEncodeRegT2_N(id->idReg2());
5863
5864             if (fmt == IF_T2_H0)
5865             {
5866                 assert(unsigned_abs(imm) <= 0x00ff);
5867                 code |= insEncodePUW_H0(id->idInsOpt(), imm);
5868                 code |= unsigned_abs(imm);
5869             }
5870             else
5871             {
5872                 assert((imm & 0x00ff) == imm);
5873                 code |= imm;
5874             }
5875             dst += emitOutput_Thumb2Instr(dst, code);
5876             break;
5877
5878         case IF_T2_I0: // T2_I0   ..........W.nnnn rrrrrrrrrrrrrrrr       R1              W, imm16
5879         case IF_T2_I1: // T2_I1   ................ rrrrrrrrrrrrrrrr                          imm16
5880             sz   = emitGetInstrDescSizeSC(id);
5881             code = emitInsCode(ins, fmt);
5882             if (fmt == IF_T2_I0)
5883             {
5884                 code |= insEncodeRegT2_N(id->idReg1());
5885                 code |= (1 << 21); //  W bit
5886             }
5887             imm = emitGetInsSC(id);
5888             assert((imm & 0x3) != 0x3);
5889             if (imm & 0x2)
5890                 code |= 0x8000; //  PC bit
5891             if (imm & 0x1)
5892                 code |= 0x4000; //  LR bit
5893             imm >>= 2;
5894             assert(imm <= 0x1fff); //  13 bits
5895             code |= imm;
5896             dst += emitOutput_Thumb2Instr(dst, code);
5897             break;
5898
5899         case IF_T2_K1: // T2_K1   ............nnnn ttttiiiiiiiiiiii       R1  R2             imm12
5900         case IF_T2_K4: // T2_K4   ........U....... ttttiiiiiiiiiiii       R1  PC          U, imm12
5901         case IF_T2_K3: // T2_K3   ........U....... ....iiiiiiiiiiii       PC              U, imm12
5902             sz   = emitGetInstrDescSize(id);
5903             imm  = emitGetInsSC(id);
5904             code = emitInsCode(ins, fmt);
5905             if (fmt != IF_T2_K3)
5906             {
5907                 code |= insEncodeRegT2_T(id->idReg1());
5908             }
5909             if (fmt == IF_T2_K1)
5910             {
5911                 code |= insEncodeRegT2_N(id->idReg2());
5912                 assert(imm <= 0xfff); //  12 bits
5913                 code |= imm;
5914             }
5915             else
5916             {
5917                 assert(unsigned_abs(imm) <= 0xfff); //  12 bits (signed)
5918                 code |= abs(imm);
5919                 if (imm >= 0)
5920                     code |= (1 << 23); //  U bit
5921             }
5922             dst += emitOutput_Thumb2Instr(dst, code);
5923             break;
5924
5925         case IF_T2_K2: // T2_K2   ............nnnn ....iiiiiiiiiiii       R1                 imm12
5926             sz   = emitGetInstrDescSizeSC(id);
5927             imm  = emitGetInsSC(id);
5928             code = emitInsCode(ins, fmt);
5929             code |= insEncodeRegT2_N(id->idReg1());
5930             assert(imm <= 0xfff); //  12 bits
5931             code |= imm;
5932             dst += emitOutput_Thumb2Instr(dst, code);
5933             break;
5934
5935         case IF_T2_L0: // T2_L0   .....i.....Snnnn .iiiddddiiiiiiii       R1  R2          S, imm8<<imm4
5936         case IF_T2_L1: // T2_L1   .....i.....S.... .iiiddddiiiiiiii       R1              S, imm8<<imm4
5937         case IF_T2_L2: // T2_L2   .....i......nnnn .iii....iiiiiiii       R1                 imm8<<imm4
5938             sz   = emitGetInstrDescSize(id);
5939             imm  = emitGetInsSC(id);
5940             code = emitInsCode(ins, fmt);
5941
5942             if (fmt == IF_T2_L2)
5943                 code |= insEncodeRegT2_N(id->idReg1());
5944             else
5945             {
5946                 code |= insEncodeSetFlags(id->idInsFlags());
5947                 code |= insEncodeRegT2_D(id->idReg1());
5948                 if (fmt == IF_T2_L0)
5949                     code |= insEncodeRegT2_N(id->idReg2());
5950             }
5951             assert(isModImmConst(imm)); // Funky ARM imm encoding
5952             imm = encodeModImmConst(imm);
5953             assert(imm <= 0xfff); //  12 bits
5954             code |= (imm & 0x00ff);
5955             code |= (imm & 0x0700) << 4;
5956             code |= (imm & 0x0800) << 15;
5957             dst += emitOutput_Thumb2Instr(dst, code);
5958             break;
5959
5960         case IF_T2_M0: // T2_M0   .....i......nnnn .iiiddddiiiiiiii       R1  R2             imm12
5961             sz   = emitGetInstrDescSizeSC(id);
5962             imm  = emitGetInsSC(id);
5963             code = emitInsCode(ins, fmt);
5964             code |= insEncodeRegT2_D(id->idReg1());
5965             if (fmt == IF_T2_M0)
5966                 code |= insEncodeRegT2_N(id->idReg2());
5967             imm = emitGetInsSC(id);
5968             assert(imm <= 0xfff); //  12 bits
5969             code |= (imm & 0x00ff);
5970             code |= (imm & 0x0700) << 4;
5971             code |= (imm & 0x0800) << 15;
5972             dst += emitOutput_Thumb2Instr(dst, code);
5973             break;
5974
5975         case IF_T2_N: // T2_N    .....i......iiii .iiiddddiiiiiiii       R1                 imm16
5976             sz   = emitGetInstrDescSizeSC(id);
5977             code = emitInsCode(ins, fmt);
5978             code |= insEncodeRegT2_D(id->idReg1());
5979             imm = emitGetInsSC(id);
5980             if (id->idIsLclVar())
5981             {
5982                 if (ins == INS_movw)
5983                 {
5984                     imm &= 0xffff;
5985                 }
5986                 else
5987                 {
5988                     assert(ins == INS_movt);
5989                     imm = (imm >> 16) & 0xffff;
5990                 }
5991             }
5992
5993             assert(!id->idIsReloc());
5994             code |= insEncodeImmT2_Mov(imm);
5995             dst += emitOutput_Thumb2Instr(dst, code);
5996             break;
5997
5998         case IF_T2_N2: // T2_N2   .....i......iiii .iiiddddiiiiiiii       R1                 imm16
5999             sz   = emitGetInstrDescSizeSC(id);
6000             code = emitInsCode(ins, fmt);
6001             code |= insEncodeRegT2_D(id->idReg1());
6002             imm  = emitGetInsSC(id);
6003             addr = emitConsBlock + imm;
6004             if (!id->idIsReloc())
6005             {
6006                 assert(sizeof(size_t) == sizeof(target_size_t));
6007                 imm = (target_size_t)addr;
6008                 if (ins == INS_movw)
6009                 {
6010                     imm &= 0xffff;
6011                 }
6012                 else
6013                 {
6014                     assert(ins == INS_movt);
6015                     imm = (imm >> 16) & 0xffff;
6016                 }
6017                 code |= insEncodeImmT2_Mov(imm);
6018                 dst += emitOutput_Thumb2Instr(dst, code);
6019             }
6020             else
6021             {
6022                 assert((ins == INS_movt) || (ins == INS_movw));
6023                 dst += emitOutput_Thumb2Instr(dst, code);
6024                 if ((ins == INS_movt) && emitComp->info.compMatchedVM)
6025                     emitHandlePCRelativeMov32((void*)(dst - 8), addr);
6026             }
6027             break;
6028
6029         case IF_T2_N3: // T2_N3   .....i......iiii .iiiddddiiiiiiii       R1                 imm16
6030             sz   = sizeof(instrDescReloc);
6031             code = emitInsCode(ins, fmt);
6032             code |= insEncodeRegT2_D(id->idReg1());
6033
6034             assert((ins == INS_movt) || (ins == INS_movw));
6035             assert(id->idIsReloc());
6036
6037             addr = emitGetInsRelocValue(id);
6038             dst += emitOutput_Thumb2Instr(dst, code);
6039             if ((ins == INS_movt) && emitComp->info.compMatchedVM)
6040                 emitHandlePCRelativeMov32((void*)(dst - 8), addr);
6041             break;
6042
6043         case IF_T2_VFP3:
6044             // these are the binary operators
6045             // d = n - m
6046             sz   = emitGetInstrDescSize(id);
6047             code = emitInsCode(ins, fmt);
6048             code |= insEncodeRegT2_VectorN(id->idReg2(), size, true);
6049             code |= insEncodeRegT2_VectorM(id->idReg3(), size, true);
6050             code |= insEncodeRegT2_VectorD(id->idReg1(), size, true);
6051             if (size == EA_8BYTE)
6052                 code |= 1 << 8;
6053             dst += emitOutput_Thumb2Instr(dst, code);
6054             break;
6055
6056         case IF_T2_VFP2:
6057         {
6058             emitAttr srcSize;
6059             emitAttr dstSize;
6060             size_t   szCode = 0;
6061
6062             switch (ins)
6063             {
6064                 case INS_vcvt_i2d:
6065                 case INS_vcvt_u2d:
6066                 case INS_vcvt_f2d:
6067                     srcSize = EA_4BYTE;
6068                     dstSize = EA_8BYTE;
6069                     break;
6070
6071                 case INS_vcvt_d2i:
6072                 case INS_vcvt_d2u:
6073                 case INS_vcvt_d2f:
6074                     srcSize = EA_8BYTE;
6075                     dstSize = EA_4BYTE;
6076                     break;
6077
6078                 case INS_vmov:
6079                 case INS_vabs:
6080                 case INS_vsqrt:
6081                 case INS_vcmp:
6082                 case INS_vneg:
6083                     if (id->idOpSize() == EA_8BYTE)
6084                         szCode |= (1 << 8);
6085                     __fallthrough;
6086
6087                 default:
6088                     srcSize = dstSize = id->idOpSize();
6089                     break;
6090             }
6091
6092             sz   = emitGetInstrDescSize(id);
6093             code = emitInsCode(ins, fmt);
6094             code |= szCode;
6095             code |= insEncodeRegT2_VectorD(id->idReg1(), dstSize, true);
6096             code |= insEncodeRegT2_VectorM(id->idReg2(), srcSize, true);
6097
6098             dst += emitOutput_Thumb2Instr(dst, code);
6099             break;
6100         }
6101
6102         case IF_T2_VLDST:
6103             sz   = emitGetInstrDescSizeSC(id);
6104             code = emitInsCode(ins, fmt);
6105             code |= insEncodeRegT2_N(id->idReg2());
6106             code |= insEncodeRegT2_VectorD(id->idReg1(), size, true);
6107
6108             imm = emitGetInsSC(id);
6109             if (imm < 0)
6110                 imm = -imm; // bit 23 at 0 means negate
6111             else
6112                 code |= 1 << 23; // set the positive bit
6113
6114             // offset is +/- 1020
6115             assert(!(imm % 4));
6116             assert(imm >> 10 == 0);
6117             code |= imm >> 2;
6118             // bit 8 is set for doubles
6119             if (id->idOpSize() == EA_8BYTE)
6120                 code |= (1 << 8);
6121             dst += emitOutput_Thumb2Instr(dst, code);
6122             break;
6123
6124         case IF_T2_VMOVD:
6125             // 3op assemble a double from two int regs (or back)
6126             sz   = emitGetInstrDescSize(id);
6127             code = emitInsCode(ins, fmt);
6128             if (ins == INS_vmov_i2d)
6129             {
6130                 code |= insEncodeRegT2_VectorM(id->idReg1(), size, true);
6131                 code |= id->idReg2() << 12;
6132                 code |= id->idReg3() << 16;
6133             }
6134             else
6135             {
6136                 assert(ins == INS_vmov_d2i);
6137                 code |= id->idReg1() << 12;
6138                 code |= id->idReg2() << 16;
6139                 code |= insEncodeRegT2_VectorM(id->idReg3(), size, true);
6140             }
6141             dst += emitOutput_Thumb2Instr(dst, code);
6142             break;
6143
6144         case IF_T2_VMOVS:
6145             // 2op assemble a float from one int reg (or back)
6146             sz   = emitGetInstrDescSize(id);
6147             code = emitInsCode(ins, fmt);
6148             if (ins == INS_vmov_f2i)
6149             {
6150                 code |= insEncodeRegT2_VectorN(id->idReg2(), EA_4BYTE, true);
6151                 code |= id->idReg1() << 12;
6152             }
6153             else
6154             {
6155                 assert(ins == INS_vmov_i2f);
6156                 code |= insEncodeRegT2_VectorN(id->idReg1(), EA_4BYTE, true);
6157                 code |= id->idReg2() << 12;
6158             }
6159
6160             dst += emitOutput_Thumb2Instr(dst, code);
6161             break;
6162
6163         case IF_T1_J3: // T1_J3   .....dddiiiiiiii                        R1  PC             imm8
6164         case IF_T2_M1: // T2_M1   .....i.......... .iiiddddiiiiiiii       R1  PC             imm12
6165             assert(id->idGCref() == GCT_NONE);
6166             assert(id->idIsBound());
6167
6168             dst = emitOutputLJ(ig, dst, id);
6169             sz  = sizeof(instrDescLbl);
6170             break;
6171
6172         case IF_T1_K:  // T1_K    ....cccciiiiiiii                       Branch              imm8, cond4
6173         case IF_T1_M:  // T1_M    .....iiiiiiiiiii                       Branch              imm11
6174         case IF_T2_J1: // T2_J1   .....Scccciiiiii ..j.jiiiiiiiiiii      Branch              imm20, cond4
6175         case IF_T2_J2: // T2_J2   .....Siiiiiiiiii ..j.jiiiiiiiiii.      Branch              imm24
6176         case IF_T2_N1: // T2_N    .....i......iiii .iiiddddiiiiiiii       R1                 imm16
6177         case IF_LARGEJMP:
6178             assert(id->idGCref() == GCT_NONE);
6179             assert(id->idIsBound());
6180
6181             dst = emitOutputLJ(ig, dst, id);
6182             sz  = sizeof(instrDescJmp);
6183             break;
6184
6185         case IF_T1_D1: // T1_D1   .........mmmm...                       R1*
6186
6187             code = emitInsCode(ins, fmt);
6188             code |= insEncodeRegT1_M4(id->idReg1());
6189             dst += emitOutput_Thumb1Instr(dst, code);
6190             sz = SMALL_IDSC_SIZE;
6191             break;
6192
6193         case IF_T1_D2: // T1_D2   .........mmmm...                                R3*
6194
6195             /* Is this a "fat" call descriptor? */
6196
6197             if (id->idIsLargeCall())
6198             {
6199                 instrDescCGCA* idCall = (instrDescCGCA*)id;
6200                 gcrefRegs             = idCall->idcGcrefRegs;
6201                 byrefRegs             = idCall->idcByrefRegs;
6202                 VarSetOps::Assign(emitComp, GCvars, idCall->idcGCvars);
6203                 sz = sizeof(instrDescCGCA);
6204             }
6205             else
6206             {
6207                 assert(!id->idIsLargeDsp());
6208                 assert(!id->idIsLargeCns());
6209
6210                 gcrefRegs = emitDecodeCallGCregs(id);
6211                 byrefRegs = 0;
6212                 VarSetOps::AssignNoCopy(emitComp, GCvars, VarSetOps::MakeEmpty(emitComp));
6213                 sz = sizeof(instrDesc);
6214             }
6215
6216             code = emitInsCode(ins, fmt);
6217             code |= insEncodeRegT1_M4(id->idReg3());
6218             callInstrSize = SafeCvtAssert<unsigned char>(emitOutput_Thumb1Instr(dst, code));
6219             dst += callInstrSize;
6220             goto DONE_CALL;
6221
6222         case IF_T2_J3: // T2_J3   .....Siiiiiiiiii ..j.jiiiiiiiiii.      Call                imm24
6223
6224             /* Is this a "fat" call descriptor? */
6225
6226             if (id->idIsLargeCall())
6227             {
6228                 instrDescCGCA* idCall = (instrDescCGCA*)id;
6229                 gcrefRegs             = idCall->idcGcrefRegs;
6230                 byrefRegs             = idCall->idcByrefRegs;
6231                 VarSetOps::Assign(emitComp, GCvars, idCall->idcGCvars);
6232                 sz = sizeof(instrDescCGCA);
6233             }
6234             else
6235             {
6236                 assert(!id->idIsLargeDsp());
6237                 assert(!id->idIsLargeCns());
6238
6239                 gcrefRegs = emitDecodeCallGCregs(id);
6240                 byrefRegs = 0;
6241                 VarSetOps::AssignNoCopy(emitComp, GCvars, VarSetOps::MakeEmpty(emitComp));
6242                 sz = sizeof(instrDesc);
6243             }
6244
6245             if (id->idAddr()->iiaAddr == NULL) /* a recursive call */
6246             {
6247                 addr = emitCodeBlock;
6248             }
6249             else
6250             {
6251                 addr = id->idAddr()->iiaAddr;
6252             }
6253             code = emitInsCode(ins, fmt);
6254
6255             if (id->idIsDspReloc())
6256             {
6257                 callInstrSize = SafeCvtAssert<unsigned char>(emitOutput_Thumb2Instr(dst, code));
6258                 dst += callInstrSize;
6259                 if (emitComp->info.compMatchedVM)
6260                     emitRecordRelocation((void*)(dst - 4), addr, IMAGE_REL_BASED_THUMB_BRANCH24);
6261             }
6262             else
6263             {
6264                 addr = (BYTE*)((size_t)addr & ~1); // Clear the lowest bit from target address
6265
6266                 /* Calculate PC relative displacement */
6267                 int  disp = addr - (dst + 4);
6268                 bool S    = (disp < 0);
6269                 bool I1   = ((disp & 0x00800000) == 0);
6270                 bool I2   = ((disp & 0x00400000) == 0);
6271
6272                 if (S)
6273                     code |= (1 << 26); // S bit
6274                 if (S ^ I1)
6275                     code |= (1 << 13); // J1 bit
6276                 if (S ^ I2)
6277                     code |= (1 << 11); // J2 bit
6278
6279                 int immLo = (disp & 0x00000ffe) >> 1;
6280                 int immHi = (disp & 0x003ff000) >> 12;
6281
6282                 code |= (immHi << 16);
6283                 code |= immLo;
6284
6285                 disp = abs(disp);
6286                 assert((disp & 0x00fffffe) == disp);
6287
6288                 callInstrSize = SafeCvtAssert<unsigned char>(emitOutput_Thumb2Instr(dst, code));
6289                 dst += callInstrSize;
6290             }
6291
6292         DONE_CALL:
6293
6294             /* We update the GC info before the call as the variables cannot be
6295                used by the call. Killing variables before the call helps with
6296                boundary conditions if the call is CORINFO_HELP_THROW - see bug 50029.
6297                If we ever track aliased variables (which could be used by the
6298                call), we would have to keep them alive past the call. */
6299
6300             emitUpdateLiveGCvars(GCvars, *dp);
6301
6302             // If the method returns a GC ref, mark R0 appropriately.
6303             if (id->idGCref() == GCT_GCREF)
6304                 gcrefRegs |= RBM_R0;
6305             else if (id->idGCref() == GCT_BYREF)
6306                 byrefRegs |= RBM_R0;
6307
6308             // If the GC register set has changed, report the new set.
6309             if (gcrefRegs != emitThisGCrefRegs)
6310                 emitUpdateLiveGCregs(GCT_GCREF, gcrefRegs, dst);
6311
6312             if (byrefRegs != emitThisByrefRegs)
6313                 emitUpdateLiveGCregs(GCT_BYREF, byrefRegs, dst);
6314
6315             // Some helper calls may be marked as not requiring GC info to be recorded.
6316             if ((!id->idIsNoGC()))
6317             {
6318                 // On ARM, as on AMD64, we don't change the stack pointer to push/pop args.
6319                 // So we're not really doing a "stack pop" here (note that "args" is 0), but we use this mechanism
6320                 // to record the call for GC info purposes.  (It might be best to use an alternate call,
6321                 // and protect "emitStackPop" under the EMIT_TRACK_STACK_DEPTH preprocessor variable.)
6322                 emitStackPop(dst, /*isCall*/ true, callInstrSize, /*args*/ 0);
6323
6324                 /* Do we need to record a call location for GC purposes? */
6325
6326                 if (!emitFullGCinfo)
6327                 {
6328                     emitRecordGCcall(dst, callInstrSize);
6329                 }
6330             }
6331
6332             break;
6333
6334         /********************************************************************/
6335         /*                            oops                                  */
6336         /********************************************************************/
6337
6338         default:
6339
6340 #ifdef DEBUG
6341             printf("unexpected format %s\n", emitIfName(id->idInsFmt()));
6342             assert(!"don't know how to encode this instruction");
6343 #endif
6344             break;
6345     }
6346
6347     // Determine if any registers now hold GC refs, or whether a register that was overwritten held a GC ref.
6348     // We assume here that "id->idGCref()" is not GC_NONE only if the instruction described by "id" writes a
6349     // GC ref to register "id->idReg1()".  (It may, apparently, also not be GC_NONE in other cases, such as
6350     // for stores, but we ignore those cases here.)
6351     if (emitInsMayWriteToGCReg(id)) // True if "id->idIns()" writes to a register than can hold GC ref.
6352     {
6353         // If we ever generate instructions that write to multiple registers (LDM, or POP),
6354         // then we'd need to more work here to ensure that changes in the status of GC refs are
6355         // tracked properly.
6356         if (emitInsMayWriteMultipleRegs(id))
6357         {
6358             // We explicitly list the multiple-destination-target instruction that we expect to
6359             // be emitted outside of the prolog and epilog here.
6360             switch (ins)
6361             {
6362                 case INS_smull:
6363                 case INS_umull:
6364                 case INS_smlal:
6365                 case INS_umlal:
6366                 case INS_vmov_d2i:
6367                     // For each of these, idReg1() and idReg2() are the destination registers.
6368                     emitGCregDeadUpd(id->idReg1(), dst);
6369                     emitGCregDeadUpd(id->idReg2(), dst);
6370                     break;
6371                 default:
6372                     assert(false); // We need to recognize this multi-target instruction...
6373             }
6374         }
6375         else
6376         {
6377             if (id->idGCref() != GCT_NONE)
6378             {
6379                 emitGCregLiveUpd(id->idGCref(), id->idReg1(), dst);
6380             }
6381             else
6382             {
6383                 // I also assume that "idReg1" is the destination register of all instructions that write to registers.
6384                 emitGCregDeadUpd(id->idReg1(), dst);
6385             }
6386         }
6387     }
6388
6389     // Now we determine if the instruction has written to a (local variable) stack location, and either written a GC
6390     // ref or overwritten one.
6391     if (emitInsWritesToLclVarStackLoc(id))
6392     {
6393         int       varNum = id->idAddr()->iiaLclVar.lvaVarNum();
6394         unsigned  ofs    = AlignDown(id->idAddr()->iiaLclVar.lvaOffset(), TARGET_POINTER_SIZE);
6395         regNumber regBase;
6396         int       adr = emitComp->lvaFrameAddress(varNum, true, &regBase, ofs);
6397         if (id->idGCref() != GCT_NONE)
6398         {
6399             emitGCvarLiveUpd(adr + ofs, varNum, id->idGCref(), dst);
6400         }
6401         else
6402         {
6403             // If the type of the local is a gc ref type, update the liveness.
6404             var_types vt;
6405             if (varNum >= 0)
6406             {
6407                 // "Regular" (non-spill-temp) local.
6408                 vt = var_types(emitComp->lvaTable[varNum].lvType);
6409             }
6410             else
6411             {
6412                 TempDsc* tmpDsc = codeGen->regSet.tmpFindNum(varNum);
6413                 vt              = tmpDsc->tdTempType();
6414             }
6415             if (vt == TYP_REF || vt == TYP_BYREF)
6416                 emitGCvarDeadUpd(adr + ofs, dst);
6417         }
6418     }
6419
6420 #ifdef DEBUG
6421     /* Make sure we set the instruction descriptor size correctly */
6422
6423     size_t expected = emitSizeOfInsDsc(id);
6424     assert(sz == expected);
6425
6426     if (emitComp->opts.disAsm || emitComp->opts.dspEmit || emitComp->verbose)
6427     {
6428         emitDispIns(id, false, dspOffs, true, emitCurCodeOffs(odst), *dp, (dst - *dp), ig);
6429     }
6430
6431     if (emitComp->compDebugBreak)
6432     {
6433         // set JitEmitPrintRefRegs=1 will print out emitThisGCrefRegs and emitThisByrefRegs
6434         // at the beginning of this method.
6435         if (JitConfig.JitEmitPrintRefRegs() != 0)
6436         {
6437             printf("Before emitOutputInstr for id->idDebugOnlyInfo()->idNum=0x%02x\n", id->idDebugOnlyInfo()->idNum);
6438             printf("  emitThisGCrefRegs(0x%p)=", dspPtr(&emitThisGCrefRegs));
6439             printRegMaskInt(emitThisGCrefRegs);
6440             emitDispRegSet(emitThisGCrefRegs);
6441             printf("\n");
6442             printf("  emitThisByrefRegs(0x%p)=", dspPtr(&emitThisByrefRegs));
6443             printRegMaskInt(emitThisByrefRegs);
6444             emitDispRegSet(emitThisByrefRegs);
6445             printf("\n");
6446         }
6447
6448         // For example, set JitBreakEmitOutputInstr=a6 will break when this method is called for
6449         // emitting instruction a6, (i.e. IN00a6 in jitdump).
6450         if ((unsigned)JitConfig.JitBreakEmitOutputInstr() == id->idDebugOnlyInfo()->idNum)
6451         {
6452             assert(!"JitBreakEmitOutputInstr reached");
6453         }
6454     }
6455 #endif
6456
6457     /* All instructions are expected to generate code */
6458
6459     assert(*dp != dst);
6460
6461     *dp = dst;
6462
6463     return sz;
6464 }
6465
6466 /*****************************************************************************/
6467 /*****************************************************************************/
6468
6469 #ifdef DEBUG
6470
6471 static bool insAlwaysSetFlags(instruction ins)
6472 {
6473     bool result = false;
6474     switch (ins)
6475     {
6476         case INS_cmp:
6477         case INS_cmn:
6478         case INS_teq:
6479         case INS_tst:
6480             result = true;
6481             break;
6482
6483         default:
6484             break;
6485     }
6486     return result;
6487 }
6488
6489 /*****************************************************************************
6490  *
6491  *  Display the instruction name, optionally the instruction
6492  *   can add the "s" suffix if it must set the flags.
6493  */
6494 void emitter::emitDispInst(instruction ins, insFlags flags)
6495 {
6496     const char* insstr = codeGen->genInsName(ins);
6497     int         len    = strlen(insstr);
6498
6499     /* Display the instruction name */
6500
6501     printf("%s", insstr);
6502     if (insSetsFlags(flags) && !insAlwaysSetFlags(ins))
6503     {
6504         printf("s");
6505         len++;
6506     }
6507
6508     //
6509     // Add at least one space after the instruction name
6510     // and add spaces until we have reach the normal size of 8
6511     do
6512     {
6513         printf(" ");
6514         len++;
6515     } while (len < 8);
6516 }
6517
6518 #define STRICT_ARM_ASM 0
6519
6520 /*****************************************************************************
6521  *
6522  *  Display an immediate value
6523  */
6524 void emitter::emitDispImm(int imm, bool addComma, bool alwaysHex /* =false */)
6525 {
6526     if (!alwaysHex && (imm > -1000) && (imm < 1000))
6527         printf("%d", imm);
6528     else if ((imm > 0) ||
6529              (imm == -imm) || // -0x80000000 == 0x80000000. So we don't want to add an extra "-" at the beginning.
6530              (emitComp->opts.disDiffable && (imm == 0xD1FFAB1E))) // Don't display this as negative
6531         printf("0x%02x", imm);
6532     else // val <= -1000
6533         printf("-0x%02x", -imm);
6534
6535     if (addComma)
6536         printf(", ");
6537 }
6538
6539 /*****************************************************************************
6540  *
6541  *  Display a relocatable immediate value
6542  */
6543 void emitter::emitDispReloc(BYTE* addr)
6544 {
6545     printf("0x%p", dspPtr(addr));
6546 }
6547
6548 /*****************************************************************************
6549  *
6550  *  Display an arm condition for the IT instructions
6551  */
6552 void emitter::emitDispCond(int cond)
6553 {
6554     const static char* armCond[16] = {"eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc",
6555                                       "hi", "ls", "ge", "lt", "gt", "le", "AL", "NV"}; // The last two are invalid
6556     assert(0 <= cond && (unsigned)cond < ArrLen(armCond));
6557     printf(armCond[cond]);
6558 }
6559
6560 /*****************************************************************************
6561  *
6562  *  Display a register range in a range format
6563  */
6564 void emitter::emitDispRegRange(regNumber reg, int len, emitAttr attr)
6565 {
6566     printf("{");
6567     emitDispReg(reg, attr, false);
6568     if (len > 1)
6569     {
6570         printf("-");
6571         emitDispReg((regNumber)(reg + len - 1), attr, false);
6572     }
6573     printf("}");
6574 }
6575
6576 /*****************************************************************************
6577  *
6578  *  Display an register mask in a list format
6579  */
6580 void emitter::emitDispRegmask(int imm, bool encodedPC_LR)
6581 {
6582     bool printedOne = false;
6583     bool hasPC;
6584     bool hasLR;
6585
6586     if (encodedPC_LR)
6587     {
6588         hasPC = (imm & 2) != 0;
6589         hasLR = (imm & 1) != 0;
6590         imm >>= 2;
6591     }
6592     else
6593     {
6594         hasPC = (imm & RBM_PC) != 0;
6595         hasLR = (imm & RBM_LR) != 0;
6596         imm &= ~(RBM_PC | RBM_LR);
6597     }
6598
6599     regNumber reg = REG_R0;
6600     unsigned  bit = 1;
6601
6602     printf("{");
6603     while (imm != 0)
6604     {
6605         if (bit & imm)
6606         {
6607             if (printedOne)
6608                 printf(",");
6609             printf("%s", emitRegName(reg));
6610             printedOne = true;
6611             imm -= bit;
6612         }
6613
6614         reg = regNumber(reg + 1);
6615         bit <<= 1;
6616     }
6617
6618     if (hasLR)
6619     {
6620         if (printedOne)
6621             printf(",");
6622         printf("%s", emitRegName(REG_LR));
6623         printedOne = true;
6624     }
6625
6626     if (hasPC)
6627     {
6628         if (printedOne)
6629             printf(",");
6630         printf("%s", emitRegName(REG_PC));
6631         printedOne = true;
6632     }
6633     printf("}");
6634 }
6635
6636 /*****************************************************************************
6637  *
6638  *  Returns the encoding for the Shift Type bits to be used in a Thumb-2 encoding
6639  */
6640
6641 void emitter::emitDispShiftOpts(insOpts opt)
6642 {
6643     if (opt == INS_OPTS_LSL)
6644         printf(" LSL ");
6645     else if (opt == INS_OPTS_LSR)
6646         printf(" LSR ");
6647     else if (opt == INS_OPTS_ASR)
6648         printf(" ASR ");
6649     else if (opt == INS_OPTS_ROR)
6650         printf(" ROR ");
6651     else if (opt == INS_OPTS_RRX)
6652         printf(" RRX ");
6653 }
6654
6655 /*****************************************************************************
6656  *
6657  *  Display a register
6658  */
6659 void emitter::emitDispReg(regNumber reg, emitAttr attr, bool addComma)
6660 {
6661     if (isFloatReg(reg))
6662     {
6663         const char* size = attr == EA_8BYTE ? "d" : "s";
6664         printf("%s%s", size, emitFloatRegName(reg, attr) + 1);
6665     }
6666     else
6667     {
6668         printf("%s", emitRegName(reg, attr));
6669     }
6670
6671     if (addComma)
6672         printf(", ");
6673 }
6674
6675 /*****************************************************************************
6676  *
6677  *  Display an addressing operand [reg]
6678  */
6679 void emitter::emitDispAddrR(regNumber reg, emitAttr attr)
6680 {
6681     printf("[");
6682     emitDispReg(reg, attr, false);
6683     printf("]");
6684     emitDispGC(attr);
6685 }
6686
6687 /*****************************************************************************
6688  *
6689  *  Display an addressing operand [reg + imm]
6690  */
6691 void emitter::emitDispAddrRI(regNumber reg, int imm, emitAttr attr)
6692 {
6693     bool regIsSPorFP = (reg == REG_SP) || (reg == REG_FP);
6694
6695     printf("[");
6696     emitDispReg(reg, attr, false);
6697     if (imm != 0)
6698     {
6699         if (imm >= 0)
6700         {
6701 #if STRICT_ARM_ASM
6702             printf(", ");
6703 #else
6704             printf("+");
6705 #endif
6706         }
6707         emitDispImm(imm, false, regIsSPorFP);
6708     }
6709     printf("]");
6710     emitDispGC(attr);
6711 }
6712
6713 /*****************************************************************************
6714  *
6715  *  Display an addressing operand [reg + reg]
6716  */
6717 void emitter::emitDispAddrRR(regNumber reg1, regNumber reg2, emitAttr attr)
6718 {
6719     printf("[");
6720     emitDispReg(reg1, attr, false);
6721 #if STRICT_ARM_ASM
6722     printf(", ");
6723 #else
6724     printf("+");
6725 #endif
6726     emitDispReg(reg2, attr, false);
6727     printf("]");
6728     emitDispGC(attr);
6729 }
6730
6731 /*****************************************************************************
6732  *
6733  *  Display an addressing operand [reg + reg * imm]
6734  */
6735 void emitter::emitDispAddrRRI(regNumber reg1, regNumber reg2, int imm, emitAttr attr)
6736 {
6737     printf("[");
6738     emitDispReg(reg1, attr, false);
6739 #if STRICT_ARM_ASM
6740     printf(", ");
6741     emitDispReg(reg2, attr, false);
6742     if (imm > 0)
6743     {
6744         printf(" LSL ");
6745         emitDispImm(1 << imm, false);
6746     }
6747 #else
6748     printf("+");
6749     if (imm > 0)
6750     {
6751         emitDispImm(1 << imm, false);
6752         printf("*");
6753     }
6754     emitDispReg(reg2, attr, false);
6755 #endif
6756     printf("]");
6757     emitDispGC(attr);
6758 }
6759
6760 /*****************************************************************************
6761  *
6762  *  Display an addressing operand [reg + imm]
6763  */
6764 void emitter::emitDispAddrPUW(regNumber reg, int imm, insOpts opt, emitAttr attr)
6765 {
6766     bool regIsSPorFP = (reg == REG_SP) || (reg == REG_FP);
6767
6768     printf("[");
6769     emitDispReg(reg, attr, false);
6770     if (insOptAnyInc(opt))
6771         printf("!");
6772
6773     if (imm != 0)
6774     {
6775         if (imm >= 0)
6776         {
6777 #if STRICT_ARM_ASM
6778             printf(", ");
6779 #else
6780             printf("+");
6781 #endif
6782         }
6783         emitDispImm(imm, false, regIsSPorFP);
6784     }
6785     printf("]");
6786
6787     emitDispGC(attr);
6788 }
6789
6790 /*****************************************************************************
6791  *
6792  *  Display the gc-ness of the operand
6793  */
6794 void emitter::emitDispGC(emitAttr attr)
6795 {
6796 #if 0
6797     // TODO-ARM-Cleanup: Fix or delete.
6798     if (attr == EA_GCREF)
6799         printf(" @gc");
6800     else if (attr == EA_BYREF)
6801         printf(" @byref");
6802 #endif
6803 }
6804
6805 /*****************************************************************************
6806  *
6807  *  Display (optionally) the instruction encoding in hex
6808  */
6809
6810 void emitter::emitDispInsHex(BYTE* code, size_t sz)
6811 {
6812     // We do not display the instruction hex if we want diff-able disassembly
6813     if (!emitComp->opts.disDiffable)
6814     {
6815         if (sz == 2)
6816         {
6817             printf("  %04X     ", (*((unsigned short*)code)));
6818         }
6819         else if (sz == 4)
6820         {
6821             printf("  %04X %04X", (*((unsigned short*)(code + 0))), (*((unsigned short*)(code + 2))));
6822         }
6823     }
6824 }
6825
6826 /****************************************************************************
6827  *
6828  *  Display the given instruction.
6829  */
6830
6831 void emitter::emitDispInsHelp(
6832     instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* code, size_t sz, insGroup* ig)
6833 {
6834     if (EMITVERBOSE)
6835     {
6836         unsigned idNum = id->idDebugOnlyInfo()->idNum; // Do not remove this!  It is needed for VisualStudio
6837                                                        // conditional breakpoints
6838
6839         printf("IN%04x: ", idNum);
6840     }
6841
6842     if (code == NULL)
6843         sz = 0;
6844
6845     if (!emitComp->opts.dspEmit && !isNew && !asmfm && sz)
6846         doffs = true;
6847
6848     /* Display the instruction offset */
6849
6850     emitDispInsOffs(offset, doffs);
6851
6852     /* Display the instruction hex code */
6853
6854     emitDispInsHex(code, sz);
6855
6856     printf("      ");
6857
6858     /* Get the instruction and format */
6859
6860     instruction ins = id->idIns();
6861     insFormat   fmt = id->idInsFmt();
6862
6863     emitDispInst(ins, id->idInsFlags());
6864
6865     /* If this instruction has just been added, check its size */
6866
6867     assert(isNew == false || (int)emitSizeOfInsDsc(id) == emitCurIGfreeNext - (BYTE*)id);
6868
6869     /* Figure out the operand size */
6870     emitAttr attr;
6871     if (id->idGCref() == GCT_GCREF)
6872         attr = EA_GCREF;
6873     else if (id->idGCref() == GCT_BYREF)
6874         attr = EA_BYREF;
6875     else
6876         attr = id->idOpSize();
6877
6878     switch (fmt)
6879     {
6880         int         imm;
6881         int         offs;
6882         const char* methodName;
6883
6884         case IF_T1_A: // None
6885         case IF_T2_A:
6886             break;
6887
6888         case IF_T1_L0: // Imm
6889         case IF_T2_B:
6890             emitDispImm(emitGetInsSC(id), false);
6891             break;
6892
6893         case IF_T1_B: // <cond>
6894             emitDispCond(emitGetInsSC(id));
6895             break;
6896
6897         case IF_T1_L1: // <regmask8>
6898         case IF_T2_I1: // <regmask16>
6899             emitDispRegmask(emitGetInsSC(id), true);
6900             break;
6901
6902         case IF_T2_E2: // Reg
6903             if (id->idIns() == INS_vmrs)
6904             {
6905                 if (id->idReg1() != REG_R15)
6906                 {
6907                     emitDispReg(id->idReg1(), attr, true);
6908                     printf("FPSCR");
6909                 }
6910                 else
6911                 {
6912                     printf("APSR, FPSCR");
6913                 }
6914             }
6915             else
6916             {
6917                 emitDispReg(id->idReg1(), attr, false);
6918             }
6919             break;
6920
6921         case IF_T1_D1:
6922             emitDispReg(id->idReg1(), attr, false);
6923             break;
6924
6925         case IF_T1_D2:
6926             emitDispReg(id->idReg3(), attr, false);
6927             {
6928                 CORINFO_METHOD_HANDLE handle = (CORINFO_METHOD_HANDLE)id->idDebugOnlyInfo()->idMemCookie;
6929                 if (handle != 0)
6930                 {
6931                     methodName = emitComp->eeGetMethodFullName(handle);
6932                     printf("\t\t// %s", methodName);
6933                 }
6934             }
6935             break;
6936
6937         case IF_T1_F: // SP, Imm
6938             emitDispReg(REG_SP, attr, true);
6939             emitDispImm(emitGetInsSC(id), false);
6940             break;
6941
6942         case IF_T1_J0: // Reg, Imm
6943         case IF_T2_L1:
6944         case IF_T2_L2:
6945             emitDispReg(id->idReg1(), attr, true);
6946             imm = emitGetInsSC(id);
6947             emitDispImm(imm, false, false);
6948             break;
6949
6950         case IF_T2_N:
6951             emitDispReg(id->idReg1(), attr, true);
6952             imm = emitGetInsSC(id);
6953             if (emitComp->opts.disDiffable)
6954                 imm = 0xD1FF;
6955             emitDispImm(imm, false, true);
6956             break;
6957
6958         case IF_T2_N3:
6959             emitDispReg(id->idReg1(), attr, true);
6960             printf("%s RELOC ", (id->idIns() == INS_movw) ? "LOW" : "HIGH");
6961             emitDispReloc(emitGetInsRelocValue(id));
6962             break;
6963
6964         case IF_T2_N2:
6965             emitDispReg(id->idReg1(), attr, true);
6966             imm = emitGetInsSC(id);
6967             {
6968                 dataSection*  jdsc = 0;
6969                 NATIVE_OFFSET offs = 0;
6970
6971                 /* Find the appropriate entry in the data section list */
6972
6973                 for (jdsc = emitConsDsc.dsdList; jdsc; jdsc = jdsc->dsNext)
6974                 {
6975                     UNATIVE_OFFSET size = jdsc->dsSize;
6976
6977                     /* Is this a label table? */
6978
6979                     if (jdsc->dsType == dataSection::blockAbsoluteAddr)
6980                     {
6981                         if (offs == imm)
6982                             break;
6983                     }
6984
6985                     offs += size;
6986                 }
6987
6988                 assert(jdsc != NULL);
6989
6990                 if (id->idIsDspReloc())
6991                 {
6992                     printf("reloc ");
6993                 }
6994                 printf("%s ADDRESS J_M%03u_DS%02u", (id->idIns() == INS_movw) ? "LOW" : "HIGH",
6995                        Compiler::s_compMethodsCount, imm);
6996
6997                 // After the MOVT, dump the table
6998                 if (id->idIns() == INS_movt)
6999                 {
7000                     unsigned     cnt = jdsc->dsSize / TARGET_POINTER_SIZE;
7001                     BasicBlock** bbp = (BasicBlock**)jdsc->dsCont;
7002
7003                     bool isBound = (emitCodeGetCookie(*bbp) != NULL);
7004
7005                     if (isBound)
7006                     {
7007                         printf("\n\n    J_M%03u_DS%02u LABEL   DWORD", Compiler::s_compMethodsCount, imm);
7008
7009                         /* Display the label table (it's stored as "BasicBlock*" values) */
7010
7011                         do
7012                         {
7013                             insGroup* lab;
7014
7015                             /* Convert the BasicBlock* value to an IG address */
7016
7017                             lab = (insGroup*)emitCodeGetCookie(*bbp++);
7018                             assert(lab);
7019
7020                             printf("\n            DD      G_M%03u_IG%02u", Compiler::s_compMethodsCount, lab->igNum);
7021                         } while (--cnt);
7022                     }
7023                 }
7024             }
7025             break;
7026
7027         case IF_T2_H2: // [Reg+imm]
7028         case IF_T2_K2:
7029             emitDispAddrRI(id->idReg1(), emitGetInsSC(id), attr);
7030             break;
7031
7032         case IF_T2_K3: // [PC+imm]
7033             emitDispAddrRI(REG_PC, emitGetInsSC(id), attr);
7034             break;
7035
7036         case IF_T1_J1: // reg, <regmask8>
7037         case IF_T2_I0: // reg, <regmask16>
7038             emitDispReg(id->idReg1(), attr, false);
7039             printf("!, ");
7040             emitDispRegmask(emitGetInsSC(id), false);
7041             break;
7042
7043         case IF_T1_D0: // Reg, Reg
7044         case IF_T1_E:
7045         case IF_T2_C3:
7046         case IF_T2_C9:
7047         case IF_T2_C10:
7048             emitDispReg(id->idReg1(), attr, true);
7049             emitDispReg(id->idReg2(), attr, false);
7050             if (fmt == IF_T1_E && id->idIns() == INS_rsb)
7051             {
7052                 printf(", 0");
7053             }
7054             break;
7055
7056         case IF_T2_E1: // Reg, [Reg]
7057             emitDispReg(id->idReg1(), attr, true);
7058             emitDispAddrR(id->idReg2(), attr);
7059             break;
7060
7061         case IF_T2_D1: // Reg, Imm, Imm
7062             emitDispReg(id->idReg1(), attr, true);
7063             imm = emitGetInsSC(id);
7064             {
7065                 int lsb  = (imm >> 5) & 0x1f;
7066                 int msb  = imm & 0x1f;
7067                 int imm1 = lsb;
7068                 int imm2 = msb + 1 - lsb;
7069                 emitDispImm(imm1, true);
7070                 emitDispImm(imm2, false);
7071             }
7072             break;
7073
7074         case IF_T1_C: // Reg, Reg, Imm
7075         case IF_T1_G:
7076         case IF_T2_C2:
7077         case IF_T2_H1:
7078         case IF_T2_K1:
7079         case IF_T2_L0:
7080         case IF_T2_M0:
7081             emitDispReg(id->idReg1(), attr, true);
7082             imm = emitGetInsSC(id);
7083             if (emitInsIsLoadOrStore(ins))
7084             {
7085                 emitDispAddrRI(id->idReg2(), imm, attr);
7086             }
7087             else
7088             {
7089                 emitDispReg(id->idReg2(), attr, true);
7090                 emitDispImm(imm, false);
7091             }
7092             break;
7093
7094         case IF_T1_J2:
7095             emitDispReg(id->idReg1(), attr, true);
7096             imm = emitGetInsSC(id);
7097             if (emitInsIsLoadOrStore(ins))
7098             {
7099                 emitDispAddrRI(REG_SP, imm, attr);
7100             }
7101             else
7102             {
7103                 emitDispReg(REG_SP, attr, true);
7104                 emitDispImm(imm, false);
7105             }
7106             break;
7107
7108         case IF_T2_K4:
7109             emitDispReg(id->idReg1(), attr, true);
7110             emitDispAddrRI(REG_PC, emitGetInsSC(id), attr);
7111             break;
7112
7113         case IF_T2_C1:
7114         case IF_T2_C8:
7115             emitDispReg(id->idReg1(), attr, true);
7116             emitDispReg(id->idReg2(), attr, false);
7117             imm = emitGetInsSC(id);
7118             if (id->idInsOpt() == INS_OPTS_RRX)
7119             {
7120                 emitDispShiftOpts(id->idInsOpt());
7121                 assert(imm == 1);
7122             }
7123             else if (imm > 0)
7124             {
7125                 emitDispShiftOpts(id->idInsOpt());
7126                 emitDispImm(imm, false);
7127             }
7128             break;
7129
7130         case IF_T2_C6:
7131             imm = emitGetInsSC(id);
7132             emitDispReg(id->idReg1(), attr, true);
7133             emitDispReg(id->idReg2(), attr, (imm != 0));
7134             if (imm != 0)
7135             {
7136                 emitDispImm(imm, false);
7137             }
7138             break;
7139
7140         case IF_T2_C7:
7141             emitDispAddrRRI(id->idReg1(), id->idReg2(), emitGetInsSC(id), attr);
7142             break;
7143
7144         case IF_T2_H0:
7145             emitDispReg(id->idReg1(), attr, true);
7146             emitDispAddrPUW(id->idReg2(), emitGetInsSC(id), id->idInsOpt(), attr);
7147             break;
7148
7149         case IF_T1_H: // Reg, Reg, Reg
7150             emitDispReg(id->idReg1(), attr, true);
7151             if (emitInsIsLoadOrStore(ins))
7152             {
7153                 emitDispAddrRR(id->idReg2(), id->idReg3(), attr);
7154             }
7155             else
7156             {
7157                 emitDispReg(id->idReg2(), attr, true);
7158                 emitDispReg(id->idReg3(), attr, false);
7159             }
7160             break;
7161
7162         case IF_T2_C4:
7163         case IF_T2_C5:
7164             emitDispReg(id->idReg1(), attr, true);
7165             emitDispReg(id->idReg2(), attr, true);
7166             emitDispReg(id->idReg3(), attr, false);
7167             break;
7168
7169         case IF_T2_VFP3:
7170             emitDispReg(id->idReg1(), attr, true);
7171             emitDispReg(id->idReg2(), attr, true);
7172             emitDispReg(id->idReg3(), attr, false);
7173             break;
7174
7175         case IF_T2_VFP2:
7176             switch (id->idIns())
7177             {
7178                 case INS_vcvt_d2i:
7179                 case INS_vcvt_d2u:
7180                 case INS_vcvt_d2f:
7181                     emitDispReg(id->idReg1(), EA_4BYTE, true);
7182                     emitDispReg(id->idReg2(), EA_8BYTE, false);
7183                     break;
7184
7185                 case INS_vcvt_i2d:
7186                 case INS_vcvt_u2d:
7187                 case INS_vcvt_f2d:
7188                     emitDispReg(id->idReg1(), EA_8BYTE, true);
7189                     emitDispReg(id->idReg2(), EA_4BYTE, false);
7190                     break;
7191
7192                 // we just use the type on the instruction
7193                 // unless it is an asymmetrical one like the converts
7194                 default:
7195                     emitDispReg(id->idReg1(), attr, true);
7196                     emitDispReg(id->idReg2(), attr, false);
7197                     break;
7198             }
7199             break;
7200
7201         case IF_T2_VLDST:
7202             imm = emitGetInsSC(id);
7203             switch (id->idIns())
7204             {
7205                 case INS_vldr:
7206                 case INS_vstr:
7207                     emitDispReg(id->idReg1(), attr, true);
7208                     emitDispAddrPUW(id->idReg2(), imm, id->idInsOpt(), attr);
7209                     break;
7210
7211                 case INS_vldm:
7212                 case INS_vstm:
7213                     emitDispReg(id->idReg2(), attr, false);
7214                     if (insOptAnyInc(id->idInsOpt()))
7215                         printf("!");
7216                     printf(", ");
7217                     emitDispRegRange(id->idReg1(), abs(imm) >> 2, attr);
7218                     break;
7219
7220                 case INS_vpush:
7221                 case INS_vpop:
7222                     emitDispRegRange(id->idReg1(), abs(imm) >> 2, attr);
7223                     break;
7224
7225                 default:
7226                     unreached();
7227             }
7228             break;
7229
7230         case IF_T2_VMOVD:
7231             switch (id->idIns())
7232             {
7233                 case INS_vmov_i2d:
7234                     emitDispReg(id->idReg1(), attr, true); // EA_8BYTE
7235                     emitDispReg(id->idReg2(), EA_4BYTE, true);
7236                     emitDispReg(id->idReg3(), EA_4BYTE, false);
7237                     break;
7238                 case INS_vmov_d2i:
7239                     emitDispReg(id->idReg1(), EA_4BYTE, true);
7240                     emitDispReg(id->idReg2(), EA_4BYTE, true);
7241                     emitDispReg(id->idReg3(), attr, false); // EA_8BYTE
7242                     break;
7243                 default:
7244                     unreached();
7245             }
7246             break;
7247
7248         case IF_T2_VMOVS:
7249             emitDispReg(id->idReg1(), attr, true);
7250             emitDispReg(id->idReg2(), attr, false);
7251             break;
7252
7253         case IF_T2_G1:
7254             emitDispReg(id->idReg1(), attr, true);
7255             emitDispAddrRR(id->idReg2(), id->idReg3(), attr);
7256             break;
7257
7258         case IF_T2_D0: // Reg, Reg, Imm, Imm
7259             emitDispReg(id->idReg1(), attr, true);
7260             emitDispReg(id->idReg2(), attr, true);
7261             imm = emitGetInsSC(id);
7262             if (ins == INS_bfi)
7263             {
7264                 int lsb  = (imm >> 5) & 0x1f;
7265                 int msb  = imm & 0x1f;
7266                 int imm1 = lsb;
7267                 int imm2 = msb + 1 - lsb;
7268                 emitDispImm(imm1, true);
7269                 emitDispImm(imm2, false);
7270             }
7271             else
7272             {
7273                 int lsb     = (imm >> 5) & 0x1f;
7274                 int widthm1 = imm & 0x1f;
7275                 int imm1    = lsb;
7276                 int imm2    = widthm1 + 1;
7277                 emitDispImm(imm1, true);
7278                 emitDispImm(imm2, false);
7279             }
7280             break;
7281
7282         case IF_T2_C0: // Reg, Reg, Reg, Imm
7283             emitDispReg(id->idReg1(), attr, true);
7284             emitDispReg(id->idReg2(), attr, true);
7285             emitDispReg(id->idReg3(), attr, false);
7286             imm = emitGetInsSC(id);
7287             if (id->idInsOpt() == INS_OPTS_RRX)
7288             {
7289                 emitDispShiftOpts(id->idInsOpt());
7290                 assert(imm == 1);
7291             }
7292             else if (imm > 0)
7293             {
7294                 emitDispShiftOpts(id->idInsOpt());
7295                 emitDispImm(imm, false);
7296             }
7297             break;
7298
7299         case IF_T2_E0:
7300             emitDispReg(id->idReg1(), attr, true);
7301             if (id->idIsLclVar())
7302             {
7303                 emitDispAddrRRI(id->idReg2(), codeGen->rsGetRsvdReg(), 0, attr);
7304             }
7305             else
7306             {
7307                 emitDispAddrRRI(id->idReg2(), id->idReg3(), emitGetInsSC(id), attr);
7308             }
7309             break;
7310
7311         case IF_T2_G0:
7312             emitDispReg(id->idReg1(), attr, true);
7313             emitDispReg(id->idReg2(), attr, true);
7314             emitDispAddrPUW(id->idReg3(), emitGetInsSC(id), id->idInsOpt(), attr);
7315             break;
7316
7317         case IF_T2_F1: // Reg, Reg, Reg, Reg
7318         case IF_T2_F2:
7319             emitDispReg(id->idReg1(), attr, true);
7320             emitDispReg(id->idReg2(), attr, true);
7321             emitDispReg(id->idReg3(), attr, true);
7322             emitDispReg(id->idReg4(), attr, false);
7323             break;
7324
7325         case IF_T1_J3:
7326         case IF_T2_M1: // Load Label
7327             emitDispReg(id->idReg1(), attr, true);
7328             if (id->idIsBound())
7329                 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
7330             else
7331                 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
7332             break;
7333
7334         case IF_T1_I: // Special Compare-and-branch
7335             emitDispReg(id->idReg1(), attr, true);
7336             __fallthrough;
7337
7338         case IF_T1_K: // Special Branch, conditional
7339         case IF_T1_M:
7340             assert(((instrDescJmp*)id)->idjShort);
7341             printf("SHORT ");
7342             __fallthrough;
7343
7344         case IF_T2_N1:
7345             if (fmt == IF_T2_N1)
7346             {
7347                 emitDispReg(id->idReg1(), attr, true);
7348                 printf("%s ADDRESS ", (id->idIns() == INS_movw) ? "LOW" : "HIGH");
7349             }
7350             __fallthrough;
7351
7352         case IF_T2_J1:
7353         case IF_T2_J2:
7354         case IF_LARGEJMP:
7355         {
7356             if (id->idAddr()->iiaHasInstrCount())
7357             {
7358                 int instrCount = id->idAddr()->iiaGetInstrCount();
7359
7360                 if (ig == NULL)
7361                 {
7362                     printf("pc%s%d instructions", (instrCount >= 0) ? "+" : "", instrCount);
7363                 }
7364                 else
7365                 {
7366                     unsigned       insNum  = emitFindInsNum(ig, id);
7367                     UNATIVE_OFFSET srcOffs = ig->igOffs + emitFindOffset(ig, insNum + 1);
7368                     UNATIVE_OFFSET dstOffs = ig->igOffs + emitFindOffset(ig, insNum + 1 + instrCount);
7369                     ssize_t        relOffs = (ssize_t)(emitOffsetToPtr(dstOffs) - emitOffsetToPtr(srcOffs));
7370                     printf("pc%s%d (%d instructions)", (relOffs >= 0) ? "+" : "", relOffs, instrCount);
7371                 }
7372             }
7373             else if (id->idIsBound())
7374                 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
7375             else
7376                 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
7377         }
7378         break;
7379
7380         case IF_T2_J3:
7381             if (id->idIsCallAddr())
7382             {
7383                 offs       = (ssize_t)id->idAddr()->iiaAddr;
7384                 methodName = "";
7385             }
7386             else
7387             {
7388                 offs       = 0;
7389                 methodName = emitComp->eeGetMethodFullName((CORINFO_METHOD_HANDLE)id->idDebugOnlyInfo()->idMemCookie);
7390             }
7391
7392             if (offs)
7393             {
7394                 if (id->idIsDspReloc())
7395                     printf("reloc ");
7396                 printf("%08X", offs);
7397             }
7398             else
7399             {
7400                 printf("%s", methodName);
7401             }
7402
7403             break;
7404
7405         default:
7406             printf("unexpected format %s", emitIfName(id->idInsFmt()));
7407             assert(!"unexpectedFormat");
7408             break;
7409     }
7410
7411     if (id->idDebugOnlyInfo()->idVarRefOffs)
7412     {
7413         printf("\t// ");
7414         emitDispFrameRef(id->idAddr()->iiaLclVar.lvaVarNum(), id->idAddr()->iiaLclVar.lvaOffset(),
7415                          id->idDebugOnlyInfo()->idVarRefOffs, asmfm);
7416     }
7417
7418     printf("\n");
7419 }
7420
7421 void emitter::emitDispIns(
7422     instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* code, size_t sz, insGroup* ig)
7423 {
7424     insFormat fmt = id->idInsFmt();
7425
7426     /* Special-case IF_LARGEJMP */
7427
7428     if ((fmt == IF_LARGEJMP) && id->idIsBound())
7429     {
7430         // This is a pseudo-instruction format representing a large conditional branch. See the comment
7431         // in emitter::emitOutputLJ() for the full description.
7432         //
7433         // For this pseudo-instruction, we will actually generate:
7434         //
7435         //      b<!cond> L_not  // 2 bytes. Note that we reverse the condition.
7436         //      b L_target      // 4 bytes
7437         //   L_not:
7438         //
7439         // These instructions don't exist in the actual instruction stream, so we need to fake them
7440         // up to display them.
7441         //
7442         // Note: don't touch the actual instrDesc. If we accidentally messed it up, it would create a very
7443         // difficult to find bug.
7444
7445         instrDescJmp  idJmp;
7446         instrDescJmp* pidJmp = &idJmp;
7447
7448         memset(&idJmp, 0, sizeof(idJmp));
7449
7450         pidJmp->idIns(emitJumpKindToIns(emitReverseJumpKind(emitInsToJumpKind(id->idIns())))); // reverse the
7451                                                                                                // conditional
7452                                                                                                // instruction
7453         pidJmp->idInsFmt(IF_T1_K);
7454         pidJmp->idInsSize(emitInsSize(IF_T1_K));
7455         pidJmp->idjShort = 1;
7456         pidJmp->idAddr()->iiaSetInstrCount(1);
7457         pidJmp->idDebugOnlyInfo(id->idDebugOnlyInfo()); // share the idDebugOnlyInfo() field
7458
7459         size_t bcondSizeOrZero = (code == NULL) ? 0 : 2; // branch is 2 bytes
7460         emitDispInsHelp(pidJmp, false, doffs, asmfm, offset, code, bcondSizeOrZero,
7461                         NULL /* force display of pc-relative branch */);
7462
7463         code += bcondSizeOrZero;
7464         offset += 2;
7465
7466         // Next, display the unconditional branch
7467
7468         // Reset the local instrDesc
7469         memset(&idJmp, 0, sizeof(idJmp));
7470
7471         pidJmp->idIns(INS_b);
7472         pidJmp->idInsFmt(IF_T2_J2);
7473         pidJmp->idInsSize(emitInsSize(IF_T2_J2));
7474         pidJmp->idjShort = 0;
7475         if (id->idIsBound())
7476         {
7477             pidJmp->idSetIsBound();
7478             pidJmp->idAddr()->iiaIGlabel = id->idAddr()->iiaIGlabel;
7479         }
7480         else
7481         {
7482             pidJmp->idAddr()->iiaBBlabel = id->idAddr()->iiaBBlabel;
7483         }
7484         pidJmp->idDebugOnlyInfo(id->idDebugOnlyInfo()); // share the idDebugOnlyInfo() field
7485
7486         size_t brSizeOrZero = (code == NULL) ? 0 : 4; // unconditional branch is 4 bytes
7487         emitDispInsHelp(pidJmp, isNew, doffs, asmfm, offset, code, brSizeOrZero, ig);
7488     }
7489     else
7490     {
7491         emitDispInsHelp(id, isNew, doffs, asmfm, offset, code, sz, ig);
7492     }
7493 }
7494
7495 /*****************************************************************************
7496  *
7497  *  Display a stack frame reference.
7498  */
7499
7500 void emitter::emitDispFrameRef(int varx, int disp, int offs, bool asmfm)
7501 {
7502     printf("[");
7503
7504     if (varx < 0)
7505         printf("TEMP_%02u", -varx);
7506     else
7507         emitComp->gtDispLclVar(+varx, false);
7508
7509     if (disp < 0)
7510         printf("-0x%02x", -disp);
7511     else if (disp > 0)
7512         printf("+0x%02x", +disp);
7513
7514     printf("]");
7515
7516     if (varx >= 0 && emitComp->opts.varNames)
7517     {
7518         LclVarDsc*  varDsc;
7519         const char* varName;
7520
7521         assert((unsigned)varx < emitComp->lvaCount);
7522         varDsc  = emitComp->lvaTable + varx;
7523         varName = emitComp->compLocalVarName(varx, offs);
7524
7525         if (varName)
7526         {
7527             printf("'%s", varName);
7528
7529             if (disp < 0)
7530                 printf("-%d", -disp);
7531             else if (disp > 0)
7532                 printf("+%d", +disp);
7533
7534             printf("'");
7535         }
7536     }
7537 }
7538
7539 #endif // DEBUG
7540
7541 void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataReg, GenTreeIndir* indir)
7542 {
7543     // Handle unaligned floating point loads/stores
7544     if ((indir->gtFlags & GTF_IND_UNALIGNED))
7545     {
7546         if (indir->OperGet() == GT_STOREIND)
7547         {
7548             var_types type = indir->AsStoreInd()->Data()->TypeGet();
7549             if (type == TYP_FLOAT)
7550             {
7551                 regNumber tmpReg = indir->GetSingleTempReg();
7552                 emitIns_R_R(INS_vmov_f2i, EA_4BYTE, tmpReg, dataReg);
7553                 emitInsLoadStoreOp(INS_str, EA_4BYTE, tmpReg, indir, 0);
7554                 return;
7555             }
7556             else if (type == TYP_DOUBLE)
7557             {
7558                 regNumber tmpReg1 = indir->ExtractTempReg();
7559                 regNumber tmpReg2 = indir->GetSingleTempReg();
7560                 emitIns_R_R_R(INS_vmov_d2i, EA_8BYTE, tmpReg1, tmpReg2, dataReg);
7561                 emitInsLoadStoreOp(INS_str, EA_4BYTE, tmpReg1, indir, 0);
7562                 emitInsLoadStoreOp(INS_str, EA_4BYTE, tmpReg2, indir, 4);
7563                 return;
7564             }
7565         }
7566         else if (indir->OperGet() == GT_IND)
7567         {
7568             var_types type = indir->TypeGet();
7569             if (type == TYP_FLOAT)
7570             {
7571                 regNumber tmpReg = indir->GetSingleTempReg();
7572                 emitInsLoadStoreOp(INS_ldr, EA_4BYTE, tmpReg, indir, 0);
7573                 emitIns_R_R(INS_vmov_i2f, EA_4BYTE, dataReg, tmpReg);
7574                 return;
7575             }
7576             else if (type == TYP_DOUBLE)
7577             {
7578                 regNumber tmpReg1 = indir->ExtractTempReg();
7579                 regNumber tmpReg2 = indir->GetSingleTempReg();
7580                 emitInsLoadStoreOp(INS_ldr, EA_4BYTE, tmpReg1, indir, 0);
7581                 emitInsLoadStoreOp(INS_ldr, EA_4BYTE, tmpReg2, indir, 4);
7582                 emitIns_R_R_R(INS_vmov_i2d, EA_8BYTE, dataReg, tmpReg1, tmpReg2);
7583                 return;
7584             }
7585         }
7586     }
7587
7588     // Proceed with ordinary loads/stores
7589     emitInsLoadStoreOp(ins, attr, dataReg, indir, 0);
7590 }
7591
7592 void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataReg, GenTreeIndir* indir, int offset)
7593 {
7594     GenTree* addr = indir->Addr();
7595
7596     if (addr->isContained())
7597     {
7598         assert(addr->OperGet() == GT_LCL_VAR_ADDR || addr->OperGet() == GT_LEA);
7599
7600         DWORD lsl = 0;
7601
7602         if (addr->OperGet() == GT_LEA)
7603         {
7604             offset += addr->AsAddrMode()->Offset();
7605             if (addr->AsAddrMode()->gtScale > 0)
7606             {
7607                 assert(isPow2(addr->AsAddrMode()->gtScale));
7608                 BitScanForward(&lsl, addr->AsAddrMode()->gtScale);
7609             }
7610         }
7611
7612         GenTree* memBase = indir->Base();
7613
7614         if (indir->HasIndex())
7615         {
7616             assert(addr->OperGet() == GT_LEA);
7617
7618             GenTree* index = indir->Index();
7619
7620             if (offset != 0)
7621             {
7622                 regNumber tmpReg = indir->GetSingleTempReg();
7623
7624                 // If the LEA produces a GCREF or BYREF, we need to be careful to mark any temp register
7625                 // computed with the base register as a BYREF.
7626                 GenTreeAddrMode* lea                    = addr->AsAddrMode();
7627                 emitAttr         leaAttr                = emitTypeSize(lea);
7628                 emitAttr         leaBasePartialAddrAttr = EA_IS_GCREF_OR_BYREF(leaAttr) ? EA_BYREF : EA_PTRSIZE;
7629
7630                 if (emitIns_valid_imm_for_add(offset, INS_FLAGS_DONT_CARE))
7631                 {
7632                     if (lsl > 0)
7633                     {
7634                         // Generate code to set tmpReg = base + index*scale
7635                         emitIns_R_R_R_I(INS_add, leaBasePartialAddrAttr, tmpReg, memBase->gtRegNum, index->gtRegNum,
7636                                         lsl, INS_FLAGS_DONT_CARE, INS_OPTS_LSL);
7637                     }
7638                     else // no scale
7639                     {
7640                         // Generate code to set tmpReg = base + index
7641                         emitIns_R_R_R(INS_add, leaBasePartialAddrAttr, tmpReg, memBase->gtRegNum, index->gtRegNum);
7642                     }
7643
7644                     noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
7645
7646                     // Then load/store dataReg from/to [tmpReg + offset]
7647                     emitIns_R_R_I(ins, attr, dataReg, tmpReg, offset);
7648                 }
7649                 else // large offset
7650                 {
7651                     // First load/store tmpReg with the large offset constant
7652                     codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
7653                     // Then add the base register
7654                     //      rd = rd + base
7655                     emitIns_R_R_R(INS_add, leaBasePartialAddrAttr, tmpReg, tmpReg, memBase->gtRegNum);
7656
7657                     noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
7658                     noway_assert(tmpReg != index->gtRegNum);
7659
7660                     // Then load/store dataReg from/to [tmpReg + index*scale]
7661                     emitIns_R_R_R_I(ins, attr, dataReg, tmpReg, index->gtRegNum, lsl, INS_FLAGS_DONT_CARE,
7662                                     INS_OPTS_LSL);
7663                 }
7664             }
7665             else // (offset == 0)
7666             {
7667                 if (lsl > 0)
7668                 {
7669                     // Then load/store dataReg from/to [memBase + index*scale]
7670                     emitIns_R_R_R_I(ins, attr, dataReg, memBase->gtRegNum, index->gtRegNum, lsl, INS_FLAGS_DONT_CARE,
7671                                     INS_OPTS_LSL);
7672                 }
7673                 else // no scale
7674                 {
7675                     // Then load/store dataReg from/to [memBase + index]
7676                     emitIns_R_R_R(ins, attr, dataReg, memBase->gtRegNum, index->gtRegNum);
7677                 }
7678             }
7679         }
7680         else // no Index
7681         {
7682             if (emitIns_valid_imm_for_ldst_offset(offset, attr))
7683             {
7684                 // Then load/store dataReg from/to [memBase + offset]
7685                 emitIns_R_R_I(ins, attr, dataReg, memBase->gtRegNum, offset);
7686             }
7687             else
7688             {
7689                 // We require a tmpReg to hold the offset
7690                 regNumber tmpReg = indir->GetSingleTempReg();
7691
7692                 // First load/store tmpReg with the large offset constant
7693                 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
7694
7695                 // Then load/store dataReg from/to [memBase + tmpReg]
7696                 emitIns_R_R_R(ins, attr, dataReg, memBase->gtRegNum, tmpReg);
7697             }
7698         }
7699     }
7700     else
7701     {
7702         if (offset != 0)
7703         {
7704             assert(emitIns_valid_imm_for_add(offset, INS_FLAGS_DONT_CARE));
7705             emitIns_R_R_I(ins, attr, dataReg, addr->gtRegNum, offset);
7706         }
7707         else
7708         {
7709             emitIns_R_R(ins, attr, dataReg, addr->gtRegNum);
7710         }
7711     }
7712 }
7713
7714 // The callee must call genConsumeReg() for any non-contained srcs
7715 // and genProduceReg() for any non-contained dsts.
7716
7717 regNumber emitter::emitInsBinary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src)
7718 {
7719     regNumber result = REG_NA;
7720
7721     // dst can only be a reg
7722     assert(!dst->isContained());
7723
7724     // src can be immed or reg
7725     assert(!src->isContained() || src->isContainedIntOrIImmed());
7726
7727     // find immed (if any) - it cannot be a dst
7728     GenTreeIntConCommon* intConst = nullptr;
7729     if (src->isContainedIntOrIImmed())
7730     {
7731         intConst = src->AsIntConCommon();
7732     }
7733
7734     if (intConst)
7735     {
7736         emitIns_R_I(ins, attr, dst->gtRegNum, (target_ssize_t)intConst->IconValue());
7737         return dst->gtRegNum;
7738     }
7739     else
7740     {
7741         emitIns_R_R(ins, attr, dst->gtRegNum, src->gtRegNum);
7742         return dst->gtRegNum;
7743     }
7744 }
7745
7746 regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src1, GenTree* src2)
7747 {
7748     // dst can only be a reg
7749     assert(!dst->isContained());
7750
7751     // find immed (if any) - it cannot be a dst
7752     // Only one src can be an int.
7753     GenTreeIntConCommon* intConst  = nullptr;
7754     GenTree*             nonIntReg = nullptr;
7755
7756     if (varTypeIsFloating(dst))
7757     {
7758         // src1 can only be a reg
7759         assert(!src1->isContained());
7760         // src2 can only be a reg
7761         assert(!src2->isContained());
7762     }
7763     else // not floating point
7764     {
7765         // src2 can be immed or reg
7766         assert(!src2->isContained() || src2->isContainedIntOrIImmed());
7767
7768         // Check src2 first as we can always allow it to be a contained immediate
7769         if (src2->isContainedIntOrIImmed())
7770         {
7771             intConst  = src2->AsIntConCommon();
7772             nonIntReg = src1;
7773         }
7774         // Only for commutative operations do we check src1 and allow it to be a contained immediate
7775         else if (dst->OperIsCommutative())
7776         {
7777             // src1 can be immed or reg
7778             assert(!src1->isContained() || src1->isContainedIntOrIImmed());
7779
7780             // Check src1 and allow it to be a contained immediate
7781             if (src1->isContainedIntOrIImmed())
7782             {
7783                 assert(!src2->isContainedIntOrIImmed());
7784                 intConst  = src1->AsIntConCommon();
7785                 nonIntReg = src2;
7786             }
7787         }
7788         else
7789         {
7790             // src1 can only be a reg
7791             assert(!src1->isContained());
7792         }
7793     }
7794
7795     insFlags flags         = INS_FLAGS_DONT_CARE;
7796     bool     isMulOverflow = false;
7797     if (dst->gtOverflowEx())
7798     {
7799         if ((ins == INS_add) || (ins == INS_adc) || (ins == INS_sub) || (ins == INS_sbc))
7800         {
7801             flags = INS_FLAGS_SET;
7802         }
7803         else if (ins == INS_mul)
7804         {
7805             isMulOverflow = true;
7806             assert(intConst == nullptr); // overflow format doesn't support an int constant operand
7807         }
7808         else
7809         {
7810             assert(!"Invalid ins for overflow check");
7811         }
7812     }
7813
7814     if (dst->gtSetFlags())
7815     {
7816         assert((ins == INS_add) || (ins == INS_adc) || (ins == INS_sub) || (ins == INS_sbc) || (ins == INS_and) ||
7817                (ins == INS_orr) || (ins == INS_eor) || (ins == INS_orn));
7818         flags = INS_FLAGS_SET;
7819     }
7820
7821     if (intConst != nullptr)
7822     {
7823         emitIns_R_R_I(ins, attr, dst->gtRegNum, nonIntReg->gtRegNum, (target_ssize_t)intConst->IconValue(), flags);
7824     }
7825     else
7826     {
7827         if (isMulOverflow)
7828         {
7829             regNumber extraReg = dst->GetSingleTempReg();
7830             assert(extraReg != dst->gtRegNum);
7831
7832             if ((dst->gtFlags & GTF_UNSIGNED) != 0)
7833             {
7834                 // Compute 8 byte result from 4 byte by 4 byte multiplication.
7835                 emitIns_R_R_R_R(INS_umull, EA_4BYTE, dst->gtRegNum, extraReg, src1->gtRegNum, src2->gtRegNum);
7836
7837                 // Overflow exists if the result's high word is non-zero.
7838                 emitIns_R_I(INS_cmp, attr, extraReg, 0);
7839             }
7840             else
7841             {
7842                 // Compute 8 byte result from 4 byte by 4 byte multiplication.
7843                 emitIns_R_R_R_R(INS_smull, EA_4BYTE, dst->gtRegNum, extraReg, src1->gtRegNum, src2->gtRegNum);
7844
7845                 // Overflow exists if the result's high word is not merely a sign bit.
7846                 emitIns_R_R_I(INS_cmp, attr, extraReg, dst->gtRegNum, 31, INS_FLAGS_DONT_CARE, INS_OPTS_ASR);
7847             }
7848         }
7849         else
7850         {
7851             // We can just do the arithmetic, setting the flags if needed.
7852             emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum, flags);
7853         }
7854     }
7855
7856     if (dst->gtOverflowEx())
7857     {
7858         assert(!varTypeIsFloating(dst));
7859
7860         emitJumpKind jumpKind;
7861
7862         if (dst->OperGet() == GT_MUL)
7863         {
7864             jumpKind = EJ_ne;
7865         }
7866         else
7867         {
7868             bool isUnsignedOverflow = ((dst->gtFlags & GTF_UNSIGNED) != 0);
7869             jumpKind                = isUnsignedOverflow ? EJ_lo : EJ_vs;
7870             if (jumpKind == EJ_lo)
7871             {
7872                 if ((dst->OperGet() != GT_SUB) && (dst->OperGet() != GT_SUB_HI))
7873                 {
7874                     jumpKind = EJ_hs;
7875                 }
7876             }
7877         }
7878
7879         // Jump to the block which will throw the exception.
7880         codeGen->genJumpToThrowHlpBlk(jumpKind, SCK_OVERFLOW);
7881     }
7882
7883     return dst->gtRegNum;
7884 }
7885
7886 #endif // defined(_TARGET_ARM_)