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