Delete unused variables in jit. Part 2. (#23481)
[platform/upstream/coreclr.git] / src / jit / emitarm64.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                             emitArm64.cpp                                 XX
9 XX                                                                           XX
10 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
11 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
12 */
13
14 #include "jitpch.h"
15 #ifdef _MSC_VER
16 #pragma hdrstop
17 #endif
18
19 #if defined(_TARGET_ARM64_)
20
21 /*****************************************************************************/
22 /*****************************************************************************/
23
24 #include "instr.h"
25 #include "emit.h"
26 #include "codegen.h"
27
28 /* static */ bool emitter::strictArmAsm = true;
29
30 /*****************************************************************************/
31
32 const instruction emitJumpKindInstructions[] = {
33     INS_nop,
34
35 #define JMP_SMALL(en, rev, ins) INS_##ins,
36 #include "emitjmps.h"
37 };
38
39 const emitJumpKind emitReverseJumpKinds[] = {
40     EJ_NONE,
41
42 #define JMP_SMALL(en, rev, ins) EJ_##rev,
43 #include "emitjmps.h"
44 };
45
46 /*****************************************************************************
47  * Look up the instruction for a jump kind
48  */
49
50 /*static*/ instruction emitter::emitJumpKindToIns(emitJumpKind jumpKind)
51 {
52     assert((unsigned)jumpKind < ArrLen(emitJumpKindInstructions));
53     return emitJumpKindInstructions[jumpKind];
54 }
55
56 /*****************************************************************************
57 * Look up the jump kind for an instruction. It better be a conditional
58 * branch instruction with a jump kind!
59 */
60
61 /*static*/ emitJumpKind emitter::emitInsToJumpKind(instruction ins)
62 {
63     for (unsigned i = 0; i < ArrLen(emitJumpKindInstructions); i++)
64     {
65         if (ins == emitJumpKindInstructions[i])
66         {
67             emitJumpKind ret = (emitJumpKind)i;
68             assert(EJ_NONE < ret && ret < EJ_COUNT);
69             return ret;
70         }
71     }
72     unreached();
73 }
74
75 /*****************************************************************************
76  * Reverse the conditional jump
77  */
78
79 /*static*/ emitJumpKind emitter::emitReverseJumpKind(emitJumpKind jumpKind)
80 {
81     assert(jumpKind < EJ_COUNT);
82     return emitReverseJumpKinds[jumpKind];
83 }
84
85 /*****************************************************************************
86  *
87  *  Return the allocated size (in bytes) of the given instruction descriptor.
88  */
89
90 size_t emitter::emitSizeOfInsDsc(instrDesc* id)
91 {
92     if (emitIsScnsInsDsc(id))
93         return SMALL_IDSC_SIZE;
94
95     assert((unsigned)id->idInsFmt() < emitFmtCount);
96
97     ID_OPS idOp      = (ID_OPS)emitFmtToOps[id->idInsFmt()];
98     bool   isCallIns = (id->idIns() == INS_bl) || (id->idIns() == INS_blr) || (id->idIns() == INS_b_tail) ||
99                      (id->idIns() == INS_br_tail);
100     bool maybeCallIns = (id->idIns() == INS_b) || (id->idIns() == INS_br);
101
102     switch (idOp)
103     {
104         case ID_OP_NONE:
105             break;
106
107         case ID_OP_JMP:
108             return sizeof(instrDescJmp);
109
110         case ID_OP_CALL:
111             assert(isCallIns || maybeCallIns);
112             if (id->idIsLargeCall())
113             {
114                 /* Must be a "fat" call descriptor */
115                 return sizeof(instrDescCGCA);
116             }
117             else
118             {
119                 assert(!id->idIsLargeDsp());
120                 assert(!id->idIsLargeCns());
121                 return sizeof(instrDesc);
122             }
123             break;
124
125         default:
126             NO_WAY("unexpected instruction descriptor format");
127             break;
128     }
129
130     if (id->idIsLargeCns())
131     {
132         if (id->idIsLargeDsp())
133             return sizeof(instrDescCnsDsp);
134         else
135             return sizeof(instrDescCns);
136     }
137     else
138     {
139         if (id->idIsLargeDsp())
140             return sizeof(instrDescDsp);
141         else
142             return sizeof(instrDesc);
143     }
144 }
145
146 #ifdef DEBUG
147 /*****************************************************************************
148  *
149  *  The following called for each recorded instruction -- use for debugging.
150  */
151 void emitter::emitInsSanityCheck(instrDesc* id)
152 {
153     /* What instruction format have we got? */
154
155     switch (id->idInsFmt())
156     {
157         instruction ins;
158         emitAttr    elemsize;
159         emitAttr    datasize;
160         emitAttr    dstsize;
161         emitAttr    srcsize;
162         ssize_t     imm;
163         unsigned    immShift;
164         ssize_t     index;
165         ssize_t     index2;
166
167         case IF_BI_0A: // BI_0A   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
168             break;
169
170         case IF_BI_0B: // BI_0B   ......iiiiiiiiii iiiiiiiiiiii....               simm19:00
171             break;
172
173         case IF_LARGEJMP:
174         case IF_LARGEADR:
175         case IF_LARGELDC:
176             break;
177
178         case IF_BI_0C: // BI_0C   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
179             break;
180
181         case IF_BI_1A: // BI_1A   ......iiiiiiiiii iiiiiiiiiiittttt      Rt       simm19:00
182             assert(isValidGeneralDatasize(id->idOpSize()));
183             assert(isGeneralRegister(id->idReg1()));
184             break;
185
186         case IF_BI_1B: // BI_1B   B.......bbbbbiii iiiiiiiiiiittttt      Rt imm6, simm14:00
187             assert(isValidGeneralDatasize(id->idOpSize()));
188             assert(isGeneralRegister(id->idReg1()));
189             assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
190             break;
191
192         case IF_BR_1A: // BR_1A   ................ ......nnnnn.....         Rn
193             assert(isGeneralRegister(id->idReg1()));
194             break;
195
196         case IF_BR_1B: // BR_1B   ................ ......nnnnn.....         Rn
197             assert(isGeneralRegister(id->idReg3()));
198             break;
199
200         case IF_LS_1A: // LS_1A   .X......iiiiiiii iiiiiiiiiiittttt      Rt    PC imm(1MB)
201             assert(isGeneralRegister(id->idReg1()) || isVectorRegister(id->idReg1()));
202             assert(insOptsNone(id->idInsOpt()));
203             break;
204
205         case IF_LS_2A:                                // LS_2A   .X.......X...... ......nnnnnttttt      Rt Rn
206             assert(isIntegerRegister(id->idReg1()) || // ZR
207                    isVectorRegister(id->idReg1()));
208             assert(isIntegerRegister(id->idReg2())); // SP
209             assert(emitGetInsSC(id) == 0);
210             assert(insOptsNone(id->idInsOpt()));
211             break;
212
213         case IF_LS_2B: // LS_2B   .X.......Xiiiiii iiiiiinnnnnttttt      Rt Rn    imm(0-4095)
214             assert(isIntegerRegister(id->idReg1()) || // ZR
215                    isVectorRegister(id->idReg1()));
216             assert(isIntegerRegister(id->idReg2())); // SP
217             assert(isValidUimm12(emitGetInsSC(id)));
218             assert(insOptsNone(id->idInsOpt()));
219             break;
220
221         case IF_LS_2C: // LS_2C   .X.......X.iiiii iiiiPPnnnnnttttt      Rt Rn    imm(-256..+255) no/pre/post inc
222             assert(isIntegerRegister(id->idReg1()) || // ZR
223                    isVectorRegister(id->idReg1()));
224             assert(isIntegerRegister(id->idReg2())); // SP
225             assert(emitGetInsSC(id) >= -0x100);
226             assert(emitGetInsSC(id) < 0x100);
227             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
228             break;
229
230         case IF_LS_3A: // LS_3A   .X.......X.mmmmm oooS..nnnnnttttt      Rt Rn Rm ext(Rm) LSL {}
231             assert(isIntegerRegister(id->idReg1()) || // ZR
232                    isVectorRegister(id->idReg1()));
233             assert(isIntegerRegister(id->idReg2())); // SP
234             if (id->idIsLclVar())
235             {
236                 assert(isGeneralRegister(codeGen->rsGetRsvdReg()));
237             }
238             else
239             {
240                 assert(isGeneralRegister(id->idReg3()));
241             }
242             assert(insOptsLSExtend(id->idInsOpt()));
243             break;
244
245         case IF_LS_3B: // LS_3B   X............... .aaaaannnnnttttt      Rt Ra Rn
246             assert((isValidGeneralDatasize(id->idOpSize()) && isIntegerRegister(id->idReg1())) ||
247                    (isValidVectorLSPDatasize(id->idOpSize()) && isVectorRegister(id->idReg1())));
248             assert(isIntegerRegister(id->idReg1()) || // ZR
249                    isVectorRegister(id->idReg1()));
250             assert(isIntegerRegister(id->idReg2()) || // ZR
251                    isVectorRegister(id->idReg2()));
252             assert(isIntegerRegister(id->idReg3())); // SP
253             assert(emitGetInsSC(id) == 0);
254             assert(insOptsNone(id->idInsOpt()));
255             break;
256
257         case IF_LS_3C: // LS_3C   X.........iiiiii iaaaaannnnnttttt      Rt Ra Rn imm(im7,sh)
258             assert((isValidGeneralDatasize(id->idOpSize()) && isIntegerRegister(id->idReg1())) ||
259                    (isValidVectorLSPDatasize(id->idOpSize()) && isVectorRegister(id->idReg1())));
260             assert(isIntegerRegister(id->idReg1()) || // ZR
261                    isVectorRegister(id->idReg1()));
262             assert(isIntegerRegister(id->idReg2()) || // ZR
263                    isVectorRegister(id->idReg2()));
264             assert(isIntegerRegister(id->idReg3())); // SP
265             assert(emitGetInsSC(id) >= -0x40);
266             assert(emitGetInsSC(id) < 0x40);
267             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
268             break;
269
270         case IF_LS_3D: // LS_3D   .X.......X.mmmmm ......nnnnnttttt      Wm Rt Rn
271             assert(isIntegerRegister(id->idReg1()));
272             assert(isIntegerRegister(id->idReg2()));
273             assert(isIntegerRegister(id->idReg3()));
274             assert(emitGetInsSC(id) == 0);
275             assert(!id->idIsLclVar());
276             assert(insOptsNone(id->idInsOpt()));
277             break;
278
279         case IF_LS_3E: // LS_3E   .X.........mmmmm ......nnnnnttttt      Rm Rt Rn ARMv8.1 LSE Atomics
280             assert(isIntegerRegister(id->idReg1()));
281             assert(isIntegerRegister(id->idReg2()));
282             assert(isIntegerRegister(id->idReg3()));
283             assert(emitGetInsSC(id) == 0);
284             assert(!id->idIsLclVar());
285             assert(insOptsNone(id->idInsOpt()));
286             break;
287
288         case IF_DI_1A: // DI_1A   X.......shiiiiii iiiiiinnnnn.....         Rn    imm(i12,sh)
289             assert(isValidGeneralDatasize(id->idOpSize()));
290             assert(isGeneralRegister(id->idReg1()));
291             assert(isValidUimm12(emitGetInsSC(id)));
292             assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
293             break;
294
295         case IF_DI_1B: // DI_1B   X........hwiiiii iiiiiiiiiiiddddd      Rd       imm(i16,hw)
296             assert(isValidGeneralDatasize(id->idOpSize()));
297             assert(isGeneralRegister(id->idReg1()));
298             assert(isValidImmHWVal(emitGetInsSC(id), id->idOpSize()));
299             break;
300
301         case IF_DI_1C: // DI_1C   X........Nrrrrrr ssssssnnnnn.....         Rn    imm(N,r,s)
302             assert(isValidGeneralDatasize(id->idOpSize()));
303             assert(isGeneralRegister(id->idReg1()));
304             assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
305             break;
306
307         case IF_DI_1D: // DI_1D   X........Nrrrrrr ssssss.....ddddd      Rd       imm(N,r,s)
308             assert(isValidGeneralDatasize(id->idOpSize()));
309             assert(isIntegerRegister(id->idReg1())); // SP
310             assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
311             break;
312
313         case IF_DI_1E: // DI_1E   .ii.....iiiiiiii iiiiiiiiiiiddddd      Rd       simm21
314             assert(isGeneralRegister(id->idReg1()));
315             break;
316
317         case IF_DI_1F: // DI_1F   X..........iiiii cccc..nnnnn.nzcv      Rn imm5  nzcv cond
318             assert(isValidGeneralDatasize(id->idOpSize()));
319             assert(isGeneralRegister(id->idReg1()));
320             assert(isValidImmCondFlagsImm5(emitGetInsSC(id)));
321             break;
322
323         case IF_DI_2A: // DI_2A   X.......shiiiiii iiiiiinnnnnddddd      Rd Rn    imm(i12,sh)
324             assert(isValidGeneralDatasize(id->idOpSize()));
325             assert(isIntegerRegister(id->idReg1())); // SP
326             assert(isIntegerRegister(id->idReg2())); // SP
327             assert(isValidUimm12(emitGetInsSC(id)));
328             assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
329             break;
330
331         case IF_DI_2B: // DI_2B   X.........Xnnnnn ssssssnnnnnddddd      Rd Rn    imm(0-63)
332             assert(isValidGeneralDatasize(id->idOpSize()));
333             assert(isGeneralRegister(id->idReg1()));
334             assert(isGeneralRegister(id->idReg2()));
335             assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
336             break;
337
338         case IF_DI_2C: // DI_2C   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imm(N,r,s)
339             assert(isValidGeneralDatasize(id->idOpSize()));
340             assert(isIntegerRegister(id->idReg1())); // SP
341             assert(isGeneralRegister(id->idReg2()));
342             assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
343             break;
344
345         case IF_DI_2D: // DI_2D   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imr, imms   (N,r,s)
346             assert(isValidGeneralDatasize(id->idOpSize()));
347             assert(isGeneralRegister(id->idReg1()));
348             assert(isGeneralRegister(id->idReg2()));
349             assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
350             break;
351
352         case IF_DR_1D: // DR_1D   X............... cccc.......ddddd      Rd       cond
353             assert(isValidGeneralDatasize(id->idOpSize()));
354             assert(isGeneralRegister(id->idReg1()));
355             assert(isValidImmCond(emitGetInsSC(id)));
356             break;
357
358         case IF_DR_2A: // DR_2A   X..........mmmmm ......nnnnn.....         Rn Rm
359             assert(isValidGeneralDatasize(id->idOpSize()));
360             assert(isGeneralRegister(id->idReg1()));
361             assert(isGeneralRegister(id->idReg2()));
362             break;
363
364         case IF_DR_2B: // DR_2B   X.......sh.mmmmm ssssssnnnnn.....         Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
365             assert(isValidGeneralDatasize(id->idOpSize()));
366             assert(isIntegerRegister(id->idReg1())); // ZR
367             assert(isGeneralRegister(id->idReg2()));
368             assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
369             if (!insOptsNone(id->idInsOpt()))
370             {
371                 if (id->idIns() == INS_tst) // tst allows ROR, cmp/cmn don't
372                 {
373                     assert(insOptsAnyShift(id->idInsOpt()));
374                 }
375                 else
376                 {
377                     assert(insOptsAluShift(id->idInsOpt()));
378                 }
379             }
380             assert(insOptsNone(id->idInsOpt()) || (emitGetInsSC(id) > 0));
381             break;
382
383         case IF_DR_2C: // DR_2C   X..........mmmmm ooosssnnnnn.....         Rn Rm ext(Rm) LSL imm(0-4)
384             assert(isValidGeneralDatasize(id->idOpSize()));
385             assert(isIntegerRegister(id->idReg1())); // SP
386             assert(isGeneralRegister(id->idReg2()));
387             assert(insOptsNone(id->idInsOpt()) || insOptsLSL(id->idInsOpt()) || insOptsAnyExtend(id->idInsOpt()));
388             assert(emitGetInsSC(id) >= 0);
389             assert(emitGetInsSC(id) <= 4);
390             if (insOptsLSL(id->idInsOpt()))
391             {
392                 assert(emitGetInsSC(id) > 0);
393             }
394             break;
395
396         case IF_DR_2D: // DR_2D   X..........nnnnn cccc..nnnnnmmmmm      Rd Rn    cond
397             assert(isValidGeneralDatasize(id->idOpSize()));
398             assert(isGeneralRegister(id->idReg1()));
399             assert(isGeneralRegister(id->idReg2()));
400             assert(isValidImmCond(emitGetInsSC(id)));
401             break;
402
403         case IF_DR_2E: // DR_2E   X..........mmmmm ...........ddddd      Rd    Rm
404             assert(isValidGeneralDatasize(id->idOpSize()));
405             assert(isGeneralRegister(id->idReg1()));
406             assert(isIntegerRegister(id->idReg2())); // ZR
407             break;
408
409         case IF_DR_2F: // DR_2F   X.......sh.mmmmm ssssss.....ddddd      Rd    Rm {LSL,LSR,ASR} imm(0-63)
410             assert(isValidGeneralDatasize(id->idOpSize()));
411             assert(isGeneralRegister(id->idReg1()));
412             assert(isGeneralRegister(id->idReg2()));
413             assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
414             assert(insOptsNone(id->idInsOpt()) || insOptsAluShift(id->idInsOpt()));
415             assert(insOptsNone(id->idInsOpt()) || (emitGetInsSC(id) > 0));
416             break;
417
418         case IF_DR_2G: // DR_2G   X............... ......nnnnnddddd      Rd    Rm
419             assert(isValidGeneralDatasize(id->idOpSize()));
420             assert(isIntegerRegister(id->idReg1())); // SP
421             assert(isIntegerRegister(id->idReg2())); // SP
422             break;
423
424         case IF_DR_2H: // DR_2H   X........X...... ......nnnnnddddd      Rd Rn
425             assert(isValidGeneralDatasize(id->idOpSize()));
426             assert(isGeneralRegister(id->idReg1()));
427             assert(isGeneralRegister(id->idReg2()));
428             break;
429
430         case IF_DR_2I: // DR_2I   X..........mmmmm cccc..nnnnn.nzcv      Rn Rm    nzcv cond
431             assert(isValidGeneralDatasize(id->idOpSize()));
432             assert(isGeneralRegister(id->idReg1()));
433             assert(isGeneralRegister(id->idReg2()));
434             assert(isValidImmCondFlags(emitGetInsSC(id)));
435             break;
436
437         case IF_DR_2J: // DR_2J   ................ ......nnnnnddddd      Sd Sn    (sha1h)
438             assert(isValidGeneralDatasize(id->idOpSize()));
439             assert(isVectorRegister(id->idReg1()));
440             assert(isVectorRegister(id->idReg2()));
441             break;
442
443         case IF_DR_3A: // DR_3A   X..........mmmmm ......nnnnnmmmmm      Rd Rn Rm
444             assert(isValidGeneralDatasize(id->idOpSize()));
445             assert(isIntegerRegister(id->idReg1())); // SP
446             assert(isIntegerRegister(id->idReg2())); // SP
447             if (id->idIsLclVar())
448             {
449                 assert(isGeneralRegister(codeGen->rsGetRsvdReg()));
450             }
451             else
452             {
453                 assert(isGeneralRegister(id->idReg3()));
454             }
455             assert(insOptsNone(id->idInsOpt()));
456             break;
457
458         case IF_DR_3B: // DR_3B   X.......sh.mmmmm ssssssnnnnnddddd      Rd Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
459             assert(isValidGeneralDatasize(id->idOpSize()));
460             assert(isGeneralRegister(id->idReg1()));
461             assert(isGeneralRegister(id->idReg2()));
462             assert(isGeneralRegister(id->idReg3()));
463             assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
464             assert(insOptsNone(id->idInsOpt()) || insOptsAnyShift(id->idInsOpt()));
465             assert(insOptsNone(id->idInsOpt()) || (emitGetInsSC(id) > 0));
466             break;
467
468         case IF_DR_3C: // DR_3C   X..........mmmmm ooosssnnnnnddddd      Rd Rn Rm ext(Rm) LSL imm(0-4)
469             assert(isValidGeneralDatasize(id->idOpSize()));
470             assert(isIntegerRegister(id->idReg1())); // SP
471             assert(isIntegerRegister(id->idReg2())); // SP
472             assert(isGeneralRegister(id->idReg3()));
473             assert(insOptsNone(id->idInsOpt()) || insOptsLSL(id->idInsOpt()) || insOptsAnyExtend(id->idInsOpt()));
474             assert(emitGetInsSC(id) >= 0);
475             assert(emitGetInsSC(id) <= 4);
476             if (insOptsLSL(id->idInsOpt()))
477             {
478                 assert((emitGetInsSC(id) > 0) ||
479                        (id->idReg2() == REG_ZR)); // REG_ZR encodes SP and we allow a shift of zero
480             }
481             break;
482
483         case IF_DR_3D: // DR_3D   X..........mmmmm cccc..nnnnnmmmmm      Rd Rn Rm cond
484             assert(isValidGeneralDatasize(id->idOpSize()));
485             assert(isGeneralRegister(id->idReg1()));
486             assert(isGeneralRegister(id->idReg2()));
487             assert(isGeneralRegister(id->idReg3()));
488             assert(isValidImmCond(emitGetInsSC(id)));
489             break;
490
491         case IF_DR_3E: // DR_3E   X........X.mmmmm ssssssnnnnnddddd      Rd Rn Rm imm(0-63)
492             assert(isValidGeneralDatasize(id->idOpSize()));
493             assert(isGeneralRegister(id->idReg1()));
494             assert(isGeneralRegister(id->idReg2()));
495             assert(isGeneralRegister(id->idReg3()));
496             assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
497             assert(insOptsNone(id->idInsOpt()));
498             break;
499
500         case IF_DR_4A: // DR_4A   X..........mmmmm .aaaaannnnnddddd      Rd Rn Rm Ra
501             assert(isValidGeneralDatasize(id->idOpSize()));
502             assert(isGeneralRegister(id->idReg1()));
503             assert(isGeneralRegister(id->idReg2()));
504             assert(isGeneralRegister(id->idReg3()));
505             assert(isGeneralRegister(id->idReg4()));
506             break;
507
508         case IF_DV_1A: // DV_1A   .........X.iiiii iii........ddddd      Vd imm8    (fmov - immediate scalar)
509             assert(insOptsNone(id->idInsOpt()));
510             elemsize = id->idOpSize();
511             assert(isValidVectorElemsizeFloat(elemsize));
512             assert(isVectorRegister(id->idReg1()));
513             assert(isValidUimm8(emitGetInsSC(id)));
514             break;
515
516         case IF_DV_1B: // DV_1B   .QX..........iii cmod..iiiiiddddd      Vd imm8    (immediate vector)
517             ins      = id->idIns();
518             imm      = emitGetInsSC(id) & 0x0ff;
519             immShift = (emitGetInsSC(id) & 0x700) >> 8;
520             assert(immShift >= 0);
521             datasize = id->idOpSize();
522             assert(isValidVectorDatasize(datasize));
523             assert(isValidArrangement(datasize, id->idInsOpt()));
524             elemsize = optGetElemsize(id->idInsOpt());
525             if (ins == INS_fmov)
526             {
527                 assert(isValidVectorElemsizeFloat(elemsize));
528                 assert(id->idInsOpt() != INS_OPTS_1D); // Reserved encoding
529                 assert(immShift == 0);
530             }
531             else
532             {
533                 assert(isValidVectorElemsize(elemsize));
534                 assert((immShift != 4) && (immShift != 7)); // always invalid values
535                 if (ins != INS_movi)                        // INS_mvni, INS_orr, INS_bic
536                 {
537                     assert((elemsize != EA_1BYTE) && (elemsize != EA_8BYTE)); // only H or S
538                     if (elemsize == EA_2BYTE)
539                     {
540                         assert(immShift < 2);
541                     }
542                     else // (elemsize == EA_4BYTE)
543                     {
544                         if (ins != INS_mvni)
545                         {
546                             assert(immShift < 4);
547                         }
548                     }
549                 }
550             }
551             assert(isVectorRegister(id->idReg1()));
552             assert(isValidUimm8(imm));
553             break;
554
555         case IF_DV_1C: // DV_1C   .........X...... ......nnnnn.....      Vn #0.0    (fcmp - with zero)
556             assert(insOptsNone(id->idInsOpt()));
557             elemsize = id->idOpSize();
558             assert(isValidVectorElemsizeFloat(elemsize));
559             assert(isVectorRegister(id->idReg1()));
560             break;
561
562         case IF_DV_2A: // DV_2A   .Q.......X...... ......nnnnnddddd      Vd Vn      (fabs, fcvt - vector)
563         case IF_DV_2M: // DV_2M   .Q......XX...... ......nnnnnddddd      Vd Vn      (abs, neg   - vector)
564         case IF_DV_2P: // DV_2P   ................ ......nnnnnddddd      Vd Vn      (aes*, sha1su1)
565             assert(isValidVectorDatasize(id->idOpSize()));
566             assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
567             assert(isVectorRegister(id->idReg1()));
568             assert(isVectorRegister(id->idReg2()));
569             break;
570
571         case IF_DV_2N: // DV_2N   .........iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - scalar)
572             assert(id->idOpSize() == EA_8BYTE);
573             assert(insOptsNone(id->idInsOpt()));
574             assert(isVectorRegister(id->idReg1()));
575             assert(isVectorRegister(id->idReg2()));
576             assert(isValidImmShift(emitGetInsSC(id), EA_8BYTE));
577             break;
578
579         case IF_DV_2O: // DV_2O   .Q.......iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - vector)
580             assert(isValidVectorDatasize(id->idOpSize()));
581             assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
582             assert(isVectorRegister(id->idReg1()));
583             assert(isVectorRegister(id->idReg2()));
584             elemsize = optGetElemsize(id->idInsOpt());
585             assert(isValidImmShift(emitGetInsSC(id), elemsize));
586             break;
587
588         case IF_DV_2B: // DV_2B   .Q.........iiiii ......nnnnnddddd      Rd Vn[]  (umov/smov    - to general)
589             elemsize = id->idOpSize();
590             index    = emitGetInsSC(id);
591             assert(insOptsNone(id->idInsOpt()));
592             assert(isValidVectorIndex(EA_16BYTE, elemsize, index));
593             assert(isValidVectorElemsize(elemsize));
594             assert(isGeneralRegister(id->idReg1()));
595             assert(isVectorRegister(id->idReg2()));
596             break;
597
598         case IF_DV_2C: // DV_2C   .Q.........iiiii ......nnnnnddddd      Vd Rn    (dup/ins - vector from general)
599             if (id->idIns() == INS_dup)
600             {
601                 datasize = id->idOpSize();
602                 assert(isValidVectorDatasize(datasize));
603                 assert(isValidArrangement(datasize, id->idInsOpt()));
604                 elemsize = optGetElemsize(id->idInsOpt());
605             }
606             else // INS_ins
607             {
608                 datasize = EA_16BYTE;
609                 elemsize = id->idOpSize();
610                 assert(isValidVectorElemsize(elemsize));
611             }
612             assert(isVectorRegister(id->idReg1()));
613             assert(isGeneralRegisterOrZR(id->idReg2()));
614             break;
615
616         case IF_DV_2D: // DV_2D   .Q.........iiiii ......nnnnnddddd      Vd Vn[]  (dup - vector)
617             datasize = id->idOpSize();
618             assert(isValidVectorDatasize(datasize));
619             assert(isValidArrangement(datasize, id->idInsOpt()));
620             elemsize = optGetElemsize(id->idInsOpt());
621             index    = emitGetInsSC(id);
622             assert(isValidVectorIndex(datasize, elemsize, index));
623             assert(isVectorRegister(id->idReg1()));
624             assert(isVectorRegister(id->idReg2()));
625             break;
626
627         case IF_DV_2E: // DV_2E   ...........iiiii ......nnnnnddddd      Vd Vn[]  (dup - scalar)
628             elemsize = id->idOpSize();
629             index    = emitGetInsSC(id);
630             assert(isValidVectorIndex(EA_16BYTE, elemsize, index));
631             assert(isValidVectorElemsize(elemsize));
632             assert(isVectorRegister(id->idReg1()));
633             assert(isVectorRegister(id->idReg2()));
634             break;
635
636         case IF_DV_2F: // DV_2F   ...........iiiii .jjjj.nnnnnddddd      Vd[] Vn[] (ins - element)
637             imm      = emitGetInsSC(id);
638             index    = (imm >> 4) & 0xf;
639             index2   = imm & 0xf;
640             elemsize = id->idOpSize();
641             assert(isValidVectorElemsize(elemsize));
642             assert(isValidVectorIndex(EA_16BYTE, elemsize, index));
643             assert(isValidVectorIndex(EA_16BYTE, elemsize, index2));
644             assert(isVectorRegister(id->idReg1()));
645             assert(isVectorRegister(id->idReg2()));
646             break;
647
648         case IF_DV_2L: // DV_2L   ........XX...... ......nnnnnddddd      Vd Vn      (abs, neg - scalar)
649             assert(id->idOpSize() == EA_8BYTE); // only type D is supported
650             __fallthrough;
651
652         case IF_DV_2G: // DV_2G   .........X...... ......nnnnnddddd      Vd Vn      (fmov, fcvtXX - register)
653         case IF_DV_2K: // DV_2K   .........X.mmmmm ......nnnnn.....      Vn Vm      (fcmp)
654             assert(insOptsNone(id->idInsOpt()));
655             assert(isValidVectorElemsizeFloat(id->idOpSize()));
656             assert(isVectorRegister(id->idReg1()));
657             assert(isVectorRegister(id->idReg2()));
658             break;
659
660         case IF_DV_2H: // DV_2H   X........X...... ......nnnnnddddd      Rd Vn      (fmov/fcvtXX - to general)
661             assert(insOptsConvertFloatToInt(id->idInsOpt()));
662             dstsize = optGetDstsize(id->idInsOpt());
663             srcsize = optGetSrcsize(id->idInsOpt());
664             assert(isValidGeneralDatasize(dstsize));
665             assert(isValidVectorElemsizeFloat(srcsize));
666             assert(dstsize == id->idOpSize());
667             assert(isGeneralRegister(id->idReg1()));
668             assert(isVectorRegister(id->idReg2()));
669             break;
670
671         case IF_DV_2I: // DV_2I   X........X...... ......nnnnnddddd      Vd Rn      (fmov/Xcvtf - from general)
672             assert(insOptsConvertIntToFloat(id->idInsOpt()));
673             dstsize = optGetDstsize(id->idInsOpt());
674             srcsize = optGetSrcsize(id->idInsOpt());
675             assert(isValidGeneralDatasize(srcsize));
676             assert(isValidVectorElemsizeFloat(dstsize));
677             assert(dstsize == id->idOpSize());
678             assert(isVectorRegister(id->idReg1()));
679             assert(isGeneralRegister(id->idReg2()));
680             break;
681
682         case IF_DV_2J: // DV_2J   ........SS.....D D.....nnnnnddddd      Vd Vn      (fcvt)
683             assert(insOptsConvertFloatToFloat(id->idInsOpt()));
684             dstsize = optGetDstsize(id->idInsOpt());
685             srcsize = optGetSrcsize(id->idInsOpt());
686             assert(isValidVectorFcvtsize(srcsize));
687             assert(isValidVectorFcvtsize(dstsize));
688             assert(dstsize == id->idOpSize());
689             assert(isVectorRegister(id->idReg1()));
690             assert(isVectorRegister(id->idReg2()));
691             break;
692
693         case IF_DV_3A: // DV_3A   .Q......XX.mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
694             assert(isValidVectorDatasize(id->idOpSize()));
695             assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
696             assert(isVectorRegister(id->idReg1()));
697             assert(isVectorRegister(id->idReg2()));
698             assert(isVectorRegister(id->idReg3()));
699             elemsize = optGetElemsize(id->idInsOpt());
700             ins      = id->idIns();
701             if (ins == INS_mul)
702             {
703                 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
704             }
705             else if (ins == INS_pmul)
706             {
707                 assert(elemsize == EA_1BYTE); // only supports 8B or 16B
708             }
709             break;
710
711         case IF_DV_3AI: // DV_3AI  .Q......XXLMmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector by elem)
712             assert(isValidVectorDatasize(id->idOpSize()));
713             assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
714             assert(isVectorRegister(id->idReg1()));
715             assert(isVectorRegister(id->idReg2()));
716             assert(isVectorRegister(id->idReg3()));
717             elemsize = optGetElemsize(id->idInsOpt());
718             assert(isValidVectorIndex(EA_16BYTE, elemsize, emitGetInsSC(id)));
719             // Only has encodings for H or S elemsize
720             assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE));
721             break;
722
723         case IF_DV_3B: // DV_3B   .Q.......X.mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
724             assert(isValidVectorDatasize(id->idOpSize()));
725             assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
726             assert(isVectorRegister(id->idReg1()));
727             assert(isVectorRegister(id->idReg2()));
728             assert(isVectorRegister(id->idReg3()));
729             break;
730
731         case IF_DV_3BI: // DV_3BI  .Q.......XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector by elem)
732             assert(isValidVectorDatasize(id->idOpSize()));
733             assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
734             assert(isVectorRegister(id->idReg1()));
735             assert(isVectorRegister(id->idReg2()));
736             assert(isVectorRegister(id->idReg3()));
737             elemsize = optGetElemsize(id->idInsOpt());
738             assert(isValidVectorIndex(id->idOpSize(), elemsize, emitGetInsSC(id)));
739             break;
740
741         case IF_DV_3C: // DV_3C   .Q.........mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
742             assert(isValidVectorDatasize(id->idOpSize()));
743             assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
744             assert(isVectorRegister(id->idReg1()));
745             assert(isVectorRegister(id->idReg2()));
746             assert(isVectorRegister(id->idReg3()));
747             break;
748
749         case IF_DV_3D: // DV_3D   .........X.mmmmm ......nnnnnddddd      Vd Vn Vm   (scalar)
750             assert(isValidScalarDatasize(id->idOpSize()));
751             assert(insOptsNone(id->idInsOpt()));
752             assert(isVectorRegister(id->idReg1()));
753             assert(isVectorRegister(id->idReg2()));
754             assert(isVectorRegister(id->idReg3()));
755             break;
756
757         case IF_DV_3DI: // DV_3DI  .........XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (scalar by elem)
758             assert(isValidScalarDatasize(id->idOpSize()));
759             assert(insOptsNone(id->idInsOpt()));
760             assert(isVectorRegister(id->idReg1()));
761             assert(isVectorRegister(id->idReg2()));
762             assert(isVectorRegister(id->idReg3()));
763             elemsize = id->idOpSize();
764             assert(isValidVectorIndex(EA_16BYTE, elemsize, emitGetInsSC(id)));
765             break;
766
767         case IF_DV_3E: // DV_3E   ...........mmmmm ......nnnnnddddd      Vd Vn Vm  (scalar)
768             assert(insOptsNone(id->idInsOpt()));
769             assert(id->idOpSize() == EA_8BYTE);
770             assert(isVectorRegister(id->idReg1()));
771             assert(isVectorRegister(id->idReg2()));
772             assert(isVectorRegister(id->idReg3()));
773             break;
774
775         case IF_DV_3F: // DV_3F   ...........mmmmm ......nnnnnddddd      Vd Vn Vm
776             assert(isValidVectorDatasize(id->idOpSize()));
777             assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
778             assert(isVectorRegister(id->idReg1()));
779             assert(isVectorRegister(id->idReg2()));
780             assert(isVectorRegister(id->idReg3()));
781             break;
782
783         case IF_DV_4A: // DR_4A   .........X.mmmmm .aaaaannnnnddddd      Rd Rn Rm Ra (scalar)
784             assert(isValidGeneralDatasize(id->idOpSize()));
785             assert(isVectorRegister(id->idReg1()));
786             assert(isVectorRegister(id->idReg2()));
787             assert(isVectorRegister(id->idReg3()));
788             assert(isVectorRegister(id->idReg4()));
789             break;
790
791         case IF_SN_0A: // SN_0A   ................ ................
792         case IF_SI_0A: // SI_0A   ...........iiiii iiiiiiiiiii.....               imm16
793         case IF_SI_0B: // SI_0B   ................ ....bbbb........               imm4 - barrier
794             break;
795
796         default:
797             printf("unexpected format %s\n", emitIfName(id->idInsFmt()));
798             assert(!"Unexpected format");
799             break;
800     }
801 }
802 #endif // DEBUG
803
804 bool emitter::emitInsMayWriteToGCReg(instrDesc* id)
805 {
806     instruction ins = id->idIns();
807     insFormat   fmt = id->idInsFmt();
808
809     switch (fmt)
810     {
811
812         // These are the formats with "destination" registers:
813
814         case IF_DI_1B: // DI_1B   X........hwiiiii iiiiiiiiiiiddddd      Rd       imm(i16,hw)
815         case IF_DI_1D: // DI_1D   X........Nrrrrrr ssssss.....ddddd      Rd       imm(N,r,s)
816         case IF_DI_1E: // DI_1E   .ii.....iiiiiiii iiiiiiiiiiiddddd      Rd       simm21
817
818         case IF_DI_2A: // DI_2A   X.......shiiiiii iiiiiinnnnnddddd      Rd Rn    imm(i12,sh)
819         case IF_DI_2B: // DI_2B   X.........Xnnnnn ssssssnnnnnddddd      Rd Rn    imm(0-63)
820         case IF_DI_2C: // DI_2C   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imm(N,r,s)
821         case IF_DI_2D: // DI_2D   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imr, imms   (N,r,s)
822
823         case IF_DR_1D: // DR_1D   X............... cccc.......ddddd      Rd       cond
824
825         case IF_DR_2D: // DR_2D   X..........nnnnn cccc..nnnnnddddd      Rd Rn    cond
826         case IF_DR_2E: // DR_2E   X..........mmmmm ...........ddddd      Rd    Rm
827         case IF_DR_2F: // DR_2F   X.......sh.mmmmm ssssss.....ddddd      Rd    Rm {LSL,LSR,ASR} imm(0-63)
828         case IF_DR_2G: // DR_2G   X............... ......nnnnnddddd      Rd Rn
829         case IF_DR_2H: // DR_2H   X........X...... ......nnnnnddddd      Rd Rn
830
831         case IF_DR_3A: // DR_3A   X..........mmmmm ......nnnnnddddd      Rd Rn Rm
832         case IF_DR_3B: // DR_3B   X.......sh.mmmmm ssssssnnnnnddddd      Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
833         case IF_DR_3C: // DR_3C   X..........mmmmm xxxsssnnnnnddddd      Rd Rn Rm ext(Rm) LSL imm(0-4)
834         case IF_DR_3D: // DR_3D   X..........mmmmm cccc..nnnnnddddd      Rd Rn Rm cond
835         case IF_DR_3E: // DR_3E   X........X.mmmmm ssssssnnnnnddddd      Rd Rn Rm imm(0-63)
836         case IF_DV_3F: // DV_3F   ...........mmmmm ......nnnnnddddd      Vd Vn Vm (vector) - Vd both source and dest
837
838         case IF_DR_4A: // DR_4A   X..........mmmmm .aaaaannnnnddddd      Rd Rn Rm Ra
839
840         case IF_DV_2B: // DV_2B   .Q.........iiiii ......nnnnnddddd      Rd Vn[]    (umov - to general)
841         case IF_DV_2H: // DV_2H   X........X...... ......nnnnnddddd      Rd Vn      (fmov - to general)
842
843             return true;
844
845         case IF_DV_2C: // DV_2C   .Q.........iiiii ......nnnnnddddd      Vd Rn      (dup/ins - vector from general)
846         case IF_DV_2D: // DV_2D   .Q.........iiiii ......nnnnnddddd      Vd Vn[]    (dup - vector)
847         case IF_DV_2E: // DV_2E   ...........iiiii ......nnnnnddddd      Vd Vn[]    (dup - scalar)
848         case IF_DV_2F: // DV_2F   ...........iiiii .jjjj.nnnnnddddd      Vd[] Vn[]  (ins - element)
849         case IF_DV_2G: // DV_2G   .........X...... ......nnnnnddddd      Vd Vn      (fmov, fcvtXX - register)
850         case IF_DV_2I: // DV_2I   X........X...... ......nnnnnddddd      Vd Rn      (fmov - from general)
851         case IF_DV_2J: // DV_2J   ........SS.....D D.....nnnnnddddd      Vd Vn      (fcvt)
852         case IF_DV_2K: // DV_2K   .........X.mmmmm ......nnnnn.....      Vn Vm      (fcmp)
853         case IF_DV_2L: // DV_2L   ........XX...... ......nnnnnddddd      Vd Vn      (abs, neg - scalar)
854         case IF_DV_2M: // DV_2M   .Q......XX...... ......nnnnnddddd      Vd Vn      (abs, neg - vector)
855         case IF_DV_2P: // DV_2P   ................ ......nnnnnddddd      Vd Vn      (aes*, sha1su1) - Vd both source and
856                        // destination
857
858         case IF_DV_3A:  // DV_3A   .Q......XX.mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
859         case IF_DV_3AI: // DV_3AI  .Q......XXLMmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector)
860         case IF_DV_3B:  // DV_3B   .Q.......X.mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
861         case IF_DV_3BI: // DV_3BI  .Q.......XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector by elem)
862         case IF_DV_3C:  // DV_3C   .Q.........mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
863         case IF_DV_3D:  // DV_3D   .........X.mmmmm ......nnnnnddddd      Vd Vn Vm   (scalar)
864         case IF_DV_3DI: // DV_3DI  .........XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (scalar by elem)
865         case IF_DV_3E:  // DV_3E   ...........mmmmm ......nnnnnddddd      Vd Vn Vm   (scalar)
866         case IF_DV_4A:  // DV_4A   .........X.mmmmm .aaaaannnnnddddd      Vd Va Vn Vm (scalar)
867             // Tracked GC pointers cannot be placed into the SIMD registers.
868             return false;
869
870         // These are the load/store formats with "target" registers:
871
872         case IF_LS_1A: // LS_1A   XX...V..iiiiiiii iiiiiiiiiiittttt      Rt    PC imm(1MB)
873         case IF_LS_2A: // LS_2A   .X.......X...... ......nnnnnttttt      Rt Rn
874         case IF_LS_2B: // LS_2B   .X.......Xiiiiii iiiiiinnnnnttttt      Rt Rn    imm(0-4095)
875         case IF_LS_2C: // LS_2C   .X.......X.iiiii iiiiP.nnnnnttttt      Rt Rn    imm(-256..+255) pre/post inc
876         case IF_LS_3A: // LS_3A   .X.......X.mmmmm xxxS..nnnnnttttt      Rt Rn Rm ext(Rm) LSL {}
877         case IF_LS_3B: // LS_3B   X............... .aaaaannnnnttttt      Rt Ra Rn
878         case IF_LS_3C: // LS_3C   X.........iiiiii iaaaaannnnnttttt      Rt Ra Rn imm(im7,sh)
879         case IF_LS_3D: // LS_3D   .X.......X.mmmmm ......nnnnnttttt      Wm Rt Rn
880
881             // For the Store instructions the "target" register is actually a "source" value
882
883             if (emitInsIsStore(ins))
884             {
885                 return false;
886             }
887             else
888             {
889                 assert(emitInsIsLoad(ins));
890                 return true;
891             }
892
893         case IF_LS_3E: // LS_3E   .X.........mmmmm ......nnnnnttttt      Rm Rt Rn ARMv8.1 LSE Atomics
894             // ARMv8.1 Atomics
895             assert(emitInsIsStore(ins));
896             assert(emitInsIsLoad(ins));
897             return true;
898
899         default:
900             return false;
901     }
902 }
903
904 bool emitter::emitInsWritesToLclVarStackLoc(instrDesc* id)
905 {
906     if (!id->idIsLclVar())
907         return false;
908
909     instruction ins = id->idIns();
910
911     // This list is related to the list of instructions used to store local vars in emitIns_S_R().
912     // We don't accept writing to float local vars.
913
914     switch (ins)
915     {
916         case INS_strb:
917         case INS_strh:
918         case INS_str:
919         case INS_stur:
920         case INS_sturb:
921         case INS_sturh:
922             return true;
923         default:
924             return false;
925     }
926 }
927
928 bool emitter::emitInsWritesToLclVarStackLocPair(instrDesc* id)
929 {
930     if (!id->idIsLclVar())
931         return false;
932
933     instruction ins = id->idIns();
934
935     // This list is related to the list of instructions used to store local vars in emitIns_S_S_R_R().
936     // We don't accept writing to float local vars.
937
938     switch (ins)
939     {
940         case INS_stnp:
941         case INS_stp:
942             return true;
943         default:
944             return false;
945     }
946 }
947
948 bool emitter::emitInsMayWriteMultipleRegs(instrDesc* id)
949 {
950     instruction ins = id->idIns();
951
952     switch (ins)
953     {
954         case INS_ldp:
955         case INS_ldpsw:
956         case INS_ldnp:
957             return true;
958         default:
959             return false;
960     }
961 }
962
963 // For the small loads/store instruction we adjust the size 'attr'
964 // depending upon whether we have a load or a store
965 //
966 emitAttr emitter::emitInsAdjustLoadStoreAttr(instruction ins, emitAttr attr)
967 {
968     if (EA_SIZE(attr) <= EA_4BYTE)
969     {
970         if (emitInsIsLoad(ins))
971         {
972             // The value of 'ins' encodes the size to load
973             // we use EA_8BYTE here because it is the size we will write (into dataReg)
974             // it is also required when ins is INS_ldrsw
975             //
976             attr = EA_8BYTE;
977         }
978         else
979         {
980             assert(emitInsIsStore(ins));
981
982             // The value of 'ins' encodes the size to store
983             // we use EA_4BYTE here because it is the size of the register
984             // that we want to display when storing small values
985             //
986             attr = EA_4BYTE;
987         }
988     }
989     return attr;
990 }
991
992 // Takes an instrDesc 'id' and uses the instruction 'ins' to determine the
993 // size of the target register that is written or read by the instruction.
994 // Note that even if EA_4BYTE is returned a load instruction will still
995 // always zero the upper 4 bytes of the target register.
996 // This method is required so that we can distinguish between loads that are
997 // sign-extending as they can have two different sizes for their target register.
998 // Additionally for instructions like 'ldr' and 'str' these can load/store
999 // either 4 byte or 8 bytes to/from the target register.
1000 // By convention the small unsigned load instructions are considered to write
1001 // a 4 byte sized target register, though since these also zero the upper 4 bytes
1002 // they could equally be considered to write the unsigned value to full 8 byte register.
1003 //
1004 emitAttr emitter::emitInsTargetRegSize(instrDesc* id)
1005 {
1006     instruction ins    = id->idIns();
1007     emitAttr    result = EA_UNKNOWN;
1008
1009     // This is used to determine the size of the target registers for a load/store instruction
1010
1011     switch (ins)
1012     {
1013         case INS_ldxrb:
1014         case INS_ldarb:
1015         case INS_ldaxrb:
1016         case INS_stxrb:
1017         case INS_stlrb:
1018         case INS_stlxrb:
1019         case INS_ldrb:
1020         case INS_strb:
1021         case INS_ldurb:
1022         case INS_sturb:
1023             result = EA_4BYTE;
1024             break;
1025
1026         case INS_ldxrh:
1027         case INS_ldarh:
1028         case INS_ldaxrh:
1029         case INS_stxrh:
1030         case INS_stlrh:
1031         case INS_stlxrh:
1032         case INS_ldrh:
1033         case INS_strh:
1034         case INS_ldurh:
1035         case INS_sturh:
1036             result = EA_4BYTE;
1037             break;
1038
1039         case INS_ldrsb:
1040         case INS_ldursb:
1041         case INS_ldrsh:
1042         case INS_ldursh:
1043             if (id->idOpSize() == EA_8BYTE)
1044                 result = EA_8BYTE;
1045             else
1046                 result = EA_4BYTE;
1047             break;
1048
1049         case INS_ldrsw:
1050         case INS_ldursw:
1051         case INS_ldpsw:
1052             result = EA_8BYTE;
1053             break;
1054
1055         case INS_ldp:
1056         case INS_stp:
1057         case INS_ldnp:
1058         case INS_stnp:
1059             result = id->idOpSize();
1060             break;
1061
1062         case INS_ldxr:
1063         case INS_ldar:
1064         case INS_ldaxr:
1065         case INS_stxr:
1066         case INS_stlr:
1067         case INS_stlxr:
1068         case INS_ldr:
1069         case INS_str:
1070         case INS_ldur:
1071         case INS_stur:
1072             result = id->idOpSize();
1073             break;
1074
1075         default:
1076             NO_WAY("unexpected instruction");
1077             break;
1078     }
1079     return result;
1080 }
1081
1082 // Takes an instrDesc and uses the instruction to determine the 'size' of the
1083 // data that is loaded from memory.
1084 //
1085 emitAttr emitter::emitInsLoadStoreSize(instrDesc* id)
1086 {
1087     instruction ins    = id->idIns();
1088     emitAttr    result = EA_UNKNOWN;
1089
1090     // The 'result' returned is the 'size' of the data that is loaded from memory.
1091
1092     switch (ins)
1093     {
1094         case INS_ldarb:
1095         case INS_stlrb:
1096         case INS_ldrb:
1097         case INS_strb:
1098         case INS_ldurb:
1099         case INS_sturb:
1100         case INS_ldrsb:
1101         case INS_ldursb:
1102             result = EA_1BYTE;
1103             break;
1104
1105         case INS_ldarh:
1106         case INS_stlrh:
1107         case INS_ldrh:
1108         case INS_strh:
1109         case INS_ldurh:
1110         case INS_sturh:
1111         case INS_ldrsh:
1112         case INS_ldursh:
1113             result = EA_2BYTE;
1114             break;
1115
1116         case INS_ldrsw:
1117         case INS_ldursw:
1118         case INS_ldpsw:
1119             result = EA_4BYTE;
1120             break;
1121
1122         case INS_ldp:
1123         case INS_stp:
1124         case INS_ldnp:
1125         case INS_stnp:
1126             result = id->idOpSize();
1127             break;
1128
1129         case INS_ldar:
1130         case INS_stlr:
1131         case INS_ldr:
1132         case INS_str:
1133         case INS_ldur:
1134         case INS_stur:
1135             result = id->idOpSize();
1136             break;
1137
1138         default:
1139             NO_WAY("unexpected instruction");
1140             break;
1141     }
1142     return result;
1143 }
1144
1145 /*****************************************************************************/
1146 #ifdef DEBUG
1147
1148 // clang-format off
1149 static const char * const  xRegNames[] =
1150 {
1151     #define REGDEF(name, rnum, mask, xname, wname) xname,
1152     #include "register.h"
1153 };
1154
1155 static const char * const  wRegNames[] =
1156 {
1157     #define REGDEF(name, rnum, mask, xname, wname) wname,
1158     #include "register.h"
1159 };
1160
1161 static const char * const  vRegNames[] =
1162 {
1163     "v0",  "v1",  "v2",  "v3",  "v4", 
1164     "v5",  "v6",  "v7",  "v8",  "v9", 
1165     "v10", "v11", "v12", "v13", "v14", 
1166     "v15", "v16", "v17", "v18", "v19", 
1167     "v20", "v21", "v22", "v23", "v24", 
1168     "v25", "v26", "v27", "v28", "v29",
1169     "v30", "v31"
1170 };
1171
1172 static const char * const  qRegNames[] =
1173 {
1174     "q0",  "q1",  "q2",  "q3",  "q4", 
1175     "q5",  "q6",  "q7",  "q8",  "q9", 
1176     "q10", "q11", "q12", "q13", "q14", 
1177     "q15", "q16", "q17", "q18", "q19", 
1178     "q20", "q21", "q22", "q23", "q24", 
1179     "q25", "q26", "q27", "q28", "q29",
1180     "q30", "q31"
1181 };
1182
1183 static const char * const  hRegNames[] =
1184 {
1185     "h0",  "h1",  "h2",  "h3",  "h4", 
1186     "h5",  "h6",  "h7",  "h8",  "h9", 
1187     "h10", "h11", "h12", "h13", "h14", 
1188     "h15", "h16", "h17", "h18", "h19", 
1189     "h20", "h21", "h22", "h23", "h24", 
1190     "h25", "h26", "h27", "h28", "h29",
1191     "h30", "h31"
1192 };
1193 static const char * const  bRegNames[] =
1194 {
1195     "b0",  "b1",  "b2",  "b3",  "b4", 
1196     "b5",  "b6",  "b7",  "b8",  "b9", 
1197     "b10", "b11", "b12", "b13", "b14", 
1198     "b15", "b16", "b17", "b18", "b19", 
1199     "b20", "b21", "b22", "b23", "b24", 
1200     "b25", "b26", "b27", "b28", "b29",
1201     "b30", "b31"
1202 };
1203 // clang-format on
1204
1205 /*****************************************************************************
1206  *
1207  *  Return a string that represents the given register.
1208  */
1209
1210 const char* emitter::emitRegName(regNumber reg, emitAttr size, bool varName)
1211 {
1212     assert(reg < REG_COUNT);
1213
1214     const char* rn = nullptr;
1215
1216     if (size == EA_8BYTE)
1217     {
1218         rn = xRegNames[reg];
1219     }
1220     else if (size == EA_4BYTE)
1221     {
1222         rn = wRegNames[reg];
1223     }
1224     else if (isVectorRegister(reg))
1225     {
1226         if (size == EA_16BYTE)
1227         {
1228             rn = qRegNames[reg - REG_V0];
1229         }
1230         else if (size == EA_2BYTE)
1231         {
1232             rn = hRegNames[reg - REG_V0];
1233         }
1234         else if (size == EA_1BYTE)
1235         {
1236             rn = bRegNames[reg - REG_V0];
1237         }
1238     }
1239
1240     assert(rn != nullptr);
1241
1242     return rn;
1243 }
1244
1245 /*****************************************************************************
1246  *
1247  *  Return a string that represents the given register.
1248  */
1249
1250 const char* emitter::emitVectorRegName(regNumber reg)
1251 {
1252     assert((reg >= REG_V0) && (reg <= REG_V31));
1253
1254     int index = (int)reg - (int)REG_V0;
1255
1256     return vRegNames[index];
1257 }
1258 #endif // DEBUG
1259
1260 /*****************************************************************************
1261  *
1262  *  Returns the base encoding of the given CPU instruction.
1263  */
1264
1265 emitter::insFormat emitter::emitInsFormat(instruction ins)
1266 {
1267     // clang-format off
1268     const static insFormat insFormats[] =
1269     {
1270         #define INST1(id, nm, fp, ldst, fmt, e1                                ) fmt,
1271         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            ) fmt,
1272         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        ) fmt,
1273         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    ) fmt,
1274         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                ) fmt,
1275         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            ) fmt,
1276         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) fmt,
1277         #include "instrs.h"
1278     };
1279     // clang-format on
1280
1281     assert(ins < ArrLen(insFormats));
1282     assert((insFormats[ins] != IF_NONE));
1283
1284     return insFormats[ins];
1285 }
1286
1287 // INST_FP is 1
1288 #define LD 2
1289 #define ST 4
1290 #define CMP 8
1291
1292 // clang-format off
1293 /*static*/ const BYTE CodeGenInterface::instInfo[] =
1294 {
1295     #define INST1(id, nm, fp, ldst, fmt, e1                                ) ldst | INST_FP*fp,
1296     #define INST2(id, nm, fp, ldst, fmt, e1, e2                            ) ldst | INST_FP*fp,
1297     #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        ) ldst | INST_FP*fp,
1298     #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    ) ldst | INST_FP*fp,
1299     #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                ) ldst | INST_FP*fp,
1300     #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            ) ldst | INST_FP*fp,
1301     #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) ldst | INST_FP*fp,
1302     #include "instrs.h"
1303 };
1304 // clang-format on
1305
1306 /*****************************************************************************
1307  *
1308  *  Returns true if the instruction is some kind of compare or test instruction
1309  */
1310
1311 bool emitter::emitInsIsCompare(instruction ins)
1312 {
1313     // We have pseudo ins like lea which are not included in emitInsLdStTab.
1314     if (ins < ArrLen(CodeGenInterface::instInfo))
1315         return (CodeGenInterface::instInfo[ins] & CMP) ? true : false;
1316     else
1317         return false;
1318 }
1319
1320 /*****************************************************************************
1321  *
1322  *  Returns true if the instruction is some kind of load instruction
1323  */
1324
1325 bool emitter::emitInsIsLoad(instruction ins)
1326 {
1327     // We have pseudo ins like lea which are not included in emitInsLdStTab.
1328     if (ins < ArrLen(CodeGenInterface::instInfo))
1329         return (CodeGenInterface::instInfo[ins] & LD) ? true : false;
1330     else
1331         return false;
1332 }
1333 /*****************************************************************************
1334  *
1335  *  Returns true if the instruction is some kind of store instruction
1336  */
1337
1338 bool emitter::emitInsIsStore(instruction ins)
1339 {
1340     // We have pseudo ins like lea which are not included in emitInsLdStTab.
1341     if (ins < ArrLen(CodeGenInterface::instInfo))
1342         return (CodeGenInterface::instInfo[ins] & ST) ? true : false;
1343     else
1344         return false;
1345 }
1346
1347 /*****************************************************************************
1348  *
1349  *  Returns true if the instruction is some kind of load/store instruction
1350  */
1351
1352 bool emitter::emitInsIsLoadOrStore(instruction ins)
1353 {
1354     // We have pseudo ins like lea which are not included in emitInsLdStTab.
1355     if (ins < ArrLen(CodeGenInterface::instInfo))
1356         return (CodeGenInterface::instInfo[ins] & (LD | ST)) ? true : false;
1357     else
1358         return false;
1359 }
1360
1361 #undef LD
1362 #undef ST
1363 #undef CMP
1364
1365 /*****************************************************************************
1366  *
1367  *  Returns the specific encoding of the given CPU instruction and format
1368  */
1369
1370 emitter::code_t emitter::emitInsCode(instruction ins, insFormat fmt)
1371 {
1372     // clang-format off
1373     const static code_t insCodes1[] =
1374     {
1375         #define INST1(id, nm, fp, ldst, fmt, e1                                ) e1,
1376         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            ) e1,
1377         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        ) e1,
1378         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    ) e1,
1379         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                ) e1,
1380         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            ) e1,
1381         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e1,
1382         #include "instrs.h"
1383     };
1384     const static code_t insCodes2[] =
1385     {
1386         #define INST1(id, nm, fp, ldst, fmt, e1                                )
1387         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            ) e2,
1388         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        ) e2,
1389         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    ) e2,
1390         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                ) e2,
1391         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            ) e2,
1392         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e2,
1393         #include "instrs.h"
1394     };
1395     const static code_t insCodes3[] =
1396     {
1397         #define INST1(id, nm, fp, ldst, fmt, e1                                )
1398         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            )
1399         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        ) e3,
1400         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    ) e3,
1401         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                ) e3,
1402         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            ) e3,
1403         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e3,
1404         #include "instrs.h"
1405     };
1406     const static code_t insCodes4[] =
1407     {
1408         #define INST1(id, nm, fp, ldst, fmt, e1                                )
1409         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            )
1410         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        )
1411         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    ) e4,
1412         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                ) e4,
1413         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            ) e4,
1414         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e4,
1415         #include "instrs.h"
1416     };
1417     const static code_t insCodes5[] =
1418     {
1419         #define INST1(id, nm, fp, ldst, fmt, e1                                )
1420         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            )
1421         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        )
1422         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    )
1423         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                ) e5,
1424         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            ) e5,
1425         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e5,
1426         #include "instrs.h"
1427     };
1428     const static code_t insCodes6[] =
1429     {
1430         #define INST1(id, nm, fp, ldst, fmt, e1                                )
1431         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            )
1432         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        )
1433         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    )
1434         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                )
1435         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            ) e6,
1436         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e6,
1437         #include "instrs.h"
1438     };
1439     const static code_t insCodes7[] =
1440     {
1441         #define INST1(id, nm, fp, ldst, fmt, e1                                )
1442         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            )
1443         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        )
1444         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    )
1445         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                )
1446         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            )
1447         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e7,
1448         #include "instrs.h"
1449     };
1450     const static code_t insCodes8[] =
1451     {
1452         #define INST1(id, nm, fp, ldst, fmt, e1                                )
1453         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            )
1454         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        )
1455         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    )
1456         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                )
1457         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            )
1458         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e8,
1459         #include "instrs.h"
1460     };
1461     const static code_t insCodes9[] =
1462     {
1463         #define INST1(id, nm, fp, ldst, fmt, e1                                )
1464         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            )
1465         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        )
1466         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    )
1467         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                )
1468         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            )
1469         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e9,
1470         #include "instrs.h"
1471     };
1472     // clang-format on
1473
1474     const static insFormat formatEncode9[9] = {IF_DR_2E, IF_DR_2G, IF_DI_1B, IF_DI_1D, IF_DV_3C,
1475                                                IF_DV_2B, IF_DV_2C, IF_DV_2E, IF_DV_2F};
1476     const static insFormat formatEncode6A[6] = {IF_DR_3A, IF_DR_3B, IF_DR_3C, IF_DI_2A, IF_DV_3A, IF_DV_3E};
1477     const static insFormat formatEncode5A[5] = {IF_LS_2A, IF_LS_2B, IF_LS_2C, IF_LS_3A, IF_LS_1A};
1478     const static insFormat formatEncode5B[5] = {IF_DV_2G, IF_DV_2H, IF_DV_2I, IF_DV_1A, IF_DV_1B};
1479     const static insFormat formatEncode5C[5] = {IF_DR_3A, IF_DR_3B, IF_DI_2C, IF_DV_3C, IF_DV_1B};
1480     const static insFormat formatEncode4A[4] = {IF_LS_2A, IF_LS_2B, IF_LS_2C, IF_LS_3A};
1481     const static insFormat formatEncode4B[4] = {IF_DR_3A, IF_DR_3B, IF_DR_3C, IF_DI_2A};
1482     const static insFormat formatEncode4C[4] = {IF_DR_2A, IF_DR_2B, IF_DR_2C, IF_DI_1A};
1483     const static insFormat formatEncode4D[4] = {IF_DV_3B, IF_DV_3D, IF_DV_3BI, IF_DV_3DI};
1484     const static insFormat formatEncode4E[4] = {IF_DR_3A, IF_DR_3B, IF_DI_2C, IF_DV_3C};
1485     const static insFormat formatEncode4F[4] = {IF_DR_3A, IF_DR_3B, IF_DV_3C, IF_DV_1B};
1486     const static insFormat formatEncode4G[4] = {IF_DR_2E, IF_DR_2F, IF_DV_2M, IF_DV_2L};
1487     const static insFormat formatEncode4H[4] = {IF_DV_3E, IF_DV_3A, IF_DV_2L, IF_DV_2M};
1488     const static insFormat formatEncode4I[4] = {IF_DV_3D, IF_DV_3B, IF_DV_2G, IF_DV_2A};
1489     const static insFormat formatEncode3A[3] = {IF_DR_3A, IF_DR_3B, IF_DI_2C};
1490     const static insFormat formatEncode3B[3] = {IF_DR_2A, IF_DR_2B, IF_DI_1C};
1491     const static insFormat formatEncode3C[3] = {IF_DR_3A, IF_DR_3B, IF_DV_3C};
1492     const static insFormat formatEncode3D[3] = {IF_DV_2C, IF_DV_2D, IF_DV_2E};
1493     const static insFormat formatEncode3E[3] = {IF_DV_3B, IF_DV_3BI, IF_DV_3DI};
1494     const static insFormat formatEncode3F[3] = {IF_DV_2A, IF_DV_2G, IF_DV_2H};
1495     const static insFormat formatEncode3G[3] = {IF_DV_2A, IF_DV_2G, IF_DV_2I};
1496     const static insFormat formatEncode3H[3] = {IF_DR_3A, IF_DV_3A, IF_DV_3AI};
1497     const static insFormat formatEncode3I[3] = {IF_DR_2E, IF_DR_2F, IF_DV_2M};
1498     const static insFormat formatEncode2A[2] = {IF_DR_2E, IF_DR_2F};
1499     const static insFormat formatEncode2B[2] = {IF_DR_3A, IF_DR_3B};
1500     const static insFormat formatEncode2C[2] = {IF_DR_3A, IF_DI_2D};
1501     const static insFormat formatEncode2D[2] = {IF_DR_3A, IF_DI_2B};
1502     const static insFormat formatEncode2E[2] = {IF_LS_3B, IF_LS_3C};
1503     const static insFormat formatEncode2F[2] = {IF_DR_2I, IF_DI_1F};
1504     const static insFormat formatEncode2G[2] = {IF_DV_3B, IF_DV_3D};
1505     const static insFormat formatEncode2H[2] = {IF_DV_2C, IF_DV_2F};
1506     const static insFormat formatEncode2I[2] = {IF_DV_2K, IF_DV_1C};
1507     const static insFormat formatEncode2J[2] = {IF_DV_2A, IF_DV_2G};
1508     const static insFormat formatEncode2K[2] = {IF_DV_2M, IF_DV_2L};
1509     const static insFormat formatEncode2L[2] = {IF_DR_2G, IF_DV_2M};
1510     const static insFormat formatEncode2M[2] = {IF_DV_3A, IF_DV_3AI};
1511     const static insFormat formatEncode2N[2] = {IF_DV_2N, IF_DV_2O};
1512     const static insFormat formatEncode2O[2] = {IF_DV_3E, IF_DV_3A};
1513     const static insFormat formatEncode2P[2] = {IF_DV_2G, IF_DV_3B};
1514
1515     code_t    code           = BAD_CODE;
1516     insFormat insFmt         = emitInsFormat(ins);
1517     bool      encoding_found = false;
1518     int       index          = -1;
1519
1520     switch (insFmt)
1521     {
1522         case IF_EN9:
1523             for (index = 0; index < 9; index++)
1524             {
1525                 if (fmt == formatEncode9[index])
1526                 {
1527                     encoding_found = true;
1528                     break;
1529                 }
1530             }
1531             break;
1532
1533         case IF_EN6A:
1534             for (index = 0; index < 6; index++)
1535             {
1536                 if (fmt == formatEncode6A[index])
1537                 {
1538                     encoding_found = true;
1539                     break;
1540                 }
1541             }
1542             break;
1543
1544         case IF_EN5A:
1545             for (index = 0; index < 5; index++)
1546             {
1547                 if (fmt == formatEncode5A[index])
1548                 {
1549                     encoding_found = true;
1550                     break;
1551                 }
1552             }
1553             break;
1554
1555         case IF_EN5B:
1556             for (index = 0; index < 5; index++)
1557             {
1558                 if (fmt == formatEncode5B[index])
1559                 {
1560                     encoding_found = true;
1561                     break;
1562                 }
1563             }
1564             break;
1565
1566         case IF_EN5C:
1567             for (index = 0; index < 5; index++)
1568             {
1569                 if (fmt == formatEncode5C[index])
1570                 {
1571                     encoding_found = true;
1572                     break;
1573                 }
1574             }
1575             break;
1576
1577         case IF_EN4A:
1578             for (index = 0; index < 4; index++)
1579             {
1580                 if (fmt == formatEncode4A[index])
1581                 {
1582                     encoding_found = true;
1583                     break;
1584                 }
1585             }
1586             break;
1587
1588         case IF_EN4B:
1589             for (index = 0; index < 4; index++)
1590             {
1591                 if (fmt == formatEncode4B[index])
1592                 {
1593                     encoding_found = true;
1594                     break;
1595                 }
1596             }
1597             break;
1598
1599         case IF_EN4C:
1600             for (index = 0; index < 4; index++)
1601             {
1602                 if (fmt == formatEncode4C[index])
1603                 {
1604                     encoding_found = true;
1605                     break;
1606                 }
1607             }
1608             break;
1609
1610         case IF_EN4D:
1611             for (index = 0; index < 4; index++)
1612             {
1613                 if (fmt == formatEncode4D[index])
1614                 {
1615                     encoding_found = true;
1616                     break;
1617                 }
1618             }
1619             break;
1620
1621         case IF_EN4E:
1622             for (index = 0; index < 4; index++)
1623             {
1624                 if (fmt == formatEncode4E[index])
1625                 {
1626                     encoding_found = true;
1627                     break;
1628                 }
1629             }
1630             break;
1631
1632         case IF_EN4F:
1633             for (index = 0; index < 4; index++)
1634             {
1635                 if (fmt == formatEncode4F[index])
1636                 {
1637                     encoding_found = true;
1638                     break;
1639                 }
1640             }
1641             break;
1642
1643         case IF_EN4G:
1644             for (index = 0; index < 4; index++)
1645             {
1646                 if (fmt == formatEncode4G[index])
1647                 {
1648                     encoding_found = true;
1649                     break;
1650                 }
1651             }
1652             break;
1653
1654         case IF_EN4H:
1655             for (index = 0; index < 4; index++)
1656             {
1657                 if (fmt == formatEncode4H[index])
1658                 {
1659                     encoding_found = true;
1660                     break;
1661                 }
1662             }
1663             break;
1664
1665         case IF_EN4I:
1666             for (index = 0; index < 4; index++)
1667             {
1668                 if (fmt == formatEncode4I[index])
1669                 {
1670                     encoding_found = true;
1671                     break;
1672                 }
1673             }
1674             break;
1675
1676         case IF_EN3A:
1677             for (index = 0; index < 3; index++)
1678             {
1679                 if (fmt == formatEncode3A[index])
1680                 {
1681                     encoding_found = true;
1682                     break;
1683                 }
1684             }
1685             break;
1686
1687         case IF_EN3B:
1688             for (index = 0; index < 3; index++)
1689             {
1690                 if (fmt == formatEncode3B[index])
1691                 {
1692                     encoding_found = true;
1693                     break;
1694                 }
1695             }
1696             break;
1697
1698         case IF_EN3C:
1699             for (index = 0; index < 3; index++)
1700             {
1701                 if (fmt == formatEncode3C[index])
1702                 {
1703                     encoding_found = true;
1704                     break;
1705                 }
1706             }
1707             break;
1708
1709         case IF_EN3D:
1710             for (index = 0; index < 3; index++)
1711             {
1712                 if (fmt == formatEncode3D[index])
1713                 {
1714                     encoding_found = true;
1715                     break;
1716                 }
1717             }
1718             break;
1719
1720         case IF_EN3E:
1721             for (index = 0; index < 3; index++)
1722             {
1723                 if (fmt == formatEncode3E[index])
1724                 {
1725                     encoding_found = true;
1726                     break;
1727                 }
1728             }
1729             break;
1730
1731         case IF_EN3F:
1732             for (index = 0; index < 3; index++)
1733             {
1734                 if (fmt == formatEncode3F[index])
1735                 {
1736                     encoding_found = true;
1737                     break;
1738                 }
1739             }
1740             break;
1741
1742         case IF_EN3G:
1743             for (index = 0; index < 3; index++)
1744             {
1745                 if (fmt == formatEncode3G[index])
1746                 {
1747                     encoding_found = true;
1748                     break;
1749                 }
1750             }
1751             break;
1752
1753         case IF_EN3H:
1754             for (index = 0; index < 3; index++)
1755             {
1756                 if (fmt == formatEncode3H[index])
1757                 {
1758                     encoding_found = true;
1759                     break;
1760                 }
1761             }
1762             break;
1763
1764         case IF_EN3I:
1765             for (index = 0; index < 3; index++)
1766             {
1767                 if (fmt == formatEncode3I[index])
1768                 {
1769                     encoding_found = true;
1770                     break;
1771                 }
1772             }
1773             break;
1774
1775         case IF_EN2A:
1776             for (index = 0; index < 2; index++)
1777             {
1778                 if (fmt == formatEncode2A[index])
1779                 {
1780                     encoding_found = true;
1781                     break;
1782                 }
1783             }
1784             break;
1785
1786         case IF_EN2B:
1787             for (index = 0; index < 2; index++)
1788             {
1789                 if (fmt == formatEncode2B[index])
1790                 {
1791                     encoding_found = true;
1792                     break;
1793                 }
1794             }
1795             break;
1796
1797         case IF_EN2C:
1798             for (index = 0; index < 2; index++)
1799             {
1800                 if (fmt == formatEncode2C[index])
1801                 {
1802                     encoding_found = true;
1803                     break;
1804                 }
1805             }
1806             break;
1807
1808         case IF_EN2D:
1809             for (index = 0; index < 2; index++)
1810             {
1811                 if (fmt == formatEncode2D[index])
1812                 {
1813                     encoding_found = true;
1814                     break;
1815                 }
1816             }
1817             break;
1818
1819         case IF_EN2E:
1820             for (index = 0; index < 2; index++)
1821             {
1822                 if (fmt == formatEncode2E[index])
1823                 {
1824                     encoding_found = true;
1825                     break;
1826                 }
1827             }
1828             break;
1829
1830         case IF_EN2F:
1831             for (index = 0; index < 2; index++)
1832             {
1833                 if (fmt == formatEncode2F[index])
1834                 {
1835                     encoding_found = true;
1836                     break;
1837                 }
1838             }
1839             break;
1840
1841         case IF_EN2G:
1842             for (index = 0; index < 2; index++)
1843             {
1844                 if (fmt == formatEncode2G[index])
1845                 {
1846                     encoding_found = true;
1847                     break;
1848                 }
1849             }
1850             break;
1851
1852         case IF_EN2H:
1853             for (index = 0; index < 2; index++)
1854             {
1855                 if (fmt == formatEncode2H[index])
1856                 {
1857                     encoding_found = true;
1858                     break;
1859                 }
1860             }
1861             break;
1862
1863         case IF_EN2I:
1864             for (index = 0; index < 2; index++)
1865             {
1866                 if (fmt == formatEncode2I[index])
1867                 {
1868                     encoding_found = true;
1869                     break;
1870                 }
1871             }
1872             break;
1873
1874         case IF_EN2J:
1875             for (index = 0; index < 2; index++)
1876             {
1877                 if (fmt == formatEncode2J[index])
1878                 {
1879                     encoding_found = true;
1880                     break;
1881                 }
1882             }
1883             break;
1884
1885         case IF_EN2K:
1886             for (index = 0; index < 2; index++)
1887             {
1888                 if (fmt == formatEncode2K[index])
1889                 {
1890                     encoding_found = true;
1891                     break;
1892                 }
1893             }
1894             break;
1895
1896         case IF_EN2L:
1897             for (index = 0; index < 2; index++)
1898             {
1899                 if (fmt == formatEncode2L[index])
1900                 {
1901                     encoding_found = true;
1902                     break;
1903                 }
1904             }
1905             break;
1906
1907         case IF_EN2M:
1908             for (index = 0; index < 2; index++)
1909             {
1910                 if (fmt == formatEncode2M[index])
1911                 {
1912                     encoding_found = true;
1913                     break;
1914                 }
1915             }
1916             break;
1917
1918         case IF_EN2N:
1919             for (index = 0; index < 2; index++)
1920             {
1921                 if (fmt == formatEncode2N[index])
1922                 {
1923                     encoding_found = true;
1924                     break;
1925                 }
1926             }
1927             break;
1928
1929         case IF_EN2O:
1930             for (index = 0; index < 2; index++)
1931             {
1932                 if (fmt == formatEncode2O[index])
1933                 {
1934                     encoding_found = true;
1935                     break;
1936                 }
1937             }
1938             break;
1939
1940         case IF_EN2P:
1941             for (index = 0; index < 2; index++)
1942             {
1943                 if (fmt == formatEncode2P[index])
1944                 {
1945                     encoding_found = true;
1946                     break;
1947                 }
1948             }
1949             break;
1950
1951         case IF_BI_0A:
1952         case IF_BI_0B:
1953         case IF_BI_0C:
1954         case IF_BI_1A:
1955         case IF_BI_1B:
1956         case IF_BR_1A:
1957         case IF_BR_1B:
1958         case IF_LS_1A:
1959         case IF_LS_2A:
1960         case IF_LS_2B:
1961         case IF_LS_2C:
1962         case IF_LS_3A:
1963         case IF_LS_3B:
1964         case IF_LS_3C:
1965         case IF_LS_3D:
1966         case IF_LS_3E:
1967         case IF_DI_1A:
1968         case IF_DI_1B:
1969         case IF_DI_1C:
1970         case IF_DI_1D:
1971         case IF_DI_1E:
1972         case IF_DI_1F:
1973         case IF_DI_2A:
1974         case IF_DI_2B:
1975         case IF_DI_2C:
1976         case IF_DI_2D:
1977         case IF_DR_1D:
1978         case IF_DR_2A:
1979         case IF_DR_2B:
1980         case IF_DR_2C:
1981         case IF_DR_2D:
1982         case IF_DR_2E:
1983         case IF_DR_2F:
1984         case IF_DR_2G:
1985         case IF_DR_2H:
1986         case IF_DR_2I:
1987         case IF_DR_2J:
1988         case IF_DR_3A:
1989         case IF_DR_3B:
1990         case IF_DR_3C:
1991         case IF_DR_3D:
1992         case IF_DR_3E:
1993         case IF_DR_4A:
1994         case IF_DV_1A:
1995         case IF_DV_1B:
1996         case IF_DV_1C:
1997         case IF_DV_2A:
1998         case IF_DV_2B:
1999         case IF_DV_2C:
2000         case IF_DV_2D:
2001         case IF_DV_2E:
2002         case IF_DV_2F:
2003         case IF_DV_2G:
2004         case IF_DV_2H:
2005         case IF_DV_2I:
2006         case IF_DV_2J:
2007         case IF_DV_2K:
2008         case IF_DV_2L:
2009         case IF_DV_2M:
2010         case IF_DV_2N:
2011         case IF_DV_2O:
2012         case IF_DV_2P:
2013         case IF_DV_3A:
2014         case IF_DV_3AI:
2015         case IF_DV_3B:
2016         case IF_DV_3BI:
2017         case IF_DV_3C:
2018         case IF_DV_3D:
2019         case IF_DV_3DI:
2020         case IF_DV_3E:
2021         case IF_DV_3F:
2022         case IF_DV_4A:
2023         case IF_SN_0A:
2024         case IF_SI_0A:
2025         case IF_SI_0B:
2026
2027             index          = 0;
2028             encoding_found = true;
2029             break;
2030
2031         default:
2032
2033             encoding_found = false;
2034             break;
2035     }
2036
2037     assert(encoding_found);
2038
2039     switch (index)
2040     {
2041         case 0:
2042             assert(ins < ArrLen(insCodes1));
2043             code = insCodes1[ins];
2044             break;
2045         case 1:
2046             assert(ins < ArrLen(insCodes2));
2047             code = insCodes2[ins];
2048             break;
2049         case 2:
2050             assert(ins < ArrLen(insCodes3));
2051             code = insCodes3[ins];
2052             break;
2053         case 3:
2054             assert(ins < ArrLen(insCodes4));
2055             code = insCodes4[ins];
2056             break;
2057         case 4:
2058             assert(ins < ArrLen(insCodes5));
2059             code = insCodes5[ins];
2060             break;
2061         case 5:
2062             assert(ins < ArrLen(insCodes6));
2063             code = insCodes6[ins];
2064             break;
2065         case 6:
2066             assert(ins < ArrLen(insCodes7));
2067             code = insCodes7[ins];
2068             break;
2069         case 7:
2070             assert(ins < ArrLen(insCodes8));
2071             code = insCodes8[ins];
2072             break;
2073         case 8:
2074             assert(ins < ArrLen(insCodes9));
2075             code = insCodes9[ins];
2076             break;
2077     }
2078
2079     assert((code != BAD_CODE));
2080
2081     return code;
2082 }
2083
2084 // true if this 'imm' can be encoded as a input operand to a mov instruction
2085 /*static*/ bool emitter::emitIns_valid_imm_for_mov(INT64 imm, emitAttr size)
2086 {
2087     // Check for "MOV (wide immediate)".
2088     if (canEncodeHalfwordImm(imm, size))
2089         return true;
2090
2091     // Next try the ones-complement form of 'halfword immediate' imm(i16,hw),
2092     // namely "MOV (inverted wide immediate)".
2093     ssize_t notOfImm = NOT_helper(imm, getBitWidth(size));
2094     if (canEncodeHalfwordImm(notOfImm, size))
2095         return true;
2096
2097     // Finally try "MOV (bitmask immediate)" imm(N,r,s)
2098     if (canEncodeBitMaskImm(imm, size))
2099         return true;
2100
2101     return false;
2102 }
2103
2104 // true if this 'imm' can be encoded as a input operand to a vector movi instruction
2105 /*static*/ bool emitter::emitIns_valid_imm_for_movi(INT64 imm, emitAttr elemsize)
2106 {
2107     if (elemsize == EA_8BYTE)
2108     {
2109         UINT64 uimm = imm;
2110         while (uimm != 0)
2111         {
2112             INT64 loByte = uimm & 0xFF;
2113             if ((loByte == 0) || (loByte == 0xFF))
2114             {
2115                 uimm >>= 8;
2116             }
2117             else
2118             {
2119                 return false;
2120             }
2121         }
2122         assert(uimm == 0);
2123         return true;
2124     }
2125     else
2126     {
2127         // First try the standard 'byteShifted immediate' imm(i8,bySh)
2128         if (canEncodeByteShiftedImm(imm, elemsize, true))
2129             return true;
2130
2131         // Next try the ones-complement form of the 'immediate' imm(i8,bySh)
2132         ssize_t notOfImm = NOT_helper(imm, getBitWidth(elemsize));
2133         if (canEncodeByteShiftedImm(notOfImm, elemsize, true))
2134             return true;
2135     }
2136     return false;
2137 }
2138
2139 // true if this 'imm' can be encoded as a input operand to a fmov instruction
2140 /*static*/ bool emitter::emitIns_valid_imm_for_fmov(double immDbl)
2141 {
2142     if (canEncodeFloatImm8(immDbl))
2143         return true;
2144
2145     return false;
2146 }
2147
2148 // true if this 'imm' can be encoded as a input operand to an add instruction
2149 /*static*/ bool emitter::emitIns_valid_imm_for_add(INT64 imm, emitAttr size)
2150 {
2151     if (unsigned_abs(imm) <= 0x0fff)
2152         return true;
2153     else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
2154         return true;
2155
2156     return false;
2157 }
2158
2159 // true if this 'imm' can be encoded as a input operand to an non-add/sub alu instruction
2160 /*static*/ bool emitter::emitIns_valid_imm_for_cmp(INT64 imm, emitAttr size)
2161 {
2162     return emitIns_valid_imm_for_add(imm, size);
2163 }
2164
2165 // true if this 'imm' can be encoded as a input operand to an non-add/sub alu instruction
2166 /*static*/ bool emitter::emitIns_valid_imm_for_alu(INT64 imm, emitAttr size)
2167 {
2168     if (canEncodeBitMaskImm(imm, size))
2169         return true;
2170
2171     return false;
2172 }
2173
2174 // true if this 'imm' can be encoded as the offset in a ldr/str instruction
2175 /*static*/ bool emitter::emitIns_valid_imm_for_ldst_offset(INT64 imm, emitAttr attr)
2176 {
2177     if (imm == 0)
2178         return true; // Encodable using IF_LS_2A
2179
2180     if ((imm >= -256) && (imm <= 255))
2181         return true; // Encodable using IF_LS_2C (or possibly IF_LS_2B)
2182
2183     if (imm < 0)
2184         return false; // not encodable
2185
2186     emitAttr size  = EA_SIZE(attr);
2187     unsigned scale = NaturalScale_helper(size);
2188     ssize_t  mask  = size - 1; // the mask of low bits that must be zero to encode the immediate
2189
2190     if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
2191         return true; // Encodable using IF_LS_2B
2192
2193     return false; // not encodable
2194 }
2195
2196 /************************************************************************
2197  *
2198  *   A helper method to return the natural scale for an EA 'size'
2199  */
2200
2201 /*static*/ unsigned emitter::NaturalScale_helper(emitAttr size)
2202 {
2203     assert(size == EA_1BYTE || size == EA_2BYTE || size == EA_4BYTE || size == EA_8BYTE || size == EA_16BYTE);
2204
2205     unsigned result = 0;
2206     unsigned utemp  = (unsigned)size;
2207
2208     // Compute log base 2 of utemp (aka 'size')
2209     while (utemp > 1)
2210     {
2211         result++;
2212         utemp >>= 1;
2213     }
2214
2215     return result;
2216 }
2217
2218 /************************************************************************
2219  *
2220  *  A helper method to perform a Rotate-Right shift operation
2221  *  the source is 'value' and it is rotated right by 'sh' bits
2222  *  'value' is considered to be a fixed size 'width' set of bits.
2223  *
2224  *  Example
2225  *      value is '00001111', sh is 2 and width is 8
2226  *     result is '11000011'
2227  */
2228
2229 /*static*/ UINT64 emitter::ROR_helper(UINT64 value, unsigned sh, unsigned width)
2230 {
2231     assert(width <= 64);
2232     // Check that 'value' fits in 'width' bits
2233     assert((width == 64) || (value < (1ULL << width)));
2234     // We don't support shifts >= width
2235     assert(sh < width);
2236
2237     UINT64 result;
2238
2239     unsigned rsh = sh;
2240     unsigned lsh = width - rsh;
2241
2242     result = (value >> rsh);
2243     result |= (value << lsh);
2244
2245     if (width < 64)
2246     {
2247         // mask off any extra bits that we got from the left shift
2248         result &= ((1ULL << width) - 1);
2249     }
2250     return result;
2251 }
2252 /************************************************************************
2253  *
2254  *  A helper method to perform a 'NOT' bitwise complement operation.
2255  *  'value' is considered to be a fixed size 'width' set of bits.
2256  *
2257  *  Example
2258  *      value is '01001011', and width is 8
2259  *     result is '10110100'
2260  */
2261
2262 /*static*/ UINT64 emitter::NOT_helper(UINT64 value, unsigned width)
2263 {
2264     assert(width <= 64);
2265
2266     UINT64 result = ~value;
2267
2268     if (width < 64)
2269     {
2270         // Check that 'value' fits in 'width' bits. Don't consider "sign" bits above width.
2271         UINT64 maxVal       = 1ULL << width;
2272         UINT64 lowBitsMask  = maxVal - 1;
2273         UINT64 signBitsMask = ~lowBitsMask | (1ULL << (width - 1)); // The high bits must be set, and the top bit
2274                                                                     // (sign bit) must be set.
2275         assert((value < maxVal) || ((value & signBitsMask) == signBitsMask));
2276
2277         // mask off any extra bits that we got from the complement operation
2278         result &= lowBitsMask;
2279     }
2280
2281     return result;
2282 }
2283
2284 /************************************************************************
2285  *
2286  *  A helper method to perform a bit Replicate operation
2287  *  the source is 'value' with a fixed size 'width' set of bits.
2288  *  value is replicated to fill out 32 or 64 bits as determined by 'size'.
2289  *
2290  *  Example
2291  *      value is '11000011' (0xE3), width is 8 and size is EA_8BYTE
2292  *     result is '11000011 11000011 11000011 11000011 11000011 11000011 11000011 11000011'
2293  *               0xE3E3E3E3E3E3E3E3
2294  */
2295
2296 /*static*/ UINT64 emitter::Replicate_helper(UINT64 value, unsigned width, emitAttr size)
2297 {
2298     assert(emitter::isValidGeneralDatasize(size));
2299
2300     unsigned immWidth = (size == EA_8BYTE) ? 64 : 32;
2301     assert(width <= immWidth);
2302
2303     UINT64   result     = value;
2304     unsigned filledBits = width;
2305
2306     while (filledBits < immWidth)
2307     {
2308         value <<= width;
2309         result |= value;
2310         filledBits += width;
2311     }
2312     return result;
2313 }
2314
2315 /************************************************************************
2316  *
2317  *  Convert an imm(N,r,s) into a 64-bit immediate
2318  *  inputs 'bmImm' a bitMaskImm struct
2319  *         'size' specifies the size of the result (64 or 32 bits)
2320  */
2321
2322 /*static*/ INT64 emitter::emitDecodeBitMaskImm(const emitter::bitMaskImm bmImm, emitAttr size)
2323 {
2324     assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2325
2326     unsigned N = bmImm.immN; // read the N,R and S values from the 'bitMaskImm' encoding
2327     unsigned R = bmImm.immR;
2328     unsigned S = bmImm.immS;
2329
2330     unsigned elemWidth = 64; // used when N == 1
2331
2332     if (N == 0) // find the smaller elemWidth when N == 0
2333     {
2334         // Scan S for the highest bit not set
2335         elemWidth = 32;
2336         for (unsigned bitNum = 5; bitNum > 0; bitNum--)
2337         {
2338             unsigned oneBit = elemWidth;
2339             if ((S & oneBit) == 0)
2340                 break;
2341             elemWidth /= 2;
2342         }
2343     }
2344     else
2345     {
2346         assert(size == EA_8BYTE);
2347     }
2348
2349     unsigned maskSR = elemWidth - 1;
2350
2351     S &= maskSR;
2352     R &= maskSR;
2353
2354     // encoding for S is one less than the number of consecutive one bits
2355     S++; // Number of consecutive ones to generate in 'welem'
2356
2357     // At this point:
2358     //
2359     //    'elemWidth' is the number of bits that we will use for the ROR and Replicate operations
2360     //    'S'         is the number of consecutive 1 bits for the immediate
2361     //    'R'         is the number of bits that we will Rotate Right the immediate
2362     //    'size'      selects the final size of the immedate that we return (64 or 32 bits)
2363
2364     assert(S < elemWidth); // 'elemWidth' consecutive one's is a reserved encoding
2365
2366     UINT64 welem;
2367     UINT64 wmask;
2368
2369     welem = (1ULL << S) - 1;
2370
2371     wmask = ROR_helper(welem, R, elemWidth);
2372     wmask = Replicate_helper(wmask, elemWidth, size);
2373
2374     return wmask;
2375 }
2376
2377 /*****************************************************************************
2378  *
2379  *  Check if an immediate can use the left shifted by 12 bits encoding
2380  */
2381
2382 /*static*/ bool emitter::canEncodeWithShiftImmBy12(INT64 imm)
2383 {
2384     if (imm < 0)
2385     {
2386         imm = -imm; // convert to unsigned
2387     }
2388
2389     if (imm < 0)
2390     {
2391         return false; // Must be MIN_INT64
2392     }
2393
2394     if ((imm & 0xfff) != 0) // Now the low 12 bits all have to be zero
2395     {
2396         return false;
2397     }
2398
2399     imm >>= 12; // shift right by 12 bits
2400
2401     return (imm <= 0x0fff); // Does it fit in 12 bits
2402 }
2403
2404 /*****************************************************************************
2405  *
2406  *  Normalize the 'imm' so that the upper bits, as defined by 'size' are zero
2407  */
2408
2409 /*static*/ INT64 emitter::normalizeImm64(INT64 imm, emitAttr size)
2410 {
2411     unsigned immWidth = getBitWidth(size);
2412     INT64    result   = imm;
2413
2414     if (immWidth < 64)
2415     {
2416         // Check that 'imm' fits in 'immWidth' bits. Don't consider "sign" bits above width.
2417         INT64 maxVal      = 1LL << immWidth;
2418         INT64 lowBitsMask = maxVal - 1;
2419         INT64 hiBitsMask  = ~lowBitsMask;
2420         INT64 signBitsMask =
2421             hiBitsMask | (1LL << (immWidth - 1)); // The high bits must be set, and the top bit (sign bit) must be set.
2422         assert((imm < maxVal) || ((imm & signBitsMask) == signBitsMask));
2423
2424         // mask off the hiBits
2425         result &= lowBitsMask;
2426     }
2427     return result;
2428 }
2429
2430 /*****************************************************************************
2431  *
2432  *  Normalize the 'imm' so that the upper bits, as defined by 'size' are zero
2433  */
2434
2435 /*static*/ INT32 emitter::normalizeImm32(INT32 imm, emitAttr size)
2436 {
2437     unsigned immWidth = getBitWidth(size);
2438     INT32    result   = imm;
2439
2440     if (immWidth < 32)
2441     {
2442         // Check that 'imm' fits in 'immWidth' bits. Don't consider "sign" bits above width.
2443         INT32 maxVal       = 1 << immWidth;
2444         INT32 lowBitsMask  = maxVal - 1;
2445         INT32 hiBitsMask   = ~lowBitsMask;
2446         INT32 signBitsMask = hiBitsMask | (1 << (immWidth - 1)); // The high bits must be set, and the top bit
2447                                                                  // (sign bit) must be set.
2448         assert((imm < maxVal) || ((imm & signBitsMask) == signBitsMask));
2449
2450         // mask off the hiBits
2451         result &= lowBitsMask;
2452     }
2453     return result;
2454 }
2455
2456 /************************************************************************
2457  *
2458  *  returns true if 'imm' of 'size bits (32/64) can be encoded
2459  *  using the ARM64 'bitmask immediate' form.
2460  *  When a non-null value is passed for 'wbBMI' then this method
2461  *  writes back the 'N','S' and 'R' values use to encode this immediate
2462  *
2463  */
2464
2465 /*static*/ bool emitter::canEncodeBitMaskImm(INT64 imm, emitAttr size, emitter::bitMaskImm* wbBMI)
2466 {
2467     assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2468
2469     unsigned immWidth = (size == EA_8BYTE) ? 64 : 32;
2470     unsigned maxLen   = (size == EA_8BYTE) ? 6 : 5;
2471
2472     imm = normalizeImm64(imm, size);
2473
2474     // Starting with len=1, elemWidth is 2 bits
2475     //               len=2, elemWidth is 4 bits
2476     //               len=3, elemWidth is 8 bits
2477     //               len=4, elemWidth is 16 bits
2478     //               len=5, elemWidth is 32 bits
2479     // (optionally)  len=6, elemWidth is 64 bits
2480     //
2481     for (unsigned len = 1; (len <= maxLen); len++)
2482     {
2483         unsigned elemWidth = 1 << len;
2484         UINT64   elemMask  = ((UINT64)-1) >> (64 - elemWidth);
2485         UINT64   tempImm   = (UINT64)imm;        // A working copy of 'imm' that we can mutate
2486         UINT64   elemVal   = tempImm & elemMask; // The low 'elemWidth' bits of 'imm'
2487
2488         // Check for all 1's or 0's as these can't be encoded
2489         if ((elemVal == 0) || (elemVal == elemMask))
2490             continue;
2491
2492         // 'checkedBits' is the count of bits that are known to match 'elemVal' when replicated
2493         unsigned checkedBits = elemWidth; // by definition the first 'elemWidth' bits match
2494
2495         // Now check to see if each of the next bits match...
2496         //
2497         while (checkedBits < immWidth)
2498         {
2499             tempImm >>= elemWidth;
2500
2501             UINT64 nextElem = tempImm & elemMask;
2502             if (nextElem != elemVal)
2503             {
2504                 // Not matching, exit this loop and checkedBits will not be equal to immWidth
2505                 break;
2506             }
2507
2508             // The 'nextElem' is matching, so increment 'checkedBits'
2509             checkedBits += elemWidth;
2510         }
2511
2512         // Did the full immediate contain bits that can be formed by repeating 'elemVal'?
2513         if (checkedBits == immWidth)
2514         {
2515             // We are not quite done, since the only values that we can encode as a
2516             // 'bitmask immediate' are those that can be formed by starting with a
2517             // bit string of 0*1* that is rotated by some number of bits.
2518             //
2519             // We check to see if 'elemVal' can be formed using these restrictions.
2520             //
2521             // Observation:
2522             // Rotating by one bit any value that passes these restrictions
2523             // can be xor-ed with the original value and will result it a string
2524             // of bits that have exactly two 1 bits: 'elemRorXor'
2525             // Further the distance between the two one bits tells us the value
2526             // of S and the location of the 1 bits tells us the value of R
2527             //
2528             // Some examples:   (immWidth is 8)
2529             //
2530             // S=4,R=0   S=5,R=3   S=3,R=6
2531             // elemVal:        00001111  11100011  00011100
2532             // elemRor:        10000111  11110001  00001110
2533             // elemRorXor:     10001000  00010010  00010010
2534             //      compute S  45678---  ---5678-  ---3210-
2535             //      compute R  01234567  ---34567  ------67
2536
2537             UINT64 elemRor    = ROR_helper(elemVal, 1, elemWidth); // Rotate 'elemVal' Right by one bit
2538             UINT64 elemRorXor = elemVal ^ elemRor;                 // Xor elemVal and elemRor
2539
2540             // If we only have a two-bit change in elemROR then we can form a mask for this value
2541             unsigned bitCount = 0;
2542             UINT64   oneBit   = 0x1;
2543             unsigned R        = elemWidth; // R is shift count for ROR (rotate right shift)
2544             unsigned S        = 0;         // S is number of consecutive one bits
2545             int      incr     = -1;
2546
2547             // Loop over the 'elemWidth' bits in 'elemRorXor'
2548             //
2549             for (unsigned bitNum = 0; bitNum < elemWidth; bitNum++)
2550             {
2551                 if (incr == -1)
2552                 {
2553                     R--; // We decrement R by one whenever incr is -1
2554                 }
2555                 if (bitCount == 1)
2556                 {
2557                     S += incr; // We incr/decr S, after we find the first one bit in 'elemRorXor'
2558                 }
2559
2560                 // Is this bit position a 1 bit in 'elemRorXor'?
2561                 //
2562                 if (oneBit & elemRorXor)
2563                 {
2564                     bitCount++;
2565                     // Is this the first 1 bit that we found in 'elemRorXor'?
2566                     if (bitCount == 1)
2567                     {
2568                         // Does this 1 bit represent a transition to zero bits?
2569                         bool toZeros = ((oneBit & elemVal) != 0);
2570                         if (toZeros)
2571                         {
2572                             // S :: Count down from elemWidth
2573                             S    = elemWidth;
2574                             incr = -1;
2575                         }
2576                         else // this 1 bit represent a transition to one bits.
2577                         {
2578                             // S :: Count up from zero
2579                             S    = 0;
2580                             incr = +1;
2581                         }
2582                     }
2583                     else // bitCount > 1
2584                     {
2585                         // We found the second (or third...) 1 bit in 'elemRorXor'
2586                         incr = 0; // stop decrementing 'R'
2587
2588                         if (bitCount > 2)
2589                         {
2590                             // More than 2 transitions from 0/1 in 'elemVal'
2591                             // This means that 'elemVal' can't be encoded
2592                             // using a 'bitmask immediate'.
2593                             //
2594                             // Furthermore, it will continue to fail
2595                             // with any larger 'len' that we try.
2596                             // so just return false.
2597                             //
2598                             return false;
2599                         }
2600                     }
2601                 }
2602
2603                 // shift oneBit left by one bit to test the next position
2604                 oneBit <<= 1;
2605             }
2606
2607             // We expect that bitCount will always be two at this point
2608             // but just in case return false for any bad cases.
2609             //
2610             assert(bitCount == 2);
2611             if (bitCount != 2)
2612                 return false;
2613
2614             // Perform some sanity checks on the values of 'S' and 'R'
2615             assert(S > 0);
2616             assert(S < elemWidth);
2617             assert(R < elemWidth);
2618
2619             // Does the caller want us to return the N,R,S encoding values?
2620             //
2621             if (wbBMI != nullptr)
2622             {
2623
2624                 // The encoding used for S is one less than the
2625                 //  number of consecutive one bits
2626                 S--;
2627
2628                 if (len == 6)
2629                 {
2630                     wbBMI->immN = 1;
2631                 }
2632                 else
2633                 {
2634                     wbBMI->immN = 0;
2635                     // The encoding used for 'S' here is a bit peculiar.
2636                     //
2637                     // The upper bits need to be complemented, followed by a zero bit
2638                     // then the value of 'S-1'
2639                     //
2640                     unsigned upperBitsOfS = 64 - (1 << (len + 1));
2641                     S |= upperBitsOfS;
2642                 }
2643                 wbBMI->immR = R;
2644                 wbBMI->immS = S;
2645
2646                 // Verify that what we are returning is correct.
2647                 assert(imm == emitDecodeBitMaskImm(*wbBMI, size));
2648             }
2649             // Tell the caller that we can successfully encode this immediate
2650             // using a 'bitmask immediate'.
2651             //
2652             return true;
2653         }
2654     }
2655     return false;
2656 }
2657
2658 /************************************************************************
2659  *
2660  *  Convert a 64-bit immediate into its 'bitmask immediate' representation imm(N,r,s)
2661  */
2662
2663 /*static*/ emitter::bitMaskImm emitter::emitEncodeBitMaskImm(INT64 imm, emitAttr size)
2664 {
2665     emitter::bitMaskImm result;
2666     result.immNRS = 0;
2667
2668     bool canEncode = canEncodeBitMaskImm(imm, size, &result);
2669     assert(canEncode);
2670
2671     return result;
2672 }
2673
2674 /************************************************************************
2675  *
2676  *  Convert an imm(i16,hw) into a 32/64-bit immediate
2677  *  inputs 'hwImm' a halfwordImm struct
2678  *         'size' specifies the size of the result (64 or 32 bits)
2679  */
2680
2681 /*static*/ INT64 emitter::emitDecodeHalfwordImm(const emitter::halfwordImm hwImm, emitAttr size)
2682 {
2683     assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2684
2685     unsigned hw  = hwImm.immHW;
2686     INT64    val = (INT64)hwImm.immVal;
2687
2688     assert((hw <= 1) || (size == EA_8BYTE));
2689
2690     INT64 result = val << (16 * hw);
2691     return result;
2692 }
2693
2694 /************************************************************************
2695  *
2696  *  returns true if 'imm' of 'size' bits (32/64) can be encoded
2697  *  using the ARM64 'halfword immediate' form.
2698  *  When a non-null value is passed for 'wbHWI' then this method
2699  *  writes back the 'immHW' and 'immVal' values use to encode this immediate
2700  *
2701  */
2702
2703 /*static*/ bool emitter::canEncodeHalfwordImm(INT64 imm, emitAttr size, emitter::halfwordImm* wbHWI)
2704 {
2705     assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2706
2707     unsigned immWidth = (size == EA_8BYTE) ? 64 : 32;
2708     unsigned maxHW    = (size == EA_8BYTE) ? 4 : 2;
2709
2710     // setup immMask to a (EA_4BYTE) 0x00000000_FFFFFFFF or (EA_8BYTE) 0xFFFFFFFF_FFFFFFFF
2711     const UINT64 immMask = ((UINT64)-1) >> (64 - immWidth);
2712     const INT64  mask16  = (INT64)0xFFFF;
2713
2714     imm = normalizeImm64(imm, size);
2715
2716     // Try each of the valid hw shift sizes
2717     for (unsigned hw = 0; (hw < maxHW); hw++)
2718     {
2719         INT64 curMask   = mask16 << (hw * 16); // Represents the mask of the bits in the current halfword
2720         INT64 checkBits = immMask & ~curMask;
2721
2722         // Excluding the current halfword (using ~curMask)
2723         //  does the immediate have zero bits in every other bit that we care about?
2724         //  note we care about all 64-bits for EA_8BYTE
2725         //  and we care about the lowest 32 bits for EA_4BYTE
2726         //
2727         if ((imm & checkBits) == 0)
2728         {
2729             // Does the caller want us to return the imm(i16,hw) encoding values?
2730             //
2731             if (wbHWI != nullptr)
2732             {
2733                 INT64 val     = ((imm & curMask) >> (hw * 16)) & mask16;
2734                 wbHWI->immHW  = hw;
2735                 wbHWI->immVal = val;
2736
2737                 // Verify that what we are returning is correct.
2738                 assert(imm == emitDecodeHalfwordImm(*wbHWI, size));
2739             }
2740             // Tell the caller that we can successfully encode this immediate
2741             // using a 'halfword immediate'.
2742             //
2743             return true;
2744         }
2745     }
2746     return false;
2747 }
2748
2749 /************************************************************************
2750  *
2751  *  Convert a 64-bit immediate into its 'halfword immediate' representation imm(i16,hw)
2752  */
2753
2754 /*static*/ emitter::halfwordImm emitter::emitEncodeHalfwordImm(INT64 imm, emitAttr size)
2755 {
2756     emitter::halfwordImm result;
2757     result.immHWVal = 0;
2758
2759     bool canEncode = canEncodeHalfwordImm(imm, size, &result);
2760     assert(canEncode);
2761
2762     return result;
2763 }
2764
2765 /************************************************************************
2766  *
2767  *  Convert an imm(i8,sh) into a 16/32-bit immediate
2768  *  inputs 'bsImm' a byteShiftedImm struct
2769  *         'size' specifies the size of the result (16 or 32 bits)
2770  */
2771
2772 /*static*/ INT32 emitter::emitDecodeByteShiftedImm(const emitter::byteShiftedImm bsImm, emitAttr size)
2773 {
2774     bool     onesShift = (bsImm.immOnes == 1);
2775     unsigned bySh      = bsImm.immBY;         // Num Bytes to shift 0,1,2,3
2776     INT32    val       = (INT32)bsImm.immVal; // 8-bit immediate
2777     INT32    result    = val;
2778
2779     if (bySh > 0)
2780     {
2781         assert((size == EA_2BYTE) || (size == EA_4BYTE)); // Only EA_2BYTE or EA_4BYTE forms
2782         if (size == EA_2BYTE)
2783         {
2784             assert(bySh < 2);
2785         }
2786         else
2787         {
2788             assert(bySh < 4);
2789         }
2790
2791         result <<= (8 * bySh);
2792
2793         if (onesShift)
2794         {
2795             result |= ((1 << (8 * bySh)) - 1);
2796         }
2797     }
2798     return result;
2799 }
2800
2801 /************************************************************************
2802  *
2803  *  returns true if 'imm' of 'size' bits (16/32) can be encoded
2804  *  using the ARM64 'byteShifted immediate' form.
2805  *  When a non-null value is passed for 'wbBSI' then this method
2806  *  writes back the 'immBY' and 'immVal' values use to encode this immediate
2807  *
2808  */
2809
2810 /*static*/ bool emitter::canEncodeByteShiftedImm(INT64                    imm,
2811                                                  emitAttr                 size,
2812                                                  bool                     allow_MSL,
2813                                                  emitter::byteShiftedImm* wbBSI)
2814 {
2815     bool     canEncode = false;
2816     bool     onesShift = false; // true if we use the shifting ones variant
2817     unsigned bySh      = 0;     // number of bytes to shift: 0, 1, 2, 3
2818     unsigned imm8      = 0;     // immediate to use in the encoding
2819
2820     imm = normalizeImm64(imm, size);
2821
2822     if (size == EA_1BYTE)
2823     {
2824         imm8 = (unsigned)imm;
2825         assert(imm8 < 0x100);
2826         canEncode = true;
2827     }
2828     else if (size == EA_8BYTE)
2829     {
2830         imm8 = (unsigned)imm;
2831         assert(imm8 < 0x100);
2832         canEncode = true;
2833     }
2834     else
2835     {
2836         assert((size == EA_2BYTE) || (size == EA_4BYTE)); // Only EA_2BYTE or EA_4BYTE forms
2837
2838         unsigned immWidth = (size == EA_4BYTE) ? 32 : 16;
2839         unsigned maxBY    = (size == EA_4BYTE) ? 4 : 2;
2840
2841         // setup immMask to a (EA_2BYTE) 0x0000FFFF or (EA_4BYTE) 0xFFFFFFFF
2842         const UINT32 immMask = ((UINT32)-1) >> (32 - immWidth);
2843         const INT32  mask8   = (INT32)0xFF;
2844
2845         // Try each of the valid by shift sizes
2846         for (bySh = 0; (bySh < maxBY); bySh++)
2847         {
2848             INT32 curMask   = mask8 << (bySh * 8); // Represents the mask of the bits in the current byteShifted
2849             INT32 checkBits = immMask & ~curMask;
2850             INT32 immCheck  = (imm & checkBits);
2851
2852             // Excluding the current byte (using ~curMask)
2853             //  does the immediate have zero bits in every other bit that we care about?
2854             //  or can be use the shifted one variant?
2855             //  note we care about all 32-bits for EA_4BYTE
2856             //  and we care about the lowest 16 bits for EA_2BYTE
2857             //
2858             if (immCheck == 0)
2859             {
2860                 canEncode = true;
2861             }
2862             if (allow_MSL)
2863             {
2864                 if ((bySh == 1) && (immCheck == 0xFF))
2865                 {
2866                     canEncode = true;
2867                     onesShift = true;
2868                 }
2869                 else if ((bySh == 2) && (immCheck == 0xFFFF))
2870                 {
2871                     canEncode = true;
2872                     onesShift = true;
2873                 }
2874             }
2875             if (canEncode)
2876             {
2877                 imm8 = (unsigned)(((imm & curMask) >> (bySh * 8)) & mask8);
2878                 break;
2879             }
2880         }
2881     }
2882
2883     if (canEncode)
2884     {
2885         // Does the caller want us to return the imm(i8,bySh) encoding values?
2886         //
2887         if (wbBSI != nullptr)
2888         {
2889             wbBSI->immOnes = onesShift;
2890             wbBSI->immBY   = bySh;
2891             wbBSI->immVal  = imm8;
2892
2893             // Verify that what we are returning is correct.
2894             assert(imm == emitDecodeByteShiftedImm(*wbBSI, size));
2895         }
2896         // Tell the caller that we can successfully encode this immediate
2897         // using a 'byteShifted immediate'.
2898         //
2899         return true;
2900     }
2901     return false;
2902 }
2903
2904 /************************************************************************
2905  *
2906  *  Convert a 32-bit immediate into its 'byteShifted immediate' representation imm(i8,by)
2907  */
2908
2909 /*static*/ emitter::byteShiftedImm emitter::emitEncodeByteShiftedImm(INT64 imm, emitAttr size, bool allow_MSL)
2910 {
2911     emitter::byteShiftedImm result;
2912     result.immBSVal = 0;
2913
2914     bool canEncode = canEncodeByteShiftedImm(imm, size, allow_MSL, &result);
2915     assert(canEncode);
2916
2917     return result;
2918 }
2919
2920 /************************************************************************
2921  *
2922  *  Convert a 'float 8-bit immediate' into a double.
2923  *  inputs 'fpImm' a floatImm8 struct
2924  */
2925
2926 /*static*/ double emitter::emitDecodeFloatImm8(const emitter::floatImm8 fpImm)
2927 {
2928     unsigned sign  = fpImm.immSign;
2929     unsigned exp   = fpImm.immExp ^ 0x4;
2930     unsigned mant  = fpImm.immMant + 16;
2931     unsigned scale = 16 * 8;
2932
2933     while (exp > 0)
2934     {
2935         scale /= 2;
2936         exp--;
2937     }
2938
2939     double result = ((double)mant) / ((double)scale);
2940     if (sign == 1)
2941     {
2942         result = -result;
2943     }
2944
2945     return result;
2946 }
2947
2948 /************************************************************************
2949  *
2950  *  returns true if the 'immDbl' can be encoded using the 'float 8-bit immediate' form.
2951  *  also returns the encoding if wbFPI is non-null
2952  *
2953  */
2954
2955 /*static*/ bool emitter::canEncodeFloatImm8(double immDbl, emitter::floatImm8* wbFPI)
2956 {
2957     bool   canEncode = false;
2958     double val       = immDbl;
2959
2960     int sign = 0;
2961     if (val < 0.0)
2962     {
2963         val  = -val;
2964         sign = 1;
2965     }
2966
2967     int exp = 0;
2968     while ((val < 1.0) && (exp >= -4))
2969     {
2970         val *= 2.0;
2971         exp--;
2972     }
2973     while ((val >= 2.0) && (exp <= 5))
2974     {
2975         val *= 0.5;
2976         exp++;
2977     }
2978     exp += 3;
2979     val *= 16.0;
2980     int ival = (int)val;
2981
2982     if ((exp >= 0) && (exp <= 7))
2983     {
2984         if (val == (double)ival)
2985         {
2986             canEncode = true;
2987
2988             if (wbFPI != nullptr)
2989             {
2990                 ival -= 16;
2991                 assert((ival >= 0) && (ival <= 15));
2992
2993                 wbFPI->immSign = sign;
2994                 wbFPI->immExp  = exp ^ 0x4;
2995                 wbFPI->immMant = ival;
2996                 unsigned imm8  = wbFPI->immFPIVal;
2997                 assert((imm8 >= 0) && (imm8 <= 0xff));
2998             }
2999         }
3000     }
3001
3002     return canEncode;
3003 }
3004
3005 /************************************************************************
3006  *
3007  *  Convert a double into its 'float 8-bit immediate' representation
3008  */
3009
3010 /*static*/ emitter::floatImm8 emitter::emitEncodeFloatImm8(double immDbl)
3011 {
3012     emitter::floatImm8 result;
3013     result.immFPIVal = 0;
3014
3015     bool canEncode = canEncodeFloatImm8(immDbl, &result);
3016     assert(canEncode);
3017
3018     return result;
3019 }
3020
3021 /*****************************************************************************
3022  *
3023  *  For the given 'ins' returns the reverse instruction
3024  *  if one exists, otherwise returns INS_INVALID
3025  */
3026
3027 /*static*/ instruction emitter::insReverse(instruction ins)
3028 {
3029     switch (ins)
3030     {
3031         case INS_add:
3032             return INS_sub;
3033         case INS_adds:
3034             return INS_subs;
3035
3036         case INS_sub:
3037             return INS_add;
3038         case INS_subs:
3039             return INS_adds;
3040
3041         case INS_cmp:
3042             return INS_cmn;
3043         case INS_cmn:
3044             return INS_cmp;
3045
3046         case INS_ccmp:
3047             return INS_ccmn;
3048         case INS_ccmn:
3049             return INS_ccmp;
3050
3051         default:
3052             return INS_invalid;
3053     }
3054 }
3055
3056 /*****************************************************************************
3057  *
3058  *  For the given 'datasize' and 'elemsize', make the proper arrangement option
3059  *  returns the insOpts that specifies the vector register arrangement
3060  *  if one does not exist returns INS_OPTS_NONE
3061  */
3062
3063 /*static*/ insOpts emitter::optMakeArrangement(emitAttr datasize, emitAttr elemsize)
3064 {
3065     insOpts result = INS_OPTS_NONE;
3066
3067     if (datasize == EA_8BYTE)
3068     {
3069         switch (elemsize)
3070         {
3071             case EA_1BYTE:
3072                 result = INS_OPTS_8B;
3073                 break;
3074             case EA_2BYTE:
3075                 result = INS_OPTS_4H;
3076                 break;
3077             case EA_4BYTE:
3078                 result = INS_OPTS_2S;
3079                 break;
3080             case EA_8BYTE:
3081                 result = INS_OPTS_1D;
3082                 break;
3083             default:
3084                 unreached();
3085                 break;
3086         }
3087     }
3088     else if (datasize == EA_16BYTE)
3089     {
3090         switch (elemsize)
3091         {
3092             case EA_1BYTE:
3093                 result = INS_OPTS_16B;
3094                 break;
3095             case EA_2BYTE:
3096                 result = INS_OPTS_8H;
3097                 break;
3098             case EA_4BYTE:
3099                 result = INS_OPTS_4S;
3100                 break;
3101             case EA_8BYTE:
3102                 result = INS_OPTS_2D;
3103                 break;
3104             default:
3105                 unreached();
3106                 break;
3107         }
3108     }
3109     return result;
3110 }
3111
3112 /*****************************************************************************
3113  *
3114  *  For the given 'datasize' and arrangement 'opts'
3115  *  returns true is the pair spcifies a valid arrangement
3116  */
3117 /*static*/ bool emitter::isValidArrangement(emitAttr datasize, insOpts opt)
3118 {
3119     if (datasize == EA_8BYTE)
3120     {
3121         if ((opt == INS_OPTS_8B) || (opt == INS_OPTS_4H) || (opt == INS_OPTS_2S) || (opt == INS_OPTS_1D))
3122         {
3123             return true;
3124         }
3125     }
3126     else if (datasize == EA_16BYTE)
3127     {
3128         if ((opt == INS_OPTS_16B) || (opt == INS_OPTS_8H) || (opt == INS_OPTS_4S) || (opt == INS_OPTS_2D))
3129         {
3130             return true;
3131         }
3132     }
3133     return false;
3134 }
3135
3136 //  For the given 'arrangement' returns the 'datasize' specified by the vector register arrangement
3137 //  asserts and returns EA_UNKNOWN if an invalid 'arrangement' value is passed
3138 //
3139 /*static*/ emitAttr emitter::optGetDatasize(insOpts arrangement)
3140 {
3141     if ((arrangement == INS_OPTS_8B) || (arrangement == INS_OPTS_4H) || (arrangement == INS_OPTS_2S) ||
3142         (arrangement == INS_OPTS_1D))
3143     {
3144         return EA_8BYTE;
3145     }
3146     else if ((arrangement == INS_OPTS_16B) || (arrangement == INS_OPTS_8H) || (arrangement == INS_OPTS_4S) ||
3147              (arrangement == INS_OPTS_2D))
3148     {
3149         return EA_16BYTE;
3150     }
3151     else
3152     {
3153         assert(!" invalid 'arrangement' value");
3154         return EA_UNKNOWN;
3155     }
3156 }
3157
3158 //  For the given 'arrangement' returns the 'elemsize' specified by the vector register arrangement
3159 //  asserts and returns EA_UNKNOWN if an invalid 'arrangement' value is passed
3160 //
3161 /*static*/ emitAttr emitter::optGetElemsize(insOpts arrangement)
3162 {
3163     if ((arrangement == INS_OPTS_8B) || (arrangement == INS_OPTS_16B))
3164     {
3165         return EA_1BYTE;
3166     }
3167     else if ((arrangement == INS_OPTS_4H) || (arrangement == INS_OPTS_8H))
3168     {
3169         return EA_2BYTE;
3170     }
3171     else if ((arrangement == INS_OPTS_2S) || (arrangement == INS_OPTS_4S))
3172     {
3173         return EA_4BYTE;
3174     }
3175     else if ((arrangement == INS_OPTS_1D) || (arrangement == INS_OPTS_2D))
3176     {
3177         return EA_8BYTE;
3178     }
3179     else
3180     {
3181         assert(!" invalid 'arrangement' value");
3182         return EA_UNKNOWN;
3183     }
3184 }
3185
3186 //  For the given 'arrangement' returns the 'widen-arrangement' specified by the vector register arrangement
3187 //  asserts and returns INS_OPTS_NONE if an invalid 'arrangement' value is passed
3188 //
3189 /*static*/ insOpts emitter::optWidenElemsize(insOpts arrangement)
3190 {
3191     if ((arrangement == INS_OPTS_8B) || (arrangement == INS_OPTS_16B))
3192     {
3193         return INS_OPTS_8H;
3194     }
3195     else if ((arrangement == INS_OPTS_4H) || (arrangement == INS_OPTS_8H))
3196     {
3197         return INS_OPTS_4S;
3198     }
3199     else if ((arrangement == INS_OPTS_2S) || (arrangement == INS_OPTS_4S))
3200     {
3201         return INS_OPTS_2D;
3202     }
3203     else
3204     {
3205         assert(!" invalid 'arrangement' value");
3206         return INS_OPTS_NONE;
3207     }
3208 }
3209
3210 //  For the given 'conversion' returns the 'dstsize' specified by the conversion option
3211 /*static*/ emitAttr emitter::optGetDstsize(insOpts conversion)
3212 {
3213     switch (conversion)
3214     {
3215         case INS_OPTS_S_TO_8BYTE:
3216         case INS_OPTS_D_TO_8BYTE:
3217         case INS_OPTS_4BYTE_TO_D:
3218         case INS_OPTS_8BYTE_TO_D:
3219         case INS_OPTS_S_TO_D:
3220         case INS_OPTS_H_TO_D:
3221
3222             return EA_8BYTE;
3223
3224         case INS_OPTS_S_TO_4BYTE:
3225         case INS_OPTS_D_TO_4BYTE:
3226         case INS_OPTS_4BYTE_TO_S:
3227         case INS_OPTS_8BYTE_TO_S:
3228         case INS_OPTS_D_TO_S:
3229         case INS_OPTS_H_TO_S:
3230
3231             return EA_4BYTE;
3232
3233         case INS_OPTS_S_TO_H:
3234         case INS_OPTS_D_TO_H:
3235
3236             return EA_2BYTE;
3237
3238         default:
3239             assert(!" invalid 'conversion' value");
3240             return EA_UNKNOWN;
3241     }
3242 }
3243
3244 //  For the given 'conversion' returns the 'srcsize' specified by the conversion option
3245 /*static*/ emitAttr emitter::optGetSrcsize(insOpts conversion)
3246 {
3247     switch (conversion)
3248     {
3249         case INS_OPTS_D_TO_8BYTE:
3250         case INS_OPTS_D_TO_4BYTE:
3251         case INS_OPTS_8BYTE_TO_D:
3252         case INS_OPTS_8BYTE_TO_S:
3253         case INS_OPTS_D_TO_S:
3254         case INS_OPTS_D_TO_H:
3255
3256             return EA_8BYTE;
3257
3258         case INS_OPTS_S_TO_8BYTE:
3259         case INS_OPTS_S_TO_4BYTE:
3260         case INS_OPTS_4BYTE_TO_S:
3261         case INS_OPTS_4BYTE_TO_D:
3262         case INS_OPTS_S_TO_D:
3263         case INS_OPTS_S_TO_H:
3264
3265             return EA_4BYTE;
3266
3267         case INS_OPTS_H_TO_S:
3268         case INS_OPTS_H_TO_D:
3269
3270             return EA_2BYTE;
3271
3272         default:
3273             assert(!" invalid 'conversion' value");
3274             return EA_UNKNOWN;
3275     }
3276 }
3277
3278 //    For the given 'size' and 'index' returns true if it specifies a valid index for a vector register of 'size'
3279 /*static*/ bool emitter::isValidVectorIndex(emitAttr datasize, emitAttr elemsize, ssize_t index)
3280 {
3281     assert(isValidVectorDatasize(datasize));
3282     assert(isValidVectorElemsize(elemsize));
3283
3284     bool result = false;
3285     if (index >= 0)
3286     {
3287         if (datasize == EA_8BYTE)
3288         {
3289             switch (elemsize)
3290             {
3291                 case EA_1BYTE:
3292                     result = (index < 8);
3293                     break;
3294                 case EA_2BYTE:
3295                     result = (index < 4);
3296                     break;
3297                 case EA_4BYTE:
3298                     result = (index < 2);
3299                     break;
3300                 case EA_8BYTE:
3301                     result = (index < 1);
3302                     break;
3303                 default:
3304                     unreached();
3305                     break;
3306             }
3307         }
3308         else if (datasize == EA_16BYTE)
3309         {
3310             switch (elemsize)
3311             {
3312                 case EA_1BYTE:
3313                     result = (index < 16);
3314                     break;
3315                 case EA_2BYTE:
3316                     result = (index < 8);
3317                     break;
3318                 case EA_4BYTE:
3319                     result = (index < 4);
3320                     break;
3321                 case EA_8BYTE:
3322                     result = (index < 2);
3323                     break;
3324                 default:
3325                     unreached();
3326                     break;
3327             }
3328         }
3329     }
3330     return result;
3331 }
3332
3333 /*****************************************************************************
3334  *
3335  *  Add an instruction with no operands.
3336  */
3337
3338 void emitter::emitIns(instruction ins)
3339 {
3340     instrDesc* id  = emitNewInstrSmall(EA_8BYTE);
3341     insFormat  fmt = emitInsFormat(ins);
3342
3343     assert(fmt == IF_SN_0A);
3344
3345     id->idIns(ins);
3346     id->idInsFmt(fmt);
3347
3348     dispIns(id);
3349     appendToCurIG(id);
3350 }
3351
3352 /*****************************************************************************
3353  *
3354  *  Add an instruction with a single immediate value.
3355  */
3356
3357 void emitter::emitIns_I(instruction ins, emitAttr attr, ssize_t imm)
3358 {
3359     insFormat fmt = IF_NONE;
3360
3361     /* Figure out the encoding format of the instruction */
3362     switch (ins)
3363     {
3364         case INS_brk:
3365             if ((imm & 0x0000ffff) == imm)
3366             {
3367                 fmt = IF_SI_0A;
3368             }
3369             else
3370             {
3371                 assert(!"Instruction cannot be encoded: IF_SI_0A");
3372             }
3373             break;
3374         default:
3375             unreached();
3376             break;
3377     }
3378     assert(fmt != IF_NONE);
3379
3380     instrDesc* id = emitNewInstrSC(attr, imm);
3381
3382     id->idIns(ins);
3383     id->idInsFmt(fmt);
3384
3385     dispIns(id);
3386     appendToCurIG(id);
3387 }
3388
3389 /*****************************************************************************
3390  *
3391  *  Add an instruction referencing a single register.
3392  */
3393
3394 void emitter::emitIns_R(instruction ins, emitAttr attr, regNumber reg)
3395 {
3396     insFormat  fmt = IF_NONE;
3397     instrDesc* id  = nullptr;
3398
3399     /* Figure out the encoding format of the instruction */
3400     switch (ins)
3401     {
3402         case INS_br:
3403         case INS_ret:
3404             assert(isGeneralRegister(reg));
3405             id = emitNewInstrSmall(attr);
3406             id->idReg1(reg);
3407             fmt = IF_BR_1A;
3408             break;
3409
3410         default:
3411             unreached();
3412     }
3413
3414     assert(fmt != IF_NONE);
3415
3416     id->idIns(ins);
3417     id->idInsFmt(fmt);
3418
3419     dispIns(id);
3420     appendToCurIG(id);
3421 }
3422
3423 /*****************************************************************************
3424  *
3425  *  Add an instruction referencing a register and a constant.
3426  */
3427
3428 void emitter::emitIns_R_I(instruction ins, emitAttr attr, regNumber reg, ssize_t imm, insOpts opt /* = INS_OPTS_NONE */)
3429 {
3430     emitAttr  size      = EA_SIZE(attr);
3431     emitAttr  elemsize  = EA_UNKNOWN;
3432     insFormat fmt       = IF_NONE;
3433     bool      canEncode = false;
3434
3435     /* Figure out the encoding format of the instruction */
3436     switch (ins)
3437     {
3438         bitMaskImm     bmi;
3439         halfwordImm    hwi;
3440         byteShiftedImm bsi;
3441         ssize_t        notOfImm;
3442
3443         case INS_tst:
3444             assert(insOptsNone(opt));
3445             assert(isGeneralRegister(reg));
3446             bmi.immNRS = 0;
3447             canEncode  = canEncodeBitMaskImm(imm, size, &bmi);
3448             if (canEncode)
3449             {
3450                 imm = bmi.immNRS;
3451                 assert(isValidImmNRS(imm, size));
3452                 fmt = IF_DI_1C;
3453             }
3454             break;
3455
3456         case INS_movk:
3457         case INS_movn:
3458         case INS_movz:
3459             assert(isValidGeneralDatasize(size));
3460             assert(insOptsNone(opt)); // No LSL here (you must use emitIns_R_I_I if a shift is needed)
3461             assert(isGeneralRegister(reg));
3462             assert(isValidUimm16(imm));
3463
3464             hwi.immHW  = 0;
3465             hwi.immVal = imm;
3466             assert(imm == emitDecodeHalfwordImm(hwi, size));
3467
3468             imm       = hwi.immHWVal;
3469             canEncode = true;
3470             fmt       = IF_DI_1B;
3471             break;
3472
3473         case INS_mov:
3474             assert(isValidGeneralDatasize(size));
3475             assert(insOptsNone(opt)); // No explicit LSL here
3476             // We will automatically determine the shift based upon the imm
3477
3478             // First try the standard 'halfword immediate' imm(i16,hw)
3479             hwi.immHWVal = 0;
3480             canEncode    = canEncodeHalfwordImm(imm, size, &hwi);
3481             if (canEncode)
3482             {
3483                 // uses a movz encoding
3484                 assert(isGeneralRegister(reg));
3485                 imm = hwi.immHWVal;
3486                 assert(isValidImmHWVal(imm, size));
3487                 fmt = IF_DI_1B;
3488                 break;
3489             }
3490
3491             // Next try the ones-complement form of 'halfword immediate' imm(i16,hw)
3492             notOfImm  = NOT_helper(imm, getBitWidth(size));
3493             canEncode = canEncodeHalfwordImm(notOfImm, size, &hwi);
3494             if (canEncode)
3495             {
3496                 assert(isGeneralRegister(reg));
3497                 imm = hwi.immHWVal;
3498                 ins = INS_movn; // uses a movn encoding
3499                 assert(isValidImmHWVal(imm, size));
3500                 fmt = IF_DI_1B;
3501                 break;
3502             }
3503
3504             // Finally try the 'bitmask immediate' imm(N,r,s)
3505             bmi.immNRS = 0;
3506             canEncode  = canEncodeBitMaskImm(imm, size, &bmi);
3507             if (canEncode)
3508             {
3509                 assert(isGeneralRegisterOrSP(reg));
3510                 reg = encodingSPtoZR(reg);
3511                 imm = bmi.immNRS;
3512                 assert(isValidImmNRS(imm, size));
3513                 fmt = IF_DI_1D;
3514                 break;
3515             }
3516             else
3517             {
3518                 assert(!"Instruction cannot be encoded: mov imm");
3519             }
3520
3521             break;
3522
3523         case INS_movi:
3524             assert(isValidVectorDatasize(size));
3525             assert(isVectorRegister(reg));
3526             if (insOptsNone(opt) && (size == EA_8BYTE))
3527             {
3528                 opt = INS_OPTS_1D;
3529             }
3530             assert(isValidArrangement(size, opt));
3531             elemsize = optGetElemsize(opt);
3532
3533             if (elemsize == EA_8BYTE)
3534             {
3535                 size_t   uimm = imm;
3536                 ssize_t  imm8 = 0;
3537                 unsigned pos  = 0;
3538                 canEncode     = true;
3539                 while (uimm != 0)
3540                 {
3541                     INT64 loByte = uimm & 0xFF;
3542                     if (((loByte == 0) || (loByte == 0xFF)) && (pos < 8))
3543                     {
3544                         if (loByte == 0xFF)
3545                         {
3546                             imm8 |= (ssize_t{1} << pos);
3547                         }
3548                         uimm >>= 8;
3549                         pos++;
3550                     }
3551                     else
3552                     {
3553                         canEncode = false;
3554                         break;
3555                     }
3556                 }
3557                 imm = imm8;
3558                 assert(isValidUimm8(imm));
3559                 fmt = IF_DV_1B;
3560                 break;
3561             }
3562             else
3563             {
3564                 // Vector operation
3565
3566                 // No explicit LSL/MSL is used for the immediate
3567                 // We will automatically determine the shift based upon the value of imm
3568
3569                 // First try the standard 'byteShifted immediate' imm(i8,bySh)
3570                 bsi.immBSVal = 0;
3571                 canEncode    = canEncodeByteShiftedImm(imm, elemsize, true, &bsi);
3572                 if (canEncode)
3573                 {
3574                     imm = bsi.immBSVal;
3575                     assert(isValidImmBSVal(imm, size));
3576                     fmt = IF_DV_1B;
3577                     break;
3578                 }
3579
3580                 // Next try the ones-complement form of the 'immediate' imm(i8,bySh)
3581                 if ((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE)) // Only EA_2BYTE or EA_4BYTE forms
3582                 {
3583                     notOfImm  = NOT_helper(imm, getBitWidth(elemsize));
3584                     canEncode = canEncodeByteShiftedImm(notOfImm, elemsize, true, &bsi);
3585                     if (canEncode)
3586                     {
3587                         imm = bsi.immBSVal;
3588                         ins = INS_mvni; // uses a mvni encoding
3589                         assert(isValidImmBSVal(imm, size));
3590                         fmt = IF_DV_1B;
3591                         break;
3592                     }
3593                 }
3594             }
3595             break;
3596
3597         case INS_orr:
3598         case INS_bic:
3599         case INS_mvni:
3600             assert(isValidVectorDatasize(size));
3601             assert(isVectorRegister(reg));
3602             assert(isValidArrangement(size, opt));
3603             elemsize = optGetElemsize(opt);
3604             assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE)); // Only EA_2BYTE or EA_4BYTE forms
3605
3606             // Vector operation
3607
3608             // No explicit LSL/MSL is used for the immediate
3609             // We will automatically determine the shift based upon the value of imm
3610
3611             // First try the standard 'byteShifted immediate' imm(i8,bySh)
3612             bsi.immBSVal = 0;
3613             canEncode    = canEncodeByteShiftedImm(imm, elemsize,
3614                                                 (ins == INS_mvni), // mvni supports the ones shifting variant (aka MSL)
3615                                                 &bsi);
3616             if (canEncode)
3617             {
3618                 imm = bsi.immBSVal;
3619                 assert(isValidImmBSVal(imm, size));
3620                 fmt = IF_DV_1B;
3621                 break;
3622             }
3623             break;
3624
3625         case INS_cmp:
3626         case INS_cmn:
3627             assert(insOptsNone(opt));
3628             assert(isGeneralRegister(reg));
3629
3630             if (unsigned_abs(imm) <= 0x0fff)
3631             {
3632                 if (imm < 0)
3633                 {
3634                     ins = insReverse(ins);
3635                     imm = -imm;
3636                 }
3637                 assert(isValidUimm12(imm));
3638                 canEncode = true;
3639                 fmt       = IF_DI_1A;
3640             }
3641             else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
3642             {
3643                 // Encoding will use a 12-bit left shift of the immediate
3644                 opt = INS_OPTS_LSL12;
3645                 if (imm < 0)
3646                 {
3647                     ins = insReverse(ins);
3648                     imm = -imm;
3649                 }
3650                 assert((imm & 0xfff) == 0);
3651                 imm >>= 12;
3652                 assert(isValidUimm12(imm));
3653                 canEncode = true;
3654                 fmt       = IF_DI_1A;
3655             }
3656             else
3657             {
3658                 assert(!"Instruction cannot be encoded: IF_DI_1A");
3659             }
3660             break;
3661
3662         default:
3663             unreached();
3664             break;
3665
3666     } // end switch (ins)
3667
3668     assert(canEncode);
3669     assert(fmt != IF_NONE);
3670
3671     instrDesc* id = emitNewInstrSC(attr, imm);
3672
3673     id->idIns(ins);
3674     id->idInsFmt(fmt);
3675     id->idInsOpt(opt);
3676
3677     id->idReg1(reg);
3678
3679     dispIns(id);
3680     appendToCurIG(id);
3681 }
3682
3683 /*****************************************************************************
3684  *
3685  *  Add an instruction referencing a register and a floating point constant.
3686  */
3687
3688 void emitter::emitIns_R_F(
3689     instruction ins, emitAttr attr, regNumber reg, double immDbl, insOpts opt /* = INS_OPTS_NONE */)
3690
3691 {
3692     emitAttr  size      = EA_SIZE(attr);
3693     emitAttr  elemsize  = EA_UNKNOWN;
3694     insFormat fmt       = IF_NONE;
3695     ssize_t   imm       = 0;
3696     bool      canEncode = false;
3697
3698     /* Figure out the encoding format of the instruction */
3699     switch (ins)
3700     {
3701         floatImm8 fpi;
3702
3703         case INS_fcmp:
3704         case INS_fcmpe:
3705             assert(insOptsNone(opt));
3706             assert(isValidVectorElemsizeFloat(size));
3707             assert(isVectorRegister(reg));
3708             if (immDbl == 0.0)
3709             {
3710                 canEncode = true;
3711                 fmt       = IF_DV_1C;
3712             }
3713             break;
3714
3715         case INS_fmov:
3716             assert(isVectorRegister(reg));
3717             fpi.immFPIVal = 0;
3718             canEncode     = canEncodeFloatImm8(immDbl, &fpi);
3719
3720             if (insOptsAnyArrangement(opt))
3721             {
3722                 // Vector operation
3723                 assert(isValidVectorDatasize(size));
3724                 assert(isValidArrangement(size, opt));
3725                 elemsize = optGetElemsize(opt);
3726                 assert(isValidVectorElemsizeFloat(elemsize));
3727                 assert(opt != INS_OPTS_1D); // Reserved encoding
3728
3729                 if (canEncode)
3730                 {
3731                     imm = fpi.immFPIVal;
3732                     assert((imm >= 0) && (imm <= 0xff));
3733                     fmt = IF_DV_1B;
3734                 }
3735             }
3736             else
3737             {
3738                 // Scalar operation
3739                 assert(insOptsNone(opt));
3740                 assert(isValidVectorElemsizeFloat(size));
3741
3742                 if (canEncode)
3743                 {
3744                     imm = fpi.immFPIVal;
3745                     assert((imm >= 0) && (imm <= 0xff));
3746                     fmt = IF_DV_1A;
3747                 }
3748             }
3749             break;
3750
3751         default:
3752             unreached();
3753             break;
3754
3755     } // end switch (ins)
3756
3757     assert(canEncode);
3758     assert(fmt != IF_NONE);
3759
3760     instrDesc* id = emitNewInstrSC(attr, imm);
3761
3762     id->idIns(ins);
3763     id->idInsFmt(fmt);
3764     id->idInsOpt(opt);
3765
3766     id->idReg1(reg);
3767
3768     dispIns(id);
3769     appendToCurIG(id);
3770 }
3771
3772 /*****************************************************************************
3773  *
3774  *  Add an instruction referencing two registers
3775  */
3776
3777 void emitter::emitIns_R_R(
3778     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insOpts opt /* = INS_OPTS_NONE */)
3779 {
3780     emitAttr  size     = EA_SIZE(attr);
3781     emitAttr  elemsize = EA_UNKNOWN;
3782     insFormat fmt      = IF_NONE;
3783
3784     /* Figure out the encoding format of the instruction */
3785     switch (ins)
3786     {
3787         case INS_mov:
3788             assert(insOptsNone(opt));
3789             // Is the mov even necessary?
3790             if (reg1 == reg2)
3791             {
3792                 // A mov with a EA_4BYTE has the side-effect of clearing the upper bits
3793                 // So only eliminate mov instructions that are not clearing the upper bits
3794                 //
3795                 if (isGeneralRegisterOrSP(reg1) && (size == EA_8BYTE))
3796                 {
3797                     return;
3798                 }
3799                 else if (isVectorRegister(reg1) && (size == EA_16BYTE))
3800                 {
3801                     return;
3802                 }
3803             }
3804
3805             // Check for the 'mov' aliases for the vector registers
3806             if (isVectorRegister(reg1))
3807             {
3808                 if (isVectorRegister(reg2) && isValidVectorDatasize(size))
3809                 {
3810                     return emitIns_R_R_R(INS_mov, size, reg1, reg2, reg2);
3811                 }
3812                 else
3813                 {
3814                     return emitIns_R_R_I(INS_mov, size, reg1, reg2, 0);
3815                 }
3816             }
3817             else
3818             {
3819                 if (isVectorRegister(reg2))
3820                 {
3821                     assert(isGeneralRegister(reg1));
3822                     return emitIns_R_R_I(INS_mov, size, reg1, reg2, 0);
3823                 }
3824             }
3825
3826             // Is this a MOV to/from SP instruction?
3827             if ((reg1 == REG_SP) || (reg2 == REG_SP))
3828             {
3829                 assert(isGeneralRegisterOrSP(reg1));
3830                 assert(isGeneralRegisterOrSP(reg2));
3831                 reg1 = encodingSPtoZR(reg1);
3832                 reg2 = encodingSPtoZR(reg2);
3833                 fmt  = IF_DR_2G;
3834             }
3835             else
3836             {
3837                 assert(insOptsNone(opt));
3838                 assert(isGeneralRegister(reg1));
3839                 assert(isGeneralRegisterOrZR(reg2));
3840                 fmt = IF_DR_2E;
3841             }
3842             break;
3843
3844         case INS_dup:
3845             // Vector operation
3846             assert(insOptsAnyArrangement(opt));
3847             assert(isVectorRegister(reg1));
3848             assert(isGeneralRegisterOrZR(reg2));
3849             assert(isValidVectorDatasize(size));
3850             assert(isValidArrangement(size, opt));
3851             fmt = IF_DV_2C;
3852             break;
3853
3854         case INS_abs:
3855         case INS_not:
3856             assert(isVectorRegister(reg1));
3857             assert(isVectorRegister(reg2));
3858             if (ins == INS_not)
3859             {
3860                 assert(isValidVectorDatasize(size));
3861                 // Bitwise behavior is independent of element size, but is always encoded as 1 Byte
3862                 opt = optMakeArrangement(size, EA_1BYTE);
3863             }
3864             if (insOptsNone(opt))
3865             {
3866                 // Scalar operation
3867                 assert(size == EA_8BYTE); // Only type D is supported
3868                 fmt = IF_DV_2L;
3869             }
3870             else
3871             {
3872                 // Vector operation
3873                 assert(insOptsAnyArrangement(opt));
3874                 assert(isValidVectorDatasize(size));
3875                 assert(isValidArrangement(size, opt));
3876                 elemsize = optGetElemsize(opt);
3877                 fmt      = IF_DV_2M;
3878             }
3879             break;
3880
3881         case INS_mvn:
3882         case INS_neg:
3883             if (isVectorRegister(reg1))
3884             {
3885                 assert(isVectorRegister(reg2));
3886                 if (ins == INS_mvn)
3887                 {
3888                     assert(isValidVectorDatasize(size));
3889                     // Bitwise behavior is independent of element size, but is always encoded as 1 Byte
3890                     opt = optMakeArrangement(size, EA_1BYTE);
3891                 }
3892                 if (insOptsNone(opt))
3893                 {
3894                     // Scalar operation
3895                     assert(size == EA_8BYTE); // Only type D is supported
3896                     fmt = IF_DV_2L;
3897                 }
3898                 else
3899                 {
3900                     // Vector operation
3901                     assert(isValidVectorDatasize(size));
3902                     assert(isValidArrangement(size, opt));
3903                     elemsize = optGetElemsize(opt);
3904                     fmt      = IF_DV_2M;
3905                 }
3906                 break;
3907             }
3908             __fallthrough;
3909
3910         case INS_negs:
3911             assert(insOptsNone(opt));
3912             assert(isGeneralRegister(reg1));
3913             assert(isGeneralRegisterOrZR(reg2));
3914             fmt = IF_DR_2E;
3915             break;
3916
3917         case INS_sxtw:
3918             assert(size == EA_8BYTE);
3919             __fallthrough;
3920
3921         case INS_sxtb:
3922         case INS_sxth:
3923         case INS_uxtb:
3924         case INS_uxth:
3925             assert(insOptsNone(opt));
3926             assert(isValidGeneralDatasize(size));
3927             assert(isGeneralRegister(reg1));
3928             assert(isGeneralRegister(reg2));
3929             fmt = IF_DR_2H;
3930             break;
3931
3932         case INS_sxtl:
3933         case INS_sxtl2:
3934         case INS_uxtl:
3935         case INS_uxtl2:
3936             return emitIns_R_R_I(ins, size, reg1, reg2, 0, opt);
3937
3938         case INS_cls:
3939         case INS_clz:
3940         case INS_rbit:
3941         case INS_rev16:
3942         case INS_rev32:
3943         case INS_cnt:
3944             if (isVectorRegister(reg1))
3945             {
3946                 assert(isVectorRegister(reg2));
3947                 assert(isValidVectorDatasize(size));
3948                 assert(isValidArrangement(size, opt));
3949                 elemsize = optGetElemsize(opt);
3950                 if ((ins == INS_cls) || (ins == INS_clz))
3951                 {
3952                     assert(elemsize != EA_8BYTE); // No encoding for type D
3953                 }
3954                 else if (ins == INS_rev32)
3955                 {
3956                     assert((elemsize == EA_2BYTE) || (elemsize == EA_1BYTE));
3957                 }
3958                 else
3959                 {
3960                     assert(elemsize == EA_1BYTE); // Only supports 8B or 16B
3961                 }
3962                 fmt = IF_DV_2M;
3963                 break;
3964             }
3965             if (ins == INS_cnt)
3966             {
3967                 // Doesn't have general register version(s)
3968                 break;
3969             }
3970
3971             __fallthrough;
3972
3973         case INS_rev:
3974             assert(insOptsNone(opt));
3975             assert(isGeneralRegister(reg1));
3976             assert(isGeneralRegister(reg2));
3977             if (ins == INS_rev32)
3978             {
3979                 assert(size == EA_8BYTE);
3980             }
3981             else
3982             {
3983                 assert(isValidGeneralDatasize(size));
3984             }
3985             fmt = IF_DR_2G;
3986             break;
3987
3988         case INS_addv:
3989         case INS_saddlv:
3990         case INS_smaxv:
3991         case INS_sminv:
3992         case INS_uaddlv:
3993         case INS_umaxv:
3994         case INS_uminv:
3995         case INS_rev64:
3996             assert(isVectorRegister(reg1));
3997             assert(isVectorRegister(reg2));
3998             assert(isValidVectorDatasize(size));
3999             assert(isValidArrangement(size, opt));
4000             elemsize = optGetElemsize(opt);
4001             assert(elemsize != EA_8BYTE); // No encoding for type D
4002             fmt = IF_DV_2M;
4003             break;
4004
4005         case INS_xtn:
4006         case INS_xtn2:
4007             assert(isVectorRegister(reg1));
4008             assert(isVectorRegister(reg2));
4009             assert(isValidVectorDatasize(size));
4010             assert(isValidArrangement(size, opt));
4011             elemsize = optGetElemsize(opt);
4012             // size is determined by instruction
4013             if (ins == INS_xtn)
4014             {
4015                 assert(size == EA_8BYTE);
4016             }
4017             else // ins == INS_xtn2
4018             {
4019                 assert(size == EA_16BYTE);
4020             }
4021             assert(elemsize != EA_8BYTE); // Narrowing must not end with 8 byte data
4022             fmt = IF_DV_2M;
4023             break;
4024
4025         case INS_ldar:
4026         case INS_ldaxr:
4027         case INS_ldxr:
4028         case INS_stlr:
4029             assert(isValidGeneralDatasize(size));
4030
4031             __fallthrough;
4032
4033         case INS_ldarb:
4034         case INS_ldaxrb:
4035         case INS_ldxrb:
4036         case INS_ldarh:
4037         case INS_ldaxrh:
4038         case INS_ldxrh:
4039         case INS_stlrb:
4040         case INS_stlrh:
4041             assert(isValidGeneralLSDatasize(size));
4042             assert(isGeneralRegisterOrZR(reg1));
4043             assert(isGeneralRegisterOrSP(reg2));
4044             assert(insOptsNone(opt));
4045
4046             reg2 = encodingSPtoZR(reg2);
4047
4048             fmt = IF_LS_2A;
4049             break;
4050
4051         case INS_ldr:
4052         case INS_ldrb:
4053         case INS_ldrh:
4054         case INS_ldrsb:
4055         case INS_ldrsh:
4056         case INS_ldrsw:
4057         case INS_str:
4058         case INS_strb:
4059         case INS_strh:
4060
4061         case INS_cmp:
4062         case INS_cmn:
4063         case INS_tst:
4064             assert(insOptsNone(opt));
4065             emitIns_R_R_I(ins, attr, reg1, reg2, 0, INS_OPTS_NONE);
4066             return;
4067
4068         case INS_staddb:
4069             emitIns_R_R_R(INS_ldaddb, attr, reg1, REG_ZR, reg2);
4070             return;
4071         case INS_staddlb:
4072             emitIns_R_R_R(INS_ldaddlb, attr, reg1, REG_ZR, reg2);
4073             return;
4074         case INS_staddh:
4075             emitIns_R_R_R(INS_ldaddh, attr, reg1, REG_ZR, reg2);
4076             return;
4077         case INS_staddlh:
4078             emitIns_R_R_R(INS_ldaddlh, attr, reg1, REG_ZR, reg2);
4079             return;
4080         case INS_stadd:
4081             emitIns_R_R_R(INS_ldadd, attr, reg1, REG_ZR, reg2);
4082             return;
4083         case INS_staddl:
4084             emitIns_R_R_R(INS_ldaddl, attr, reg1, REG_ZR, reg2);
4085             return;
4086
4087         case INS_fmov:
4088             assert(isValidVectorElemsizeFloat(size));
4089
4090             // Is the mov even necessary?
4091             if (reg1 == reg2)
4092             {
4093                 return;
4094             }
4095
4096             if (isVectorRegister(reg1))
4097             {
4098                 if (isVectorRegister(reg2))
4099                 {
4100                     assert(insOptsNone(opt));
4101                     fmt = IF_DV_2G;
4102                 }
4103                 else
4104                 {
4105                     assert(isGeneralRegister(reg2));
4106
4107                     // if the optional conversion specifier is not present we calculate it
4108                     if (opt == INS_OPTS_NONE)
4109                     {
4110                         opt = (size == EA_4BYTE) ? INS_OPTS_4BYTE_TO_S : INS_OPTS_8BYTE_TO_D;
4111                     }
4112                     assert(insOptsConvertIntToFloat(opt));
4113
4114                     fmt = IF_DV_2I;
4115                 }
4116             }
4117             else
4118             {
4119                 assert(isGeneralRegister(reg1));
4120                 assert(isVectorRegister(reg2));
4121
4122                 // if the optional conversion specifier is not present we calculate it
4123                 if (opt == INS_OPTS_NONE)
4124                 {
4125                     opt = (size == EA_4BYTE) ? INS_OPTS_S_TO_4BYTE : INS_OPTS_D_TO_8BYTE;
4126                 }
4127                 assert(insOptsConvertFloatToInt(opt));
4128
4129                 fmt = IF_DV_2H;
4130             }
4131             break;
4132
4133         case INS_fcmp:
4134         case INS_fcmpe:
4135             assert(insOptsNone(opt));
4136             assert(isValidVectorElemsizeFloat(size));
4137             assert(isVectorRegister(reg1));
4138             assert(isVectorRegister(reg2));
4139             fmt = IF_DV_2K;
4140             break;
4141
4142         case INS_fcvtns:
4143         case INS_fcvtnu:
4144         case INS_fcvtas:
4145         case INS_fcvtau:
4146         case INS_fcvtps:
4147         case INS_fcvtpu:
4148         case INS_fcvtms:
4149         case INS_fcvtmu:
4150         case INS_fcvtzs:
4151         case INS_fcvtzu:
4152             if (insOptsAnyArrangement(opt))
4153             {
4154                 // Vector operation
4155                 assert(isVectorRegister(reg1));
4156                 assert(isVectorRegister(reg2));
4157                 assert(isValidVectorDatasize(size));
4158                 assert(isValidArrangement(size, opt));
4159                 elemsize = optGetElemsize(opt);
4160                 assert(isValidVectorElemsizeFloat(elemsize));
4161                 assert(opt != INS_OPTS_1D); // Reserved encoding
4162                 fmt = IF_DV_2A;
4163             }
4164             else
4165             {
4166                 // Scalar operation
4167                 assert(isVectorRegister(reg2));
4168                 if (isVectorRegister(reg1))
4169                 {
4170                     assert(insOptsNone(opt));
4171                     assert(isValidVectorElemsizeFloat(size));
4172                     fmt = IF_DV_2G;
4173                 }
4174                 else
4175                 {
4176                     assert(isGeneralRegister(reg1));
4177                     assert(insOptsConvertFloatToInt(opt));
4178                     assert(isValidVectorElemsizeFloat(size));
4179                     fmt = IF_DV_2H;
4180                 }
4181             }
4182             break;
4183
4184         case INS_fcvtl:
4185         case INS_fcvtl2:
4186         case INS_fcvtn:
4187         case INS_fcvtn2:
4188             assert(isVectorRegister(reg1));
4189             assert(isVectorRegister(reg2));
4190             assert(isValidVectorDatasize(size));
4191             assert(insOptsNone(opt));
4192             assert(size == EA_8BYTE); // Narrowing from Double or Widening to Double (Half not supported)
4193             fmt = IF_DV_2G;
4194             break;
4195
4196         case INS_scvtf:
4197         case INS_ucvtf:
4198             if (insOptsAnyArrangement(opt))
4199             {
4200                 // Vector operation
4201                 assert(isVectorRegister(reg1));
4202                 assert(isVectorRegister(reg2));
4203                 assert(isValidVectorDatasize(size));
4204                 assert(isValidArrangement(size, opt));
4205                 elemsize = optGetElemsize(opt);
4206                 assert(isValidVectorElemsizeFloat(elemsize));
4207                 assert(opt != INS_OPTS_1D); // Reserved encoding
4208                 fmt = IF_DV_2A;
4209             }
4210             else
4211             {
4212                 // Scalar operation
4213                 assert(isVectorRegister(reg1));
4214                 if (isVectorRegister(reg2))
4215                 {
4216                     assert(insOptsNone(opt));
4217                     assert(isValidVectorElemsizeFloat(size));
4218                     fmt = IF_DV_2G;
4219                 }
4220                 else
4221                 {
4222                     assert(isGeneralRegister(reg2));
4223                     assert(insOptsConvertIntToFloat(opt));
4224                     assert(isValidVectorElemsizeFloat(size));
4225                     fmt = IF_DV_2I;
4226                 }
4227             }
4228             break;
4229
4230         case INS_fabs:
4231         case INS_fneg:
4232         case INS_fsqrt:
4233         case INS_frinta:
4234         case INS_frinti:
4235         case INS_frintm:
4236         case INS_frintn:
4237         case INS_frintp:
4238         case INS_frintx:
4239         case INS_frintz:
4240             if (insOptsAnyArrangement(opt))
4241             {
4242                 // Vector operation
4243                 assert(isVectorRegister(reg1));
4244                 assert(isVectorRegister(reg2));
4245                 assert(isValidVectorDatasize(size));
4246                 assert(isValidArrangement(size, opt));
4247                 elemsize = optGetElemsize(opt);
4248                 assert(isValidVectorElemsizeFloat(elemsize));
4249                 assert(opt != INS_OPTS_1D); // Reserved encoding
4250                 fmt = IF_DV_2A;
4251             }
4252             else
4253             {
4254                 // Scalar operation
4255                 assert(insOptsNone(opt));
4256                 assert(isValidVectorElemsizeFloat(size));
4257                 assert(isVectorRegister(reg1));
4258                 assert(isVectorRegister(reg2));
4259                 fmt = IF_DV_2G;
4260             }
4261             break;
4262
4263         case INS_faddp:
4264             // Scalar operation
4265             assert(insOptsNone(opt));
4266             assert(isValidVectorElemsizeFloat(size));
4267             assert(isVectorRegister(reg1));
4268             assert(isVectorRegister(reg2));
4269             fmt = IF_DV_2G;
4270             break;
4271
4272         case INS_fcvt:
4273             assert(insOptsConvertFloatToFloat(opt));
4274             assert(isValidVectorFcvtsize(size));
4275             assert(isVectorRegister(reg1));
4276             assert(isVectorRegister(reg2));
4277             fmt = IF_DV_2J;
4278             break;
4279
4280         case INS_cmeq:
4281         case INS_cmge:
4282         case INS_cmgt:
4283         case INS_cmle:
4284         case INS_cmlt:
4285             assert(isVectorRegister(reg1));
4286             assert(isVectorRegister(reg2));
4287
4288             if (isValidVectorDatasize(size))
4289             {
4290                 // Vector operation
4291                 assert(insOptsAnyArrangement(opt));
4292                 assert(isValidArrangement(size, opt));
4293                 elemsize = optGetElemsize(opt);
4294                 fmt      = IF_DV_2M;
4295             }
4296             else
4297             {
4298                 NYI("Untested");
4299                 // Scalar operation
4300                 assert(size == EA_8BYTE); // Only Double supported
4301                 fmt = IF_DV_2L;
4302             }
4303             break;
4304
4305         case INS_fcmeq:
4306         case INS_fcmge:
4307         case INS_fcmgt:
4308         case INS_fcmle:
4309         case INS_fcmlt:
4310             assert(isVectorRegister(reg1));
4311             assert(isVectorRegister(reg2));
4312
4313             if (isValidVectorDatasize(size))
4314             {
4315                 // Vector operation
4316                 assert(insOptsAnyArrangement(opt));
4317                 assert(isValidArrangement(size, opt));
4318                 elemsize = optGetElemsize(opt);
4319                 assert((elemsize == EA_8BYTE) || (elemsize == EA_4BYTE)); // Only Double/Float supported
4320                 assert(opt != INS_OPTS_1D);                               // Reserved encoding
4321                 fmt = IF_DV_2A;
4322             }
4323             else
4324             {
4325                 NYI("Untested");
4326                 // Scalar operation
4327                 assert((size == EA_8BYTE) || (size == EA_4BYTE)); // Only Double/Float supported
4328                 fmt = IF_DV_2G;
4329             }
4330             break;
4331         case INS_aesd:
4332         case INS_aese:
4333         case INS_aesmc:
4334         case INS_aesimc:
4335             assert(isVectorRegister(reg1));
4336             assert(isVectorRegister(reg2));
4337             assert(isValidVectorDatasize(size));
4338             elemsize = optGetElemsize(opt);
4339             assert(elemsize == EA_1BYTE);
4340             fmt = IF_DV_2P;
4341             break;
4342
4343         case INS_sha1h:
4344             assert(insOptsNone(opt));
4345             assert(isVectorRegister(reg1));
4346             assert(isVectorRegister(reg2));
4347             fmt = IF_DR_2J;
4348             break;
4349
4350         case INS_sha256su0:
4351         case INS_sha1su1:
4352             assert(isVectorRegister(reg1));
4353             assert(isVectorRegister(reg2));
4354             assert(isValidVectorDatasize(size));
4355             elemsize = optGetElemsize(opt);
4356             assert(elemsize == EA_4BYTE);
4357             fmt = IF_DV_2P;
4358             break;
4359
4360         default:
4361             unreached();
4362             break;
4363
4364     } // end switch (ins)
4365
4366     assert(fmt != IF_NONE);
4367
4368     instrDesc* id = emitNewInstrSmall(attr);
4369
4370     id->idIns(ins);
4371     id->idInsFmt(fmt);
4372     id->idInsOpt(opt);
4373
4374     id->idReg1(reg1);
4375     id->idReg2(reg2);
4376
4377     dispIns(id);
4378     appendToCurIG(id);
4379 }
4380
4381 /*****************************************************************************
4382  *
4383  *  Add an instruction referencing a register and two constants.
4384  */
4385
4386 void emitter::emitIns_R_I_I(
4387     instruction ins, emitAttr attr, regNumber reg, ssize_t imm1, ssize_t imm2, insOpts opt /* = INS_OPTS_NONE */)
4388 {
4389     emitAttr  size   = EA_SIZE(attr);
4390     insFormat fmt    = IF_NONE;
4391     size_t    immOut = 0; // composed from imm1 and imm2 and stored in the instrDesc
4392
4393     /* Figure out the encoding format of the instruction */
4394     switch (ins)
4395     {
4396         bool        canEncode;
4397         halfwordImm hwi;
4398
4399         case INS_mov:
4400             ins = INS_movz; // INS_mov with LSL is an alias for INS_movz LSL
4401             __fallthrough;
4402
4403         case INS_movk:
4404         case INS_movn:
4405         case INS_movz:
4406             assert(isValidGeneralDatasize(size));
4407             assert(isGeneralRegister(reg));
4408             assert(isValidUimm16(imm1));
4409             assert(insOptsLSL(opt)); // Must be INS_OPTS_LSL
4410
4411             if (size == EA_8BYTE)
4412             {
4413                 assert((imm2 == 0) || (imm2 == 16) || // shift amount: 0, 16, 32 or 48
4414                        (imm2 == 32) || (imm2 == 48));
4415             }
4416             else // EA_4BYTE
4417             {
4418                 assert((imm2 == 0) || (imm2 == 16)); // shift amount: 0 or 16
4419             }
4420
4421             hwi.immHWVal = 0;
4422
4423             switch (imm2)
4424             {
4425                 case 0:
4426                     hwi.immHW = 0;
4427                     canEncode = true;
4428                     break;
4429
4430                 case 16:
4431                     hwi.immHW = 1;
4432                     canEncode = true;
4433                     break;
4434
4435                 case 32:
4436                     hwi.immHW = 2;
4437                     canEncode = true;
4438                     break;
4439
4440                 case 48:
4441                     hwi.immHW = 3;
4442                     canEncode = true;
4443                     break;
4444
4445                 default:
4446                     canEncode = false;
4447             }
4448
4449             if (canEncode)
4450             {
4451                 hwi.immVal = imm1;
4452
4453                 immOut = hwi.immHWVal;
4454                 assert(isValidImmHWVal(immOut, size));
4455                 fmt = IF_DI_1B;
4456             }
4457             break;
4458
4459         default:
4460             unreached();
4461             break;
4462
4463     } // end switch (ins)
4464
4465     assert(fmt != IF_NONE);
4466
4467     instrDesc* id = emitNewInstrSC(attr, immOut);
4468
4469     id->idIns(ins);
4470     id->idInsFmt(fmt);
4471
4472     id->idReg1(reg);
4473
4474     dispIns(id);
4475     appendToCurIG(id);
4476 }
4477
4478 /*****************************************************************************
4479  *
4480  *  Add an instruction referencing two registers and a constant.
4481  */
4482
4483 void emitter::emitIns_R_R_I(
4484     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm, insOpts opt /* = INS_OPTS_NONE */)
4485 {
4486     emitAttr  size       = EA_SIZE(attr);
4487     emitAttr  elemsize   = EA_UNKNOWN;
4488     insFormat fmt        = IF_NONE;
4489     bool      isLdSt     = false;
4490     bool      isSIMD     = false;
4491     bool      isAddSub   = false;
4492     bool      setFlags   = false;
4493     unsigned  scale      = 0;
4494     bool      unscaledOp = false;
4495
4496     /* Figure out the encoding format of the instruction */
4497     switch (ins)
4498     {
4499         bool       canEncode;
4500         bitMaskImm bmi;
4501
4502         case INS_mov:
4503             // Check for the 'mov' aliases for the vector registers
4504             assert(insOptsNone(opt));
4505             assert(isValidVectorElemsize(size));
4506             elemsize = size;
4507             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4508
4509             if (isVectorRegister(reg1))
4510             {
4511                 if (isGeneralRegisterOrZR(reg2))
4512                 {
4513                     fmt = IF_DV_2C; // Alias for 'ins'
4514                     break;
4515                 }
4516                 else if (isVectorRegister(reg2))
4517                 {
4518                     fmt = IF_DV_2E; // Alias for 'dup'
4519                     break;
4520                 }
4521             }
4522             else // isGeneralRegister(reg1)
4523             {
4524                 assert(isGeneralRegister(reg1));
4525                 if (isVectorRegister(reg2))
4526                 {
4527                     fmt = IF_DV_2B; // Alias for 'umov'
4528                     break;
4529                 }
4530             }
4531             assert(!" invalid INS_mov operands");
4532             break;
4533
4534         case INS_lsl:
4535         case INS_lsr:
4536         case INS_asr:
4537             assert(insOptsNone(opt));
4538             assert(isValidGeneralDatasize(size));
4539             assert(isGeneralRegister(reg1));
4540             assert(isGeneralRegister(reg2));
4541             assert(isValidImmShift(imm, size));
4542             fmt = IF_DI_2D;
4543             break;
4544
4545         case INS_ror:
4546             assert(insOptsNone(opt));
4547             assert(isValidGeneralDatasize(size));
4548             assert(isGeneralRegister(reg1));
4549             assert(isGeneralRegister(reg2));
4550             assert(isValidImmShift(imm, size));
4551             fmt = IF_DI_2B;
4552             break;
4553
4554         case INS_sshr:
4555         case INS_ssra:
4556         case INS_srshr:
4557         case INS_srsra:
4558         case INS_shl:
4559         case INS_ushr:
4560         case INS_usra:
4561         case INS_urshr:
4562         case INS_ursra:
4563         case INS_sri:
4564         case INS_sli:
4565             assert(isVectorRegister(reg1));
4566             assert(isVectorRegister(reg2));
4567             if (insOptsAnyArrangement(opt))
4568             {
4569                 // Vector operation
4570                 assert(isValidVectorDatasize(size));
4571                 assert(isValidArrangement(size, opt));
4572                 elemsize = optGetElemsize(opt);
4573                 assert(isValidVectorElemsize(elemsize));
4574                 assert(isValidImmShift(imm, elemsize));
4575                 assert(opt != INS_OPTS_1D); // Reserved encoding
4576                 fmt = IF_DV_2O;
4577                 break;
4578             }
4579             else
4580             {
4581                 // Scalar operation
4582                 assert(insOptsNone(opt));
4583                 assert(size == EA_8BYTE); // only supported size
4584                 assert(isValidImmShift(imm, size));
4585                 fmt = IF_DV_2N;
4586             }
4587             break;
4588
4589         case INS_sxtl:
4590         case INS_uxtl:
4591             assert(imm == 0);
4592             __fallthrough;
4593
4594         case INS_shrn:
4595         case INS_rshrn:
4596         case INS_sshll:
4597         case INS_ushll:
4598             assert(isVectorRegister(reg1));
4599             assert(isVectorRegister(reg2));
4600             // Vector operation
4601             assert(size == EA_8BYTE);
4602             assert(isValidArrangement(size, opt));
4603             elemsize = optGetElemsize(opt);
4604             assert(elemsize != EA_8BYTE); // Reserved encodings
4605             assert(isValidVectorElemsize(elemsize));
4606             assert(isValidImmShift(imm, elemsize));
4607             fmt = IF_DV_2O;
4608             break;
4609
4610         case INS_sxtl2:
4611         case INS_uxtl2:
4612             assert(imm == 0);
4613             __fallthrough;
4614
4615         case INS_shrn2:
4616         case INS_rshrn2:
4617         case INS_sshll2:
4618         case INS_ushll2:
4619             assert(isVectorRegister(reg1));
4620             assert(isVectorRegister(reg2));
4621             // Vector operation
4622             assert(size == EA_16BYTE);
4623             assert(isValidArrangement(size, opt));
4624             elemsize = optGetElemsize(opt);
4625             assert(elemsize != EA_8BYTE); // Reserved encodings
4626             assert(isValidVectorElemsize(elemsize));
4627             assert(isValidImmShift(imm, elemsize));
4628             fmt = IF_DV_2O;
4629             break;
4630
4631         case INS_mvn:
4632         case INS_neg:
4633         case INS_negs:
4634             assert(isValidGeneralDatasize(size));
4635             assert(isGeneralRegister(reg1));
4636             assert(isGeneralRegisterOrZR(reg2));
4637
4638             if (imm == 0)
4639             {
4640                 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4641
4642                 fmt = IF_DR_2E;
4643             }
4644             else
4645             {
4646                 if (ins == INS_mvn)
4647                 {
4648                     assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
4649                 }
4650                 else // neg or negs
4651                 {
4652                     assert(insOptsAluShift(opt)); // a non-zero imm, must select shift kind, can't use ROR
4653                 }
4654                 assert(isValidImmShift(imm, size));
4655                 fmt = IF_DR_2F;
4656             }
4657             break;
4658
4659         case INS_tst:
4660             assert(isValidGeneralDatasize(size));
4661             assert(isGeneralRegisterOrZR(reg1));
4662             assert(isGeneralRegister(reg2));
4663
4664             if (insOptsAnyShift(opt))
4665             {
4666                 assert(isValidImmShift(imm, size) && (imm != 0));
4667                 fmt = IF_DR_2B;
4668             }
4669             else
4670             {
4671                 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4672                 assert(imm == 0);
4673                 fmt = IF_DR_2A;
4674             }
4675             break;
4676
4677         case INS_cmp:
4678         case INS_cmn:
4679             assert(isValidGeneralDatasize(size));
4680             assert(isGeneralRegisterOrSP(reg1));
4681             assert(isGeneralRegister(reg2));
4682
4683             reg1 = encodingSPtoZR(reg1);
4684             if (insOptsAnyExtend(opt))
4685             {
4686                 assert((imm >= 0) && (imm <= 4));
4687
4688                 fmt = IF_DR_2C;
4689             }
4690             else if (imm == 0)
4691             {
4692                 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4693
4694                 fmt = IF_DR_2A;
4695             }
4696             else
4697             {
4698                 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
4699                 assert(isValidImmShift(imm, size));
4700                 fmt = IF_DR_2B;
4701             }
4702             break;
4703
4704         case INS_ands:
4705         case INS_and:
4706         case INS_eor:
4707         case INS_orr:
4708             assert(insOptsNone(opt));
4709             assert(isGeneralRegister(reg2));
4710             if (ins == INS_ands)
4711             {
4712                 assert(isGeneralRegister(reg1));
4713             }
4714             else
4715             {
4716                 assert(isGeneralRegisterOrSP(reg1));
4717                 reg1 = encodingSPtoZR(reg1);
4718             }
4719
4720             bmi.immNRS = 0;
4721             canEncode  = canEncodeBitMaskImm(imm, size, &bmi);
4722             if (canEncode)
4723             {
4724                 imm = bmi.immNRS;
4725                 assert(isValidImmNRS(imm, size));
4726                 fmt = IF_DI_2C;
4727             }
4728             break;
4729
4730         case INS_dup: // by element, imm selects the element of reg2
4731             assert(isVectorRegister(reg1));
4732             if (isVectorRegister(reg2))
4733             {
4734                 if (insOptsAnyArrangement(opt))
4735                 {
4736                     // Vector operation
4737                     assert(isValidVectorDatasize(size));
4738                     assert(isValidArrangement(size, opt));
4739                     elemsize = optGetElemsize(opt);
4740                     assert(isValidVectorElemsize(elemsize));
4741                     assert(isValidVectorIndex(size, elemsize, imm));
4742                     assert(opt != INS_OPTS_1D); // Reserved encoding
4743                     fmt = IF_DV_2D;
4744                     break;
4745                 }
4746                 else
4747                 {
4748                     // Scalar operation
4749                     assert(insOptsNone(opt));
4750                     elemsize = size;
4751                     assert(isValidVectorElemsize(elemsize));
4752                     assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4753                     fmt = IF_DV_2E;
4754                     break;
4755                 }
4756             }
4757             __fallthrough;
4758
4759         case INS_ins: // (MOV from general)
4760             assert(insOptsNone(opt));
4761             assert(isValidVectorElemsize(size));
4762             assert(isVectorRegister(reg1));
4763             assert(isGeneralRegisterOrZR(reg2));
4764             elemsize = size;
4765             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4766             fmt = IF_DV_2C;
4767             break;
4768
4769         case INS_umov: // (MOV to general)
4770             assert(insOptsNone(opt));
4771             assert(isValidVectorElemsize(size));
4772             assert(isGeneralRegister(reg1));
4773             assert(isVectorRegister(reg2));
4774             elemsize = size;
4775             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4776             fmt = IF_DV_2B;
4777             break;
4778
4779         case INS_smov:
4780             assert(insOptsNone(opt));
4781             assert(isValidVectorElemsize(size));
4782             assert(size != EA_8BYTE); // no encoding, use INS_umov
4783             assert(isGeneralRegister(reg1));
4784             assert(isVectorRegister(reg2));
4785             elemsize = size;
4786             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4787             fmt = IF_DV_2B;
4788             break;
4789
4790         case INS_add:
4791         case INS_sub:
4792             setFlags = false;
4793             isAddSub = true;
4794             break;
4795
4796         case INS_adds:
4797         case INS_subs:
4798             setFlags = true;
4799             isAddSub = true;
4800             break;
4801
4802         case INS_ldrsb:
4803         case INS_ldursb:
4804             // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4805             assert(isValidGeneralDatasize(size));
4806             unscaledOp = (ins == INS_ldursb);
4807             scale      = 0;
4808             isLdSt     = true;
4809             break;
4810
4811         case INS_ldrsh:
4812         case INS_ldursh:
4813             // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4814             assert(isValidGeneralDatasize(size));
4815             unscaledOp = (ins == INS_ldursh);
4816             scale      = 1;
4817             isLdSt     = true;
4818             break;
4819
4820         case INS_ldrsw:
4821         case INS_ldursw:
4822             // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4823             assert(size == EA_8BYTE);
4824             unscaledOp = (ins == INS_ldursw);
4825             scale      = 2;
4826             isLdSt     = true;
4827             break;
4828
4829         case INS_ldrb:
4830         case INS_strb:
4831             // size is ignored
4832             unscaledOp = false;
4833             scale      = 0;
4834             isLdSt     = true;
4835             break;
4836
4837         case INS_ldurb:
4838         case INS_sturb:
4839             // size is ignored
4840             unscaledOp = true;
4841             scale      = 0;
4842             isLdSt     = true;
4843             break;
4844
4845         case INS_ldrh:
4846         case INS_strh:
4847             // size is ignored
4848             unscaledOp = false;
4849             scale      = 1;
4850             isLdSt     = true;
4851             break;
4852
4853         case INS_ldurh:
4854         case INS_sturh:
4855             // size is ignored
4856             unscaledOp = true;
4857             scale      = 0;
4858             isLdSt     = true;
4859             break;
4860
4861         case INS_ldr:
4862         case INS_str:
4863             // Is the target a vector register?
4864             if (isVectorRegister(reg1))
4865             {
4866                 assert(isValidVectorLSDatasize(size));
4867                 assert(isGeneralRegisterOrSP(reg2));
4868                 isSIMD = true;
4869             }
4870             else
4871             {
4872                 assert(isValidGeneralDatasize(size));
4873             }
4874             unscaledOp = false;
4875             scale      = NaturalScale_helper(size);
4876             isLdSt     = true;
4877             break;
4878
4879         case INS_ldur:
4880         case INS_stur:
4881             // Is the target a vector register?
4882             if (isVectorRegister(reg1))
4883             {
4884                 assert(isValidVectorLSDatasize(size));
4885                 assert(isGeneralRegisterOrSP(reg2));
4886                 isSIMD = true;
4887             }
4888             else
4889             {
4890                 assert(isValidGeneralDatasize(size));
4891             }
4892             unscaledOp = true;
4893             scale      = 0;
4894             isLdSt     = true;
4895             break;
4896
4897         default:
4898             unreached();
4899             break;
4900
4901     } // end switch (ins)
4902
4903     if (isLdSt)
4904     {
4905         assert(!isAddSub);
4906
4907         if (isSIMD)
4908         {
4909             assert(isValidVectorLSDatasize(size));
4910             assert(isVectorRegister(reg1));
4911             assert((scale >= 0) && (scale <= 4));
4912         }
4913         else
4914         {
4915             assert(isValidGeneralLSDatasize(size));
4916             assert(isGeneralRegisterOrZR(reg1));
4917             assert((scale >= 0) && (scale <= 3));
4918         }
4919
4920         assert(isGeneralRegisterOrSP(reg2));
4921
4922         // Load/Store reserved encodings:
4923         if (insOptsIndexed(opt))
4924         {
4925             assert(reg1 != reg2);
4926         }
4927
4928         reg2 = encodingSPtoZR(reg2);
4929
4930         ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
4931         if (imm == 0)
4932         {
4933             assert(insOptsNone(opt)); // PRE/POST Index doesn't make sense with an immediate of zero
4934
4935             fmt = IF_LS_2A;
4936         }
4937         else if (insOptsIndexed(opt) || unscaledOp || (imm < 0) || ((imm & mask) != 0))
4938         {
4939             if ((imm >= -256) && (imm <= 255))
4940             {
4941                 fmt = IF_LS_2C;
4942             }
4943             else
4944             {
4945                 assert(!"Instruction cannot be encoded: IF_LS_2C");
4946             }
4947         }
4948         else if (imm > 0)
4949         {
4950             assert(insOptsNone(opt));
4951             assert(!unscaledOp);
4952
4953             if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
4954             {
4955                 imm >>= scale; // The immediate is scaled by the size of the ld/st
4956
4957                 fmt = IF_LS_2B;
4958             }
4959             else
4960             {
4961                 assert(!"Instruction cannot be encoded: IF_LS_2B");
4962             }
4963         }
4964     }
4965     else if (isAddSub)
4966     {
4967         assert(!isLdSt);
4968         assert(insOptsNone(opt));
4969
4970         if (setFlags) // Can't encode SP with setFlags
4971         {
4972             assert(isGeneralRegister(reg1));
4973             assert(isGeneralRegister(reg2));
4974         }
4975         else
4976         {
4977             assert(isGeneralRegisterOrSP(reg1));
4978             assert(isGeneralRegisterOrSP(reg2));
4979
4980             // Is it just a mov?
4981             if (imm == 0)
4982             {
4983                 // Is the mov even necessary?
4984                 if (reg1 != reg2)
4985                 {
4986                     emitIns_R_R(INS_mov, attr, reg1, reg2);
4987                 }
4988                 return;
4989             }
4990
4991             reg1 = encodingSPtoZR(reg1);
4992             reg2 = encodingSPtoZR(reg2);
4993         }
4994
4995         if (unsigned_abs(imm) <= 0x0fff)
4996         {
4997             if (imm < 0)
4998             {
4999                 ins = insReverse(ins);
5000                 imm = -imm;
5001             }
5002             assert(isValidUimm12(imm));
5003             fmt = IF_DI_2A;
5004         }
5005         else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
5006         {
5007             // Encoding will use a 12-bit left shift of the immediate
5008             opt = INS_OPTS_LSL12;
5009             if (imm < 0)
5010             {
5011                 ins = insReverse(ins);
5012                 imm = -imm;
5013             }
5014             assert((imm & 0xfff) == 0);
5015             imm >>= 12;
5016             assert(isValidUimm12(imm));
5017             fmt = IF_DI_2A;
5018         }
5019         else
5020         {
5021             assert(!"Instruction cannot be encoded: IF_DI_2A");
5022         }
5023     }
5024
5025     assert(fmt != IF_NONE);
5026
5027     instrDesc* id = emitNewInstrSC(attr, imm);
5028
5029     id->idIns(ins);
5030     id->idInsFmt(fmt);
5031     id->idInsOpt(opt);
5032
5033     id->idReg1(reg1);
5034     id->idReg2(reg2);
5035
5036     dispIns(id);
5037     appendToCurIG(id);
5038 }
5039
5040 /*****************************************************************************
5041 *
5042 *  Add an instruction referencing two registers and a constant.
5043 *  Also checks for a large immediate that needs a second instruction
5044 *  and will load it in reg1
5045 *
5046 *  - Supports instructions: add, adds, sub, subs, and, ands, eor and orr
5047 *  - Requires that reg1 is a general register and not SP or ZR
5048 *  - Requires that reg1 != reg2
5049 */
5050 void emitter::emitIns_R_R_Imm(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm)
5051 {
5052     assert(isGeneralRegister(reg1));
5053     assert(reg1 != reg2);
5054
5055     bool immFits = true;
5056
5057     switch (ins)
5058     {
5059         case INS_add:
5060         case INS_adds:
5061         case INS_sub:
5062         case INS_subs:
5063             immFits = emitter::emitIns_valid_imm_for_add(imm, attr);
5064             break;
5065
5066         case INS_ands:
5067         case INS_and:
5068         case INS_eor:
5069         case INS_orr:
5070             immFits = emitter::emitIns_valid_imm_for_alu(imm, attr);
5071             break;
5072
5073         default:
5074             assert(!"Unsupported instruction in emitIns_R_R_Imm");
5075     }
5076
5077     if (immFits)
5078     {
5079         emitIns_R_R_I(ins, attr, reg1, reg2, imm);
5080     }
5081     else
5082     {
5083         // Load 'imm' into the reg1 register
5084         // then issue:   'ins'  reg1, reg2, reg1
5085         //
5086         codeGen->instGen_Set_Reg_To_Imm(attr, reg1, imm);
5087         emitIns_R_R_R(ins, attr, reg1, reg2, reg1);
5088     }
5089 }
5090
5091 /*****************************************************************************
5092  *
5093  *  Add an instruction referencing three registers.
5094  */
5095
5096 void emitter::emitIns_R_R_R(
5097     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insOpts opt) /* = INS_OPTS_NONE */
5098 {
5099     emitAttr  size     = EA_SIZE(attr);
5100     emitAttr  elemsize = EA_UNKNOWN;
5101     insFormat fmt      = IF_NONE;
5102
5103     /* Figure out the encoding format of the instruction */
5104     switch (ins)
5105     {
5106         case INS_lsl:
5107         case INS_lsr:
5108         case INS_asr:
5109         case INS_ror:
5110         case INS_adc:
5111         case INS_adcs:
5112         case INS_sbc:
5113         case INS_sbcs:
5114         case INS_udiv:
5115         case INS_sdiv:
5116         case INS_mneg:
5117         case INS_smull:
5118         case INS_smnegl:
5119         case INS_smulh:
5120         case INS_umull:
5121         case INS_umnegl:
5122         case INS_umulh:
5123         case INS_lslv:
5124         case INS_lsrv:
5125         case INS_asrv:
5126         case INS_rorv:
5127             assert(insOptsNone(opt));
5128             assert(isValidGeneralDatasize(size));
5129             assert(isGeneralRegister(reg1));
5130             assert(isGeneralRegister(reg2));
5131             assert(isGeneralRegister(reg3));
5132             fmt = IF_DR_3A;
5133             break;
5134
5135         case INS_mul:
5136             if (insOptsNone(opt))
5137             {
5138                 // general register
5139                 assert(isValidGeneralDatasize(size));
5140                 assert(isGeneralRegister(reg1));
5141                 assert(isGeneralRegister(reg2));
5142                 assert(isGeneralRegister(reg3));
5143                 fmt = IF_DR_3A;
5144                 break;
5145             }
5146             __fallthrough;
5147
5148         case INS_mla:
5149         case INS_mls:
5150         case INS_pmul:
5151             assert(insOptsAnyArrangement(opt));
5152             assert(isVectorRegister(reg1));
5153             assert(isVectorRegister(reg2));
5154             assert(isVectorRegister(reg3));
5155             assert(isValidVectorDatasize(size));
5156             assert(isValidArrangement(size, opt));
5157             elemsize = optGetElemsize(opt);
5158             if (ins == INS_pmul)
5159             {
5160                 assert(elemsize == EA_1BYTE); // only supports 8B or 16B
5161             }
5162             else // INS_mul, INS_mla, INS_mls
5163             {
5164                 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
5165             }
5166             fmt = IF_DV_3A;
5167             break;
5168
5169         case INS_add:
5170         case INS_sub:
5171             if (isVectorRegister(reg1))
5172             {
5173                 assert(isVectorRegister(reg2));
5174                 assert(isVectorRegister(reg3));
5175
5176                 if (insOptsAnyArrangement(opt))
5177                 {
5178                     // Vector operation
5179                     assert(opt != INS_OPTS_1D); // Reserved encoding
5180                     assert(isValidVectorDatasize(size));
5181                     assert(isValidArrangement(size, opt));
5182                     fmt = IF_DV_3A;
5183                 }
5184                 else
5185                 {
5186                     // Scalar operation
5187                     assert(insOptsNone(opt));
5188                     assert(size == EA_8BYTE);
5189                     fmt = IF_DV_3E;
5190                 }
5191                 break;
5192             }
5193             __fallthrough;
5194
5195         case INS_adds:
5196         case INS_subs:
5197             emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, INS_OPTS_NONE);
5198             return;
5199
5200         case INS_cmeq:
5201         case INS_cmge:
5202         case INS_cmgt:
5203         case INS_cmhi:
5204         case INS_cmhs:
5205         case INS_ctst:
5206             assert(isVectorRegister(reg1));
5207             assert(isVectorRegister(reg2));
5208             assert(isVectorRegister(reg3));
5209
5210             if (isValidVectorDatasize(size))
5211             {
5212                 // Vector operation
5213                 assert(insOptsAnyArrangement(opt));
5214                 assert(isValidArrangement(size, opt));
5215                 elemsize = optGetElemsize(opt);
5216                 fmt      = IF_DV_3A;
5217             }
5218             else
5219             {
5220                 NYI("Untested");
5221                 // Scalar operation
5222                 assert(size == EA_8BYTE); // Only Double supported
5223                 fmt = IF_DV_3E;
5224             }
5225             break;
5226
5227         case INS_fcmeq:
5228         case INS_fcmge:
5229         case INS_fcmgt:
5230             assert(isVectorRegister(reg1));
5231             assert(isVectorRegister(reg2));
5232             assert(isVectorRegister(reg3));
5233
5234             if (isValidVectorDatasize(size))
5235             {
5236                 // Vector operation
5237                 assert(insOptsAnyArrangement(opt));
5238                 assert(isValidArrangement(size, opt));
5239                 elemsize = optGetElemsize(opt);
5240                 assert((elemsize == EA_8BYTE) || (elemsize == EA_4BYTE)); // Only Double/Float supported
5241                 assert(opt != INS_OPTS_1D);                               // Reserved encoding
5242                 fmt = IF_DV_3B;
5243             }
5244             else
5245             {
5246                 NYI("Untested");
5247                 // Scalar operation
5248                 assert((size == EA_8BYTE) || (size == EA_4BYTE)); // Only Double/Float supported
5249                 fmt = IF_DV_3D;
5250             }
5251             break;
5252
5253         case INS_saba:
5254         case INS_sabd:
5255         case INS_smax:
5256         case INS_smin:
5257         case INS_uaba:
5258         case INS_uabd:
5259         case INS_umax:
5260         case INS_umin:
5261             assert(isVectorRegister(reg1));
5262             assert(isVectorRegister(reg2));
5263             assert(isVectorRegister(reg3));
5264             assert(insOptsAnyArrangement(opt));
5265
5266             // Vector operation
5267             assert(isValidVectorDatasize(size));
5268             assert(isValidArrangement(size, opt));
5269             elemsize = optGetElemsize(opt);
5270             assert(elemsize != EA_8BYTE); // can't use 2D or 1D
5271
5272             fmt = IF_DV_3A;
5273             break;
5274
5275         case INS_mov:
5276             assert(isVectorRegister(reg1));
5277             assert(isVectorRegister(reg2));
5278             assert(reg2 == reg3);
5279             assert(isValidVectorDatasize(size));
5280             // INS_mov is an alias for INS_orr (vector register)
5281             if (opt == INS_OPTS_NONE)
5282             {
5283                 elemsize = EA_1BYTE;
5284                 opt      = optMakeArrangement(size, elemsize);
5285             }
5286             assert(isValidArrangement(size, opt));
5287             fmt = IF_DV_3C;
5288             break;
5289
5290         case INS_and:
5291         case INS_bic:
5292         case INS_eor:
5293         case INS_orr:
5294         case INS_orn:
5295             if (isVectorRegister(reg1))
5296             {
5297                 assert(isValidVectorDatasize(size));
5298                 assert(isVectorRegister(reg2));
5299                 assert(isVectorRegister(reg3));
5300                 if (opt == INS_OPTS_NONE)
5301                 {
5302                     elemsize = EA_1BYTE;
5303                     opt      = optMakeArrangement(size, elemsize);
5304                 }
5305                 assert(isValidArrangement(size, opt));
5306                 fmt = IF_DV_3C;
5307                 break;
5308             }
5309             __fallthrough;
5310
5311         case INS_ands:
5312         case INS_bics:
5313         case INS_eon:
5314             emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, INS_OPTS_NONE);
5315             return;
5316
5317         case INS_bsl:
5318         case INS_bit:
5319         case INS_bif:
5320             assert(isValidVectorDatasize(size));
5321             assert(isVectorRegister(reg1));
5322             assert(isVectorRegister(reg2));
5323             assert(isVectorRegister(reg3));
5324             if (opt == INS_OPTS_NONE)
5325             {
5326                 elemsize = EA_1BYTE;
5327                 opt      = optMakeArrangement(size, elemsize);
5328             }
5329             assert(isValidArrangement(size, opt));
5330             fmt = IF_DV_3C;
5331             break;
5332
5333         case INS_fadd:
5334         case INS_fsub:
5335         case INS_fdiv:
5336         case INS_fmax:
5337         case INS_fmin:
5338         case INS_fabd:
5339         case INS_fmul:
5340         case INS_fmulx:
5341             assert(isVectorRegister(reg1));
5342             assert(isVectorRegister(reg2));
5343             assert(isVectorRegister(reg3));
5344             if (insOptsAnyArrangement(opt))
5345             {
5346                 // Vector operation
5347                 assert(isValidVectorDatasize(size));
5348                 assert(isValidArrangement(size, opt));
5349                 elemsize = optGetElemsize(opt);
5350                 assert(isValidVectorElemsizeFloat(elemsize));
5351                 assert(opt != INS_OPTS_1D); // Reserved encoding
5352                 fmt = IF_DV_3B;
5353             }
5354             else
5355             {
5356                 // Scalar operation
5357                 assert(insOptsNone(opt));
5358                 assert(isValidScalarDatasize(size));
5359                 fmt = IF_DV_3D;
5360             }
5361             break;
5362
5363         case INS_fnmul:
5364             // Scalar operation
5365             assert(insOptsNone(opt));
5366             assert(isVectorRegister(reg1));
5367             assert(isVectorRegister(reg2));
5368             assert(isVectorRegister(reg3));
5369             assert(isValidScalarDatasize(size));
5370             fmt = IF_DV_3D;
5371             break;
5372
5373         case INS_faddp:
5374         case INS_fmla:
5375         case INS_fmls:
5376             assert(isVectorRegister(reg1));
5377             assert(isVectorRegister(reg2));
5378             assert(isVectorRegister(reg3));
5379             assert(insOptsAnyArrangement(opt)); // no scalar encoding, use 4-operand 'fmadd' or 'fmsub'
5380
5381             // Vector operation
5382             assert(isValidVectorDatasize(size));
5383             assert(isValidArrangement(size, opt));
5384             elemsize = optGetElemsize(opt);
5385             assert(isValidVectorElemsizeFloat(elemsize));
5386             assert(opt != INS_OPTS_1D); // Reserved encoding
5387             fmt = IF_DV_3B;
5388             break;
5389
5390         case INS_ldr:
5391         case INS_ldrb:
5392         case INS_ldrh:
5393         case INS_ldrsb:
5394         case INS_ldrsh:
5395         case INS_ldrsw:
5396         case INS_str:
5397         case INS_strb:
5398         case INS_strh:
5399             emitIns_R_R_R_Ext(ins, attr, reg1, reg2, reg3, opt);
5400             return;
5401
5402         case INS_ldp:
5403         case INS_ldpsw:
5404         case INS_ldnp:
5405         case INS_stp:
5406         case INS_stnp:
5407             emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0);
5408             return;
5409
5410         case INS_stxr:
5411         case INS_stxrb:
5412         case INS_stxrh:
5413         case INS_stlxr:
5414         case INS_stlxrb:
5415         case INS_stlxrh:
5416             assert(isGeneralRegisterOrZR(reg1));
5417             assert(isGeneralRegisterOrZR(reg2));
5418             assert(isGeneralRegisterOrSP(reg3));
5419             fmt = IF_LS_3D;
5420             break;
5421
5422         case INS_casb:
5423         case INS_casab:
5424         case INS_casalb:
5425         case INS_caslb:
5426         case INS_cash:
5427         case INS_casah:
5428         case INS_casalh:
5429         case INS_caslh:
5430         case INS_cas:
5431         case INS_casa:
5432         case INS_casal:
5433         case INS_casl:
5434         case INS_ldaddb:
5435         case INS_ldaddab:
5436         case INS_ldaddalb:
5437         case INS_ldaddlb:
5438         case INS_ldaddh:
5439         case INS_ldaddah:
5440         case INS_ldaddalh:
5441         case INS_ldaddlh:
5442         case INS_ldadd:
5443         case INS_ldadda:
5444         case INS_ldaddal:
5445         case INS_ldaddl:
5446         case INS_swpb:
5447         case INS_swpab:
5448         case INS_swpalb:
5449         case INS_swplb:
5450         case INS_swph:
5451         case INS_swpah:
5452         case INS_swpalh:
5453         case INS_swplh:
5454         case INS_swp:
5455         case INS_swpa:
5456         case INS_swpal:
5457         case INS_swpl:
5458             assert(isGeneralRegisterOrZR(reg1));
5459             assert(isGeneralRegisterOrZR(reg2));
5460             assert(isGeneralRegisterOrSP(reg3));
5461             fmt = IF_LS_3E;
5462             break;
5463
5464         case INS_sha256h:
5465         case INS_sha256h2:
5466         case INS_sha256su1:
5467         case INS_sha1su0:
5468         case INS_sha1c:
5469         case INS_sha1p:
5470         case INS_sha1m:
5471             assert(isValidVectorDatasize(size));
5472             assert(isVectorRegister(reg1));
5473             assert(isVectorRegister(reg2));
5474             assert(isVectorRegister(reg3));
5475             if (opt == INS_OPTS_NONE)
5476             {
5477                 elemsize = EA_4BYTE;
5478                 opt      = optMakeArrangement(size, elemsize);
5479             }
5480             assert(isValidArrangement(size, opt));
5481             fmt = IF_DV_3F;
5482             break;
5483
5484         default:
5485             unreached();
5486             break;
5487
5488     } // end switch (ins)
5489
5490     assert(fmt != IF_NONE);
5491
5492     instrDesc* id = emitNewInstr(attr);
5493
5494     id->idIns(ins);
5495     id->idInsFmt(fmt);
5496     id->idInsOpt(opt);
5497
5498     id->idReg1(reg1);
5499     id->idReg2(reg2);
5500     id->idReg3(reg3);
5501
5502     dispIns(id);
5503     appendToCurIG(id);
5504 }
5505
5506 /*****************************************************************************
5507  *
5508  *  Add an instruction referencing three registers and a constant.
5509  */
5510
5511 void emitter::emitIns_R_R_R_I(instruction ins,
5512                               emitAttr    attr,
5513                               regNumber   reg1,
5514                               regNumber   reg2,
5515                               regNumber   reg3,
5516                               ssize_t     imm,
5517                               insOpts     opt /* = INS_OPTS_NONE */,
5518                               emitAttr    attrReg2 /* = EA_UNKNOWN */)
5519 {
5520     emitAttr  size     = EA_SIZE(attr);
5521     emitAttr  elemsize = EA_UNKNOWN;
5522     insFormat fmt      = IF_NONE;
5523     bool      isLdSt   = false;
5524     bool      isSIMD   = false;
5525     bool      isAddSub = false;
5526     bool      setFlags = false;
5527     unsigned  scale    = 0;
5528
5529     /* Figure out the encoding format of the instruction */
5530     switch (ins)
5531     {
5532         case INS_extr:
5533             assert(insOptsNone(opt));
5534             assert(isValidGeneralDatasize(size));
5535             assert(isGeneralRegister(reg1));
5536             assert(isGeneralRegister(reg2));
5537             assert(isGeneralRegister(reg3));
5538             assert(isValidImmShift(imm, size));
5539             fmt = IF_DR_3E;
5540             break;
5541
5542         case INS_and:
5543         case INS_ands:
5544         case INS_eor:
5545         case INS_orr:
5546         case INS_bic:
5547         case INS_bics:
5548         case INS_eon:
5549         case INS_orn:
5550             assert(isValidGeneralDatasize(size));
5551             assert(isGeneralRegister(reg1));
5552             assert(isGeneralRegister(reg2));
5553             assert(isGeneralRegister(reg3));
5554             assert(isValidImmShift(imm, size));
5555             if (imm == 0)
5556             {
5557                 assert(insOptsNone(opt)); // a zero imm, means no shift kind
5558                 fmt = IF_DR_3A;
5559             }
5560             else
5561             {
5562                 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
5563                 fmt = IF_DR_3B;
5564             }
5565             break;
5566
5567         case INS_fmul: // by element, imm[0..3] selects the element of reg3
5568         case INS_fmla:
5569         case INS_fmls:
5570         case INS_fmulx:
5571             assert(isVectorRegister(reg1));
5572             assert(isVectorRegister(reg2));
5573             assert(isVectorRegister(reg3));
5574             if (insOptsAnyArrangement(opt))
5575             {
5576                 // Vector operation
5577                 assert(isValidVectorDatasize(size));
5578                 assert(isValidArrangement(size, opt));
5579                 elemsize = optGetElemsize(opt);
5580                 assert(isValidVectorElemsizeFloat(elemsize));
5581                 assert(isValidVectorIndex(size, elemsize, imm));
5582                 assert(opt != INS_OPTS_1D); // Reserved encoding
5583                 fmt = IF_DV_3BI;
5584             }
5585             else
5586             {
5587                 // Scalar operation
5588                 assert(insOptsNone(opt));
5589                 assert(isValidScalarDatasize(size));
5590                 elemsize = size;
5591                 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
5592                 fmt = IF_DV_3DI;
5593             }
5594             break;
5595
5596         case INS_mul: // by element, imm[0..7] selects the element of reg3
5597         case INS_mla:
5598         case INS_mls:
5599             assert(isVectorRegister(reg1));
5600             assert(isVectorRegister(reg2));
5601             assert(isVectorRegister(reg3));
5602             // Vector operation
5603             assert(insOptsAnyArrangement(opt));
5604             assert(isValidVectorDatasize(size));
5605             assert(isValidArrangement(size, opt));
5606             elemsize = optGetElemsize(opt);
5607             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
5608             // Only has encodings for H or S elemsize
5609             assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE));
5610             // Only has encodings for V0..V15
5611             if ((elemsize == EA_2BYTE) && (reg3 >= REG_V16))
5612             {
5613                 noway_assert(!"Invalid reg3");
5614             }
5615             fmt = IF_DV_3AI;
5616             break;
5617
5618         case INS_add:
5619         case INS_sub:
5620             setFlags = false;
5621             isAddSub = true;
5622             break;
5623
5624         case INS_adds:
5625         case INS_subs:
5626             setFlags = true;
5627             isAddSub = true;
5628             break;
5629
5630         case INS_ldpsw:
5631             scale  = 2;
5632             isLdSt = true;
5633             break;
5634
5635         case INS_ldnp:
5636         case INS_stnp:
5637             assert(insOptsNone(opt)); // Can't use Pre/Post index on these two instructions
5638             __fallthrough;
5639
5640         case INS_ldp:
5641         case INS_stp:
5642             // Is the target a vector register?
5643             if (isVectorRegister(reg1))
5644             {
5645                 scale  = NaturalScale_helper(size);
5646                 isSIMD = true;
5647             }
5648             else
5649             {
5650                 scale = (size == EA_8BYTE) ? 3 : 2;
5651             }
5652             isLdSt = true;
5653             break;
5654
5655         default:
5656             unreached();
5657             break;
5658
5659     } // end switch (ins)
5660
5661     if (isLdSt)
5662     {
5663         assert(!isAddSub);
5664         assert(isGeneralRegisterOrSP(reg3));
5665         assert(insOptsNone(opt) || insOptsIndexed(opt));
5666
5667         if (isSIMD)
5668         {
5669             assert(isValidVectorLSPDatasize(size));
5670             assert(isVectorRegister(reg1));
5671             assert(isVectorRegister(reg2));
5672             assert((scale >= 2) && (scale <= 4));
5673         }
5674         else
5675         {
5676             assert(isValidGeneralDatasize(size));
5677             assert(isGeneralRegisterOrZR(reg1));
5678             assert(isGeneralRegisterOrZR(reg2));
5679             assert((scale == 2) || (scale == 3));
5680         }
5681
5682         // Load/Store Pair reserved encodings:
5683         if (emitInsIsLoad(ins))
5684         {
5685             assert(reg1 != reg2);
5686         }
5687         if (insOptsIndexed(opt))
5688         {
5689             assert(reg1 != reg3);
5690             assert(reg2 != reg3);
5691         }
5692
5693         reg3 = encodingSPtoZR(reg3);
5694
5695         ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
5696         if (imm == 0)
5697         {
5698             assert(insOptsNone(opt)); // PRE/POST Index doesn't make sense with an immediate of zero
5699
5700             fmt = IF_LS_3B;
5701         }
5702         else
5703         {
5704             if ((imm & mask) == 0)
5705             {
5706                 imm >>= scale; // The immediate is scaled by the size of the ld/st
5707
5708                 if ((imm >= -64) && (imm <= 63))
5709                 {
5710                     fmt = IF_LS_3C;
5711                 }
5712             }
5713 #ifdef DEBUG
5714             if (fmt != IF_LS_3C)
5715             {
5716                 assert(!"Instruction cannot be encoded: IF_LS_3C");
5717             }
5718 #endif
5719         }
5720     }
5721     else if (isAddSub)
5722     {
5723         bool reg2IsSP = (reg2 == REG_SP);
5724         assert(!isLdSt);
5725         assert(isValidGeneralDatasize(size));
5726         assert(isGeneralRegister(reg3));
5727
5728         if (setFlags || insOptsAluShift(opt)) // Can't encode SP in reg1 with setFlags or AluShift option
5729         {
5730             assert(isGeneralRegisterOrZR(reg1));
5731         }
5732         else
5733         {
5734             assert(isGeneralRegisterOrSP(reg1));
5735             reg1 = encodingSPtoZR(reg1);
5736         }
5737
5738         if (insOptsAluShift(opt)) // Can't encode SP in reg2 with AluShift option
5739         {
5740             assert(isGeneralRegister(reg2));
5741         }
5742         else
5743         {
5744             assert(isGeneralRegisterOrSP(reg2));
5745             reg2 = encodingSPtoZR(reg2);
5746         }
5747
5748         if (insOptsAnyExtend(opt))
5749         {
5750             assert((imm >= 0) && (imm <= 4));
5751
5752             fmt = IF_DR_3C;
5753         }
5754         else if (insOptsAluShift(opt))
5755         {
5756             // imm should be non-zero and in [1..63]
5757             assert(isValidImmShift(imm, size) && (imm != 0));
5758             fmt = IF_DR_3B;
5759         }
5760         else if (imm == 0)
5761         {
5762             assert(insOptsNone(opt));
5763
5764             if (reg2IsSP)
5765             {
5766                 // To encode the SP register as reg2 we must use the IF_DR_3C encoding
5767                 // and also specify a LSL of zero (imm == 0)
5768                 opt = INS_OPTS_LSL;
5769                 fmt = IF_DR_3C;
5770             }
5771             else
5772             {
5773                 fmt = IF_DR_3A;
5774             }
5775         }
5776         else
5777         {
5778             assert(!"Instruction cannot be encoded: Add/Sub IF_DR_3A");
5779         }
5780     }
5781     assert(fmt != IF_NONE);
5782
5783     instrDesc* id = emitNewInstrCns(attr, imm);
5784
5785     id->idIns(ins);
5786     id->idInsFmt(fmt);
5787     id->idInsOpt(opt);
5788
5789     id->idReg1(reg1);
5790     id->idReg2(reg2);
5791     id->idReg3(reg3);
5792
5793     // Record the attribute for the second register in the pair
5794     id->idGCrefReg2(GCT_NONE);
5795     if (attrReg2 != EA_UNKNOWN)
5796     {
5797         // Record the attribute for the second register in the pair
5798         assert((fmt == IF_LS_3B) || (fmt == IF_LS_3C));
5799         if (EA_IS_GCREF(attrReg2))
5800         {
5801             id->idGCrefReg2(GCT_GCREF);
5802         }
5803         else if (EA_IS_BYREF(attrReg2))
5804         {
5805             id->idGCrefReg2(GCT_BYREF);
5806         }
5807     }
5808
5809     dispIns(id);
5810     appendToCurIG(id);
5811 }
5812
5813 /*****************************************************************************
5814  *
5815  *  Add an instruction referencing three registers, with an extend option
5816  */
5817
5818 void emitter::emitIns_R_R_R_Ext(instruction ins,
5819                                 emitAttr    attr,
5820                                 regNumber   reg1,
5821                                 regNumber   reg2,
5822                                 regNumber   reg3,
5823                                 insOpts     opt,         /* = INS_OPTS_NONE */
5824                                 int         shiftAmount) /* = -1 -- unset   */
5825 {
5826     emitAttr  size   = EA_SIZE(attr);
5827     insFormat fmt    = IF_NONE;
5828     bool      isSIMD = false;
5829     int       scale  = -1;
5830
5831     /* Figure out the encoding format of the instruction */
5832     switch (ins)
5833     {
5834         case INS_ldrb:
5835         case INS_ldrsb:
5836         case INS_strb:
5837             scale = 0;
5838             break;
5839
5840         case INS_ldrh:
5841         case INS_ldrsh:
5842         case INS_strh:
5843             scale = 1;
5844             break;
5845
5846         case INS_ldrsw:
5847             scale = 2;
5848             break;
5849
5850         case INS_ldr:
5851         case INS_str:
5852             // Is the target a vector register?
5853             if (isVectorRegister(reg1))
5854             {
5855                 assert(isValidVectorLSDatasize(size));
5856                 scale  = NaturalScale_helper(size);
5857                 isSIMD = true;
5858             }
5859             else
5860             {
5861                 assert(isValidGeneralDatasize(size));
5862                 scale = (size == EA_8BYTE) ? 3 : 2;
5863             }
5864
5865             break;
5866
5867         default:
5868             unreached();
5869             break;
5870
5871     } // end switch (ins)
5872
5873     assert(scale != -1);
5874     assert(insOptsLSExtend(opt));
5875
5876     if (isSIMD)
5877     {
5878         assert(isValidVectorLSDatasize(size));
5879         assert(isVectorRegister(reg1));
5880     }
5881     else
5882     {
5883         assert(isValidGeneralLSDatasize(size));
5884         assert(isGeneralRegisterOrZR(reg1));
5885     }
5886
5887     assert(isGeneralRegisterOrSP(reg2));
5888     assert(isGeneralRegister(reg3));
5889
5890     // Load/Store reserved encodings:
5891     if (insOptsIndexed(opt))
5892     {
5893         assert(reg1 != reg2);
5894     }
5895
5896     if (shiftAmount == -1)
5897     {
5898         shiftAmount = insOptsLSL(opt) ? scale : 0;
5899     }
5900     assert((shiftAmount == scale) || (shiftAmount == 0));
5901
5902     reg2 = encodingSPtoZR(reg2);
5903     fmt  = IF_LS_3A;
5904
5905     instrDesc* id = emitNewInstr(attr);
5906
5907     id->idIns(ins);
5908     id->idInsFmt(fmt);
5909     id->idInsOpt(opt);
5910
5911     id->idReg1(reg1);
5912     id->idReg2(reg2);
5913     id->idReg3(reg3);
5914     id->idReg3Scaled(shiftAmount == scale);
5915
5916     dispIns(id);
5917     appendToCurIG(id);
5918 }
5919
5920 /*****************************************************************************
5921  *
5922  *  Add an instruction referencing two registers and two constants.
5923  */
5924
5925 void emitter::emitIns_R_R_I_I(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, int imm1, int imm2)
5926 {
5927     emitAttr  size     = EA_SIZE(attr);
5928     emitAttr  elemsize = EA_UNKNOWN;
5929     insFormat fmt      = IF_NONE;
5930     size_t    immOut   = 0; // composed from imm1 and imm2 and stored in the instrDesc
5931
5932     /* Figure out the encoding format of the instruction */
5933     switch (ins)
5934     {
5935         int        lsb;
5936         int        width;
5937         bitMaskImm bmi;
5938
5939         case INS_bfm:
5940         case INS_sbfm:
5941         case INS_ubfm:
5942             assert(isGeneralRegister(reg1));
5943             assert(isGeneralRegister(reg2));
5944             assert(isValidImmShift(imm1, size));
5945             assert(isValidImmShift(imm2, size));
5946             bmi.immNRS = 0;
5947             bmi.immN   = (size == EA_8BYTE);
5948             bmi.immR   = imm1;
5949             bmi.immS   = imm2;
5950             immOut     = bmi.immNRS;
5951             fmt        = IF_DI_2D;
5952             break;
5953
5954         case INS_bfi:
5955         case INS_sbfiz:
5956         case INS_ubfiz:
5957             assert(isGeneralRegister(reg1));
5958             assert(isGeneralRegister(reg2));
5959             lsb   = getBitWidth(size) - imm1;
5960             width = imm2 - 1;
5961             assert(isValidImmShift(lsb, size));
5962             assert(isValidImmShift(width, size));
5963             bmi.immNRS = 0;
5964             bmi.immN   = (size == EA_8BYTE);
5965             bmi.immR   = lsb;
5966             bmi.immS   = width;
5967             immOut     = bmi.immNRS;
5968             fmt        = IF_DI_2D;
5969             break;
5970
5971         case INS_bfxil:
5972         case INS_sbfx:
5973         case INS_ubfx:
5974             assert(isGeneralRegister(reg1));
5975             assert(isGeneralRegister(reg2));
5976             lsb   = imm1;
5977             width = imm2 + imm1 - 1;
5978             assert(isValidImmShift(lsb, size));
5979             assert(isValidImmShift(width, size));
5980             bmi.immNRS = 0;
5981             bmi.immN   = (size == EA_8BYTE);
5982             bmi.immR   = imm1;
5983             bmi.immS   = imm2 + imm1 - 1;
5984             immOut     = bmi.immNRS;
5985             fmt        = IF_DI_2D;
5986             break;
5987
5988         case INS_mov:
5989         case INS_ins:
5990             assert(isVectorRegister(reg1));
5991             assert(isVectorRegister(reg2));
5992             elemsize = size;
5993             assert(isValidVectorElemsize(elemsize));
5994             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm1));
5995             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm2));
5996             immOut = (imm1 << 4) + imm2;
5997             fmt    = IF_DV_2F;
5998             break;
5999
6000         default:
6001             unreached();
6002             break;
6003     }
6004     assert(fmt != IF_NONE);
6005
6006     instrDesc* id = emitNewInstrSC(attr, immOut);
6007
6008     id->idIns(ins);
6009     id->idInsFmt(fmt);
6010
6011     id->idReg1(reg1);
6012     id->idReg2(reg2);
6013
6014     dispIns(id);
6015     appendToCurIG(id);
6016 }
6017
6018 /*****************************************************************************
6019  *
6020  *  Add an instruction referencing four registers.
6021  */
6022
6023 void emitter::emitIns_R_R_R_R(
6024     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, regNumber reg4)
6025 {
6026     emitAttr  size = EA_SIZE(attr);
6027     insFormat fmt  = IF_NONE;
6028
6029     /* Figure out the encoding format of the instruction */
6030     switch (ins)
6031     {
6032         case INS_madd:
6033         case INS_msub:
6034         case INS_smaddl:
6035         case INS_smsubl:
6036         case INS_umaddl:
6037         case INS_umsubl:
6038             assert(isValidGeneralDatasize(size));
6039             assert(isGeneralRegister(reg1));
6040             assert(isGeneralRegister(reg2));
6041             assert(isGeneralRegister(reg3));
6042             assert(isGeneralRegister(reg4));
6043             fmt = IF_DR_4A;
6044             break;
6045
6046         case INS_fmadd:
6047         case INS_fmsub:
6048         case INS_fnmadd:
6049         case INS_fnmsub:
6050             // Scalar operation
6051             assert(isValidScalarDatasize(size));
6052             assert(isVectorRegister(reg1));
6053             assert(isVectorRegister(reg2));
6054             assert(isVectorRegister(reg3));
6055             assert(isVectorRegister(reg4));
6056             fmt = IF_DV_4A;
6057             break;
6058
6059         case INS_invalid:
6060             fmt = IF_NONE;
6061             break;
6062
6063         default:
6064             unreached();
6065             break;
6066     }
6067     assert(fmt != IF_NONE);
6068
6069     instrDesc* id = emitNewInstr(attr);
6070
6071     id->idIns(ins);
6072     id->idInsFmt(fmt);
6073
6074     id->idReg1(reg1);
6075     id->idReg2(reg2);
6076     id->idReg3(reg3);
6077     id->idReg4(reg4);
6078
6079     dispIns(id);
6080     appendToCurIG(id);
6081 }
6082
6083 /*****************************************************************************
6084  *
6085  *  Add an instruction referencing a register and a condition code
6086  */
6087
6088 void emitter::emitIns_R_COND(instruction ins, emitAttr attr, regNumber reg, insCond cond)
6089 {
6090     insFormat    fmt = IF_NONE;
6091     condFlagsImm cfi;
6092     cfi.immCFVal = 0;
6093
6094     /* Figure out the encoding format of the instruction */
6095     switch (ins)
6096     {
6097         case INS_cset:
6098         case INS_csetm:
6099             assert(isGeneralRegister(reg));
6100             cfi.cond = cond;
6101             fmt      = IF_DR_1D;
6102             break;
6103
6104         default:
6105             unreached();
6106             break;
6107
6108     } // end switch (ins)
6109
6110     assert(fmt != IF_NONE);
6111     assert(isValidImmCond(cfi.immCFVal));
6112
6113     instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6114
6115     id->idIns(ins);
6116     id->idInsFmt(fmt);
6117     id->idInsOpt(INS_OPTS_NONE);
6118
6119     id->idReg1(reg);
6120
6121     dispIns(id);
6122     appendToCurIG(id);
6123 }
6124
6125 /*****************************************************************************
6126  *
6127  *  Add an instruction referencing two registers and a condition code
6128  */
6129
6130 void emitter::emitIns_R_R_COND(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insCond cond)
6131 {
6132     insFormat    fmt = IF_NONE;
6133     condFlagsImm cfi;
6134     cfi.immCFVal = 0;
6135
6136     /* Figure out the encoding format of the instruction */
6137     switch (ins)
6138     {
6139         case INS_cinc:
6140         case INS_cinv:
6141         case INS_cneg:
6142             assert(isGeneralRegister(reg1));
6143             assert(isGeneralRegister(reg2));
6144             cfi.cond = cond;
6145             fmt      = IF_DR_2D;
6146             break;
6147         default:
6148             unreached();
6149             break;
6150
6151     } // end switch (ins)
6152
6153     assert(fmt != IF_NONE);
6154     assert(isValidImmCond(cfi.immCFVal));
6155
6156     instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6157
6158     id->idIns(ins);
6159     id->idInsFmt(fmt);
6160     id->idInsOpt(INS_OPTS_NONE);
6161
6162     id->idReg1(reg1);
6163     id->idReg2(reg2);
6164
6165     dispIns(id);
6166     appendToCurIG(id);
6167 }
6168
6169 /*****************************************************************************
6170  *
6171  *  Add an instruction referencing two registers and a condition code
6172  */
6173
6174 void emitter::emitIns_R_R_R_COND(
6175     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insCond cond)
6176 {
6177     insFormat    fmt = IF_NONE;
6178     condFlagsImm cfi;
6179     cfi.immCFVal = 0;
6180
6181     /* Figure out the encoding format of the instruction */
6182     switch (ins)
6183     {
6184         case INS_csel:
6185         case INS_csinc:
6186         case INS_csinv:
6187         case INS_csneg:
6188             assert(isGeneralRegister(reg1));
6189             assert(isGeneralRegister(reg2));
6190             assert(isGeneralRegister(reg3));
6191             cfi.cond = cond;
6192             fmt      = IF_DR_3D;
6193             break;
6194
6195         default:
6196             unreached();
6197             break;
6198
6199     } // end switch (ins)
6200
6201     assert(fmt != IF_NONE);
6202     assert(isValidImmCond(cfi.immCFVal));
6203
6204     instrDesc* id = emitNewInstr(attr);
6205
6206     id->idIns(ins);
6207     id->idInsFmt(fmt);
6208     id->idInsOpt(INS_OPTS_NONE);
6209
6210     id->idReg1(reg1);
6211     id->idReg2(reg2);
6212     id->idReg3(reg3);
6213     id->idSmallCns(cfi.immCFVal);
6214
6215     dispIns(id);
6216     appendToCurIG(id);
6217 }
6218
6219 /*****************************************************************************
6220  *
6221  *  Add an instruction referencing two registers the flags and a condition code
6222  */
6223
6224 void emitter::emitIns_R_R_FLAGS_COND(
6225     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insCflags flags, insCond cond)
6226 {
6227     insFormat    fmt = IF_NONE;
6228     condFlagsImm cfi;
6229     cfi.immCFVal = 0;
6230
6231     /* Figure out the encoding format of the instruction */
6232     switch (ins)
6233     {
6234         case INS_ccmp:
6235         case INS_ccmn:
6236             assert(isGeneralRegister(reg1));
6237             assert(isGeneralRegister(reg2));
6238             cfi.flags = flags;
6239             cfi.cond  = cond;
6240             fmt       = IF_DR_2I;
6241             break;
6242         default:
6243             unreached();
6244             break;
6245     } // end switch (ins)
6246
6247     assert(fmt != IF_NONE);
6248     assert(isValidImmCondFlags(cfi.immCFVal));
6249
6250     instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6251
6252     id->idIns(ins);
6253     id->idInsFmt(fmt);
6254     id->idInsOpt(INS_OPTS_NONE);
6255
6256     id->idReg1(reg1);
6257     id->idReg2(reg2);
6258
6259     dispIns(id);
6260     appendToCurIG(id);
6261 }
6262
6263 /*****************************************************************************
6264  *
6265  *  Add an instruction referencing a register, an immediate, the flags and a condition code
6266  */
6267
6268 void emitter::emitIns_R_I_FLAGS_COND(
6269     instruction ins, emitAttr attr, regNumber reg, int imm, insCflags flags, insCond cond)
6270 {
6271     insFormat    fmt = IF_NONE;
6272     condFlagsImm cfi;
6273     cfi.immCFVal = 0;
6274
6275     /* Figure out the encoding format of the instruction */
6276     switch (ins)
6277     {
6278         case INS_ccmp:
6279         case INS_ccmn:
6280             assert(isGeneralRegister(reg));
6281             if (imm < 0)
6282             {
6283                 ins = insReverse(ins);
6284                 imm = -imm;
6285             }
6286             if ((imm >= 0) && (imm <= 31))
6287             {
6288                 cfi.imm5  = imm;
6289                 cfi.flags = flags;
6290                 cfi.cond  = cond;
6291                 fmt       = IF_DI_1F;
6292             }
6293             else
6294             {
6295                 assert(!"Instruction cannot be encoded: ccmp/ccmn imm5");
6296             }
6297             break;
6298         default:
6299             unreached();
6300             break;
6301     } // end switch (ins)
6302
6303     assert(fmt != IF_NONE);
6304     assert(isValidImmCondFlagsImm5(cfi.immCFVal));
6305
6306     instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6307
6308     id->idIns(ins);
6309     id->idInsFmt(fmt);
6310     id->idInsOpt(INS_OPTS_NONE);
6311
6312     id->idReg1(reg);
6313
6314     dispIns(id);
6315     appendToCurIG(id);
6316 }
6317
6318 /*****************************************************************************
6319  *
6320  *  Add a memory barrier instruction with a 'barrier' immediate
6321  */
6322
6323 void emitter::emitIns_BARR(instruction ins, insBarrier barrier)
6324 {
6325     insFormat fmt = IF_NONE;
6326     ssize_t   imm = 0;
6327
6328     /* Figure out the encoding format of the instruction */
6329     switch (ins)
6330     {
6331         case INS_dsb:
6332         case INS_dmb:
6333         case INS_isb:
6334
6335             fmt = IF_SI_0B;
6336             imm = (ssize_t)barrier;
6337             break;
6338         default:
6339             unreached();
6340             break;
6341     } // end switch (ins)
6342
6343     assert(fmt != IF_NONE);
6344
6345     instrDesc* id = emitNewInstrSC(EA_8BYTE, imm);
6346
6347     id->idIns(ins);
6348     id->idInsFmt(fmt);
6349     id->idInsOpt(INS_OPTS_NONE);
6350
6351     dispIns(id);
6352     appendToCurIG(id);
6353 }
6354
6355 /*****************************************************************************
6356  *
6357  *  Add an instruction with a static data member operand. If 'size' is 0, the
6358  *  instruction operates on the address of the static member instead of its
6359  *  value (e.g. "push offset clsvar", rather than "push dword ptr [clsvar]").
6360  */
6361
6362 void emitter::emitIns_C(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, int offs)
6363 {
6364     NYI("emitIns_C");
6365 }
6366
6367 /*****************************************************************************
6368  *
6369  *  Add an instruction referencing stack-based local variable.
6370  */
6371
6372 void emitter::emitIns_S(instruction ins, emitAttr attr, int varx, int offs)
6373 {
6374     NYI("emitIns_S");
6375 }
6376
6377 /*****************************************************************************
6378  *
6379  *  Add an instruction referencing a register and a stack-based local variable.
6380  */
6381 void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
6382 {
6383     emitAttr  size  = EA_SIZE(attr);
6384     insFormat fmt   = IF_NONE;
6385     int       disp  = 0;
6386     unsigned  scale = 0;
6387
6388     assert(offs >= 0);
6389
6390     // TODO-ARM64-CQ: use unscaled loads?
6391     /* Figure out the encoding format of the instruction */
6392     switch (ins)
6393     {
6394         case INS_strb:
6395         case INS_ldrb:
6396         case INS_ldrsb:
6397             scale = 0;
6398             break;
6399
6400         case INS_strh:
6401         case INS_ldrh:
6402         case INS_ldrsh:
6403             scale = 1;
6404             break;
6405
6406         case INS_ldrsw:
6407             scale = 2;
6408             break;
6409
6410         case INS_str:
6411         case INS_ldr:
6412             assert(isValidGeneralDatasize(size) || isValidVectorDatasize(size));
6413             scale = genLog2(EA_SIZE_IN_BYTES(size));
6414             break;
6415
6416         case INS_lea:
6417             assert(size == EA_8BYTE);
6418             scale = 0;
6419             break;
6420
6421         default:
6422             NYI("emitIns_R_S"); // FP locals?
6423             return;
6424
6425     } // end switch (ins)
6426
6427     /* Figure out the variable's frame position */
6428     ssize_t imm;
6429     int     base;
6430     bool    FPbased;
6431
6432     base = emitComp->lvaFrameAddress(varx, &FPbased);
6433     disp = base + offs;
6434     assert((scale >= 0) && (scale <= 4));
6435
6436     regNumber reg2 = FPbased ? REG_FPBASE : REG_SPBASE;
6437     reg2           = encodingSPtoZR(reg2);
6438
6439     if (ins == INS_lea)
6440     {
6441         if (disp >= 0)
6442         {
6443             ins = INS_add;
6444             imm = disp;
6445         }
6446         else
6447         {
6448             ins = INS_sub;
6449             imm = -disp;
6450         }
6451
6452         if (imm <= 0x0fff)
6453         {
6454             fmt = IF_DI_2A; // add reg1,reg2,#disp
6455         }
6456         else
6457         {
6458             regNumber rsvdReg = codeGen->rsGetRsvdReg();
6459             codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6460             fmt = IF_DR_3A; // add reg1,reg2,rsvdReg
6461         }
6462     }
6463     else
6464     {
6465         bool    useRegForImm = false;
6466         ssize_t mask         = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6467
6468         imm = disp;
6469         if (imm == 0)
6470         {
6471             fmt = IF_LS_2A;
6472         }
6473         else if ((imm < 0) || ((imm & mask) != 0))
6474         {
6475             if ((imm >= -256) && (imm <= 255))
6476             {
6477                 fmt = IF_LS_2C;
6478             }
6479             else
6480             {
6481                 useRegForImm = true;
6482             }
6483         }
6484         else if (imm > 0)
6485         {
6486             if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
6487             {
6488                 imm >>= scale; // The immediate is scaled by the size of the ld/st
6489
6490                 fmt = IF_LS_2B;
6491             }
6492             else
6493             {
6494                 useRegForImm = true;
6495             }
6496         }
6497
6498         if (useRegForImm)
6499         {
6500             regNumber rsvdReg = codeGen->rsGetRsvdReg();
6501             codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6502             fmt = IF_LS_3A;
6503         }
6504     }
6505
6506     assert(fmt != IF_NONE);
6507
6508     instrDesc* id = emitNewInstrCns(attr, imm);
6509
6510     id->idIns(ins);
6511     id->idInsFmt(fmt);
6512     id->idInsOpt(INS_OPTS_NONE);
6513
6514     id->idReg1(reg1);
6515     id->idReg2(reg2);
6516     id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6517     id->idSetIsLclVar();
6518
6519 #ifdef DEBUG
6520     id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6521 #endif
6522
6523     dispIns(id);
6524     appendToCurIG(id);
6525 }
6526
6527 /*****************************************************************************
6528  *
6529  *  Add an instruction referencing two register and consectutive stack-based local variable slots.
6530  */
6531 void emitter::emitIns_R_R_S_S(
6532     instruction ins, emitAttr attr1, emitAttr attr2, regNumber reg1, regNumber reg2, int varx, int offs)
6533 {
6534     assert((ins == INS_ldp) || (ins == INS_ldnp));
6535     assert(EA_8BYTE == EA_SIZE(attr1));
6536     assert(EA_8BYTE == EA_SIZE(attr2));
6537     assert(isGeneralRegisterOrZR(reg1));
6538     assert(isGeneralRegisterOrZR(reg2));
6539     assert(offs >= 0);
6540
6541     insFormat      fmt   = IF_LS_3B;
6542     int            disp  = 0;
6543     const unsigned scale = 3;
6544
6545     /* Figure out the variable's frame position */
6546     int  base;
6547     bool FPbased;
6548
6549     base = emitComp->lvaFrameAddress(varx, &FPbased);
6550     disp = base + offs;
6551
6552     // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6553     regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE;
6554     reg3           = encodingSPtoZR(reg3);
6555
6556     bool    useRegForAdr = true;
6557     ssize_t imm          = disp;
6558     ssize_t mask         = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6559     if (imm == 0)
6560     {
6561         useRegForAdr = false;
6562     }
6563     else
6564     {
6565         if ((imm & mask) == 0)
6566         {
6567             ssize_t immShift = imm >> scale; // The immediate is scaled by the size of the ld/st
6568
6569             if ((immShift >= -64) && (immShift <= 63))
6570             {
6571                 fmt          = IF_LS_3C;
6572                 useRegForAdr = false;
6573                 imm          = immShift;
6574             }
6575         }
6576     }
6577
6578     if (useRegForAdr)
6579     {
6580         regNumber rsvd = codeGen->rsGetRsvdReg();
6581         emitIns_R_R_Imm(INS_add, EA_PTRSIZE, rsvd, reg3, imm);
6582         reg3 = rsvd;
6583         imm  = 0;
6584     }
6585
6586     assert(fmt != IF_NONE);
6587
6588     instrDesc* id = emitNewInstrCns(attr1, imm);
6589
6590     id->idIns(ins);
6591     id->idInsFmt(fmt);
6592     id->idInsOpt(INS_OPTS_NONE);
6593
6594     // Record the attribute for the second register in the pair
6595     if (EA_IS_GCREF(attr2))
6596     {
6597         id->idGCrefReg2(GCT_GCREF);
6598     }
6599     else if (EA_IS_BYREF(attr2))
6600     {
6601         id->idGCrefReg2(GCT_BYREF);
6602     }
6603     else
6604     {
6605         id->idGCrefReg2(GCT_NONE);
6606     }
6607
6608     id->idReg1(reg1);
6609     id->idReg2(reg2);
6610     id->idReg3(reg3);
6611     id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6612     id->idSetIsLclVar();
6613
6614 #ifdef DEBUG
6615     id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6616 #endif
6617
6618     dispIns(id);
6619     appendToCurIG(id);
6620 }
6621
6622 /*****************************************************************************
6623  *
6624  *  Add an instruction referencing a stack-based local variable and a register
6625  */
6626 void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
6627 {
6628     assert(offs >= 0);
6629     emitAttr  size          = EA_SIZE(attr);
6630     insFormat fmt           = IF_NONE;
6631     int       disp          = 0;
6632     unsigned  scale         = 0;
6633     bool      isVectorStore = false;
6634
6635     // TODO-ARM64-CQ: use unscaled loads?
6636     /* Figure out the encoding format of the instruction */
6637     switch (ins)
6638     {
6639         case INS_strb:
6640             scale = 0;
6641             assert(isGeneralRegisterOrZR(reg1));
6642             break;
6643
6644         case INS_strh:
6645             scale = 1;
6646             assert(isGeneralRegisterOrZR(reg1));
6647             break;
6648
6649         case INS_str:
6650             if (isGeneralRegisterOrZR(reg1))
6651             {
6652                 assert(isValidGeneralDatasize(size));
6653                 scale = (size == EA_8BYTE) ? 3 : 2;
6654             }
6655             else
6656             {
6657                 assert(isVectorRegister(reg1));
6658                 assert(isValidVectorLSDatasize(size));
6659                 scale         = NaturalScale_helper(size);
6660                 isVectorStore = true;
6661             }
6662             break;
6663
6664         default:
6665             NYI("emitIns_S_R"); // FP locals?
6666             return;
6667
6668     } // end switch (ins)
6669
6670     /* Figure out the variable's frame position */
6671     int  base;
6672     bool FPbased;
6673
6674     base = emitComp->lvaFrameAddress(varx, &FPbased);
6675     disp = base + offs;
6676     assert(scale >= 0);
6677     if (isVectorStore)
6678     {
6679         assert(scale <= 4);
6680     }
6681     else
6682     {
6683         assert(scale <= 3);
6684     }
6685
6686     // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6687     regNumber reg2 = FPbased ? REG_FPBASE : REG_SPBASE;
6688     reg2           = encodingSPtoZR(reg2);
6689
6690     bool    useRegForImm = false;
6691     ssize_t imm          = disp;
6692     ssize_t mask         = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6693     if (imm == 0)
6694     {
6695         fmt = IF_LS_2A;
6696     }
6697     else if ((imm < 0) || ((imm & mask) != 0))
6698     {
6699         if ((imm >= -256) && (imm <= 255))
6700         {
6701             fmt = IF_LS_2C;
6702         }
6703         else
6704         {
6705             useRegForImm = true;
6706         }
6707     }
6708     else if (imm > 0)
6709     {
6710         if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
6711         {
6712             imm >>= scale; // The immediate is scaled by the size of the ld/st
6713
6714             fmt = IF_LS_2B;
6715         }
6716         else
6717         {
6718             useRegForImm = true;
6719         }
6720     }
6721
6722     if (useRegForImm)
6723     {
6724         // The reserved register is not stored in idReg3() since that field overlaps with iiaLclVar.
6725         // It is instead implicit when idSetIsLclVar() is set, with this encoding format.
6726         regNumber rsvdReg = codeGen->rsGetRsvdReg();
6727         codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6728         fmt = IF_LS_3A;
6729     }
6730
6731     assert(fmt != IF_NONE);
6732
6733     instrDesc* id = emitNewInstrCns(attr, imm);
6734
6735     id->idIns(ins);
6736     id->idInsFmt(fmt);
6737     id->idInsOpt(INS_OPTS_NONE);
6738
6739     id->idReg1(reg1);
6740     id->idReg2(reg2);
6741     id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6742     id->idSetIsLclVar();
6743
6744 #ifdef DEBUG
6745     id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6746 #endif
6747
6748     dispIns(id);
6749     appendToCurIG(id);
6750 }
6751
6752 /*****************************************************************************
6753  *
6754  *  Add an instruction referencing consecutive stack-based local variable slots and two registers
6755  */
6756 void emitter::emitIns_S_S_R_R(
6757     instruction ins, emitAttr attr1, emitAttr attr2, regNumber reg1, regNumber reg2, int varx, int offs)
6758 {
6759     assert((ins == INS_stp) || (ins == INS_stnp));
6760     assert(EA_8BYTE == EA_SIZE(attr1));
6761     assert(EA_8BYTE == EA_SIZE(attr2));
6762     assert(isGeneralRegisterOrZR(reg1));
6763     assert(isGeneralRegisterOrZR(reg2));
6764     assert(offs >= 0);
6765
6766     insFormat      fmt   = IF_LS_3B;
6767     int            disp  = 0;
6768     const unsigned scale = 3;
6769
6770     /* Figure out the variable's frame position */
6771     int  base;
6772     bool FPbased;
6773
6774     base = emitComp->lvaFrameAddress(varx, &FPbased);
6775     disp = base + offs;
6776
6777     // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6778     regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE;
6779
6780     bool    useRegForAdr = true;
6781     ssize_t imm          = disp;
6782     ssize_t mask         = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6783     if (imm == 0)
6784     {
6785         useRegForAdr = false;
6786     }
6787     else
6788     {
6789         if ((imm & mask) == 0)
6790         {
6791             ssize_t immShift = imm >> scale; // The immediate is scaled by the size of the ld/st
6792
6793             if ((immShift >= -64) && (immShift <= 63))
6794             {
6795                 fmt          = IF_LS_3C;
6796                 useRegForAdr = false;
6797                 imm          = immShift;
6798             }
6799         }
6800     }
6801
6802     if (useRegForAdr)
6803     {
6804         regNumber rsvd = codeGen->rsGetRsvdReg();
6805         emitIns_R_R_Imm(INS_add, EA_PTRSIZE, rsvd, reg3, imm);
6806         reg3 = rsvd;
6807         imm  = 0;
6808     }
6809
6810     assert(fmt != IF_NONE);
6811
6812     instrDesc* id = emitNewInstrCns(attr1, imm);
6813
6814     id->idIns(ins);
6815     id->idInsFmt(fmt);
6816     id->idInsOpt(INS_OPTS_NONE);
6817
6818     // Record the attribute for the second register in the pair
6819     if (EA_IS_GCREF(attr2))
6820     {
6821         id->idGCrefReg2(GCT_GCREF);
6822     }
6823     else if (EA_IS_BYREF(attr2))
6824     {
6825         id->idGCrefReg2(GCT_BYREF);
6826     }
6827     else
6828     {
6829         id->idGCrefReg2(GCT_NONE);
6830     }
6831
6832     reg3 = encodingSPtoZR(reg3);
6833
6834     id->idReg1(reg1);
6835     id->idReg2(reg2);
6836     id->idReg3(reg3);
6837     id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6838     id->idSetIsLclVar();
6839
6840 #ifdef DEBUG
6841     id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6842 #endif
6843
6844     dispIns(id);
6845     appendToCurIG(id);
6846 }
6847
6848 /*****************************************************************************
6849  *
6850  *  Add an instruction referencing stack-based local variable and an immediate
6851  */
6852 void emitter::emitIns_S_I(instruction ins, emitAttr attr, int varx, int offs, int val)
6853 {
6854     NYI("emitIns_S_I");
6855 }
6856
6857 /*****************************************************************************
6858  *
6859  *  Add an instruction with a register + static member operands.
6860  *  Constant is stored into JIT data which is adjacent to code.
6861  *  No relocation is needed. PC-relative offset will be encoded directly into instruction.
6862  *
6863  */
6864 void emitter::emitIns_R_C(
6865     instruction ins, emitAttr attr, regNumber reg, regNumber addrReg, CORINFO_FIELD_HANDLE fldHnd, int offs)
6866 {
6867     assert(offs >= 0);
6868     assert(instrDesc::fitsInSmallCns(offs));
6869
6870     emitAttr      size = EA_SIZE(attr);
6871     insFormat     fmt  = IF_NONE;
6872     instrDescJmp* id   = emitNewInstrJmp();
6873
6874     switch (ins)
6875     {
6876         case INS_adr:
6877             // This is case to get address to the constant data.
6878             fmt = IF_LARGEADR;
6879             assert(isGeneralRegister(reg));
6880             assert(isValidGeneralDatasize(size));
6881             break;
6882
6883         case INS_ldr:
6884             fmt = IF_LARGELDC;
6885             if (isVectorRegister(reg))
6886             {
6887                 assert(isValidScalarDatasize(size));
6888                 // For vector (float/double) register, we should have an integer address reg to
6889                 // compute long address which consists of page address and page offset.
6890                 // For integer constant, this is not needed since the dest reg can be used to
6891                 // compute address as well as contain the final contents.
6892                 assert(isGeneralRegister(reg) || (addrReg != REG_NA));
6893             }
6894             else
6895             {
6896                 assert(isGeneralRegister(reg));
6897                 assert(isValidGeneralDatasize(size));
6898             }
6899             break;
6900         default:
6901             unreached();
6902     }
6903
6904     assert(fmt != IF_NONE);
6905
6906     id->idIns(ins);
6907     id->idInsFmt(fmt);
6908     id->idInsOpt(INS_OPTS_NONE);
6909     id->idSmallCns(offs);
6910     id->idOpSize(size);
6911     id->idAddr()->iiaFieldHnd = fldHnd;
6912     id->idSetIsBound(); // We won't patch address since we will know the exact distance once JIT code and data are
6913                         // allocated together.
6914
6915     id->idReg1(reg); // destination register that will get the constant value.
6916     if (addrReg != REG_NA)
6917     {
6918         id->idReg2(addrReg); // integer register to compute long address (used for vector dest when we end up with long
6919                              // address)
6920     }
6921     id->idjShort = false; // Assume loading constant from long address
6922
6923     // Keep it long if it's in cold code.
6924     id->idjKeepLong = emitComp->fgIsBlockCold(emitComp->compCurBB);
6925
6926 #ifdef DEBUG
6927     if (emitComp->opts.compLongAddress)
6928         id->idjKeepLong = 1;
6929 #endif // DEBUG
6930
6931     // If it's possible to be shortened, then put it in jump list
6932     // to be revisited by emitJumpDistBind.
6933     if (!id->idjKeepLong)
6934     {
6935         /* Record the jump's IG and offset within it */
6936         id->idjIG   = emitCurIG;
6937         id->idjOffs = emitCurIGsize;
6938
6939         /* Append this jump to this IG's jump list */
6940         id->idjNext      = emitCurIGjmpList;
6941         emitCurIGjmpList = id;
6942
6943 #if EMITTER_STATS
6944         emitTotalIGjmps++;
6945 #endif
6946     }
6947
6948     dispIns(id);
6949     appendToCurIG(id);
6950 }
6951
6952 /*****************************************************************************
6953  *
6954  *  Add an instruction with a static member + constant.
6955  */
6956
6957 void emitter::emitIns_C_I(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, ssize_t offs, ssize_t val)
6958 {
6959     NYI("emitIns_C_I");
6960 }
6961
6962 /*****************************************************************************
6963  *
6964  *  Add an instruction with a static member + register operands.
6965  */
6966
6967 void emitter::emitIns_C_R(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, regNumber reg, int offs)
6968 {
6969     assert(!"emitIns_C_R not supported for RyuJIT backend");
6970 }
6971
6972 void emitter::emitIns_R_AR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
6973 {
6974     NYI("emitIns_R_AR");
6975 }
6976
6977 // This computes address from the immediate which is relocatable.
6978 void emitter::emitIns_R_AI(instruction ins, emitAttr attr, regNumber ireg, ssize_t addr)
6979 {
6980     assert(EA_IS_RELOC(attr));
6981     emitAttr      size    = EA_SIZE(attr);
6982     insFormat     fmt     = IF_DI_1E;
6983     bool          needAdd = false;
6984     instrDescJmp* id      = emitNewInstrJmp();
6985
6986     switch (ins)
6987     {
6988         case INS_adrp:
6989             // This computes page address.
6990             // page offset is needed using add.
6991             needAdd = true;
6992             break;
6993         case INS_adr:
6994             break;
6995         default:
6996             unreached();
6997     }
6998
6999     id->idIns(ins);
7000     id->idInsFmt(fmt);
7001     id->idInsOpt(INS_OPTS_NONE);
7002     id->idOpSize(size);
7003     id->idAddr()->iiaAddr = (BYTE*)addr;
7004     id->idReg1(ireg);
7005     id->idSetIsDspReloc();
7006
7007     dispIns(id);
7008     appendToCurIG(id);
7009
7010     if (needAdd)
7011     {
7012         // add reg, reg, imm
7013         ins           = INS_add;
7014         fmt           = IF_DI_2A;
7015         instrDesc* id = emitNewInstr(attr);
7016         assert(id->idIsReloc());
7017
7018         id->idIns(ins);
7019         id->idInsFmt(fmt);
7020         id->idInsOpt(INS_OPTS_NONE);
7021         id->idOpSize(size);
7022         id->idAddr()->iiaAddr = (BYTE*)addr;
7023         id->idReg1(ireg);
7024         id->idReg2(ireg);
7025
7026         dispIns(id);
7027         appendToCurIG(id);
7028     }
7029 }
7030
7031 void emitter::emitIns_AR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
7032 {
7033     NYI("emitIns_AR_R");
7034 }
7035
7036 void emitter::emitIns_R_ARR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
7037 {
7038     NYI("emitIns_R_ARR");
7039 }
7040
7041 void emitter::emitIns_ARR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
7042 {
7043     NYI("emitIns_R_ARR");
7044 }
7045
7046 void emitter::emitIns_R_ARX(
7047     instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, unsigned mul, int disp)
7048 {
7049     NYI("emitIns_R_ARR");
7050 }
7051
7052 /*****************************************************************************
7053  *
7054  *  Record that a jump instruction uses the short encoding
7055  *
7056  */
7057 void emitter::emitSetShortJump(instrDescJmp* id)
7058 {
7059     if (id->idjKeepLong)
7060         return;
7061
7062     insFormat fmt = IF_NONE;
7063     if (emitIsCondJump(id))
7064     {
7065         switch (id->idIns())
7066         {
7067             case INS_cbz:
7068             case INS_cbnz:
7069                 fmt = IF_BI_1A;
7070                 break;
7071             case INS_tbz:
7072             case INS_tbnz:
7073                 fmt = IF_BI_1B;
7074                 break;
7075             default:
7076                 fmt = IF_BI_0B;
7077                 break;
7078         }
7079     }
7080     else if (emitIsLoadLabel(id))
7081     {
7082         fmt = IF_DI_1E;
7083     }
7084     else if (emitIsLoadConstant(id))
7085     {
7086         fmt = IF_LS_1A;
7087     }
7088     else
7089     {
7090         unreached();
7091     }
7092
7093     id->idInsFmt(fmt);
7094     id->idjShort = true;
7095 }
7096
7097 /*****************************************************************************
7098  *
7099  *  Add a label instruction.
7100  */
7101
7102 void emitter::emitIns_R_L(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
7103 {
7104     assert(dst->bbFlags & BBF_JMP_TARGET);
7105
7106     insFormat fmt = IF_NONE;
7107
7108     switch (ins)
7109     {
7110         case INS_adr:
7111             fmt = IF_LARGEADR;
7112             break;
7113         default:
7114             unreached();
7115     }
7116
7117     instrDescJmp* id = emitNewInstrJmp();
7118
7119     id->idIns(ins);
7120     id->idInsFmt(fmt);
7121     id->idjShort             = false;
7122     id->idAddr()->iiaBBlabel = dst;
7123     id->idReg1(reg);
7124     id->idOpSize(EA_PTRSIZE);
7125
7126 #ifdef DEBUG
7127     // Mark the catch return
7128     if (emitComp->compCurBB->bbJumpKind == BBJ_EHCATCHRET)
7129     {
7130         id->idDebugOnlyInfo()->idCatchRet = true;
7131     }
7132 #endif // DEBUG
7133
7134     id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7135
7136 #ifdef DEBUG
7137     if (emitComp->opts.compLongAddress)
7138         id->idjKeepLong = 1;
7139 #endif // DEBUG
7140
7141     /* Record the jump's IG and offset within it */
7142
7143     id->idjIG   = emitCurIG;
7144     id->idjOffs = emitCurIGsize;
7145
7146     /* Append this jump to this IG's jump list */
7147
7148     id->idjNext      = emitCurIGjmpList;
7149     emitCurIGjmpList = id;
7150
7151 #if EMITTER_STATS
7152     emitTotalIGjmps++;
7153 #endif
7154
7155     dispIns(id);
7156     appendToCurIG(id);
7157 }
7158
7159 /*****************************************************************************
7160  *
7161  *  Add a data label instruction.
7162  */
7163
7164 void emitter::emitIns_R_D(instruction ins, emitAttr attr, unsigned offs, regNumber reg)
7165 {
7166     NYI("emitIns_R_D");
7167 }
7168
7169 void emitter::emitIns_J_R(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
7170 {
7171     assert((ins == INS_cbz) || (ins == INS_cbnz));
7172
7173     assert(dst != nullptr);
7174     assert((dst->bbFlags & BBF_JMP_TARGET) != 0);
7175
7176     insFormat fmt = IF_LARGEJMP;
7177
7178     instrDescJmp* id = emitNewInstrJmp();
7179
7180     id->idIns(ins);
7181     id->idInsFmt(fmt);
7182     id->idReg1(reg);
7183     id->idjShort = false;
7184     id->idOpSize(EA_SIZE(attr));
7185
7186     id->idAddr()->iiaBBlabel = dst;
7187     id->idjKeepLong          = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7188
7189     /* Record the jump's IG and offset within it */
7190
7191     id->idjIG   = emitCurIG;
7192     id->idjOffs = emitCurIGsize;
7193
7194     /* Append this jump to this IG's jump list */
7195
7196     id->idjNext      = emitCurIGjmpList;
7197     emitCurIGjmpList = id;
7198
7199 #if EMITTER_STATS
7200     emitTotalIGjmps++;
7201 #endif
7202
7203     dispIns(id);
7204     appendToCurIG(id);
7205 }
7206
7207 void emitter::emitIns_J_R_I(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg, int imm)
7208 {
7209     assert((ins == INS_tbz) || (ins == INS_tbnz));
7210
7211     assert(dst != nullptr);
7212     assert((dst->bbFlags & BBF_JMP_TARGET) != 0);
7213     assert((EA_SIZE(attr) == EA_4BYTE) || (EA_SIZE(attr) == EA_8BYTE));
7214     assert(imm < ((EA_SIZE(attr) == EA_4BYTE) ? 32 : 64));
7215
7216     insFormat fmt = IF_LARGEJMP;
7217
7218     instrDescJmp* id = emitNewInstrJmp();
7219
7220     id->idIns(ins);
7221     id->idInsFmt(fmt);
7222     id->idReg1(reg);
7223     id->idjShort = false;
7224     id->idSmallCns(imm);
7225     id->idOpSize(EA_SIZE(attr));
7226
7227     id->idAddr()->iiaBBlabel = dst;
7228     id->idjKeepLong          = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7229
7230     /* Record the jump's IG and offset within it */
7231
7232     id->idjIG   = emitCurIG;
7233     id->idjOffs = emitCurIGsize;
7234
7235     /* Append this jump to this IG's jump list */
7236
7237     id->idjNext      = emitCurIGjmpList;
7238     emitCurIGjmpList = id;
7239
7240 #if EMITTER_STATS
7241     emitTotalIGjmps++;
7242 #endif
7243
7244     dispIns(id);
7245     appendToCurIG(id);
7246 }
7247
7248 void emitter::emitIns_J(instruction ins, BasicBlock* dst, int instrCount)
7249 {
7250     insFormat fmt = IF_NONE;
7251
7252     if (dst != nullptr)
7253     {
7254         assert(dst->bbFlags & BBF_JMP_TARGET);
7255     }
7256     else
7257     {
7258         assert(instrCount != 0);
7259     }
7260
7261     /* Figure out the encoding format of the instruction */
7262
7263     bool idjShort = false;
7264     switch (ins)
7265     {
7266         case INS_bl_local:
7267         case INS_b:
7268             // Unconditional jump is a single form.
7269             idjShort = true;
7270             fmt      = IF_BI_0A;
7271             break;
7272
7273         case INS_beq:
7274         case INS_bne:
7275         case INS_bhs:
7276         case INS_blo:
7277         case INS_bmi:
7278         case INS_bpl:
7279         case INS_bvs:
7280         case INS_bvc:
7281         case INS_bhi:
7282         case INS_bls:
7283         case INS_bge:
7284         case INS_blt:
7285         case INS_bgt:
7286         case INS_ble:
7287             // Assume conditional jump is long.
7288             fmt = IF_LARGEJMP;
7289             break;
7290
7291         default:
7292             unreached();
7293             break;
7294     }
7295
7296     instrDescJmp* id = emitNewInstrJmp();
7297
7298     id->idIns(ins);
7299     id->idInsFmt(fmt);
7300     id->idjShort = idjShort;
7301
7302 #ifdef DEBUG
7303     // Mark the finally call
7304     if (ins == INS_bl_local && emitComp->compCurBB->bbJumpKind == BBJ_CALLFINALLY)
7305     {
7306         id->idDebugOnlyInfo()->idFinallyCall = true;
7307     }
7308 #endif // DEBUG
7309
7310     if (dst != nullptr)
7311     {
7312         id->idAddr()->iiaBBlabel = dst;
7313
7314         // Skip unconditional jump that has a single form.
7315         // TODO-ARM64-NYI: enable hot/cold splittingNYI.
7316         // The target needs to be relocated.
7317         if (!idjShort)
7318         {
7319             id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7320
7321 #ifdef DEBUG
7322             if (emitComp->opts.compLongAddress) // Force long branches
7323                 id->idjKeepLong = 1;
7324 #endif // DEBUG
7325         }
7326     }
7327     else
7328     {
7329         id->idAddr()->iiaSetInstrCount(instrCount);
7330         id->idjKeepLong = false;
7331         /* This jump must be short */
7332         emitSetShortJump(id);
7333         id->idSetIsBound();
7334     }
7335
7336     /* Record the jump's IG and offset within it */
7337
7338     id->idjIG   = emitCurIG;
7339     id->idjOffs = emitCurIGsize;
7340
7341     /* Append this jump to this IG's jump list */
7342
7343     id->idjNext      = emitCurIGjmpList;
7344     emitCurIGjmpList = id;
7345
7346 #if EMITTER_STATS
7347     emitTotalIGjmps++;
7348 #endif
7349
7350     dispIns(id);
7351     appendToCurIG(id);
7352 }
7353
7354 /*****************************************************************************
7355  *
7356  *  Add a call instruction (direct or indirect).
7357  *      argSize<0 means that the caller will pop the arguments
7358  *
7359  * The other arguments are interpreted depending on callType as shown:
7360  * Unless otherwise specified, ireg,xreg,xmul,disp should have default values.
7361  *
7362  * EC_FUNC_TOKEN       : addr is the method address
7363  * EC_FUNC_ADDR        : addr is the absolute address of the function
7364  *
7365  * If callType is one of these emitCallTypes, addr has to be NULL.
7366  * EC_INDIR_R          : "call ireg".
7367  *
7368  * For ARM xreg, xmul and disp are never used and should always be 0/REG_NA.
7369  *
7370  *  Please consult the "debugger team notification" comment in genFnProlog().
7371  */
7372
7373 void emitter::emitIns_Call(EmitCallType          callType,
7374                            CORINFO_METHOD_HANDLE methHnd,
7375                            INDEBUG_LDISASM_COMMA(CORINFO_SIG_INFO* sigInfo) // used to report call sites to the EE
7376                            void*            addr,
7377                            ssize_t          argSize,
7378                            emitAttr         retSize,
7379                            emitAttr         secondRetSize,
7380                            VARSET_VALARG_TP ptrVars,
7381                            regMaskTP        gcrefRegs,
7382                            regMaskTP        byrefRegs,
7383                            IL_OFFSETX       ilOffset /* = BAD_IL_OFFSET */,
7384                            regNumber        ireg /* = REG_NA */,
7385                            regNumber        xreg /* = REG_NA */,
7386                            unsigned         xmul /* = 0     */,
7387                            ssize_t          disp /* = 0     */,
7388                            bool             isJump /* = false */)
7389 {
7390     /* Sanity check the arguments depending on callType */
7391
7392     assert(callType < EC_COUNT);
7393     assert((callType != EC_FUNC_TOKEN && callType != EC_FUNC_ADDR) ||
7394            (ireg == REG_NA && xreg == REG_NA && xmul == 0 && disp == 0));
7395     assert(callType < EC_INDIR_R || addr == NULL);
7396     assert(callType != EC_INDIR_R || (ireg < REG_COUNT && xreg == REG_NA && xmul == 0 && disp == 0));
7397
7398     // ARM never uses these
7399     assert(xreg == REG_NA && xmul == 0 && disp == 0);
7400
7401     // Our stack level should be always greater than the bytes of arguments we push. Just
7402     // a sanity test.
7403     assert((unsigned)abs(argSize) <= codeGen->genStackLevel);
7404
7405     // Trim out any callee-trashed registers from the live set.
7406     regMaskTP savedSet = emitGetGCRegsSavedOrModified(methHnd);
7407     gcrefRegs &= savedSet;
7408     byrefRegs &= savedSet;
7409
7410 #ifdef DEBUG
7411     if (EMIT_GC_VERBOSE)
7412     {
7413         printf("Call: GCvars=%s ", VarSetOps::ToString(emitComp, ptrVars));
7414         dumpConvertedVarSet(emitComp, ptrVars);
7415         printf(", gcrefRegs=");
7416         printRegMaskInt(gcrefRegs);
7417         emitDispRegSet(gcrefRegs);
7418         printf(", byrefRegs=");
7419         printRegMaskInt(byrefRegs);
7420         emitDispRegSet(byrefRegs);
7421         printf("\n");
7422     }
7423 #endif
7424
7425     /* Managed RetVal: emit sequence point for the call */
7426     if (emitComp->opts.compDbgInfo && ilOffset != BAD_IL_OFFSET)
7427     {
7428         codeGen->genIPmappingAdd(ilOffset, false);
7429     }
7430
7431     /*
7432         We need to allocate the appropriate instruction descriptor based
7433         on whether this is a direct/indirect call, and whether we need to
7434         record an updated set of live GC variables.
7435      */
7436     instrDesc* id;
7437
7438     assert(argSize % REGSIZE_BYTES == 0);
7439     int argCnt = (int)(argSize / (int)REGSIZE_BYTES);
7440
7441     if (callType >= EC_INDIR_R)
7442     {
7443         /* Indirect call, virtual calls */
7444
7445         assert(callType == EC_INDIR_R);
7446
7447         id = emitNewInstrCallInd(argCnt, disp, ptrVars, gcrefRegs, byrefRegs, retSize, secondRetSize);
7448     }
7449     else
7450     {
7451         /* Helper/static/nonvirtual/function calls (direct or through handle),
7452            and calls to an absolute addr. */
7453
7454         assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
7455
7456         id = emitNewInstrCallDir(argCnt, ptrVars, gcrefRegs, byrefRegs, retSize, secondRetSize);
7457     }
7458
7459     /* Update the emitter's live GC ref sets */
7460
7461     VarSetOps::Assign(emitComp, emitThisGCrefVars, ptrVars);
7462     emitThisGCrefRegs = gcrefRegs;
7463     emitThisByrefRegs = byrefRegs;
7464
7465     id->idSetIsNoGC(emitNoGChelper(methHnd));
7466
7467     /* Set the instruction - special case jumping a function */
7468     instruction ins;
7469     insFormat   fmt = IF_NONE;
7470
7471     /* Record the address: method, indirection, or funcptr */
7472
7473     if (callType > EC_FUNC_ADDR)
7474     {
7475         /* This is an indirect call (either a virtual call or func ptr call) */
7476
7477         switch (callType)
7478         {
7479             case EC_INDIR_R: // the address is in a register
7480
7481                 id->idSetIsCallRegPtr();
7482
7483                 if (isJump)
7484                 {
7485                     ins = INS_br_tail; // INS_br_tail  Reg
7486                 }
7487                 else
7488                 {
7489                     ins = INS_blr; // INS_blr Reg
7490                 }
7491                 fmt = IF_BR_1B;
7492
7493                 id->idIns(ins);
7494                 id->idInsFmt(fmt);
7495
7496                 id->idReg3(ireg);
7497                 assert(xreg == REG_NA);
7498                 break;
7499
7500             default:
7501                 NO_WAY("unexpected instruction");
7502                 break;
7503         }
7504     }
7505     else
7506     {
7507         /* This is a simple direct call: "call helper/method/addr" */
7508
7509         assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
7510
7511         assert(addr != NULL);
7512
7513         if (isJump)
7514         {
7515             ins = INS_b_tail; // INS_b_tail imm28
7516         }
7517         else
7518         {
7519             ins = INS_bl; // INS_bl imm28
7520         }
7521         fmt = IF_BI_0C;
7522
7523         id->idIns(ins);
7524         id->idInsFmt(fmt);
7525
7526         id->idAddr()->iiaAddr = (BYTE*)addr;
7527
7528         if (callType == EC_FUNC_ADDR)
7529         {
7530             id->idSetIsCallAddr();
7531         }
7532
7533         if (emitComp->opts.compReloc)
7534         {
7535             id->idSetIsDspReloc();
7536         }
7537     }
7538
7539 #ifdef DEBUG
7540     if (EMIT_GC_VERBOSE)
7541     {
7542         if (id->idIsLargeCall())
7543         {
7544             printf("[%02u] Rec call GC vars = %s\n", id->idDebugOnlyInfo()->idNum,
7545                    VarSetOps::ToString(emitComp, ((instrDescCGCA*)id)->idcGCvars));
7546         }
7547     }
7548
7549     id->idDebugOnlyInfo()->idMemCookie = (size_t)methHnd; // method token
7550     id->idDebugOnlyInfo()->idCallSig   = sigInfo;
7551 #endif // DEBUG
7552
7553 #ifdef LATE_DISASM
7554     if (addr != nullptr)
7555     {
7556         codeGen->getDisAssembler().disSetMethod((size_t)addr, methHnd);
7557     }
7558 #endif // LATE_DISASM
7559
7560     dispIns(id);
7561     appendToCurIG(id);
7562 }
7563
7564 /*****************************************************************************
7565  *
7566  *  Returns true if 'imm' is valid Cond encoding
7567  */
7568
7569 /*static*/ bool emitter::isValidImmCond(ssize_t imm)
7570 {
7571     // range check the ssize_t value, to make sure it is a small unsigned value
7572     // and that only the bits in the cfi.cond are set
7573     if ((imm < 0) || (imm > 0xF))
7574         return false;
7575
7576     condFlagsImm cfi;
7577     cfi.immCFVal = (unsigned)imm;
7578
7579     return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7580 }
7581
7582 /*****************************************************************************
7583  *
7584  *  Returns true if 'imm' is valid Cond/Flags encoding
7585  */
7586
7587 /*static*/ bool emitter::isValidImmCondFlags(ssize_t imm)
7588 {
7589     // range check the ssize_t value, to make sure it is a small unsigned value
7590     // and that only the bits in the cfi.cond or cfi.flags are set
7591     if ((imm < 0) || (imm > 0xFF))
7592         return false;
7593
7594     condFlagsImm cfi;
7595     cfi.immCFVal = (unsigned)imm;
7596
7597     return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7598 }
7599
7600 /*****************************************************************************
7601  *
7602  *  Returns true if 'imm' is valid Cond/Flags/Imm5 encoding
7603  */
7604
7605 /*static*/ bool emitter::isValidImmCondFlagsImm5(ssize_t imm)
7606 {
7607     // range check the ssize_t value, to make sure it is a small unsigned value
7608     // and that only the bits in the cfi.cond, cfi.flags or cfi.imm5 are set
7609     if ((imm < 0) || (imm > 0x1FFF))
7610         return false;
7611
7612     condFlagsImm cfi;
7613     cfi.immCFVal = (unsigned)imm;
7614
7615     return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7616 }
7617
7618 /*****************************************************************************
7619  *
7620  *  Returns an encoding for the specified register used in the 'Rd' position
7621  */
7622
7623 /*static*/ emitter::code_t emitter::insEncodeReg_Rd(regNumber reg)
7624 {
7625     assert(isIntegerRegister(reg));
7626     emitter::code_t ureg = (emitter::code_t)reg;
7627     assert((ureg >= 0) && (ureg <= 31));
7628     return ureg;
7629 }
7630
7631 /*****************************************************************************
7632  *
7633  *  Returns an encoding for the specified register used in the 'Rt' position
7634  */
7635
7636 /*static*/ emitter::code_t emitter::insEncodeReg_Rt(regNumber reg)
7637 {
7638     assert(isIntegerRegister(reg));
7639     emitter::code_t ureg = (emitter::code_t)reg;
7640     assert((ureg >= 0) && (ureg <= 31));
7641     return ureg;
7642 }
7643
7644 /*****************************************************************************
7645  *
7646  *  Returns an encoding for the specified register used in the 'Rn' position
7647  */
7648
7649 /*static*/ emitter::code_t emitter::insEncodeReg_Rn(regNumber reg)
7650 {
7651     assert(isIntegerRegister(reg));
7652     emitter::code_t ureg = (emitter::code_t)reg;
7653     assert((ureg >= 0) && (ureg <= 31));
7654     return ureg << 5;
7655 }
7656
7657 /*****************************************************************************
7658  *
7659  *  Returns an encoding for the specified register used in the 'Rm' position
7660  */
7661
7662 /*static*/ emitter::code_t emitter::insEncodeReg_Rm(regNumber reg)
7663 {
7664     assert(isIntegerRegister(reg));
7665     emitter::code_t ureg = (emitter::code_t)reg;
7666     assert((ureg >= 0) && (ureg <= 31));
7667     return ureg << 16;
7668 }
7669
7670 /*****************************************************************************
7671  *
7672  *  Returns an encoding for the specified register used in the 'Ra' position
7673  */
7674
7675 /*static*/ emitter::code_t emitter::insEncodeReg_Ra(regNumber reg)
7676 {
7677     assert(isIntegerRegister(reg));
7678     emitter::code_t ureg = (emitter::code_t)reg;
7679     assert((ureg >= 0) && (ureg <= 31));
7680     return ureg << 10;
7681 }
7682
7683 /*****************************************************************************
7684  *
7685  *  Returns an encoding for the specified register used in the 'Vd' position
7686  */
7687
7688 /*static*/ emitter::code_t emitter::insEncodeReg_Vd(regNumber reg)
7689 {
7690     assert(emitter::isVectorRegister(reg));
7691     emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7692     assert((ureg >= 0) && (ureg <= 31));
7693     return ureg;
7694 }
7695
7696 /*****************************************************************************
7697  *
7698  *  Returns an encoding for the specified register used in the 'Vt' position
7699  */
7700
7701 /*static*/ emitter::code_t emitter::insEncodeReg_Vt(regNumber reg)
7702 {
7703     assert(emitter::isVectorRegister(reg));
7704     emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7705     assert((ureg >= 0) && (ureg <= 31));
7706     return ureg;
7707 }
7708
7709 /*****************************************************************************
7710  *
7711  *  Returns an encoding for the specified register used in the 'Vn' position
7712  */
7713
7714 /*static*/ emitter::code_t emitter::insEncodeReg_Vn(regNumber reg)
7715 {
7716     assert(emitter::isVectorRegister(reg));
7717     emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7718     assert((ureg >= 0) && (ureg <= 31));
7719     return ureg << 5;
7720 }
7721
7722 /*****************************************************************************
7723  *
7724  *  Returns an encoding for the specified register used in the 'Vm' position
7725  */
7726
7727 /*static*/ emitter::code_t emitter::insEncodeReg_Vm(regNumber reg)
7728 {
7729     assert(emitter::isVectorRegister(reg));
7730     emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7731     assert((ureg >= 0) && (ureg <= 31));
7732     return ureg << 16;
7733 }
7734
7735 /*****************************************************************************
7736  *
7737  *  Returns an encoding for the specified register used in the 'Va' position
7738  */
7739
7740 /*static*/ emitter::code_t emitter::insEncodeReg_Va(regNumber reg)
7741 {
7742     assert(emitter::isVectorRegister(reg));
7743     emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7744     assert((ureg >= 0) && (ureg <= 31));
7745     return ureg << 10;
7746 }
7747
7748 /*****************************************************************************
7749  *
7750  *  Returns an encoding for the specified condition code.
7751  */
7752
7753 /*static*/ emitter::code_t emitter::insEncodeCond(insCond cond)
7754 {
7755     emitter::code_t uimm = (emitter::code_t)cond;
7756     return uimm << 12;
7757 }
7758
7759 /*****************************************************************************
7760  *
7761  *  Returns an encoding for the condition code with the lowest bit inverted (marked by invert(<cond>) in the
7762  *  architecture manual).
7763  */
7764
7765 /*static*/ emitter::code_t emitter::insEncodeInvertedCond(insCond cond)
7766 {
7767     emitter::code_t uimm = (emitter::code_t)cond;
7768     uimm ^= 1; // invert the lowest bit
7769     return uimm << 12;
7770 }
7771
7772 /*****************************************************************************
7773  *
7774  *  Returns an encoding for the specified flags.
7775  */
7776
7777 /*static*/ emitter::code_t emitter::insEncodeFlags(insCflags flags)
7778 {
7779     emitter::code_t uimm = (emitter::code_t)flags;
7780     return uimm;
7781 }
7782
7783 /*****************************************************************************
7784  *
7785  *  Returns the encoding for the Shift Count bits to be used for Arm64 encodings
7786  */
7787
7788 /*static*/ emitter::code_t emitter::insEncodeShiftCount(ssize_t imm, emitAttr size)
7789 {
7790     assert((imm & 0x003F) == imm);
7791     assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
7792
7793     return (emitter::code_t)imm << 10;
7794 }
7795
7796 /*****************************************************************************
7797  *
7798  *  Returns the encoding to select a 64-bit datasize for an Arm64 instruction
7799  */
7800
7801 /*static*/ emitter::code_t emitter::insEncodeDatasize(emitAttr size)
7802 {
7803     if (size == EA_8BYTE)
7804     {
7805         return 0x80000000; // set the bit at location 31
7806     }
7807     else
7808     {
7809         assert(size == EA_4BYTE);
7810         return 0;
7811     }
7812 }
7813
7814 /*****************************************************************************
7815  *
7816  *  Returns the encoding to select the datasize for the general load/store Arm64 instructions
7817  *
7818  */
7819
7820 /*static*/ emitter::code_t emitter::insEncodeDatasizeLS(emitter::code_t code, emitAttr size)
7821 {
7822     bool exclusive = ((code & 0x35000000) == 0);
7823     bool atomic    = ((code & 0x31200C00) == 0x30200000);
7824
7825     if ((code & 0x00800000) && !exclusive && !atomic) // Is this a sign-extending opcode? (i.e. ldrsw, ldrsh, ldrsb)
7826     {
7827         if ((code & 0x80000000) == 0) // Is it a ldrsh or ldrsb and not ldrsw ?
7828         {
7829             if (EA_SIZE(size) != EA_8BYTE) // Do we need to encode the 32-bit Rt size bit?
7830             {
7831                 return 0x00400000; // set the bit at location 22
7832             }
7833         }
7834     }
7835     else if (code & 0x80000000) // Is this a ldr/str/ldur/stur opcode?
7836     {
7837         if (EA_SIZE(size) == EA_8BYTE) // Do we need to encode the 64-bit size bit?
7838         {
7839             return 0x40000000; // set the bit at location 30
7840         }
7841     }
7842     return 0;
7843 }
7844
7845 /*****************************************************************************
7846  *
7847  *  Returns the encoding to select the datasize for the vector load/store Arm64 instructions
7848  *
7849  */
7850
7851 /*static*/ emitter::code_t emitter::insEncodeDatasizeVLS(emitter::code_t code, emitAttr size)
7852 {
7853     code_t result = 0;
7854
7855     // Check bit 29
7856     if ((code & 0x20000000) == 0)
7857     {
7858         // LDR literal
7859
7860         if (size == EA_16BYTE)
7861         {
7862             // set the operation size in bit 31
7863             result = 0x80000000;
7864         }
7865         else if (size == EA_8BYTE)
7866         {
7867             // set the operation size in bit 30
7868             result = 0x40000000;
7869         }
7870         else
7871         {
7872             assert(size == EA_4BYTE);
7873             // no bits are set
7874             result = 0x00000000;
7875         }
7876     }
7877     else
7878     {
7879         // LDR non-literal
7880
7881         if (size == EA_16BYTE)
7882         {
7883             // The operation size in bits 31 and 30 are zero
7884             // Bit 23 specifies a 128-bit Load/Store
7885             result = 0x00800000;
7886         }
7887         else if (size == EA_8BYTE)
7888         {
7889             // set the operation size in bits 31 and 30
7890             result = 0xC0000000;
7891         }
7892         else if (size == EA_4BYTE)
7893         {
7894             // set the operation size in bit 31
7895             result = 0x80000000;
7896         }
7897         else if (size == EA_2BYTE)
7898         {
7899             // set the operation size in bit 30
7900             result = 0x40000000;
7901         }
7902         else
7903         {
7904             assert(size == EA_1BYTE);
7905             // The operation size in bits 31 and 30 are zero
7906             result = 0x00000000;
7907         }
7908     }
7909
7910     // Or in bit 26 to indicate a Vector register is used as 'target'
7911     result |= 0x04000000;
7912
7913     return result;
7914 }
7915
7916 /*****************************************************************************
7917  *
7918  *  Returns the encoding to select the datasize for the vector load/store Arm64 instructions
7919  *
7920  */
7921
7922 /*static*/ emitter::code_t emitter::insEncodeDatasizeVPLS(emitter::code_t code, emitAttr size)
7923 {
7924     code_t result = 0;
7925
7926     if (size == EA_16BYTE)
7927     {
7928         // The operation size in bits 31 and 30 are zero
7929         // Bit 23 specifies a 128-bit Load/Store
7930         result = 0x80000000;
7931     }
7932     else if (size == EA_8BYTE)
7933     {
7934         // set the operation size in bits 31 and 30
7935         result = 0x40000000;
7936     }
7937     else if (size == EA_4BYTE)
7938     {
7939         // set the operation size in bit 31
7940         result = 0x00000000;
7941     }
7942
7943     // Or in bit 26 to indicate a Vector register is used as 'target'
7944     result |= 0x04000000;
7945
7946     return result;
7947 }
7948
7949 /*****************************************************************************
7950  *
7951  *  Returns the encoding to set the size bit and the N bits for a 'bitfield' instruction
7952  *
7953  */
7954
7955 /*static*/ emitter::code_t emitter::insEncodeDatasizeBF(emitter::code_t code, emitAttr size)
7956 {
7957     // is bit 30 equal to 0?
7958     if ((code & 0x40000000) == 0) // is the opcode one of extr, sxtb, sxth or sxtw
7959     {
7960         if (size == EA_8BYTE) // Do we need to set the sf and N bits?
7961         {
7962             return 0x80400000; // set the sf-bit at location 31 and the N-bit at location 22
7963         }
7964     }
7965     return 0; // don't set any bits
7966 }
7967
7968 /*****************************************************************************
7969  *
7970  *  Returns the encoding to select the 64/128-bit datasize for an Arm64 vector instruction
7971  */
7972
7973 /*static*/ emitter::code_t emitter::insEncodeVectorsize(emitAttr size)
7974 {
7975     if (size == EA_16BYTE)
7976     {
7977         return 0x40000000; // set the bit at location 30
7978     }
7979     else
7980     {
7981         assert(size == EA_8BYTE);
7982         return 0;
7983     }
7984 }
7985
7986 /*****************************************************************************
7987  *
7988  *  Returns the encoding to select 'index' for an Arm64 vector elem instruction
7989  */
7990 /*static*/ emitter::code_t emitter::insEncodeVectorIndex(emitAttr elemsize, ssize_t index)
7991 {
7992     code_t bits = (code_t)index;
7993     if (elemsize == EA_1BYTE)
7994     {
7995         bits <<= 1;
7996         bits |= 1;
7997     }
7998     else if (elemsize == EA_2BYTE)
7999     {
8000         bits <<= 2;
8001         bits |= 2;
8002     }
8003     else if (elemsize == EA_4BYTE)
8004     {
8005         bits <<= 3;
8006         bits |= 4;
8007     }
8008     else
8009     {
8010         assert(elemsize == EA_8BYTE);
8011         bits <<= 4;
8012         bits |= 8;
8013     }
8014     assert((bits >= 1) && (bits <= 0x1f));
8015
8016     return (bits << 16); // bits at locations [20,19,18,17,16]
8017 }
8018
8019 /*****************************************************************************
8020  *
8021  *  Returns the encoding to select 'index2' for an Arm64 'ins' elem instruction
8022  */
8023 /*static*/ emitter::code_t emitter::insEncodeVectorIndex2(emitAttr elemsize, ssize_t index2)
8024 {
8025     code_t bits = (code_t)index2;
8026     if (elemsize == EA_1BYTE)
8027     {
8028         // bits are correct
8029     }
8030     else if (elemsize == EA_2BYTE)
8031     {
8032         bits <<= 1;
8033     }
8034     else if (elemsize == EA_4BYTE)
8035     {
8036         bits <<= 2;
8037     }
8038     else
8039     {
8040         assert(elemsize == EA_8BYTE);
8041         bits <<= 3;
8042     }
8043     assert((bits >= 0) && (bits <= 0xf));
8044
8045     return (bits << 11); // bits at locations [14,13,12,11]
8046 }
8047
8048 /*****************************************************************************
8049  *
8050  *  Returns the encoding to select the 'index' for an Arm64 'mul' by elem instruction
8051  */
8052 /*static*/ emitter::code_t emitter::insEncodeVectorIndexLMH(emitAttr elemsize, ssize_t index)
8053 {
8054     code_t bits = 0;
8055
8056     if (elemsize == EA_2BYTE)
8057     {
8058         assert((index >= 0) && (index <= 7));
8059         if (index & 0x4)
8060         {
8061             bits |= (1 << 11); // set bit 11 'H'
8062         }
8063         if (index & 0x2)
8064         {
8065             bits |= (1 << 21); // set bit 21 'L'
8066         }
8067         if (index & 0x1)
8068         {
8069             bits |= (1 << 20); // set bit 20 'M'
8070         }
8071     }
8072     else if (elemsize == EA_4BYTE)
8073     {
8074         assert((index >= 0) && (index <= 3));
8075         if (index & 0x2)
8076         {
8077             bits |= (1 << 11); // set bit 11 'H'
8078         }
8079         if (index & 0x1)
8080         {
8081             bits |= (1 << 21); // set bit 21 'L'
8082         }
8083     }
8084     else
8085     {
8086         assert(!"Invalid 'elemsize' value");
8087     }
8088
8089     return bits;
8090 }
8091
8092 /*****************************************************************************
8093  *
8094  *   Returns the encoding to shift by 'shift' for an Arm64 vector or scalar instruction
8095  */
8096
8097 /*static*/ emitter::code_t emitter::insEncodeVectorShift(emitAttr size, ssize_t shift)
8098 {
8099     assert(shift < getBitWidth(size));
8100
8101     code_t imm = (code_t)(getBitWidth(size) + shift);
8102
8103     return imm << 16;
8104 }
8105
8106 /*****************************************************************************
8107  *
8108  *  Returns the encoding to select the 1/2/4/8 byte elemsize for an Arm64 vector instruction
8109  */
8110
8111 /*static*/ emitter::code_t emitter::insEncodeElemsize(emitAttr size)
8112 {
8113     if (size == EA_8BYTE)
8114     {
8115         return 0x00C00000; // set the bit at location 23 and 22
8116     }
8117     else if (size == EA_4BYTE)
8118     {
8119         return 0x00800000; // set the bit at location 23
8120     }
8121     else if (size == EA_2BYTE)
8122     {
8123         return 0x00400000; // set the bit at location 22
8124     }
8125     assert(size == EA_1BYTE);
8126     return 0x00000000;
8127 }
8128
8129 /*****************************************************************************
8130  *
8131  *  Returns the encoding to select the 4/8 byte elemsize for an Arm64 float vector instruction
8132  */
8133
8134 /*static*/ emitter::code_t emitter::insEncodeFloatElemsize(emitAttr size)
8135 {
8136     if (size == EA_8BYTE)
8137     {
8138         return 0x00400000; // set the bit at location 22
8139     }
8140     assert(size == EA_4BYTE);
8141     return 0x00000000;
8142 }
8143
8144 // Returns the encoding to select the index for an Arm64 float vector by elem instruction
8145 /*static*/ emitter::code_t emitter::insEncodeFloatIndex(emitAttr elemsize, ssize_t index)
8146 {
8147     code_t result = 0x00000000;
8148     if (elemsize == EA_8BYTE)
8149     {
8150         assert((index >= 0) && (index <= 1));
8151         if (index == 1)
8152         {
8153             result |= 0x00000800; // 'H' - set the bit at location 11
8154         }
8155     }
8156     else
8157     {
8158         assert(elemsize == EA_4BYTE);
8159         assert((index >= 0) && (index <= 3));
8160         if (index & 2)
8161         {
8162             result |= 0x00000800; // 'H' - set the bit at location 11
8163         }
8164         if (index & 1)
8165         {
8166             result |= 0x00200000; // 'L' - set the bit at location 21
8167         }
8168     }
8169     return result;
8170 }
8171
8172 /*****************************************************************************
8173  *
8174  *  Returns the encoding to select the fcvt operation for Arm64 instructions
8175  */
8176 /*static*/ emitter::code_t emitter::insEncodeConvertOpt(insFormat fmt, insOpts conversion)
8177 {
8178     code_t result = 0;
8179     switch (conversion)
8180     {
8181         case INS_OPTS_S_TO_D: // Single to Double
8182             assert(fmt == IF_DV_2J);
8183             result = 0x00008000; // type=00, opc=01
8184             break;
8185
8186         case INS_OPTS_D_TO_S: // Double to Single
8187             assert(fmt == IF_DV_2J);
8188             result = 0x00400000; // type=01, opc=00
8189             break;
8190
8191         case INS_OPTS_H_TO_S: // Half to Single
8192             assert(fmt == IF_DV_2J);
8193             result = 0x00C00000; // type=11, opc=00
8194             break;
8195
8196         case INS_OPTS_H_TO_D: // Half to Double
8197             assert(fmt == IF_DV_2J);
8198             result = 0x00C08000; // type=11, opc=01
8199             break;
8200
8201         case INS_OPTS_S_TO_H: // Single to Half
8202             assert(fmt == IF_DV_2J);
8203             result = 0x00018000; // type=00, opc=11
8204             break;
8205
8206         case INS_OPTS_D_TO_H: // Double to Half
8207             assert(fmt == IF_DV_2J);
8208             result = 0x00418000; // type=01, opc=11
8209             break;
8210
8211         case INS_OPTS_S_TO_4BYTE: // Single to INT32
8212             assert(fmt == IF_DV_2H);
8213             result = 0x00000000; // sf=0, type=00
8214             break;
8215
8216         case INS_OPTS_D_TO_4BYTE: // Double to INT32
8217             assert(fmt == IF_DV_2H);
8218             result = 0x00400000; // sf=0, type=01
8219             break;
8220
8221         case INS_OPTS_S_TO_8BYTE: // Single to INT64
8222             assert(fmt == IF_DV_2H);
8223             result = 0x80000000; // sf=1, type=00
8224             break;
8225
8226         case INS_OPTS_D_TO_8BYTE: // Double to INT64
8227             assert(fmt == IF_DV_2H);
8228             result = 0x80400000; // sf=1, type=01
8229             break;
8230
8231         case INS_OPTS_4BYTE_TO_S: // INT32 to Single
8232             assert(fmt == IF_DV_2I);
8233             result = 0x00000000; // sf=0, type=00
8234             break;
8235
8236         case INS_OPTS_4BYTE_TO_D: // INT32 to Double
8237             assert(fmt == IF_DV_2I);
8238             result = 0x00400000; // sf=0, type=01
8239             break;
8240
8241         case INS_OPTS_8BYTE_TO_S: // INT64 to Single
8242             assert(fmt == IF_DV_2I);
8243             result = 0x80000000; // sf=1, type=00
8244             break;
8245
8246         case INS_OPTS_8BYTE_TO_D: // INT64 to Double
8247             assert(fmt == IF_DV_2I);
8248             result = 0x80400000; // sf=1, type=01
8249             break;
8250
8251         default:
8252             assert(!"Invalid 'conversion' value");
8253             break;
8254     }
8255     return result;
8256 }
8257
8258 /*****************************************************************************
8259  *
8260  *  Returns the encoding to have the Rn register be updated Pre/Post indexed
8261  *  or not updated
8262  */
8263
8264 /*static*/ emitter::code_t emitter::insEncodeIndexedOpt(insOpts opt)
8265 {
8266     assert(emitter::insOptsNone(opt) || emitter::insOptsIndexed(opt));
8267
8268     if (emitter::insOptsIndexed(opt))
8269     {
8270         if (emitter::insOptsPostIndex(opt))
8271         {
8272             return 0x00000400; // set the bit at location 10
8273         }
8274         else
8275         {
8276             assert(emitter::insOptsPreIndex(opt));
8277             return 0x00000C00; // set the bit at location 10 and 11
8278         }
8279     }
8280     else
8281     {
8282         assert(emitter::insOptsNone(opt));
8283         return 0; // bits 10 and 11 are zero
8284     }
8285 }
8286
8287 /*****************************************************************************
8288  *
8289  *  Returns the encoding for a ldp/stp instruction to have the Rn register
8290  *  be updated Pre/Post indexed or not updated
8291  */
8292
8293 /*static*/ emitter::code_t emitter::insEncodePairIndexedOpt(instruction ins, insOpts opt)
8294 {
8295     assert(emitter::insOptsNone(opt) || emitter::insOptsIndexed(opt));
8296
8297     if ((ins == INS_ldnp) || (ins == INS_stnp))
8298     {
8299         assert(emitter::insOptsNone(opt));
8300         return 0; // bits 23 and 24 are zero
8301     }
8302     else
8303     {
8304         if (emitter::insOptsIndexed(opt))
8305         {
8306             if (emitter::insOptsPostIndex(opt))
8307             {
8308                 return 0x00800000; // set the bit at location 23
8309             }
8310             else
8311             {
8312                 assert(emitter::insOptsPreIndex(opt));
8313                 return 0x01800000; // set the bit at location 24 and 23
8314             }
8315         }
8316         else
8317         {
8318             assert(emitter::insOptsNone(opt));
8319             return 0x01000000; // set the bit at location 24
8320         }
8321     }
8322 }
8323
8324 /*****************************************************************************
8325  *
8326  *  Returns the encoding to apply a Shift Type on the Rm register
8327  */
8328
8329 /*static*/ emitter::code_t emitter::insEncodeShiftType(insOpts opt)
8330 {
8331     if (emitter::insOptsNone(opt))
8332     {
8333         // None implies the we encode LSL (with a zero immediate)
8334         opt = INS_OPTS_LSL;
8335     }
8336     assert(emitter::insOptsAnyShift(opt));
8337
8338     emitter::code_t option = (emitter::code_t)opt - (emitter::code_t)INS_OPTS_LSL;
8339     assert(option <= 3);
8340
8341     return option << 22; // bits 23, 22
8342 }
8343
8344 /*****************************************************************************
8345  *
8346  *  Returns the encoding to apply a 12 bit left shift to the immediate
8347  */
8348
8349 /*static*/ emitter::code_t emitter::insEncodeShiftImm12(insOpts opt)
8350 {
8351     if (emitter::insOptsLSL12(opt))
8352     {
8353         return 0x00400000; // set the bit at location 22
8354     }
8355     return 0;
8356 }
8357
8358 /*****************************************************************************
8359  *
8360  *  Returns the encoding to have the Rm register use an extend operation
8361  */
8362
8363 /*static*/ emitter::code_t emitter::insEncodeExtend(insOpts opt)
8364 {
8365     if (emitter::insOptsNone(opt) || (opt == INS_OPTS_LSL))
8366     {
8367         // None or LSL implies the we encode UXTX
8368         opt = INS_OPTS_UXTX;
8369     }
8370     assert(emitter::insOptsAnyExtend(opt));
8371
8372     emitter::code_t option = (emitter::code_t)opt - (emitter::code_t)INS_OPTS_UXTB;
8373     assert(option <= 7);
8374
8375     return option << 13; // bits 15,14,13
8376 }
8377
8378 /*****************************************************************************
8379  *
8380  *  Returns the encoding to scale the Rm register by {0,1,2,3,4}
8381  *  when using an extend operation
8382  */
8383
8384 /*static*/ emitter::code_t emitter::insEncodeExtendScale(ssize_t imm)
8385 {
8386     assert((imm >= 0) && (imm <= 4));
8387
8388     return (emitter::code_t)imm << 10; // bits 12,11,10
8389 }
8390
8391 /*****************************************************************************
8392  *
8393  *  Returns the encoding to have the Rm register be auto scaled by the ld/st size
8394  */
8395
8396 /*static*/ emitter::code_t emitter::insEncodeReg3Scale(bool isScaled)
8397 {
8398     if (isScaled)
8399     {
8400         return 0x00001000; // set the bit at location 12
8401     }
8402     else
8403     {
8404         return 0;
8405     }
8406 }
8407
8408 BYTE* emitter::emitOutputLoadLabel(BYTE* dst, BYTE* srcAddr, BYTE* dstAddr, instrDescJmp* id)
8409 {
8410     instruction ins    = id->idIns();
8411     insFormat   fmt    = id->idInsFmt();
8412     regNumber   dstReg = id->idReg1();
8413     if (id->idjShort)
8414     {
8415         // adr x, [rel addr] --  compute address: current addr(ip) + rel addr.
8416         assert(ins == INS_adr);
8417         assert(fmt == IF_DI_1E);
8418         ssize_t distVal = (ssize_t)(dstAddr - srcAddr);
8419         dst             = emitOutputShortAddress(dst, ins, fmt, distVal, dstReg);
8420     }
8421     else
8422     {
8423         // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8424         assert(fmt == IF_LARGEADR);
8425         ssize_t relPageAddr =
8426             (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8427         dst = emitOutputShortAddress(dst, INS_adrp, IF_DI_1E, relPageAddr, dstReg);
8428
8429         // add x, x, page offs -- compute address = page addr + page offs
8430         ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8431         assert(isValidUimm12(imm12));
8432         code_t code =
8433             emitInsCode(INS_add, IF_DI_2A);  // DI_2A  X0010001shiiiiii iiiiiinnnnnddddd   1100 0000   imm(i12, sh)
8434         code |= insEncodeDatasize(EA_8BYTE); // X
8435         code |= ((code_t)imm12 << 10);       // iiiiiiiiiiii
8436         code |= insEncodeReg_Rd(dstReg);     // ddddd
8437         code |= insEncodeReg_Rn(dstReg);     // nnnnn
8438         dst += emitOutput_Instr(dst, code);
8439     }
8440     return dst;
8441 }
8442
8443 /*****************************************************************************
8444  *
8445  *  Output a local jump or other instruction with a pc-relative immediate.
8446  *  Note that this may be invoked to overwrite an existing jump instruction at 'dst'
8447  *  to handle forward branch patching.
8448  */
8449
8450 BYTE* emitter::emitOutputLJ(insGroup* ig, BYTE* dst, instrDesc* i)
8451 {
8452     instrDescJmp* id = (instrDescJmp*)i;
8453
8454     unsigned srcOffs;
8455     unsigned dstOffs;
8456     BYTE*    srcAddr;
8457     BYTE*    dstAddr;
8458     ssize_t  distVal;
8459
8460     // Set default ins/fmt from id.
8461     instruction ins = id->idIns();
8462     insFormat   fmt = id->idInsFmt();
8463
8464     bool loadLabel    = false;
8465     bool isJump       = false;
8466     bool loadConstant = false;
8467
8468     switch (ins)
8469     {
8470         default:
8471             isJump = true;
8472             break;
8473
8474         case INS_tbz:
8475         case INS_tbnz:
8476         case INS_cbz:
8477         case INS_cbnz:
8478             isJump = true;
8479             break;
8480
8481         case INS_ldr:
8482         case INS_ldrsw:
8483             loadConstant = true;
8484             break;
8485
8486         case INS_adr:
8487         case INS_adrp:
8488             loadLabel = true;
8489             break;
8490     }
8491
8492     /* Figure out the distance to the target */
8493
8494     srcOffs = emitCurCodeOffs(dst);
8495     srcAddr = emitOffsetToPtr(srcOffs);
8496
8497     if (id->idAddr()->iiaIsJitDataOffset())
8498     {
8499         assert(loadConstant || loadLabel);
8500         int doff = id->idAddr()->iiaGetJitDataOffset();
8501         assert(doff >= 0);
8502         ssize_t imm = emitGetInsSC(id);
8503         assert((imm >= 0) && (imm < 0x1000)); // 0x1000 is arbitrary, currently 'imm' is always 0
8504
8505         unsigned dataOffs = (unsigned)(doff + imm);
8506         assert(dataOffs < emitDataSize());
8507         dstAddr = emitDataOffsetToPtr(dataOffs);
8508
8509         regNumber dstReg  = id->idReg1();
8510         regNumber addrReg = dstReg; // an integer register to compute long address.
8511         emitAttr  opSize  = id->idOpSize();
8512
8513         if (loadConstant)
8514         {
8515             if (id->idjShort)
8516             {
8517                 // ldr x/v, [rel addr] -- load constant from current addr(ip) + rel addr.
8518                 assert(ins == INS_ldr);
8519                 assert(fmt == IF_LS_1A);
8520                 distVal = (ssize_t)(dstAddr - srcAddr);
8521                 dst     = emitOutputShortConstant(dst, ins, fmt, distVal, dstReg, opSize);
8522             }
8523             else
8524             {
8525                 // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8526                 assert(fmt == IF_LARGELDC);
8527                 ssize_t relPageAddr =
8528                     (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8529                 if (isVectorRegister(dstReg))
8530                 {
8531                     // Update addrReg with the reserved integer register
8532                     // since we cannot use dstReg (vector) to load constant directly from memory.
8533                     addrReg = id->idReg2();
8534                     assert(isGeneralRegister(addrReg));
8535                 }
8536                 ins = INS_adrp;
8537                 fmt = IF_DI_1E;
8538                 dst = emitOutputShortAddress(dst, ins, fmt, relPageAddr, addrReg);
8539
8540                 // ldr x, [x, page offs] -- load constant from page address + page offset into integer register.
8541                 ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8542                 assert(isValidUimm12(imm12));
8543                 ins = INS_ldr;
8544                 fmt = IF_LS_2B;
8545                 dst = emitOutputShortConstant(dst, ins, fmt, imm12, addrReg, opSize);
8546
8547                 // fmov v, d -- copy constant in integer register to vector register.
8548                 // This is needed only for vector constant.
8549                 if (addrReg != dstReg)
8550                 {
8551                     //  fmov    Vd,Rn                DV_2I  X00111100X100111 000000nnnnnddddd   1E27 0000   Vd,Rn
8552                     //  (scalar, from general)
8553                     assert(isVectorRegister(dstReg) && isGeneralRegister(addrReg));
8554                     ins         = INS_fmov;
8555                     fmt         = IF_DV_2I;
8556                     code_t code = emitInsCode(ins, fmt);
8557
8558                     code |= insEncodeReg_Vd(dstReg);  // ddddd
8559                     code |= insEncodeReg_Rn(addrReg); // nnnnn
8560                     if (id->idOpSize() == EA_8BYTE)
8561                     {
8562                         code |= 0x80400000; // X ... X
8563                     }
8564                     dst += emitOutput_Instr(dst, code);
8565                 }
8566             }
8567         }
8568         else
8569         {
8570             assert(loadLabel);
8571             dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8572         }
8573
8574         return dst;
8575     }
8576
8577     assert(loadLabel || isJump);
8578
8579     if (id->idAddr()->iiaHasInstrCount())
8580     {
8581         assert(ig != NULL);
8582         int      instrCount = id->idAddr()->iiaGetInstrCount();
8583         unsigned insNum     = emitFindInsNum(ig, id);
8584         if (instrCount < 0)
8585         {
8586             // Backward branches using instruction count must be within the same instruction group.
8587             assert(insNum + 1 >= (unsigned)(-instrCount));
8588         }
8589         dstOffs = ig->igOffs + emitFindOffset(ig, (insNum + 1 + instrCount));
8590         dstAddr = emitOffsetToPtr(dstOffs);
8591     }
8592     else
8593     {
8594         dstOffs = id->idAddr()->iiaIGlabel->igOffs;
8595         dstAddr = emitOffsetToPtr(dstOffs);
8596     }
8597
8598     distVal = (ssize_t)(dstAddr - srcAddr);
8599
8600     if (dstOffs <= srcOffs)
8601     {
8602 #if DEBUG_EMIT
8603         /* This is a backward jump - distance is known at this point */
8604
8605         if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8606         {
8607             size_t blkOffs = id->idjIG->igOffs;
8608
8609             if (INTERESTING_JUMP_NUM == 0)
8610                 printf("[3] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8611             printf("[3] Jump  block is at %08X - %02X = %08X\n", blkOffs, emitOffsAdj, blkOffs - emitOffsAdj);
8612             printf("[3] Jump        is at %08X - %02X = %08X\n", srcOffs, emitOffsAdj, srcOffs - emitOffsAdj);
8613             printf("[3] Label block is at %08X - %02X = %08X\n", dstOffs, emitOffsAdj, dstOffs - emitOffsAdj);
8614         }
8615 #endif
8616     }
8617     else
8618     {
8619         /* This is a  forward jump - distance will be an upper limit */
8620
8621         emitFwdJumps = true;
8622
8623         /* The target offset will be closer by at least 'emitOffsAdj', but only if this
8624            jump doesn't cross the hot-cold boundary. */
8625
8626         if (!emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8627         {
8628             dstOffs -= emitOffsAdj;
8629             distVal -= emitOffsAdj;
8630         }
8631
8632         /* Record the location of the jump for later patching */
8633
8634         id->idjOffs = dstOffs;
8635
8636         /* Are we overflowing the id->idjOffs bitfield? */
8637         if (id->idjOffs != dstOffs)
8638             IMPL_LIMITATION("Method is too large");
8639
8640 #if DEBUG_EMIT
8641         if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8642         {
8643             size_t blkOffs = id->idjIG->igOffs;
8644
8645             if (INTERESTING_JUMP_NUM == 0)
8646                 printf("[4] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8647             printf("[4] Jump  block is at %08X\n", blkOffs);
8648             printf("[4] Jump        is at %08X\n", srcOffs);
8649             printf("[4] Label block is at %08X - %02X = %08X\n", dstOffs + emitOffsAdj, emitOffsAdj, dstOffs);
8650         }
8651 #endif
8652     }
8653
8654 #ifdef DEBUG
8655     if (0 && emitComp->verbose)
8656     {
8657         size_t sz          = 4;
8658         int    distValSize = id->idjShort ? 4 : 8;
8659         printf("; %s jump [%08X/%03u] from %0*X to %0*X: dist = %08XH\n", (dstOffs <= srcOffs) ? "Fwd" : "Bwd",
8660                dspPtr(id), id->idDebugOnlyInfo()->idNum, distValSize, srcOffs + sz, distValSize, dstOffs, distVal);
8661     }
8662 #endif
8663
8664     /* For forward jumps, record the address of the distance value */
8665     id->idjTemp.idjAddr = (distVal > 0) ? dst : NULL;
8666
8667     if (emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8668     {
8669         assert(!id->idjShort);
8670         NYI_ARM64("Relocation Support for long address");
8671     }
8672
8673     assert(insOptsNone(id->idInsOpt()));
8674
8675     if (isJump)
8676     {
8677         if (id->idjShort)
8678         {
8679             // Short conditional/unconditional jump
8680             assert(!id->idjKeepLong);
8681             assert(emitJumpCrossHotColdBoundary(srcOffs, dstOffs) == false);
8682             assert((fmt == IF_BI_0A) || (fmt == IF_BI_0B) || (fmt == IF_BI_1A) || (fmt == IF_BI_1B));
8683         }
8684         else
8685         {
8686             // Long conditional jump
8687             assert(fmt == IF_LARGEJMP);
8688             // This is a pseudo-instruction format representing a large conditional branch, to allow
8689             // us to get a greater branch target range than we can get by using a straightforward conditional
8690             // branch. It is encoded as a short conditional branch that branches around a long unconditional
8691             // branch.
8692             //
8693             // Conceptually, we have:
8694             //
8695             //      b<cond> L_target
8696             //
8697             // The code we emit is:
8698             //
8699             //      b<!cond> L_not  // 4 bytes. Note that we reverse the condition.
8700             //      b L_target      // 4 bytes
8701             //   L_not:
8702             //
8703             // Note that we don't actually insert any blocks: we simply encode "b <!cond> L_not" as a branch with
8704             // the correct offset. Note also that this works for both integer and floating-point conditions, because
8705             // the condition inversion takes ordered/unordered into account, preserving NaN behavior. For example,
8706             // "GT" (greater than) is inverted to "LE" (less than, equal, or unordered).
8707
8708             instruction reverseIns;
8709             insFormat   reverseFmt;
8710
8711             switch (ins)
8712             {
8713                 case INS_cbz:
8714                     reverseIns = INS_cbnz;
8715                     reverseFmt = IF_BI_1A;
8716                     break;
8717                 case INS_cbnz:
8718                     reverseIns = INS_cbz;
8719                     reverseFmt = IF_BI_1A;
8720                     break;
8721                 case INS_tbz:
8722                     reverseIns = INS_tbnz;
8723                     reverseFmt = IF_BI_1B;
8724                     break;
8725                 case INS_tbnz:
8726                     reverseIns = INS_tbz;
8727                     reverseFmt = IF_BI_1B;
8728                     break;
8729                 default:
8730                     reverseIns = emitJumpKindToIns(emitReverseJumpKind(emitInsToJumpKind(ins)));
8731                     reverseFmt = IF_BI_0B;
8732             }
8733
8734             dst =
8735                 emitOutputShortBranch(dst,
8736                                       reverseIns, // reverse the conditional instruction
8737                                       reverseFmt,
8738                                       8, /* 8 bytes from start of this large conditional pseudo-instruction to L_not. */
8739                                       id);
8740
8741             // Now, pretend we've got a normal unconditional branch, and fall through to the code to emit that.
8742             ins = INS_b;
8743             fmt = IF_BI_0A;
8744
8745             // The distVal was computed based on the beginning of the pseudo-instruction,
8746             // So subtract the size of the conditional branch so that it is relative to the
8747             // unconditional branch.
8748             distVal -= 4;
8749         }
8750
8751         dst = emitOutputShortBranch(dst, ins, fmt, distVal, id);
8752     }
8753     else if (loadLabel)
8754     {
8755         dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8756     }
8757
8758     return dst;
8759 }
8760
8761 /*****************************************************************************
8762 *
8763 *  Output a short branch instruction.
8764 */
8765 BYTE* emitter::emitOutputShortBranch(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, instrDescJmp* id)
8766 {
8767     code_t code = emitInsCode(ins, fmt);
8768
8769     ssize_t loBits = (distVal & 3);
8770     noway_assert(loBits == 0);
8771     distVal >>= 2; // branch offset encodings are scaled by 4.
8772
8773     if (fmt == IF_BI_0A)
8774     {
8775         // INS_b or INS_bl_local
8776         noway_assert(isValidSimm26(distVal));
8777         distVal &= 0x3FFFFFFLL;
8778         code |= distVal;
8779     }
8780     else if (fmt == IF_BI_0B) // BI_0B   01010100iiiiiiii iiiiiiiiiiiXXXXX      simm19:00
8781     {
8782         // INS_beq, INS_bne, etc...
8783         noway_assert(isValidSimm19(distVal));
8784         distVal &= 0x7FFFFLL;
8785         code |= distVal << 5;
8786     }
8787     else if (fmt == IF_BI_1A) // BI_1A   X.......iiiiiiii iiiiiiiiiiittttt      Rt simm19:00
8788     {
8789         // INS_cbz or INS_cbnz
8790         assert(id != nullptr);
8791         code |= insEncodeDatasize(id->idOpSize()); // X
8792         code |= insEncodeReg_Rt(id->idReg1());     // ttttt
8793
8794         noway_assert(isValidSimm19(distVal));
8795         distVal &= 0x7FFFFLL; // 19 bits
8796         code |= distVal << 5;
8797     }
8798     else if (fmt == IF_BI_1B) // BI_1B   B.......bbbbbiii iiiiiiiiiiittttt      Rt imm6, simm14:00
8799     {
8800         // INS_tbz or INS_tbnz
8801         assert(id != nullptr);
8802         ssize_t imm = emitGetInsSC(id);
8803         assert(isValidImmShift(imm, id->idOpSize()));
8804
8805         if (imm & 0x20) // test bit 32-63 ?
8806         {
8807             code |= 0x80000000; // B
8808         }
8809         code |= ((imm & 0x1F) << 19);          // bbbbb
8810         code |= insEncodeReg_Rt(id->idReg1()); // ttttt
8811
8812         noway_assert(isValidSimm14(distVal));
8813         distVal &= 0x3FFFLL; // 14 bits
8814         code |= distVal << 5;
8815     }
8816     else
8817     {
8818         assert(!"Unknown fmt for emitOutputShortBranch");
8819     }
8820
8821     dst += emitOutput_Instr(dst, code);
8822
8823     return dst;
8824 }
8825
8826 /*****************************************************************************
8827 *
8828 *  Output a short address instruction.
8829 */
8830 BYTE* emitter::emitOutputShortAddress(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, regNumber reg)
8831 {
8832     ssize_t loBits = (distVal & 3);
8833     distVal >>= 2;
8834
8835     code_t code = emitInsCode(ins, fmt);
8836     if (fmt == IF_DI_1E) // DI_1E   .ii.....iiiiiiii iiiiiiiiiiiddddd      Rd simm21
8837     {
8838         // INS_adr or INS_adrp
8839         code |= insEncodeReg_Rd(reg); // ddddd
8840
8841         noway_assert(isValidSimm19(distVal));
8842         distVal &= 0x7FFFFLL; // 19 bits
8843         code |= distVal << 5;
8844         code |= loBits << 29; //  2 bits
8845     }
8846     else
8847     {
8848         assert(!"Unknown fmt for emitOutputShortAddress");
8849     }
8850
8851     dst += emitOutput_Instr(dst, code);
8852
8853     return dst;
8854 }
8855
8856 /*****************************************************************************
8857 *
8858 *  Output a short constant instruction.
8859 */
8860 BYTE* emitter::emitOutputShortConstant(
8861     BYTE* dst, instruction ins, insFormat fmt, ssize_t imm, regNumber reg, emitAttr opSize)
8862 {
8863     code_t code = emitInsCode(ins, fmt);
8864
8865     if (fmt == IF_LS_1A)
8866     {
8867         // LS_1A   XX...V..iiiiiiii iiiiiiiiiiittttt      Rt simm21
8868         // INS_ldr or INS_ldrsw (PC-Relative)
8869
8870         ssize_t loBits = (imm & 3);
8871         noway_assert(loBits == 0);
8872         ssize_t distVal = imm >>= 2; // load offset encodings are scaled by 4.
8873
8874         noway_assert(isValidSimm19(distVal));
8875
8876         // Is the target a vector register?
8877         if (isVectorRegister(reg))
8878         {
8879             code |= insEncodeDatasizeVLS(code, opSize); // XX V
8880             code |= insEncodeReg_Vt(reg);               // ttttt
8881         }
8882         else
8883         {
8884             assert(isGeneralRegister(reg));
8885             // insEncodeDatasizeLS is not quite right for this case.
8886             // So just specialize it.
8887             if ((ins == INS_ldr) && (opSize == EA_8BYTE))
8888             {
8889                 // set the operation size in bit 30
8890                 code |= 0x40000000;
8891             }
8892
8893             code |= insEncodeReg_Rt(reg); // ttttt
8894         }
8895
8896         distVal &= 0x7FFFFLL; // 19 bits
8897         code |= distVal << 5;
8898     }
8899     else if (fmt == IF_LS_2B)
8900     {
8901         //  ldr     Rt,[Xn+pimm12]       LS_2B  1X11100101iiiiii iiiiiinnnnnttttt   B940 0000   imm(0-4095<<{2,3})
8902         // INS_ldr or INS_ldrsw (PC-Relative)
8903         noway_assert(isValidUimm12(imm));
8904         assert(isGeneralRegister(reg));
8905
8906         if (opSize == EA_8BYTE)
8907         {
8908             // insEncodeDatasizeLS is not quite right for this case.
8909             // So just specialize it.
8910             if (ins == INS_ldr)
8911             {
8912                 // set the operation size in bit 30
8913                 code |= 0x40000000;
8914             }
8915             // Low 3 bits should be 0 -- 8 byte JIT data should be aligned on 8 byte.
8916             assert((imm & 7) == 0);
8917             imm >>= 3;
8918         }
8919         else
8920         {
8921             assert(opSize == EA_4BYTE);
8922             // Low 2 bits should be 0 -- 4 byte aligned data.
8923             assert((imm & 3) == 0);
8924             imm >>= 2;
8925         }
8926
8927         code |= insEncodeReg_Rt(reg); // ttttt
8928         code |= insEncodeReg_Rn(reg); // nnnnn
8929         code |= imm << 10;
8930     }
8931     else
8932     {
8933         assert(!"Unknown fmt for emitOutputShortConstant");
8934     }
8935
8936     dst += emitOutput_Instr(dst, code);
8937
8938     return dst;
8939 }
8940 /*****************************************************************************
8941  *
8942  *  Output a call instruction.
8943  */
8944
8945 unsigned emitter::emitOutputCall(insGroup* ig, BYTE* dst, instrDesc* id, code_t code)
8946 {
8947     const unsigned char callInstrSize = sizeof(code_t); // 4 bytes
8948     regMaskTP           gcrefRegs;
8949     regMaskTP           byrefRegs;
8950
8951     VARSET_TP GCvars(VarSetOps::UninitVal());
8952
8953     // Is this a "fat" call descriptor?
8954     if (id->idIsLargeCall())
8955     {
8956         instrDescCGCA* idCall = (instrDescCGCA*)id;
8957         gcrefRegs             = idCall->idcGcrefRegs;
8958         byrefRegs             = idCall->idcByrefRegs;
8959         VarSetOps::Assign(emitComp, GCvars, idCall->idcGCvars);
8960     }
8961     else
8962     {
8963         assert(!id->idIsLargeDsp());
8964         assert(!id->idIsLargeCns());
8965
8966         gcrefRegs = emitDecodeCallGCregs(id);
8967         byrefRegs = 0;
8968         VarSetOps::AssignNoCopy(emitComp, GCvars, VarSetOps::MakeEmpty(emitComp));
8969     }
8970
8971     /* We update the GC info before the call as the variables cannot be
8972         used by the call. Killing variables before the call helps with
8973         boundary conditions if the call is CORINFO_HELP_THROW - see bug 50029.
8974         If we ever track aliased variables (which could be used by the
8975         call), we would have to keep them alive past the call. */
8976
8977     emitUpdateLiveGCvars(GCvars, dst);
8978
8979     // Now output the call instruction and update the 'dst' pointer
8980     //
8981     unsigned outputInstrSize = emitOutput_Instr(dst, code);
8982     dst += outputInstrSize;
8983
8984     // All call instructions are 4-byte in size on ARM64
8985     //
8986     assert(outputInstrSize == callInstrSize);
8987
8988     // If the method returns a GC ref, mark INTRET (R0) appropriately.
8989     if (id->idGCref() == GCT_GCREF)
8990     {
8991         gcrefRegs |= RBM_INTRET;
8992     }
8993     else if (id->idGCref() == GCT_BYREF)
8994     {
8995         byrefRegs |= RBM_INTRET;
8996     }
8997
8998     // If is a multi-register return method is called, mark INTRET_1 (X1) appropriately
8999     if (id->idIsLargeCall())
9000     {
9001         instrDescCGCA* idCall = (instrDescCGCA*)id;
9002         if (idCall->idSecondGCref() == GCT_GCREF)
9003         {
9004             gcrefRegs |= RBM_INTRET_1;
9005         }
9006         else if (idCall->idSecondGCref() == GCT_BYREF)
9007         {
9008             byrefRegs |= RBM_INTRET_1;
9009         }
9010     }
9011
9012     // If the GC register set has changed, report the new set.
9013     if (gcrefRegs != emitThisGCrefRegs)
9014     {
9015         emitUpdateLiveGCregs(GCT_GCREF, gcrefRegs, dst);
9016     }
9017     // If the Byref register set has changed, report the new set.
9018     if (byrefRegs != emitThisByrefRegs)
9019     {
9020         emitUpdateLiveGCregs(GCT_BYREF, byrefRegs, dst);
9021     }
9022
9023     // Some helper calls may be marked as not requiring GC info to be recorded.
9024     if ((!id->idIsNoGC()))
9025     {
9026         // On ARM64, as on AMD64, we don't change the stack pointer to push/pop args.
9027         // So we're not really doing a "stack pop" here (note that "args" is 0), but we use this mechanism
9028         // to record the call for GC info purposes.  (It might be best to use an alternate call,
9029         // and protect "emitStackPop" under the EMIT_TRACK_STACK_DEPTH preprocessor variable.)
9030         emitStackPop(dst, /*isCall*/ true, callInstrSize, /*args*/ 0);
9031
9032         // Do we need to record a call location for GC purposes?
9033         //
9034         if (!emitFullGCinfo)
9035         {
9036             emitRecordGCcall(dst, callInstrSize);
9037         }
9038     }
9039     return callInstrSize;
9040 }
9041
9042 /*****************************************************************************
9043  *
9044  *  Emit a 32-bit Arm64 instruction
9045  */
9046
9047 /*static*/ unsigned emitter::emitOutput_Instr(BYTE* dst, code_t code)
9048 {
9049     assert(sizeof(code_t) == 4);
9050     *((code_t*)dst) = code;
9051
9052     return sizeof(code_t);
9053 }
9054
9055 /*****************************************************************************
9056 *
9057  *  Append the machine code corresponding to the given instruction descriptor
9058  *  to the code block at '*dp'; the base of the code block is 'bp', and 'ig'
9059  *  is the instruction group that contains the instruction. Updates '*dp' to
9060  *  point past the generated code, and returns the size of the instruction
9061  *  descriptor in bytes.
9062  */
9063
9064 size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
9065 {
9066     BYTE*       dst  = *dp;
9067     BYTE*       odst = dst;
9068     code_t      code = 0;
9069     size_t      sz   = emitGetInstrDescSize(id); // TODO-ARM64-Cleanup: on ARM, this is set in each case. why?
9070     instruction ins  = id->idIns();
9071     insFormat   fmt  = id->idInsFmt();
9072     emitAttr    size = id->idOpSize();
9073
9074 #ifdef DEBUG
9075 #if DUMP_GC_TABLES
9076     bool dspOffs = emitComp->opts.dspGCtbls;
9077 #else
9078     bool dspOffs = !emitComp->opts.disDiffable;
9079 #endif
9080 #endif // DEBUG
9081
9082     assert(REG_NA == (int)REG_NA);
9083
9084     /* What instruction format have we got? */
9085
9086     switch (fmt)
9087     {
9088         ssize_t  imm;
9089         ssize_t  index;
9090         ssize_t  index2;
9091         unsigned cmode;
9092         unsigned immShift;
9093         emitAttr elemsize;
9094         emitAttr datasize;
9095
9096         case IF_BI_0A: // BI_0A   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
9097         case IF_BI_0B: // BI_0B   ......iiiiiiiiii iiiiiiiiiii.....               simm19:00
9098         case IF_LARGEJMP:
9099             assert(id->idGCref() == GCT_NONE);
9100             assert(id->idIsBound());
9101             dst = emitOutputLJ(ig, dst, id);
9102             sz  = sizeof(instrDescJmp);
9103             break;
9104
9105         case IF_BI_0C: // BI_0C   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
9106             code = emitInsCode(ins, fmt);
9107             sz   = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
9108             dst += emitOutputCall(ig, dst, id, code);
9109             // Always call RecordRelocation so that we wire in a JumpStub when we don't reach
9110             emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_BRANCH26);
9111             break;
9112
9113         case IF_BI_1A: // BI_1A   ......iiiiiiiiii iiiiiiiiiiittttt      Rt       simm19:00
9114             assert(insOptsNone(id->idInsOpt()));
9115             assert(id->idIsBound());
9116
9117             dst = emitOutputLJ(ig, dst, id);
9118             sz  = sizeof(instrDescJmp);
9119             break;
9120
9121         case IF_BI_1B: // BI_1B   B.......bbbbbiii iiiiiiiiiiittttt      Rt imm6, simm14:00
9122             assert(insOptsNone(id->idInsOpt()));
9123             assert(id->idIsBound());
9124
9125             dst = emitOutputLJ(ig, dst, id);
9126             sz  = sizeof(instrDescJmp);
9127             break;
9128
9129         case IF_BR_1A: // BR_1A   ................ ......nnnnn.....         Rn
9130             assert(insOptsNone(id->idInsOpt()));
9131             assert((ins == INS_ret) || (ins == INS_br));
9132             code = emitInsCode(ins, fmt);
9133             code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9134
9135             dst += emitOutput_Instr(dst, code);
9136             break;
9137
9138         case IF_BR_1B: // BR_1B   ................ ......nnnnn.....         Rn
9139             assert(insOptsNone(id->idInsOpt()));
9140             assert((ins == INS_br_tail) || (ins == INS_blr));
9141             code = emitInsCode(ins, fmt);
9142             code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9143
9144             sz = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
9145             dst += emitOutputCall(ig, dst, id, code);
9146             break;
9147
9148         case IF_LS_1A: // LS_1A   XX...V..iiiiiiii iiiiiiiiiiittttt      Rt    PC imm(1MB)
9149         case IF_LARGELDC:
9150             assert(insOptsNone(id->idInsOpt()));
9151             assert(id->idIsBound());
9152
9153             dst = emitOutputLJ(ig, dst, id);
9154             sz  = sizeof(instrDescJmp);
9155             break;
9156
9157         case IF_LS_2A: // LS_2A   .X.......X...... ......nnnnnttttt      Rt Rn
9158             assert(insOptsNone(id->idInsOpt()));
9159             code = emitInsCode(ins, fmt);
9160             // Is the target a vector register?
9161             if (isVectorRegister(id->idReg1()))
9162             {
9163                 code &= 0x3FFFFFFF;                                 // clear the size bits
9164                 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9165                 code |= insEncodeReg_Vt(id->idReg1());              // ttttt
9166             }
9167             else
9168             {
9169                 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9170                 code |= insEncodeReg_Rt(id->idReg1());             // ttttt
9171             }
9172             code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9173             dst += emitOutput_Instr(dst, code);
9174             break;
9175
9176         case IF_LS_2B: // LS_2B   .X.......Xiiiiii iiiiiinnnnnttttt      Rt Rn    imm(0-4095)
9177             assert(insOptsNone(id->idInsOpt()));
9178             imm = emitGetInsSC(id);
9179             assert(isValidUimm12(imm));
9180             code = emitInsCode(ins, fmt);
9181             // Is the target a vector register?
9182             if (isVectorRegister(id->idReg1()))
9183             {
9184                 code &= 0x3FFFFFFF;                                 // clear the size bits
9185                 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9186                 code |= insEncodeReg_Vt(id->idReg1());              // ttttt
9187             }
9188             else
9189             {
9190                 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9191                 code |= insEncodeReg_Rt(id->idReg1());             // ttttt
9192             }
9193             code |= ((code_t)imm << 10);           // iiiiiiiiiiii
9194             code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9195             dst += emitOutput_Instr(dst, code);
9196             break;
9197
9198         case IF_LS_2C: // LS_2C   .X.......X.iiiii iiiiPPnnnnnttttt      Rt Rn    imm(-256..+255) no/pre/post inc
9199             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9200             imm = emitGetInsSC(id);
9201             assert((imm >= -256) && (imm <= 255)); // signed 9 bits
9202             imm &= 0x1ff;                          // force into unsigned 9 bit representation
9203             code = emitInsCode(ins, fmt);
9204             // Is the target a vector register?
9205             if (isVectorRegister(id->idReg1()))
9206             {
9207                 code &= 0x3FFFFFFF;                                 // clear the size bits
9208                 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9209                 code |= insEncodeReg_Vt(id->idReg1());              // ttttt
9210             }
9211             else
9212             {
9213                 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9214                 code |= insEncodeReg_Rt(id->idReg1());             // ttttt
9215             }
9216             code |= insEncodeIndexedOpt(id->idInsOpt()); // PP
9217             code |= ((code_t)imm << 12);                 // iiiiiiiii
9218             code |= insEncodeReg_Rn(id->idReg2());       // nnnnn
9219             dst += emitOutput_Instr(dst, code);
9220             break;
9221
9222         case IF_LS_3A: // LS_3A   .X.......X.mmmmm oooS..nnnnnttttt      Rt Rn Rm ext(Rm) LSL {}
9223             assert(insOptsLSExtend(id->idInsOpt()));
9224             code = emitInsCode(ins, fmt);
9225             // Is the target a vector register?
9226             if (isVectorRegister(id->idReg1()))
9227             {
9228                 code &= 0x3FFFFFFF;                                 // clear the size bits
9229                 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9230                 code |= insEncodeReg_Vt(id->idReg1());              // ttttt
9231             }
9232             else
9233             {
9234                 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9235                 code |= insEncodeReg_Rt(id->idReg1());             // ttttt
9236             }
9237             code |= insEncodeExtend(id->idInsOpt()); // ooo
9238             code |= insEncodeReg_Rn(id->idReg2());   // nnnnn
9239             if (id->idIsLclVar())
9240             {
9241                 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9242             }
9243             else
9244             {
9245                 code |= insEncodeReg3Scale(id->idReg3Scaled()); // S
9246                 code |= insEncodeReg_Rm(id->idReg3());          // mmmmm
9247             }
9248             dst += emitOutput_Instr(dst, code);
9249             break;
9250
9251         case IF_LS_3B: // LS_3B   X............... .aaaaannnnnddddd      Rd Ra Rn
9252             assert(insOptsNone(id->idInsOpt()));
9253             code = emitInsCode(ins, fmt);
9254             // Is the target a vector register?
9255             if (isVectorRegister(id->idReg1()))
9256             {
9257                 code &= 0x3FFFFFFF;                                  // clear the size bits
9258                 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9259                 code |= insEncodeReg_Vt(id->idReg1());               // ttttt
9260                 code |= insEncodeReg_Va(id->idReg2());               // aaaaa
9261             }
9262             else
9263             {
9264                 code |= insEncodeDatasize(id->idOpSize()); // X
9265                 code |= insEncodeReg_Rt(id->idReg1());     // ttttt
9266                 code |= insEncodeReg_Ra(id->idReg2());     // aaaaa
9267             }
9268             code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9269             dst += emitOutput_Instr(dst, code);
9270             break;
9271
9272         case IF_LS_3C: // LS_3C   X......PP.iiiiii iaaaaannnnnddddd      Rd Ra Rn imm(im7,sh)
9273             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9274             imm = emitGetInsSC(id);
9275             assert((imm >= -64) && (imm <= 63)); // signed 7 bits
9276             imm &= 0x7f;                         // force into unsigned 7 bit representation
9277             code = emitInsCode(ins, fmt);
9278             // Is the target a vector register?
9279             if (isVectorRegister(id->idReg1()))
9280             {
9281                 code &= 0x3FFFFFFF;                                  // clear the size bits
9282                 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9283                 code |= insEncodeReg_Vt(id->idReg1());               // ttttt
9284                 code |= insEncodeReg_Va(id->idReg2());               // aaaaa
9285             }
9286             else
9287             {
9288                 code |= insEncodeDatasize(id->idOpSize()); // X
9289                 code |= insEncodeReg_Rt(id->idReg1());     // ttttt
9290                 code |= insEncodeReg_Ra(id->idReg2());     // aaaaa
9291             }
9292             code |= insEncodePairIndexedOpt(ins, id->idInsOpt()); // PP
9293             code |= ((code_t)imm << 15);                          // iiiiiiiii
9294             code |= insEncodeReg_Rn(id->idReg3());                // nnnnn
9295             dst += emitOutput_Instr(dst, code);
9296             break;
9297
9298         case IF_LS_3D: // LS_3D   .X.......X.mmmmm ......nnnnnttttt      Wm Rt Rn
9299             code = emitInsCode(ins, fmt);
9300             // Arm64 store exclusive unpredictable cases
9301             assert(id->idReg1() != id->idReg2());
9302             assert(id->idReg1() != id->idReg3());
9303             code |= insEncodeDatasizeLS(code, id->idOpSize()); // X
9304             code |= insEncodeReg_Rm(id->idReg1());             // mmmmm
9305             code |= insEncodeReg_Rt(id->idReg2());             // ttttt
9306             code |= insEncodeReg_Rn(id->idReg3());             // nnnnn
9307             dst += emitOutput_Instr(dst, code);
9308             break;
9309
9310         case IF_LS_3E: // LS_3E   .X.........mmmmm ......nnnnnttttt      Rm Rt Rn ARMv8.1 LSE Atomics
9311             code = emitInsCode(ins, fmt);
9312             code |= insEncodeDatasizeLS(code, id->idOpSize()); // X
9313             code |= insEncodeReg_Rm(id->idReg1());             // mmmmm
9314             code |= insEncodeReg_Rt(id->idReg2());             // ttttt
9315             code |= insEncodeReg_Rn(id->idReg3());             // nnnnn
9316             dst += emitOutput_Instr(dst, code);
9317             break;
9318
9319         case IF_DI_1A: // DI_1A   X.......shiiiiii iiiiiinnnnn.....         Rn    imm(i12,sh)
9320             assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9321             imm = emitGetInsSC(id);
9322             assert(isValidUimm12(imm));
9323             code = emitInsCode(ins, fmt);
9324             code |= insEncodeDatasize(id->idOpSize());   // X
9325             code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9326             code |= ((code_t)imm << 10);                 // iiiiiiiiiiii
9327             code |= insEncodeReg_Rn(id->idReg1());       // nnnnn
9328             dst += emitOutput_Instr(dst, code);
9329             break;
9330
9331         case IF_DI_1B: // DI_1B   X........hwiiiii iiiiiiiiiiiddddd      Rd       imm(i16,hw)
9332             imm = emitGetInsSC(id);
9333             assert(isValidImmHWVal(imm, id->idOpSize()));
9334             code = emitInsCode(ins, fmt);
9335             code |= insEncodeDatasize(id->idOpSize()); // X
9336             code |= ((code_t)imm << 5);                // hwiiiii iiiiiiiiiii
9337             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9338             dst += emitOutput_Instr(dst, code);
9339             break;
9340
9341         case IF_DI_1C: // DI_1C   X........Nrrrrrr ssssssnnnnn.....         Rn    imm(N,r,s)
9342             imm = emitGetInsSC(id);
9343             assert(isValidImmNRS(imm, id->idOpSize()));
9344             code = emitInsCode(ins, fmt);
9345             code |= ((code_t)imm << 10);               // Nrrrrrrssssss
9346             code |= insEncodeDatasize(id->idOpSize()); // X
9347             code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9348             dst += emitOutput_Instr(dst, code);
9349             break;
9350
9351         case IF_DI_1D: // DI_1D   X........Nrrrrrr ssssss.....ddddd      Rd       imm(N,r,s)
9352             imm = emitGetInsSC(id);
9353             assert(isValidImmNRS(imm, id->idOpSize()));
9354             code = emitInsCode(ins, fmt);
9355             code |= ((code_t)imm << 10);               // Nrrrrrrssssss
9356             code |= insEncodeDatasize(id->idOpSize()); // X
9357             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9358             dst += emitOutput_Instr(dst, code);
9359             break;
9360
9361         case IF_DI_1E: // DI_1E   .ii.....iiiiiiii iiiiiiiiiiiddddd      Rd       simm21
9362         case IF_LARGEADR:
9363             assert(insOptsNone(id->idInsOpt()));
9364             if (id->idIsReloc())
9365             {
9366                 code = emitInsCode(ins, fmt);
9367                 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9368                 dst += emitOutput_Instr(dst, code);
9369                 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEBASE_REL21);
9370             }
9371             else
9372             {
9373                 // Local jmp/load case which does not need a relocation.
9374                 assert(id->idIsBound());
9375                 dst = emitOutputLJ(ig, dst, id);
9376             }
9377             sz = sizeof(instrDescJmp);
9378             break;
9379
9380         case IF_DI_1F: // DI_1F   X..........iiiii cccc..nnnnn.nzcv      Rn imm5  nzcv cond
9381             imm = emitGetInsSC(id);
9382             assert(isValidImmCondFlagsImm5(imm));
9383             {
9384                 condFlagsImm cfi;
9385                 cfi.immCFVal = (unsigned)imm;
9386                 code         = emitInsCode(ins, fmt);
9387                 code |= insEncodeDatasize(id->idOpSize()); // X
9388                 code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9389                 code |= ((code_t)cfi.imm5 << 16);          // iiiii
9390                 code |= insEncodeFlags(cfi.flags);         // nzcv
9391                 code |= insEncodeCond(cfi.cond);           // cccc
9392                 dst += emitOutput_Instr(dst, code);
9393             }
9394             break;
9395
9396         case IF_DI_2A: // DI_2A   X.......shiiiiii iiiiiinnnnnddddd      Rd Rn    imm(i12,sh)
9397             assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9398             imm = emitGetInsSC(id);
9399             assert(isValidUimm12(imm));
9400             code = emitInsCode(ins, fmt);
9401             code |= insEncodeDatasize(id->idOpSize());   // X
9402             code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9403             code |= ((code_t)imm << 10);                 // iiiiiiiiiiii
9404             code |= insEncodeReg_Rd(id->idReg1());       // ddddd
9405             code |= insEncodeReg_Rn(id->idReg2());       // nnnnn
9406             dst += emitOutput_Instr(dst, code);
9407
9408             if (id->idIsReloc())
9409             {
9410                 assert(sz == sizeof(instrDesc));
9411                 assert(id->idAddr()->iiaAddr != nullptr);
9412                 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEOFFSET_12A);
9413             }
9414             break;
9415
9416         case IF_DI_2B: // DI_2B   X.........Xnnnnn ssssssnnnnnddddd      Rd Rn    imm(0-63)
9417             code = emitInsCode(ins, fmt);
9418             imm  = emitGetInsSC(id);
9419             assert(isValidImmShift(imm, id->idOpSize()));
9420             code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9421             code |= insEncodeReg_Rd(id->idReg1());             // ddddd
9422             code |= insEncodeReg_Rn(id->idReg2());             // nnnnn
9423             code |= insEncodeReg_Rm(id->idReg2());             // Reg2 also in mmmmm
9424             code |= insEncodeShiftCount(imm, id->idOpSize());  // ssssss
9425             dst += emitOutput_Instr(dst, code);
9426             break;
9427
9428         case IF_DI_2C: // DI_2C   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imm(N,r,s)
9429             imm = emitGetInsSC(id);
9430             assert(isValidImmNRS(imm, id->idOpSize()));
9431             code = emitInsCode(ins, fmt);
9432             code |= ((code_t)imm << 10);               // Nrrrrrrssssss
9433             code |= insEncodeDatasize(id->idOpSize()); // X
9434             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9435             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9436             dst += emitOutput_Instr(dst, code);
9437             break;
9438
9439         case IF_DI_2D: // DI_2D   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imr, imms   (N,r,s)
9440             if (ins == INS_asr || ins == INS_lsl || ins == INS_lsr)
9441             {
9442                 imm = emitGetInsSC(id);
9443                 assert(isValidImmShift(imm, id->idOpSize()));
9444
9445                 // Shift immediates are aliases of the SBFM/UBFM instructions
9446                 // that actually take 2 registers and 2 constants,
9447                 // Since we stored the shift immediate value
9448                 // we need to calculate the N,R and S values here.
9449
9450                 bitMaskImm bmi;
9451                 bmi.immNRS = 0;
9452
9453                 bmi.immN = (size == EA_8BYTE) ? 1 : 0;
9454                 bmi.immR = imm;
9455                 bmi.immS = (size == EA_8BYTE) ? 0x3f : 0x1f;
9456
9457                 // immR and immS are now set correctly for INS_asr and INS_lsr
9458                 // but for INS_lsl we have to adjust the values for immR and immS
9459                 //
9460                 if (ins == INS_lsl)
9461                 {
9462                     bmi.immR = -imm & bmi.immS;
9463                     bmi.immS = bmi.immS - imm;
9464                 }
9465
9466                 // setup imm with the proper 13 bit value N:R:S
9467                 //
9468                 imm = bmi.immNRS;
9469             }
9470             else
9471             {
9472                 // The other instructions have already have encoded N,R and S values
9473                 imm = emitGetInsSC(id);
9474             }
9475             assert(isValidImmNRS(imm, id->idOpSize()));
9476
9477             code = emitInsCode(ins, fmt);
9478             code |= ((code_t)imm << 10);               // Nrrrrrrssssss
9479             code |= insEncodeDatasize(id->idOpSize()); // X
9480             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9481             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9482             dst += emitOutput_Instr(dst, code);
9483             break;
9484
9485         case IF_DR_1D: // DR_1D   X............... cccc.......ddddd      Rd       cond
9486             imm = emitGetInsSC(id);
9487             assert(isValidImmCond(imm));
9488             {
9489                 condFlagsImm cfi;
9490                 cfi.immCFVal = (unsigned)imm;
9491                 code         = emitInsCode(ins, fmt);
9492                 code |= insEncodeDatasize(id->idOpSize()); // X
9493                 code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9494                 code |= insEncodeInvertedCond(cfi.cond);   // cccc
9495                 dst += emitOutput_Instr(dst, code);
9496             }
9497             break;
9498
9499         case IF_DR_2A: // DR_2A   X..........mmmmm ......nnnnn.....         Rn Rm
9500             assert(insOptsNone(id->idInsOpt()));
9501             code = emitInsCode(ins, fmt);
9502             code |= insEncodeDatasize(id->idOpSize()); // X
9503             code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9504             code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9505             dst += emitOutput_Instr(dst, code);
9506             break;
9507
9508         case IF_DR_2B: // DR_2B   X.......sh.mmmmm ssssssnnnnn.....         Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
9509             code = emitInsCode(ins, fmt);
9510             imm  = emitGetInsSC(id);
9511             assert(isValidImmShift(imm, id->idOpSize()));
9512             code |= insEncodeDatasize(id->idOpSize());        // X
9513             code |= insEncodeShiftType(id->idInsOpt());       // sh
9514             code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9515             code |= insEncodeReg_Rn(id->idReg1());            // nnnnn
9516             code |= insEncodeReg_Rm(id->idReg2());            // mmmmm
9517             dst += emitOutput_Instr(dst, code);
9518             break;
9519
9520         case IF_DR_2C: // DR_2C   X..........mmmmm ooosssnnnnn.....         Rn Rm ext(Rm) LSL imm(0-4)
9521             code = emitInsCode(ins, fmt);
9522             imm  = emitGetInsSC(id);
9523             assert((imm >= 0) && (imm <= 4));          // imm [0..4]
9524             code |= insEncodeDatasize(id->idOpSize()); // X
9525             code |= insEncodeExtend(id->idInsOpt());   // ooo
9526             code |= insEncodeExtendScale(imm);         // sss
9527             code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9528             code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9529             dst += emitOutput_Instr(dst, code);
9530             break;
9531
9532         case IF_DR_2D: // DR_2D   X..........nnnnn cccc..nnnnnddddd      Rd Rn    cond
9533             imm = emitGetInsSC(id);
9534             assert(isValidImmCond(imm));
9535             {
9536                 condFlagsImm cfi;
9537                 cfi.immCFVal = (unsigned)imm;
9538                 code         = emitInsCode(ins, fmt);
9539                 code |= insEncodeDatasize(id->idOpSize()); // X
9540                 code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9541                 code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9542                 code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9543                 code |= insEncodeInvertedCond(cfi.cond);   // cccc
9544                 dst += emitOutput_Instr(dst, code);
9545             }
9546             break;
9547
9548         case IF_DR_2E: // DR_2E   X..........mmmmm ...........ddddd      Rd    Rm
9549             code = emitInsCode(ins, fmt);
9550             code |= insEncodeDatasize(id->idOpSize()); // X
9551             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9552             code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9553             dst += emitOutput_Instr(dst, code);
9554             break;
9555
9556         case IF_DR_2F: // DR_2F   X.......sh.mmmmm ssssss.....ddddd      Rd    Rm {LSL,LSR,ASR} imm(0-63)
9557             code = emitInsCode(ins, fmt);
9558             imm  = emitGetInsSC(id);
9559             assert(isValidImmShift(imm, id->idOpSize()));
9560             code |= insEncodeDatasize(id->idOpSize());        // X
9561             code |= insEncodeShiftType(id->idInsOpt());       // sh
9562             code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9563             code |= insEncodeReg_Rd(id->idReg1());            // ddddd
9564             code |= insEncodeReg_Rm(id->idReg2());            // mmmmm
9565             dst += emitOutput_Instr(dst, code);
9566             break;
9567
9568         case IF_DR_2G: // DR_2G   X............... .....xnnnnnddddd      Rd Rn
9569             code = emitInsCode(ins, fmt);
9570             code |= insEncodeDatasize(id->idOpSize()); // X
9571             if (ins == INS_rev)
9572             {
9573                 if (size == EA_8BYTE)
9574                 {
9575                     code |= 0x00000400; // x - bit at location 10
9576                 }
9577             }
9578             code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9579             code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9580             dst += emitOutput_Instr(dst, code);
9581             break;
9582
9583         case IF_DR_2H: // DR_2H   X........X...... ......nnnnnddddd      Rd Rn
9584             code = emitInsCode(ins, fmt);
9585             code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9586             code |= insEncodeReg_Rd(id->idReg1());             // ddddd
9587             code |= insEncodeReg_Rn(id->idReg2());             // nnnnn
9588             dst += emitOutput_Instr(dst, code);
9589             break;
9590
9591         case IF_DR_2I: // DR_2I   X..........mmmmm cccc..nnnnn.nzcv      Rn Rm    nzcv cond
9592             imm = emitGetInsSC(id);
9593             assert(isValidImmCondFlags(imm));
9594             {
9595                 condFlagsImm cfi;
9596                 cfi.immCFVal = (unsigned)imm;
9597                 code         = emitInsCode(ins, fmt);
9598                 code |= insEncodeDatasize(id->idOpSize()); // X
9599                 code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9600                 code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9601                 code |= insEncodeFlags(cfi.flags);         // nzcv
9602                 code |= insEncodeCond(cfi.cond);           // cccc
9603                 dst += emitOutput_Instr(dst, code);
9604             }
9605             break;
9606
9607         case IF_DR_2J: // DR_2J   ................ ......nnnnnddddd      Sd Sn   (sha1h)
9608             code = emitInsCode(ins, fmt);
9609             code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9610             code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9611             dst += emitOutput_Instr(dst, code);
9612             break;
9613
9614         case IF_DR_3A: // DR_3A   X..........mmmmm ......nnnnnmmmmm      Rd Rn Rm
9615             code = emitInsCode(ins, fmt);
9616             code |= insEncodeDatasize(id->idOpSize()); // X
9617             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9618             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9619             if (id->idIsLclVar())
9620             {
9621                 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9622             }
9623             else
9624             {
9625                 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9626             }
9627             dst += emitOutput_Instr(dst, code);
9628             break;
9629
9630         case IF_DR_3B: // DR_3B   X.......sh.mmmmm ssssssnnnnnddddd      Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
9631             code = emitInsCode(ins, fmt);
9632             imm  = emitGetInsSC(id);
9633             assert(isValidImmShift(imm, id->idOpSize()));
9634             code |= insEncodeDatasize(id->idOpSize());        // X
9635             code |= insEncodeReg_Rd(id->idReg1());            // ddddd
9636             code |= insEncodeReg_Rn(id->idReg2());            // nnnnn
9637             code |= insEncodeReg_Rm(id->idReg3());            // mmmmm
9638             code |= insEncodeShiftType(id->idInsOpt());       // sh
9639             code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9640             dst += emitOutput_Instr(dst, code);
9641             break;
9642
9643         case IF_DR_3C: // DR_3C   X..........mmmmm ooosssnnnnnddddd      Rd Rn Rm ext(Rm) LSL imm(0-4)
9644             code = emitInsCode(ins, fmt);
9645             imm  = emitGetInsSC(id);
9646             assert((imm >= 0) && (imm <= 4));          // imm [0..4]
9647             code |= insEncodeDatasize(id->idOpSize()); // X
9648             code |= insEncodeExtend(id->idInsOpt());   // ooo
9649             code |= insEncodeExtendScale(imm);         // sss
9650             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9651             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9652             code |= insEncodeReg_Rm(id->idReg3());     // mmmmm
9653             dst += emitOutput_Instr(dst, code);
9654             break;
9655
9656         case IF_DR_3D: // DR_3D   X..........mmmmm cccc..nnnnnddddd      Rd Rn Rm cond
9657             imm = emitGetInsSC(id);
9658             assert(isValidImmCond(imm));
9659             {
9660                 condFlagsImm cfi;
9661                 cfi.immCFVal = (unsigned)imm;
9662                 code         = emitInsCode(ins, fmt);
9663                 code |= insEncodeDatasize(id->idOpSize()); // X
9664                 code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9665                 code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9666                 code |= insEncodeReg_Rm(id->idReg3());     // mmmmm
9667                 code |= insEncodeCond(cfi.cond);           // cccc
9668                 dst += emitOutput_Instr(dst, code);
9669             }
9670             break;
9671
9672         case IF_DR_3E: // DR_3E   X........X.mmmmm ssssssnnnnnddddd      Rd Rn Rm imm(0-63)
9673             code = emitInsCode(ins, fmt);
9674             imm  = emitGetInsSC(id);
9675             assert(isValidImmShift(imm, id->idOpSize()));
9676             code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9677             code |= insEncodeReg_Rd(id->idReg1());             // ddddd
9678             code |= insEncodeReg_Rn(id->idReg2());             // nnnnn
9679             code |= insEncodeReg_Rm(id->idReg3());             // mmmmm
9680             code |= insEncodeShiftCount(imm, id->idOpSize());  // ssssss
9681             dst += emitOutput_Instr(dst, code);
9682             break;
9683
9684         case IF_DR_4A: // DR_4A   X..........mmmmm .aaaaannnnnmmmmm      Rd Rn Rm Ra
9685             code = emitInsCode(ins, fmt);
9686             code |= insEncodeDatasize(id->idOpSize()); // X
9687             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9688             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9689             code |= insEncodeReg_Rm(id->idReg3());     // mmmmm
9690             code |= insEncodeReg_Ra(id->idReg4());     // aaaaa
9691             dst += emitOutput_Instr(dst, code);
9692             break;
9693
9694         case IF_DV_1A: // DV_1A   .........X.iiiii iii........ddddd      Vd imm8    (fmov - immediate scalar)
9695             imm      = emitGetInsSC(id);
9696             elemsize = id->idOpSize();
9697             code     = emitInsCode(ins, fmt);
9698             code |= insEncodeFloatElemsize(elemsize); // X
9699             code |= ((code_t)imm << 13);              // iiiii iii
9700             code |= insEncodeReg_Vd(id->idReg1());    // ddddd
9701             dst += emitOutput_Instr(dst, code);
9702             break;
9703
9704         case IF_DV_1B: // DV_1B   .QX..........iii cmod..iiiiiddddd      Vd imm8    (immediate vector)
9705             imm      = emitGetInsSC(id) & 0x0ff;
9706             immShift = (emitGetInsSC(id) & 0x700) >> 8;
9707             elemsize = optGetElemsize(id->idInsOpt());
9708             cmode    = 0;
9709             switch (elemsize)
9710             { // cmode
9711                 case EA_1BYTE:
9712                     cmode = 0xE; // 1110
9713                     break;
9714                 case EA_2BYTE:
9715                     cmode = 0x8;
9716                     cmode |= (immShift << 1); // 10x0
9717                     break;
9718                 case EA_4BYTE:
9719                     if (immShift < 4)
9720                     {
9721                         cmode = 0x0;
9722                         cmode |= (immShift << 1); // 0xx0
9723                     }
9724                     else // MSL
9725                     {
9726                         cmode = 0xC;
9727                         if (immShift & 2)
9728                             cmode |= 1; // 110x
9729                     }
9730                     break;
9731                 case EA_8BYTE:
9732                     cmode = 0xE; // 1110
9733                     break;
9734                 default:
9735                     unreached();
9736                     break;
9737             }
9738
9739             code = emitInsCode(ins, fmt);
9740             code |= insEncodeVectorsize(id->idOpSize()); // Q
9741             if ((ins == INS_fmov) || (ins == INS_movi))
9742             {
9743                 if (elemsize == EA_8BYTE)
9744                 {
9745                     code |= 0x20000000; // X
9746                 }
9747             }
9748             if (ins != INS_fmov)
9749             {
9750                 assert((cmode >= 0) && (cmode <= 0xF));
9751                 code |= (cmode << 12); // cmod
9752             }
9753             code |= (((code_t)imm >> 5) << 16);    // iii
9754             code |= (((code_t)imm & 0x1f) << 5);   // iiiii
9755             code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9756             dst += emitOutput_Instr(dst, code);
9757             break;
9758
9759         case IF_DV_1C: // DV_1C   .........X...... ......nnnnn.....      Vn #0.0    (fcmp - with zero)
9760             elemsize = id->idOpSize();
9761             code     = emitInsCode(ins, fmt);
9762             code |= insEncodeFloatElemsize(elemsize); // X
9763             code |= insEncodeReg_Vn(id->idReg1());    // nnnnn
9764             dst += emitOutput_Instr(dst, code);
9765             break;
9766
9767         case IF_DV_2A: // DV_2A   .Q.......X...... ......nnnnnddddd      Vd Vn      (fabs, fcvt - vector)
9768             elemsize = optGetElemsize(id->idInsOpt());
9769             code     = emitInsCode(ins, fmt);
9770             code |= insEncodeVectorsize(id->idOpSize()); // Q
9771             code |= insEncodeFloatElemsize(elemsize);    // X
9772             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9773             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9774             dst += emitOutput_Instr(dst, code);
9775             break;
9776
9777         case IF_DV_2B: // DV_2B   .Q.........iiiii ......nnnnnddddd      Rd Vn[] (umov/smov    - to general)
9778             elemsize = id->idOpSize();
9779             index    = emitGetInsSC(id);
9780             datasize = (elemsize == EA_8BYTE) ? EA_16BYTE : EA_8BYTE;
9781             if (ins == INS_smov)
9782             {
9783                 datasize = EA_16BYTE;
9784             }
9785             code = emitInsCode(ins, fmt);
9786             code |= insEncodeVectorsize(datasize);         // Q
9787             code |= insEncodeVectorIndex(elemsize, index); // iiiii
9788             code |= insEncodeReg_Rd(id->idReg1());         // ddddd
9789             code |= insEncodeReg_Vn(id->idReg2());         // nnnnn
9790             dst += emitOutput_Instr(dst, code);
9791             break;
9792
9793         case IF_DV_2C: // DV_2C   .Q.........iiiii ......nnnnnddddd      Vd Rn   (dup/ins - vector from general)
9794             if (ins == INS_dup)
9795             {
9796                 datasize = id->idOpSize();
9797                 elemsize = optGetElemsize(id->idInsOpt());
9798                 index    = 0;
9799             }
9800             else // INS_ins
9801             {
9802                 datasize = EA_16BYTE;
9803                 elemsize = id->idOpSize();
9804                 index    = emitGetInsSC(id);
9805             }
9806             code = emitInsCode(ins, fmt);
9807             code |= insEncodeVectorsize(datasize);         // Q
9808             code |= insEncodeVectorIndex(elemsize, index); // iiiii
9809             code |= insEncodeReg_Vd(id->idReg1());         // ddddd
9810             code |= insEncodeReg_Rn(id->idReg2());         // nnnnn
9811             dst += emitOutput_Instr(dst, code);
9812             break;
9813
9814         case IF_DV_2D: // DV_2D   .Q.........iiiii ......nnnnnddddd      Vd Vn[]   (dup - vector)
9815             index    = emitGetInsSC(id);
9816             elemsize = optGetElemsize(id->idInsOpt());
9817             code     = emitInsCode(ins, fmt);
9818             code |= insEncodeVectorsize(id->idOpSize());   // Q
9819             code |= insEncodeVectorIndex(elemsize, index); // iiiii
9820             code |= insEncodeReg_Vd(id->idReg1());         // ddddd
9821             code |= insEncodeReg_Vn(id->idReg2());         // nnnnn
9822             dst += emitOutput_Instr(dst, code);
9823             break;
9824
9825         case IF_DV_2E: // DV_2E   ...........iiiii ......nnnnnddddd      Vd Vn[]   (dup - scalar)
9826             index    = emitGetInsSC(id);
9827             elemsize = id->idOpSize();
9828             code     = emitInsCode(ins, fmt);
9829             code |= insEncodeVectorIndex(elemsize, index); // iiiii
9830             code |= insEncodeReg_Vd(id->idReg1());         // ddddd
9831             code |= insEncodeReg_Vn(id->idReg2());         // nnnnn
9832             dst += emitOutput_Instr(dst, code);
9833             break;
9834
9835         case IF_DV_2F: // DV_2F   ...........iiiii .jjjj.nnnnnddddd      Vd[] Vn[] (ins - element)
9836             elemsize = id->idOpSize();
9837             imm      = emitGetInsSC(id);
9838             index    = (imm >> 4) & 0xf;
9839             index2   = imm & 0xf;
9840             code     = emitInsCode(ins, fmt);
9841             code |= insEncodeVectorIndex(elemsize, index);   // iiiii
9842             code |= insEncodeVectorIndex2(elemsize, index2); // jjjj
9843             code |= insEncodeReg_Vd(id->idReg1());           // ddddd
9844             code |= insEncodeReg_Vn(id->idReg2());           // nnnnn
9845             dst += emitOutput_Instr(dst, code);
9846             break;
9847
9848         case IF_DV_2G: // DV_2G   .........X...... ......nnnnnddddd      Vd Vn      (fmov,fcvtXX - register)
9849             elemsize = id->idOpSize();
9850             code     = emitInsCode(ins, fmt);
9851             code |= insEncodeFloatElemsize(elemsize); // X
9852             code |= insEncodeReg_Vd(id->idReg1());    // ddddd
9853             code |= insEncodeReg_Vn(id->idReg2());    // nnnnn
9854             dst += emitOutput_Instr(dst, code);
9855             break;
9856
9857         case IF_DV_2H: // DV_2H   X........X...... ......nnnnnddddd      Rd Vn      (fmov - to general)
9858             elemsize = id->idOpSize();
9859             code     = emitInsCode(ins, fmt);
9860             code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X   X
9861             code |= insEncodeReg_Rd(id->idReg1());            // ddddd
9862             code |= insEncodeReg_Vn(id->idReg2());            // nnnnn
9863             dst += emitOutput_Instr(dst, code);
9864             break;
9865
9866         case IF_DV_2I: // DV_2I   X........X...... ......nnnnnddddd      Vd Rn      (fmov - from general)
9867             elemsize = id->idOpSize();
9868             code     = emitInsCode(ins, fmt);
9869             code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X   X
9870             code |= insEncodeReg_Vd(id->idReg1());            // ddddd
9871             code |= insEncodeReg_Rn(id->idReg2());            // nnnnn
9872             dst += emitOutput_Instr(dst, code);
9873             break;
9874
9875         case IF_DV_2J: // DV_2J   ........SS.....D D.....nnnnnddddd      Vd Vn      (fcvt)
9876             code = emitInsCode(ins, fmt);
9877             code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // SS DD
9878             code |= insEncodeReg_Vd(id->idReg1());            // ddddd
9879             code |= insEncodeReg_Vn(id->idReg2());            // nnnnn
9880             dst += emitOutput_Instr(dst, code);
9881             break;
9882
9883         case IF_DV_2K: // DV_2K   .........X.mmmmm ......nnnnn.....      Vn Vm      (fcmp)
9884             elemsize = id->idOpSize();
9885             code     = emitInsCode(ins, fmt);
9886             code |= insEncodeFloatElemsize(elemsize); // X
9887             code |= insEncodeReg_Vn(id->idReg1());    // nnnnn
9888             code |= insEncodeReg_Vm(id->idReg2());    // mmmmm
9889             dst += emitOutput_Instr(dst, code);
9890             break;
9891
9892         case IF_DV_2L: // DV_2L   ........XX...... ......nnnnnddddd      Vd Vn      (abs, neg - scalar)
9893             elemsize = id->idOpSize();
9894             code     = emitInsCode(ins, fmt);
9895             code |= insEncodeElemsize(elemsize);   // XX
9896             code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9897             code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9898             dst += emitOutput_Instr(dst, code);
9899             break;
9900
9901         case IF_DV_2M: // DV_2M   .Q......XX...... ......nnnnnddddd      Vd Vn      (abs, neg   - vector)
9902             elemsize = optGetElemsize(id->idInsOpt());
9903             code     = emitInsCode(ins, fmt);
9904             code |= insEncodeVectorsize(id->idOpSize()); // Q
9905             code |= insEncodeElemsize(elemsize);         // XX
9906             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9907             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9908             dst += emitOutput_Instr(dst, code);
9909             break;
9910
9911         case IF_DV_2N: // DV_2N   .........iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - scalar)
9912             imm  = emitGetInsSC(id);
9913             code = emitInsCode(ins, fmt);
9914             code |= insEncodeVectorShift(EA_8BYTE, imm); // iiiiiii
9915             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9916             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9917             dst += emitOutput_Instr(dst, code);
9918             break;
9919
9920         case IF_DV_2O: // DV_2O   .Q.......iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - vector)
9921             imm      = emitGetInsSC(id);
9922             elemsize = optGetElemsize(id->idInsOpt());
9923             code     = emitInsCode(ins, fmt);
9924             code |= insEncodeVectorsize(id->idOpSize()); // Q
9925             code |= insEncodeVectorShift(elemsize, imm); // iiiiiii
9926             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9927             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9928             dst += emitOutput_Instr(dst, code);
9929             break;
9930
9931         case IF_DV_2P: // DV_2P   ............... ......nnnnnddddd      Vd Vn      (aes*, sha1su1)
9932             elemsize = optGetElemsize(id->idInsOpt());
9933             code     = emitInsCode(ins, fmt);
9934             code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9935             code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9936             dst += emitOutput_Instr(dst, code);
9937             break;
9938
9939         case IF_DV_3A: // DV_3A   .Q......XX.mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
9940             code     = emitInsCode(ins, fmt);
9941             elemsize = optGetElemsize(id->idInsOpt());
9942             code |= insEncodeVectorsize(id->idOpSize()); // Q
9943             code |= insEncodeElemsize(elemsize);         // XX
9944             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9945             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9946             code |= insEncodeReg_Vm(id->idReg3());       // mmmmm
9947             dst += emitOutput_Instr(dst, code);
9948             break;
9949
9950         case IF_DV_3AI: // DV_3AI  .Q......XXLMmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector)
9951             code     = emitInsCode(ins, fmt);
9952             imm      = emitGetInsSC(id);
9953             elemsize = optGetElemsize(id->idInsOpt());
9954             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
9955             code |= insEncodeVectorsize(id->idOpSize());    // Q
9956             code |= insEncodeElemsize(elemsize);            // XX
9957             code |= insEncodeVectorIndexLMH(elemsize, imm); // LM H
9958             code |= insEncodeReg_Vd(id->idReg1());          // ddddd
9959             code |= insEncodeReg_Vn(id->idReg2());          // nnnnn
9960             code |= insEncodeReg_Vm(id->idReg3());          // mmmmm
9961             dst += emitOutput_Instr(dst, code);
9962             break;
9963
9964         case IF_DV_3B: // DV_3B   .Q.......X.mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
9965             code     = emitInsCode(ins, fmt);
9966             elemsize = optGetElemsize(id->idInsOpt());
9967             code |= insEncodeVectorsize(id->idOpSize()); // Q
9968             code |= insEncodeFloatElemsize(elemsize);    // X
9969             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9970             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9971             code |= insEncodeReg_Vm(id->idReg3());       // mmmmm
9972             dst += emitOutput_Instr(dst, code);
9973             break;
9974
9975         case IF_DV_3BI: // DV_3BI  .Q.......XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector by elem)
9976             code     = emitInsCode(ins, fmt);
9977             imm      = emitGetInsSC(id);
9978             elemsize = optGetElemsize(id->idInsOpt());
9979             assert(isValidVectorIndex(id->idOpSize(), elemsize, imm));
9980             code |= insEncodeVectorsize(id->idOpSize()); // Q
9981             code |= insEncodeFloatElemsize(elemsize);    // X
9982             code |= insEncodeFloatIndex(elemsize, imm);  // L H
9983             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9984             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9985             code |= insEncodeReg_Vm(id->idReg3());       // mmmmm
9986             dst += emitOutput_Instr(dst, code);
9987             break;
9988
9989         case IF_DV_3C: // DV_3C   .Q.........mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
9990             code = emitInsCode(ins, fmt);
9991             code |= insEncodeVectorsize(id->idOpSize()); // Q
9992             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9993             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9994             code |= insEncodeReg_Vm(id->idReg3());       // mmmmm
9995             dst += emitOutput_Instr(dst, code);
9996             break;
9997
9998         case IF_DV_3D: // DV_3D   .........X.mmmmm ......nnnnnddddd      Vd Vn Vm   (scalar)
9999             code = emitInsCode(ins, fmt);
10000             code |= insEncodeFloatElemsize(id->idOpSize()); // X
10001             code |= insEncodeReg_Vd(id->idReg1());          // ddddd
10002             code |= insEncodeReg_Vn(id->idReg2());          // nnnnn
10003             code |= insEncodeReg_Vm(id->idReg3());          // mmmmm
10004             dst += emitOutput_Instr(dst, code);
10005             break;
10006
10007         case IF_DV_3DI: // DV_3DI  .........XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (scalar by elem)
10008             code     = emitInsCode(ins, fmt);
10009             imm      = emitGetInsSC(id);
10010             elemsize = id->idOpSize();
10011             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
10012             code |= insEncodeFloatElemsize(elemsize);   // X
10013             code |= insEncodeFloatIndex(elemsize, imm); // L H
10014             code |= insEncodeReg_Vd(id->idReg1());      // ddddd
10015             code |= insEncodeReg_Vn(id->idReg2());      // nnnnn
10016             code |= insEncodeReg_Vm(id->idReg3());      // mmmmm
10017             dst += emitOutput_Instr(dst, code);
10018             break;
10019
10020         case IF_DV_3E: // DV_3E   ...........mmmmm ......nnnnnddddd      Vd Vn Vm   (scalar)
10021         case IF_DV_3F: // DV_3F   ...........mmmmm ......nnnnnddddd      Vd Vn Vm   (vector) - source dest regs overlap
10022             code = emitInsCode(ins, fmt);
10023             code |= insEncodeReg_Vd(id->idReg1()); // ddddd
10024             code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
10025             code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
10026             dst += emitOutput_Instr(dst, code);
10027             break;
10028
10029         case IF_DV_4A: // DV_4A   .........X.mmmmm .aaaaannnnnddddd      Vd Va Vn Vm (scalar)
10030             code     = emitInsCode(ins, fmt);
10031             elemsize = id->idOpSize();
10032             code |= insEncodeFloatElemsize(elemsize); // X
10033             code |= insEncodeReg_Vd(id->idReg1());    // ddddd
10034             code |= insEncodeReg_Vn(id->idReg2());    // nnnnn
10035             code |= insEncodeReg_Vm(id->idReg3());    // mmmmm
10036             code |= insEncodeReg_Va(id->idReg4());    // aaaaa
10037             dst += emitOutput_Instr(dst, code);
10038             break;
10039
10040         case IF_SN_0A: // SN_0A   ................ ................
10041             code = emitInsCode(ins, fmt);
10042             dst += emitOutput_Instr(dst, code);
10043             break;
10044
10045         case IF_SI_0A: // SI_0A   ...........iiiii iiiiiiiiiii.....               imm16
10046             imm = emitGetInsSC(id);
10047             assert(isValidUimm16(imm));
10048             code = emitInsCode(ins, fmt);
10049             code |= ((code_t)imm << 5); // iiiii iiiiiiiiiii
10050             dst += emitOutput_Instr(dst, code);
10051             break;
10052
10053         case IF_SI_0B: // SI_0B   ................ ....bbbb........               imm4 - barrier
10054             imm = emitGetInsSC(id);
10055             assert((imm >= 0) && (imm <= 15));
10056             code = emitInsCode(ins, fmt);
10057             code |= ((code_t)imm << 8); // bbbb
10058             dst += emitOutput_Instr(dst, code);
10059             break;
10060
10061         default:
10062             assert(!"Unexpected format");
10063             break;
10064     }
10065
10066     // Determine if any registers now hold GC refs, or whether a register that was overwritten held a GC ref.
10067     // We assume here that "id->idGCref()" is not GC_NONE only if the instruction described by "id" writes a
10068     // GC ref to register "id->idReg1()".  (It may, apparently, also not be GC_NONE in other cases, such as
10069     // for stores, but we ignore those cases here.)
10070     if (emitInsMayWriteToGCReg(id)) // True if "id->idIns()" writes to a register than can hold GC ref.
10071     {
10072         // We assume that "idReg1" is the primary destination register for all instructions
10073         if (id->idGCref() != GCT_NONE)
10074         {
10075             emitGCregLiveUpd(id->idGCref(), id->idReg1(), dst);
10076         }
10077         else
10078         {
10079             emitGCregDeadUpd(id->idReg1(), dst);
10080         }
10081
10082         if (emitInsMayWriteMultipleRegs(id))
10083         {
10084             // INS_ldp etc...
10085             // "idReg2" is the secondary destination register
10086             if (id->idGCrefReg2() != GCT_NONE)
10087             {
10088                 emitGCregLiveUpd(id->idGCrefReg2(), id->idReg2(), dst);
10089             }
10090             else
10091             {
10092                 emitGCregDeadUpd(id->idReg2(), dst);
10093             }
10094         }
10095     }
10096
10097     // Now we determine if the instruction has written to a (local variable) stack location, and either written a GC
10098     // ref or overwritten one.
10099     if (emitInsWritesToLclVarStackLoc(id) || emitInsWritesToLclVarStackLocPair(id))
10100     {
10101         int      varNum = id->idAddr()->iiaLclVar.lvaVarNum();
10102         unsigned ofs    = AlignDown(id->idAddr()->iiaLclVar.lvaOffset(), TARGET_POINTER_SIZE);
10103         bool     FPbased;
10104         int      adr = emitComp->lvaFrameAddress(varNum, &FPbased);
10105         if (id->idGCref() != GCT_NONE)
10106         {
10107             emitGCvarLiveUpd(adr + ofs, varNum, id->idGCref(), dst);
10108         }
10109         else
10110         {
10111             // If the type of the local is a gc ref type, update the liveness.
10112             var_types vt;
10113             if (varNum >= 0)
10114             {
10115                 // "Regular" (non-spill-temp) local.
10116                 vt = var_types(emitComp->lvaTable[varNum].lvType);
10117             }
10118             else
10119             {
10120                 TempDsc* tmpDsc = codeGen->regSet.tmpFindNum(varNum);
10121                 vt              = tmpDsc->tdTempType();
10122             }
10123             if (vt == TYP_REF || vt == TYP_BYREF)
10124                 emitGCvarDeadUpd(adr + ofs, dst);
10125         }
10126         if (emitInsWritesToLclVarStackLocPair(id))
10127         {
10128             unsigned ofs2 = ofs + TARGET_POINTER_SIZE;
10129             if (id->idGCrefReg2() != GCT_NONE)
10130             {
10131                 emitGCvarLiveUpd(adr + ofs2, varNum, id->idGCrefReg2(), dst);
10132             }
10133             else
10134             {
10135                 // If the type of the local is a gc ref type, update the liveness.
10136                 var_types vt;
10137                 if (varNum >= 0)
10138                 {
10139                     // "Regular" (non-spill-temp) local.
10140                     vt = var_types(emitComp->lvaTable[varNum].lvType);
10141                 }
10142                 else
10143                 {
10144                     TempDsc* tmpDsc = codeGen->regSet.tmpFindNum(varNum);
10145                     vt              = tmpDsc->tdTempType();
10146                 }
10147                 if (vt == TYP_REF || vt == TYP_BYREF)
10148                     emitGCvarDeadUpd(adr + ofs2, dst);
10149             }
10150         }
10151     }
10152
10153 #ifdef DEBUG
10154     /* Make sure we set the instruction descriptor size correctly */
10155
10156     size_t expected = emitSizeOfInsDsc(id);
10157     assert(sz == expected);
10158
10159     if (emitComp->opts.disAsm || emitComp->opts.dspEmit || emitComp->verbose)
10160     {
10161         emitDispIns(id, false, dspOffs, true, emitCurCodeOffs(odst), *dp, (dst - *dp), ig);
10162     }
10163
10164     if (emitComp->compDebugBreak)
10165     {
10166         // For example, set JitBreakEmitOutputInstr=a6 will break when this method is called for
10167         // emitting instruction a6, (i.e. IN00a6 in jitdump).
10168         if ((unsigned)JitConfig.JitBreakEmitOutputInstr() == id->idDebugOnlyInfo()->idNum)
10169         {
10170             assert(!"JitBreakEmitOutputInstr reached");
10171         }
10172     }
10173 #endif
10174
10175     /* All instructions are expected to generate code */
10176
10177     assert(*dp != dst);
10178
10179     *dp = dst;
10180
10181     return sz;
10182 }
10183
10184 /*****************************************************************************/
10185 /*****************************************************************************/
10186
10187 #ifdef DEBUG
10188
10189 /*****************************************************************************
10190  *
10191  *  Display the instruction name
10192  */
10193 void emitter::emitDispInst(instruction ins)
10194 {
10195     const char* insstr = codeGen->genInsName(ins);
10196     size_t      len    = strlen(insstr);
10197
10198     /* Display the instruction name */
10199
10200     printf("%s", insstr);
10201
10202     //
10203     // Add at least one space after the instruction name
10204     // and add spaces until we have reach the normal size of 8
10205     do
10206     {
10207         printf(" ");
10208         len++;
10209     } while (len < 8);
10210 }
10211
10212 /*****************************************************************************
10213  *
10214  *  Display an immediate value
10215  */
10216 void emitter::emitDispImm(ssize_t imm, bool addComma, bool alwaysHex /* =false */)
10217 {
10218     if (strictArmAsm)
10219     {
10220         printf("#");
10221     }
10222
10223     // Munge any pointers if we want diff-able disassembly.
10224     // Since some may be emitted as partial words, print as diffable anything that has
10225     // significant bits beyond the lowest 8-bits.
10226     if (emitComp->opts.disDiffable)
10227     {
10228         ssize_t top56bits = (imm >> 8);
10229         if ((top56bits != 0) && (top56bits != -1))
10230             imm = 0xD1FFAB1E;
10231     }
10232
10233     if (!alwaysHex && (imm > -1000) && (imm < 1000))
10234     {
10235         printf("%d", imm);
10236     }
10237     else
10238     {
10239         if ((imm < 0) && ((imm & 0xFFFFFFFF00000000LL) == 0xFFFFFFFF00000000LL))
10240         {
10241             printf("-");
10242             imm = -imm;
10243         }
10244
10245         if ((imm & 0xFFFFFFFF00000000LL) != 0)
10246         {
10247             printf("0x%llx", imm);
10248         }
10249         else
10250         {
10251             printf("0x%02x", imm);
10252         }
10253     }
10254
10255     if (addComma)
10256         printf(", ");
10257 }
10258
10259 /*****************************************************************************
10260  *
10261  *  Display a float zero constant
10262  */
10263 void emitter::emitDispFloatZero()
10264 {
10265     if (strictArmAsm)
10266     {
10267         printf("#");
10268     }
10269     printf("0.0");
10270 }
10271
10272 /*****************************************************************************
10273  *
10274  *  Display an encoded float constant value
10275  */
10276 void emitter::emitDispFloatImm(ssize_t imm8)
10277 {
10278     assert((0 <= imm8) && (imm8 <= 0x0ff));
10279     if (strictArmAsm)
10280     {
10281         printf("#");
10282     }
10283
10284     floatImm8 fpImm;
10285     fpImm.immFPIVal = (unsigned)imm8;
10286     double result   = emitDecodeFloatImm8(fpImm);
10287
10288     printf("%.4f", result);
10289 }
10290
10291 /*****************************************************************************
10292  *
10293  *  Display an immediate that is optionally LSL12.
10294  */
10295 void emitter::emitDispImmOptsLSL12(ssize_t imm, insOpts opt)
10296 {
10297     if (!strictArmAsm && insOptsLSL12(opt))
10298     {
10299         imm <<= 12;
10300     }
10301     emitDispImm(imm, false);
10302     if (strictArmAsm && insOptsLSL12(opt))
10303     {
10304         printf(", LSL #12");
10305     }
10306 }
10307
10308 /*****************************************************************************
10309  *
10310  *  Display an ARM64 condition code for the conditional instructions
10311  */
10312 void emitter::emitDispCond(insCond cond)
10313 {
10314     const static char* armCond[16] = {"eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc",
10315                                       "hi", "ls", "ge", "lt", "gt", "le", "AL", "NV"}; // The last two are invalid
10316     unsigned imm = (unsigned)cond;
10317     assert((0 <= imm) && (imm < ArrLen(armCond)));
10318     printf(armCond[imm]);
10319 }
10320
10321 /*****************************************************************************
10322  *
10323  *  Display an ARM64 flags for the conditional instructions
10324  */
10325 void emitter::emitDispFlags(insCflags flags)
10326 {
10327     const static char* armFlags[16] = {"0", "v",  "c",  "cv",  "z",  "zv",  "zc",  "zcv",
10328                                        "n", "nv", "nc", "ncv", "nz", "nzv", "nzc", "nzcv"};
10329     unsigned imm = (unsigned)flags;
10330     assert((0 <= imm) && (imm < ArrLen(armFlags)));
10331     printf(armFlags[imm]);
10332 }
10333
10334 /*****************************************************************************
10335  *
10336  *  Display an ARM64 'barrier' for the memory barrier instructions
10337  */
10338 void emitter::emitDispBarrier(insBarrier barrier)
10339 {
10340     const static char* armBarriers[16] = {"#0", "oshld", "oshst", "osh", "#4",  "nshld", "nshst", "nsh",
10341                                           "#8", "ishld", "ishst", "ish", "#12", "ld",    "st",    "sy"};
10342     unsigned imm = (unsigned)barrier;
10343     assert((0 <= imm) && (imm < ArrLen(armBarriers)));
10344     printf(armBarriers[imm]);
10345 }
10346
10347 /*****************************************************************************
10348  *
10349  *  Prints the encoding for the Shift Type encoding
10350  */
10351
10352 void emitter::emitDispShiftOpts(insOpts opt)
10353 {
10354     if (opt == INS_OPTS_LSL)
10355         printf(" LSL ");
10356     else if (opt == INS_OPTS_LSR)
10357         printf(" LSR ");
10358     else if (opt == INS_OPTS_ASR)
10359         printf(" ASR ");
10360     else if (opt == INS_OPTS_ROR)
10361         printf(" ROR ");
10362     else if (opt == INS_OPTS_MSL)
10363         printf(" MSL ");
10364     else
10365         assert(!"Bad value");
10366 }
10367
10368 /*****************************************************************************
10369  *
10370  *  Prints the encoding for the Extend Type encoding
10371  */
10372
10373 void emitter::emitDispExtendOpts(insOpts opt)
10374 {
10375     if (opt == INS_OPTS_UXTB)
10376         printf("UXTB");
10377     else if (opt == INS_OPTS_UXTH)
10378         printf("UXTH");
10379     else if (opt == INS_OPTS_UXTW)
10380         printf("UXTW");
10381     else if (opt == INS_OPTS_UXTX)
10382         printf("UXTX");
10383     else if (opt == INS_OPTS_SXTB)
10384         printf("SXTB");
10385     else if (opt == INS_OPTS_SXTH)
10386         printf("SXTH");
10387     else if (opt == INS_OPTS_SXTW)
10388         printf("SXTW");
10389     else if (opt == INS_OPTS_SXTX)
10390         printf("SXTX");
10391     else
10392         assert(!"Bad value");
10393 }
10394
10395 /*****************************************************************************
10396  *
10397  *  Prints the encoding for the Extend Type encoding in loads/stores
10398  */
10399
10400 void emitter::emitDispLSExtendOpts(insOpts opt)
10401 {
10402     if (opt == INS_OPTS_LSL)
10403         printf("LSL");
10404     else if (opt == INS_OPTS_UXTW)
10405         printf("UXTW");
10406     else if (opt == INS_OPTS_UXTX)
10407         printf("UXTX");
10408     else if (opt == INS_OPTS_SXTW)
10409         printf("SXTW");
10410     else if (opt == INS_OPTS_SXTX)
10411         printf("SXTX");
10412     else
10413         assert(!"Bad value");
10414 }
10415
10416 /*****************************************************************************
10417  *
10418  *  Display a register
10419  */
10420 void emitter::emitDispReg(regNumber reg, emitAttr attr, bool addComma)
10421 {
10422     emitAttr size = EA_SIZE(attr);
10423     printf(emitRegName(reg, size));
10424
10425     if (addComma)
10426         printf(", ");
10427 }
10428
10429 /*****************************************************************************
10430  *
10431  *  Display a vector register with an arrangement suffix
10432  */
10433 void emitter::emitDispVectorReg(regNumber reg, insOpts opt, bool addComma)
10434 {
10435     assert(isVectorRegister(reg));
10436     printf(emitVectorRegName(reg));
10437     emitDispArrangement(opt);
10438
10439     if (addComma)
10440         printf(", ");
10441 }
10442
10443 /*****************************************************************************
10444  *
10445  *  Display an vector register index suffix
10446  */
10447 void emitter::emitDispVectorRegIndex(regNumber reg, emitAttr elemsize, ssize_t index, bool addComma)
10448 {
10449     assert(isVectorRegister(reg));
10450     printf(emitVectorRegName(reg));
10451
10452     switch (elemsize)
10453     {
10454         case EA_1BYTE:
10455             printf(".b");
10456             break;
10457         case EA_2BYTE:
10458             printf(".h");
10459             break;
10460         case EA_4BYTE:
10461             printf(".s");
10462             break;
10463         case EA_8BYTE:
10464             printf(".d");
10465             break;
10466         default:
10467             assert(!"invalid elemsize");
10468             break;
10469     }
10470
10471     printf("[%d]", index);
10472
10473     if (addComma)
10474         printf(", ");
10475 }
10476
10477 /*****************************************************************************
10478  *
10479  *  Display an arrangement suffix
10480  */
10481 void emitter::emitDispArrangement(insOpts opt)
10482 {
10483     const char* str = "???";
10484
10485     switch (opt)
10486     {
10487         case INS_OPTS_8B:
10488             str = "8b";
10489             break;
10490         case INS_OPTS_16B:
10491             str = "16b";
10492             break;
10493         case INS_OPTS_4H:
10494             str = "4h";
10495             break;
10496         case INS_OPTS_8H:
10497             str = "8h";
10498             break;
10499         case INS_OPTS_2S:
10500             str = "2s";
10501             break;
10502         case INS_OPTS_4S:
10503             str = "4s";
10504             break;
10505         case INS_OPTS_1D:
10506             str = "1d";
10507             break;
10508         case INS_OPTS_2D:
10509             str = "2d";
10510             break;
10511
10512         default:
10513             assert(!"Invalid insOpt for vector register");
10514     }
10515     printf(".");
10516     printf(str);
10517 }
10518
10519 /*****************************************************************************
10520  *
10521  *  Display a register with an optional shift operation
10522  */
10523 void emitter::emitDispShiftedReg(regNumber reg, insOpts opt, ssize_t imm, emitAttr attr)
10524 {
10525     emitAttr size = EA_SIZE(attr);
10526     assert((imm & 0x003F) == imm);
10527     assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
10528
10529     printf(emitRegName(reg, size));
10530
10531     if (imm > 0)
10532     {
10533         if (strictArmAsm)
10534         {
10535             printf(",");
10536         }
10537         emitDispShiftOpts(opt);
10538         emitDispImm(imm, false);
10539     }
10540 }
10541
10542 /*****************************************************************************
10543  *
10544  *  Display a register with an optional extend and scale operations
10545  */
10546 void emitter::emitDispExtendReg(regNumber reg, insOpts opt, ssize_t imm)
10547 {
10548     assert((imm >= 0) && (imm <= 4));
10549     assert(insOptsNone(opt) || insOptsAnyExtend(opt) || (opt == INS_OPTS_LSL));
10550
10551     // size is based on the extend option, not the instr size.
10552     emitAttr size = insOpts32BitExtend(opt) ? EA_4BYTE : EA_8BYTE;
10553
10554     if (strictArmAsm)
10555     {
10556         if (insOptsNone(opt))
10557         {
10558             emitDispReg(reg, size, false);
10559         }
10560         else
10561         {
10562             emitDispReg(reg, size, true);
10563             if (opt == INS_OPTS_LSL)
10564                 printf("LSL");
10565             else
10566                 emitDispExtendOpts(opt);
10567             if ((imm > 0) || (opt == INS_OPTS_LSL))
10568             {
10569                 printf(" ");
10570                 emitDispImm(imm, false);
10571             }
10572         }
10573     }
10574     else // !strictArmAsm
10575     {
10576         if (insOptsNone(opt))
10577         {
10578             emitDispReg(reg, size, false);
10579         }
10580         else
10581         {
10582             if (opt != INS_OPTS_LSL)
10583             {
10584                 emitDispExtendOpts(opt);
10585                 printf("(");
10586                 emitDispReg(reg, size, false);
10587                 printf(")");
10588             }
10589         }
10590         if (imm > 0)
10591         {
10592             printf("*");
10593             emitDispImm(ssize_t{1} << imm, false);
10594         }
10595     }
10596 }
10597
10598 /*****************************************************************************
10599  *
10600  *  Display an addressing operand [reg + imm]
10601  */
10602 void emitter::emitDispAddrRI(regNumber reg, insOpts opt, ssize_t imm)
10603 {
10604     reg = encodingZRtoSP(reg); // ZR (R31) encodes the SP register
10605
10606     if (strictArmAsm)
10607     {
10608         printf("[");
10609
10610         emitDispReg(reg, EA_8BYTE, false);
10611
10612         if (!insOptsPostIndex(opt) && (imm != 0))
10613         {
10614             printf(",");
10615             emitDispImm(imm, false);
10616         }
10617         printf("]");
10618
10619         if (insOptsPreIndex(opt))
10620         {
10621             printf("!");
10622         }
10623         else if (insOptsPostIndex(opt))
10624         {
10625             printf(",");
10626             emitDispImm(imm, false);
10627         }
10628     }
10629     else // !strictArmAsm
10630     {
10631         printf("[");
10632
10633         const char* operStr = "++";
10634         if (imm < 0)
10635         {
10636             operStr = "--";
10637             imm     = -imm;
10638         }
10639
10640         if (insOptsPreIndex(opt))
10641         {
10642             printf(operStr);
10643         }
10644
10645         emitDispReg(reg, EA_8BYTE, false);
10646
10647         if (insOptsPostIndex(opt))
10648         {
10649             printf(operStr);
10650         }
10651
10652         if (insOptsIndexed(opt))
10653         {
10654             printf(", ");
10655         }
10656         else
10657         {
10658             printf("%c", operStr[1]);
10659         }
10660         emitDispImm(imm, false);
10661         printf("]");
10662     }
10663 }
10664
10665 /*****************************************************************************
10666  *
10667  *  Display an addressing operand [reg + extended reg]
10668  */
10669 void emitter::emitDispAddrRRExt(regNumber reg1, regNumber reg2, insOpts opt, bool isScaled, emitAttr size)
10670 {
10671     reg1 = encodingZRtoSP(reg1); // ZR (R31) encodes the SP register
10672
10673     unsigned scale = 0;
10674     if (isScaled)
10675     {
10676         scale = NaturalScale_helper(size);
10677     }
10678
10679     printf("[");
10680
10681     if (strictArmAsm)
10682     {
10683         emitDispReg(reg1, EA_8BYTE, true);
10684         emitDispExtendReg(reg2, opt, scale);
10685     }
10686     else // !strictArmAsm
10687     {
10688         emitDispReg(reg1, EA_8BYTE, false);
10689         printf("+");
10690         emitDispExtendReg(reg2, opt, scale);
10691     }
10692
10693     printf("]");
10694 }
10695
10696 /*****************************************************************************
10697  *
10698  *  Display (optionally) the instruction encoding in hex
10699  */
10700
10701 void emitter::emitDispInsHex(BYTE* code, size_t sz)
10702 {
10703     // We do not display the instruction hex if we want diff-able disassembly
10704     if (!emitComp->opts.disDiffable)
10705     {
10706         if (sz == 4)
10707         {
10708             printf("  %08X    ", (*((code_t*)code)));
10709         }
10710         else
10711         {
10712             printf("              ");
10713         }
10714     }
10715 }
10716
10717 /****************************************************************************
10718  *
10719  *  Display the given instruction.
10720  */
10721
10722 void emitter::emitDispIns(
10723     instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* pCode, size_t sz, insGroup* ig)
10724 {
10725     if (EMITVERBOSE)
10726     {
10727         unsigned idNum =
10728             id->idDebugOnlyInfo()->idNum; // Do not remove this!  It is needed for VisualStudio conditional breakpoints
10729
10730         printf("IN%04x: ", idNum);
10731     }
10732
10733     if (pCode == NULL)
10734         sz = 0;
10735
10736     if (!emitComp->opts.dspEmit && !isNew && !asmfm && sz)
10737         doffs = true;
10738
10739     /* Display the instruction offset */
10740
10741     emitDispInsOffs(offset, doffs);
10742
10743     /* Display the instruction hex code */
10744
10745     emitDispInsHex(pCode, sz);
10746
10747     printf("      ");
10748
10749     /* Get the instruction and format */
10750
10751     instruction ins = id->idIns();
10752     insFormat   fmt = id->idInsFmt();
10753
10754     emitDispInst(ins);
10755
10756     /* If this instruction has just been added, check its size */
10757
10758     assert(isNew == false || (int)emitSizeOfInsDsc(id) == emitCurIGfreeNext - (BYTE*)id);
10759
10760     /* Figure out the operand size */
10761     emitAttr size = id->idOpSize();
10762     emitAttr attr = size;
10763     if (id->idGCref() == GCT_GCREF)
10764         attr = EA_GCREF;
10765     else if (id->idGCref() == GCT_BYREF)
10766         attr = EA_BYREF;
10767
10768     switch (fmt)
10769     {
10770         code_t       code;
10771         ssize_t      imm;
10772         int          doffs;
10773         bool         isExtendAlias;
10774         bitMaskImm   bmi;
10775         halfwordImm  hwi;
10776         condFlagsImm cfi;
10777         unsigned     scale;
10778         unsigned     immShift;
10779         bool         hasShift;
10780         ssize_t      offs;
10781         const char*  methodName;
10782         emitAttr     elemsize;
10783         emitAttr     datasize;
10784         emitAttr     srcsize;
10785         emitAttr     dstsize;
10786         ssize_t      index;
10787         ssize_t      index2;
10788
10789         case IF_BI_0A: // BI_0A   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
10790         case IF_BI_0B: // BI_0B   ......iiiiiiiiii iiiiiiiiiii.....               simm19:00
10791         case IF_LARGEJMP:
10792         {
10793             if (fmt == IF_LARGEJMP)
10794             {
10795                 printf("(LARGEJMP)");
10796             }
10797             if (id->idAddr()->iiaHasInstrCount())
10798             {
10799                 int instrCount = id->idAddr()->iiaGetInstrCount();
10800
10801                 if (ig == nullptr)
10802                 {
10803                     printf("pc%s%d instructions", (instrCount >= 0) ? "+" : "", instrCount);
10804                 }
10805                 else
10806                 {
10807                     unsigned       insNum  = emitFindInsNum(ig, id);
10808                     UNATIVE_OFFSET srcOffs = ig->igOffs + emitFindOffset(ig, insNum + 1);
10809                     UNATIVE_OFFSET dstOffs = ig->igOffs + emitFindOffset(ig, insNum + 1 + instrCount);
10810                     ssize_t        relOffs = (ssize_t)(emitOffsetToPtr(dstOffs) - emitOffsetToPtr(srcOffs));
10811                     printf("pc%s%d (%d instructions)", (relOffs >= 0) ? "+" : "", relOffs, instrCount);
10812                 }
10813             }
10814             else if (id->idIsBound())
10815             {
10816                 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10817             }
10818             else
10819             {
10820                 printf("L_M%03u_" FMT_BB, Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10821             }
10822         }
10823         break;
10824
10825         case IF_BI_0C: // BI_0C   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
10826             if (id->idIsCallAddr())
10827             {
10828                 offs       = (ssize_t)id->idAddr()->iiaAddr;
10829                 methodName = "";
10830             }
10831             else
10832             {
10833                 offs       = 0;
10834                 methodName = emitComp->eeGetMethodFullName((CORINFO_METHOD_HANDLE)id->idDebugOnlyInfo()->idMemCookie);
10835             }
10836
10837             if (offs)
10838             {
10839                 if (id->idIsDspReloc())
10840                     printf("reloc ");
10841                 printf("%08X", offs);
10842             }
10843             else
10844             {
10845                 printf("%s", methodName);
10846             }
10847             break;
10848
10849         case IF_BI_1A: // BI_1A   ......iiiiiiiiii iiiiiiiiiiittttt      Rt       simm19:00
10850             assert(insOptsNone(id->idInsOpt()));
10851             emitDispReg(id->idReg1(), size, true);
10852             if (id->idIsBound())
10853             {
10854                 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10855             }
10856             else
10857             {
10858                 printf("L_M%03u_" FMT_BB, Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10859             }
10860             break;
10861
10862         case IF_BI_1B: // BI_1B   B.......bbbbbiii iiiiiiiiiiittttt      Rt imm6, simm14:00
10863             assert(insOptsNone(id->idInsOpt()));
10864             emitDispReg(id->idReg1(), size, true);
10865             emitDispImm(emitGetInsSC(id), true);
10866             if (id->idIsBound())
10867             {
10868                 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10869             }
10870             else
10871             {
10872                 printf("L_M%03u_" FMT_BB, Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10873             }
10874             break;
10875
10876         case IF_BR_1A: // BR_1A   ................ ......nnnnn.....         Rn
10877             assert(insOptsNone(id->idInsOpt()));
10878             emitDispReg(id->idReg1(), size, false);
10879             break;
10880
10881         case IF_BR_1B: // BR_1B   ................ ......nnnnn.....         Rn
10882             assert(insOptsNone(id->idInsOpt()));
10883             emitDispReg(id->idReg3(), size, false);
10884             break;
10885
10886         case IF_LS_1A: // LS_1A   XX...V..iiiiiiii iiiiiiiiiiittttt      Rt    PC imm(1MB)
10887         case IF_DI_1E: // DI_1E   .ii.....iiiiiiii iiiiiiiiiiiddddd      Rd       simm21
10888         case IF_LARGELDC:
10889         case IF_LARGEADR:
10890             assert(insOptsNone(id->idInsOpt()));
10891             emitDispReg(id->idReg1(), size, true);
10892             imm = emitGetInsSC(id);
10893
10894             /* Is this actually a reference to a data section? */
10895             if (fmt == IF_LARGEADR)
10896             {
10897                 printf("(LARGEADR)");
10898             }
10899             else if (fmt == IF_LARGELDC)
10900             {
10901                 printf("(LARGELDC)");
10902             }
10903
10904             printf("[");
10905             if (id->idAddr()->iiaIsJitDataOffset())
10906             {
10907                 doffs = Compiler::eeGetJitDataOffs(id->idAddr()->iiaFieldHnd);
10908                 /* Display a data section reference */
10909
10910                 if (doffs & 1)
10911                     printf("@CNS%02u", doffs - 1);
10912                 else
10913                     printf("@RWD%02u", doffs);
10914
10915                 if (imm != 0)
10916                     printf("%+Id", imm);
10917             }
10918             else
10919             {
10920                 assert(imm == 0);
10921                 if (id->idIsReloc())
10922                 {
10923                     printf("RELOC ");
10924                     emitDispImm((ssize_t)id->idAddr()->iiaAddr, false);
10925                 }
10926                 else if (id->idIsBound())
10927                 {
10928                     printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10929                 }
10930                 else
10931                 {
10932                     printf("L_M%03u_" FMT_BB, Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10933                 }
10934             }
10935             printf("]");
10936             break;
10937
10938         case IF_LS_2A: // LS_2A   .X.......X...... ......nnnnnttttt      Rt Rn
10939             assert(insOptsNone(id->idInsOpt()));
10940             assert(emitGetInsSC(id) == 0);
10941             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10942             emitDispAddrRI(id->idReg2(), id->idInsOpt(), 0);
10943             break;
10944
10945         case IF_LS_2B: // LS_2B   .X.......Xiiiiii iiiiiinnnnnttttt      Rt Rn    imm(0-4095)
10946             assert(insOptsNone(id->idInsOpt()));
10947             imm   = emitGetInsSC(id);
10948             scale = NaturalScale_helper(emitInsLoadStoreSize(id));
10949             imm <<= scale; // The immediate is scaled by the size of the ld/st
10950             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10951             emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
10952             break;
10953
10954         case IF_LS_2C: // LS_2C   .X.......X.iiiii iiiiPPnnnnnttttt      Rt Rn    imm(-256..+255) no/pre/post inc
10955             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
10956             imm = emitGetInsSC(id);
10957             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10958             emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
10959             break;
10960
10961         case IF_LS_3A: // LS_3A   .X.......X.mmmmm oooS..nnnnnttttt      Rt Rn Rm ext(Rm) LSL {}
10962             assert(insOptsLSExtend(id->idInsOpt()));
10963             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10964             if (id->idIsLclVar())
10965             {
10966                 emitDispAddrRRExt(id->idReg2(), codeGen->rsGetRsvdReg(), id->idInsOpt(), false, size);
10967             }
10968             else
10969             {
10970                 emitDispAddrRRExt(id->idReg2(), id->idReg3(), id->idInsOpt(), id->idReg3Scaled(), size);
10971             }
10972             break;
10973
10974         case IF_LS_3B: // LS_3B   X............... .aaaaannnnnddddd      Rt Ra Rn
10975             assert(insOptsNone(id->idInsOpt()));
10976             assert(emitGetInsSC(id) == 0);
10977             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10978             emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10979             emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
10980             break;
10981
10982         case IF_LS_3C: // LS_3C   X.........iiiiii iaaaaannnnnddddd      Rt Ra Rn imm(im7,sh)
10983             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
10984             imm   = emitGetInsSC(id);
10985             scale = NaturalScale_helper(emitInsLoadStoreSize(id));
10986             imm <<= scale;
10987             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10988             emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10989             emitDispAddrRI(id->idReg3(), id->idInsOpt(), imm);
10990             break;
10991
10992         case IF_LS_3D: // LS_3D   .X.......X.mmmmm ......nnnnnttttt      Wm Rt Rn
10993             assert(insOptsNone(id->idInsOpt()));
10994             emitDispReg(id->idReg1(), EA_4BYTE, true);
10995             emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10996             emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
10997             break;
10998
10999         case IF_LS_3E: // LS_3E   .X.........mmmmm ......nnnnnttttt      Rm Rt Rn ARMv8.1 LSE Atomics
11000             assert(insOptsNone(id->idInsOpt()));
11001             assert((EA_SIZE(size) == 4) || (EA_SIZE(size) == 8));
11002             emitDispReg(id->idReg1(), size, true);
11003             emitDispReg(id->idReg2(), size, true);
11004             emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
11005             break;
11006
11007         case IF_DI_1A: // DI_1A   X.......shiiiiii iiiiiinnnnn.....      Rn       imm(i12,sh)
11008             emitDispReg(id->idReg1(), size, true);
11009             emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
11010             break;
11011
11012         case IF_DI_1B: // DI_1B   X........hwiiiii iiiiiiiiiiiddddd      Rd       imm(i16,hw)
11013             emitDispReg(id->idReg1(), size, true);
11014             hwi.immHWVal = (unsigned)emitGetInsSC(id);
11015             if (ins == INS_mov)
11016             {
11017                 emitDispImm(emitDecodeHalfwordImm(hwi, size), false);
11018             }
11019             else // movz, movn, movk
11020             {
11021                 emitDispImm(hwi.immVal, false);
11022                 if (hwi.immHW != 0)
11023                 {
11024                     emitDispShiftOpts(INS_OPTS_LSL);
11025                     emitDispImm(hwi.immHW * 16, false);
11026                 }
11027             }
11028             break;
11029
11030         case IF_DI_1C: // DI_1C   X........Nrrrrrr ssssssnnnnn.....         Rn    imm(N,r,s)
11031             emitDispReg(id->idReg1(), size, true);
11032             bmi.immNRS = (unsigned)emitGetInsSC(id);
11033             emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
11034             break;
11035
11036         case IF_DI_1D: // DI_1D   X........Nrrrrrr ssssss.....ddddd      Rd       imm(N,r,s)
11037             emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11038             bmi.immNRS = (unsigned)emitGetInsSC(id);
11039             emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
11040             break;
11041
11042         case IF_DI_2A: // DI_2A   X.......shiiiiii iiiiiinnnnnddddd      Rd Rn    imm(i12,sh)
11043             if ((ins == INS_add) || (ins == INS_sub))
11044             {
11045                 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11046                 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11047             }
11048             else
11049             {
11050                 emitDispReg(id->idReg1(), size, true);
11051                 emitDispReg(id->idReg2(), size, true);
11052             }
11053             emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
11054             break;
11055
11056         case IF_DI_2B: // DI_2B   X........X.nnnnn ssssssnnnnnddddd      Rd Rn    imm(0-63)
11057             emitDispReg(id->idReg1(), size, true);
11058             emitDispReg(id->idReg2(), size, true);
11059             emitDispImm(emitGetInsSC(id), false);
11060             break;
11061
11062         case IF_DI_2C: // DI_2C   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imm(N,r,s)
11063             if (ins == INS_ands)
11064             {
11065                 emitDispReg(id->idReg1(), size, true);
11066             }
11067             else
11068             {
11069                 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11070             }
11071             emitDispReg(id->idReg2(), size, true);
11072             bmi.immNRS = (unsigned)emitGetInsSC(id);
11073             emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
11074             break;
11075
11076         case IF_DI_2D: // DI_2D   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imr, ims   (N,r,s)
11077             emitDispReg(id->idReg1(), size, true);
11078             emitDispReg(id->idReg2(), size, true);
11079
11080             imm        = emitGetInsSC(id);
11081             bmi.immNRS = (unsigned)imm;
11082
11083             switch (ins)
11084             {
11085                 case INS_bfm:
11086                 case INS_sbfm:
11087                 case INS_ubfm:
11088                     emitDispImm(bmi.immR, true);
11089                     emitDispImm(bmi.immS, false);
11090                     break;
11091
11092                 case INS_bfi:
11093                 case INS_sbfiz:
11094                 case INS_ubfiz:
11095                     emitDispImm(getBitWidth(size) - bmi.immR, true);
11096                     emitDispImm(bmi.immS + 1, false);
11097                     break;
11098
11099                 case INS_bfxil:
11100                 case INS_sbfx:
11101                 case INS_ubfx:
11102                     emitDispImm(bmi.immR, true);
11103                     emitDispImm(bmi.immS - bmi.immR + 1, false);
11104                     break;
11105
11106                 case INS_asr:
11107                 case INS_lsr:
11108                 case INS_lsl:
11109                     emitDispImm(imm, false);
11110                     break;
11111
11112                 default:
11113                     assert(!"Unexpected instruction in IF_DI_2D");
11114             }
11115
11116             break;
11117
11118         case IF_DI_1F: // DI_1F   X..........iiiii cccc..nnnnn.nzcv      Rn imm5  nzcv cond
11119             emitDispReg(id->idReg1(), size, true);
11120             cfi.immCFVal = (unsigned)emitGetInsSC(id);
11121             emitDispImm(cfi.imm5, true);
11122             emitDispFlags(cfi.flags);
11123             printf(",");
11124             emitDispCond(cfi.cond);
11125             break;
11126
11127         case IF_DR_1D: // DR_1D   X............... cccc.......mmmmm      Rd       cond
11128             emitDispReg(id->idReg1(), size, true);
11129             cfi.immCFVal = (unsigned)emitGetInsSC(id);
11130             emitDispCond(cfi.cond);
11131             break;
11132
11133         case IF_DR_2A: // DR_2A   X..........mmmmm ......nnnnn.....         Rn Rm
11134             emitDispReg(id->idReg1(), size, true);
11135             emitDispReg(id->idReg2(), size, false);
11136             break;
11137
11138         case IF_DR_2B: // DR_2B   X.......sh.mmmmm ssssssnnnnn.....         Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
11139             emitDispReg(id->idReg1(), size, true);
11140             emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
11141             break;
11142
11143         case IF_DR_2C: // DR_2C   X..........mmmmm ooosssnnnnn.....         Rn Rm ext(Rm) LSL imm(0-4)
11144             emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11145             imm = emitGetInsSC(id);
11146             emitDispExtendReg(id->idReg2(), id->idInsOpt(), imm);
11147             break;
11148
11149         case IF_DR_2D: // DR_2D   X..........nnnnn cccc..nnnnnddddd      Rd Rn    cond
11150             emitDispReg(id->idReg1(), size, true);
11151             emitDispReg(id->idReg2(), size, true);
11152             cfi.immCFVal = (unsigned)emitGetInsSC(id);
11153             emitDispCond(cfi.cond);
11154             break;
11155
11156         case IF_DR_2E: // DR_2E   X..........mmmmm ...........ddddd      Rd    Rm
11157         case IF_DR_2J: // DR_2J   ................ ......nnnnnddddd      Sd    Sn
11158             emitDispReg(id->idReg1(), size, true);
11159             emitDispReg(id->idReg2(), size, false);
11160             break;
11161
11162         case IF_DR_2F: // DR_2F   X.......sh.mmmmm ssssss.....ddddd      Rd    Rm {LSL,LSR,ASR} imm(0-63)
11163             emitDispReg(id->idReg1(), size, true);
11164             emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
11165             break;
11166
11167         case IF_DR_2G: // DR_2G   X............... ......nnnnnddddd      Rd Rn
11168             emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11169             emitDispReg(encodingZRtoSP(id->idReg2()), size, false);
11170             break;
11171
11172         case IF_DR_2H: // DR_2H   X........X...... ......nnnnnddddd      Rd Rn
11173             emitDispReg(id->idReg1(), size, true);
11174             emitDispReg(id->idReg2(), size, false);
11175             break;
11176
11177         case IF_DR_2I: // DR_2I   X..........mmmmm cccc..nnnnn.nzcv      Rn Rm    nzcv cond
11178             emitDispReg(id->idReg1(), size, true);
11179             emitDispReg(id->idReg2(), size, true);
11180             cfi.immCFVal = (unsigned)emitGetInsSC(id);
11181             emitDispFlags(cfi.flags);
11182             printf(",");
11183             emitDispCond(cfi.cond);
11184             break;
11185
11186         case IF_DR_3A: // DR_3A   X..........mmmmm ......nnnnnmmmmm      Rd Rn Rm
11187             if ((ins == INS_add) || (ins == INS_sub))
11188             {
11189                 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11190                 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11191             }
11192             else if ((ins == INS_smull) || (ins == INS_smulh))
11193             {
11194                 // Rd is always 8 bytes
11195                 emitDispReg(id->idReg1(), EA_8BYTE, true);
11196
11197                 // Rn, Rm effective size depends on instruction type
11198                 size = (ins == INS_smulh) ? EA_8BYTE : EA_4BYTE;
11199                 emitDispReg(id->idReg2(), size, true);
11200             }
11201             else
11202             {
11203                 emitDispReg(id->idReg1(), size, true);
11204                 emitDispReg(id->idReg2(), size, true);
11205             }
11206             if (id->idIsLclVar())
11207             {
11208                 emitDispReg(codeGen->rsGetRsvdReg(), size, false);
11209             }
11210             else
11211             {
11212                 emitDispReg(id->idReg3(), size, false);
11213             }
11214
11215             break;
11216
11217         case IF_DR_3B: // DR_3B   X.......sh.mmmmm ssssssnnnnnddddd      Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
11218             emitDispReg(id->idReg1(), size, true);
11219             emitDispReg(id->idReg2(), size, true);
11220             emitDispShiftedReg(id->idReg3(), id->idInsOpt(), emitGetInsSC(id), size);
11221             break;
11222
11223         case IF_DR_3C: // DR_3C   X..........mmmmm ooosssnnnnnddddd      Rd Rn Rm ext(Rm) LSL imm(0-4)
11224             emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11225             emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11226             imm = emitGetInsSC(id);
11227             emitDispExtendReg(id->idReg3(), id->idInsOpt(), imm);
11228             break;
11229
11230         case IF_DR_3D: // DR_3D   X..........mmmmm cccc..nnnnnmmmmm      Rd Rn Rm cond
11231             emitDispReg(id->idReg1(), size, true);
11232             emitDispReg(id->idReg2(), size, true);
11233             emitDispReg(id->idReg3(), size, true);
11234             cfi.immCFVal = (unsigned)emitGetInsSC(id);
11235             emitDispCond(cfi.cond);
11236             break;
11237
11238         case IF_DR_3E: // DR_3E   X........X.mmmmm ssssssnnnnnddddd      Rd Rn Rm imm(0-63)
11239             emitDispReg(id->idReg1(), size, true);
11240             emitDispReg(id->idReg2(), size, true);
11241             emitDispReg(id->idReg3(), size, true);
11242             emitDispImm(emitGetInsSC(id), false);
11243             break;
11244
11245         case IF_DR_4A: // DR_4A   X..........mmmmm .aaaaannnnnmmmmm      Rd Rn Rm Ra
11246             emitDispReg(id->idReg1(), size, true);
11247             emitDispReg(id->idReg2(), size, true);
11248             emitDispReg(id->idReg3(), size, true);
11249             emitDispReg(id->idReg4(), size, false);
11250             break;
11251
11252         case IF_DV_1A: // DV_1A   .........X.iiiii iii........ddddd      Vd imm8 (fmov - immediate scalar)
11253             elemsize = id->idOpSize();
11254             emitDispReg(id->idReg1(), elemsize, true);
11255             emitDispFloatImm(emitGetInsSC(id));
11256             break;
11257
11258         case IF_DV_1B: // DV_1B   .QX..........iii cmod..iiiiiddddd      Vd imm8 (immediate vector)
11259             imm      = emitGetInsSC(id) & 0x0ff;
11260             immShift = (emitGetInsSC(id) & 0x700) >> 8;
11261             hasShift = (immShift != 0);
11262             elemsize = optGetElemsize(id->idInsOpt());
11263             if (id->idInsOpt() == INS_OPTS_1D)
11264             {
11265                 assert(elemsize == size);
11266                 emitDispReg(id->idReg1(), size, true);
11267             }
11268             else
11269             {
11270                 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11271             }
11272             if (ins == INS_fmov)
11273             {
11274                 emitDispFloatImm(imm);
11275                 assert(hasShift == false);
11276             }
11277             else
11278             {
11279                 if (elemsize == EA_8BYTE)
11280                 {
11281                     assert(ins == INS_movi);
11282                     ssize_t       imm64 = 0;
11283                     const ssize_t mask8 = 0xFF;
11284                     for (unsigned b = 0; b < 8; b++)
11285                     {
11286                         if (imm & (ssize_t{1} << b))
11287                         {
11288                             imm64 |= (mask8 << (b * 8));
11289                         }
11290                     }
11291                     emitDispImm(imm64, hasShift, true);
11292                 }
11293                 else
11294                 {
11295                     emitDispImm(imm, hasShift, true);
11296                 }
11297                 if (hasShift)
11298                 {
11299                     insOpts  opt   = (immShift & 0x4) ? INS_OPTS_MSL : INS_OPTS_LSL;
11300                     unsigned shift = (immShift & 0x3) * 8;
11301                     emitDispShiftOpts(opt);
11302                     emitDispImm(shift, false);
11303                 }
11304             }
11305             break;
11306
11307         case IF_DV_1C: // DV_1C   .........X...... ......nnnnn.....      Vn #0.0 (fcmp - with zero)
11308             elemsize = id->idOpSize();
11309             emitDispReg(id->idReg1(), elemsize, true);
11310             emitDispFloatZero();
11311             break;
11312
11313         case IF_DV_2A: // DV_2A   .Q.......X...... ......nnnnnddddd      Vd Vn   (fabs, fcvt - vector)
11314         case IF_DV_2M: // DV_2M   .Q......XX...... ......nnnnnddddd      Vd Vn   (abs, neg   - vector)
11315         case IF_DV_2P: // DV_2P   ................ ......nnnnnddddd      Vd Vn   (aes*, sha1su1)
11316             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11317             emitDispVectorReg(id->idReg2(), id->idInsOpt(), false);
11318             break;
11319
11320         case IF_DV_2N: // DV_2N   .........iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - scalar)
11321             elemsize = id->idOpSize();
11322             emitDispReg(id->idReg1(), elemsize, true);
11323             emitDispReg(id->idReg2(), elemsize, true);
11324             emitDispImm(emitGetInsSC(id), false);
11325             break;
11326
11327         case IF_DV_2O: // DV_2O   .Q.......iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - vector)
11328             imm = emitGetInsSC(id);
11329             // Do we have a sxtl or uxtl instruction?
11330             isExtendAlias = ((ins == INS_sxtl) || (ins == INS_sxtl2) || (ins == INS_uxtl) || (ins == INS_uxtl2));
11331             code          = emitInsCode(ins, fmt);
11332             if (code & 0x00008000) // widen/narrow opcodes
11333             {
11334                 if (code & 0x00002000) // SHL opcodes
11335                 {
11336                     emitDispVectorReg(id->idReg1(), optWidenElemsize(id->idInsOpt()), true);
11337                     emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11338                 }
11339                 else // SHR opcodes
11340                 {
11341                     emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11342                     emitDispVectorReg(id->idReg2(), optWidenElemsize(id->idInsOpt()), !isExtendAlias);
11343                 }
11344             }
11345             else
11346             {
11347                 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11348                 emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11349             }
11350             // Print the immediate unless we have a sxtl or uxtl instruction
11351             if (!isExtendAlias)
11352             {
11353                 emitDispImm(imm, false);
11354             }
11355             break;
11356
11357         case IF_DV_2B: // DV_2B   .Q.........iiiii ......nnnnnddddd      Rd Vn[] (umov/smov    - to general)
11358             srcsize = id->idOpSize();
11359             index   = emitGetInsSC(id);
11360             if (ins == INS_smov)
11361             {
11362                 dstsize = EA_8BYTE;
11363             }
11364             else // INS_umov or INS_mov
11365             {
11366                 dstsize = (srcsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE;
11367             }
11368             emitDispReg(id->idReg1(), dstsize, true);
11369             emitDispVectorRegIndex(id->idReg2(), srcsize, index, false);
11370             break;
11371
11372         case IF_DV_2C: // DV_2C   .Q.........iiiii ......nnnnnddddd      Vd Rn   (dup/ins - vector from general)
11373             if (ins == INS_dup)
11374             {
11375                 datasize = id->idOpSize();
11376                 assert(isValidVectorDatasize(datasize));
11377                 assert(isValidArrangement(datasize, id->idInsOpt()));
11378                 elemsize = optGetElemsize(id->idInsOpt());
11379                 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11380             }
11381             else // INS_ins
11382             {
11383                 elemsize = id->idOpSize();
11384                 index    = emitGetInsSC(id);
11385                 assert(isValidVectorElemsize(elemsize));
11386                 emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11387             }
11388             emitDispReg(id->idReg2(), (elemsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE, false);
11389             break;
11390
11391         case IF_DV_2D: // DV_2D   .Q.........iiiii ......nnnnnddddd      Vd Vn[]   (dup - vector)
11392             datasize = id->idOpSize();
11393             assert(isValidVectorDatasize(datasize));
11394             assert(isValidArrangement(datasize, id->idInsOpt()));
11395             elemsize = optGetElemsize(id->idInsOpt());
11396             index    = emitGetInsSC(id);
11397             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11398             emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11399             break;
11400
11401         case IF_DV_2E: // DV_2E   ...........iiiii ......nnnnnddddd      Vd Vn[]   (dup - scalar)
11402             elemsize = id->idOpSize();
11403             index    = emitGetInsSC(id);
11404             emitDispReg(id->idReg1(), elemsize, true);
11405             emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11406             break;
11407
11408         case IF_DV_2F: // DV_2F   ...........iiiii .jjjj.nnnnnddddd      Vd[] Vn[] (ins - element)
11409             imm      = emitGetInsSC(id);
11410             index    = (imm >> 4) & 0xf;
11411             index2   = imm & 0xf;
11412             elemsize = id->idOpSize();
11413             emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11414             emitDispVectorRegIndex(id->idReg2(), elemsize, index2, false);
11415             break;
11416
11417         case IF_DV_2G: // DV_2G   .........X...... ......nnnnnddddd      Vd Vn      (fmov, fcvtXX - register)
11418         case IF_DV_2K: // DV_2K   .........X.mmmmm ......nnnnn.....      Vn Vm      (fcmp)
11419         case IF_DV_2L: // DV_2L   ........XX...... ......nnnnnddddd      Vd Vn      (abs, neg - scalar)
11420             elemsize = id->idOpSize();
11421             emitDispReg(id->idReg1(), elemsize, true);
11422             emitDispReg(id->idReg2(), elemsize, false);
11423             break;
11424
11425         case IF_DV_2H: // DV_2H   X........X...... ......nnnnnddddd      Rd Vn      (fmov, fcvtXX - to general)
11426         case IF_DV_2I: // DV_2I   X........X...... ......nnnnnddddd      Vd Rn      (fmov, Xcvtf - from general)
11427         case IF_DV_2J: // DV_2J   ........SS.....D D.....nnnnnddddd      Vd Vn      (fcvt)
11428             dstsize = optGetDstsize(id->idInsOpt());
11429             srcsize = optGetSrcsize(id->idInsOpt());
11430
11431             emitDispReg(id->idReg1(), dstsize, true);
11432             emitDispReg(id->idReg2(), srcsize, false);
11433             break;
11434
11435         case IF_DV_3A: // DV_3A   .Q......XX.mmmmm ......nnnnnddddd      Vd Vn Vm  (vector)
11436         case IF_DV_3B: // DV_3B   .Q.........mmmmm ......nnnnnddddd      Vd Vn Vm  (vector)
11437             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11438             emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11439             emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11440             break;
11441
11442         case IF_DV_3C: // DV_3C   .Q.........mmmmm ......nnnnnddddd      Vd Vn Vm  (vector)
11443             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11444             if (ins != INS_mov)
11445             {
11446                 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11447             }
11448             emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11449             break;
11450
11451         case IF_DV_3AI: // DV_3AI  .Q......XXLMmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector by elem)
11452         case IF_DV_3BI: // DV_3BI  .Q........Lmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector by elem)
11453             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11454             emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11455             elemsize = optGetElemsize(id->idInsOpt());
11456             emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11457             break;
11458
11459         case IF_DV_3D: // DV_3D   .........X.mmmmm ......nnnnnddddd      Vd Vn Vm  (scalar)
11460         case IF_DV_3E: // DV_3E   ...........mmmmm ......nnnnnddddd      Vd Vn Vm  (scalar)
11461             emitDispReg(id->idReg1(), size, true);
11462             emitDispReg(id->idReg2(), size, true);
11463             emitDispReg(id->idReg3(), size, false);
11464             break;
11465
11466         case IF_DV_3F: // DV_3F   ..........mmmmm ......nnnnnddddd       Vd Vn Vm (vector)
11467             if ((ins == INS_sha1c) || (ins == INS_sha1m) || (ins == INS_sha1p))
11468             {
11469                 // Qd, Sn, Vm (vector)
11470                 emitDispReg(id->idReg1(), size, true);
11471                 emitDispReg(id->idReg2(), EA_4BYTE, true);
11472                 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11473             }
11474             else if ((ins == INS_sha256h) || (ins == INS_sha256h2))
11475             {
11476                 // Qd Qn Vm (vector)
11477                 emitDispReg(id->idReg1(), size, true);
11478                 emitDispReg(id->idReg2(), size, true);
11479                 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11480             }
11481             else // INS_sha1su0, INS_sha256su1
11482             {
11483                 // Vd, Vn, Vm   (vector)
11484                 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11485                 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11486                 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11487             }
11488             break;
11489
11490         case IF_DV_3DI: // DV_3DI  .........XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (scalar by elem)
11491             emitDispReg(id->idReg1(), size, true);
11492             emitDispReg(id->idReg2(), size, true);
11493             elemsize = size;
11494             emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11495             break;
11496
11497         case IF_DV_4A: // DV_4A   .........X.mmmmm .aaaaannnnnddddd      Vd Va Vn Vm (scalar)
11498             emitDispReg(id->idReg1(), size, true);
11499             emitDispReg(id->idReg2(), size, true);
11500             emitDispReg(id->idReg3(), size, true);
11501             emitDispReg(id->idReg4(), size, false);
11502             break;
11503
11504         case IF_SN_0A: // SN_0A   ................ ................
11505             break;
11506
11507         case IF_SI_0A: // SI_0A   ...........iiiii iiiiiiiiiii.....               imm16
11508             emitDispImm(emitGetInsSC(id), false);
11509             break;
11510
11511         case IF_SI_0B: // SI_0B   ................ ....bbbb........               imm4 - barrier
11512             emitDispBarrier((insBarrier)emitGetInsSC(id));
11513             break;
11514
11515         default:
11516             printf("unexpected format %s", emitIfName(id->idInsFmt()));
11517             assert(!"unexpectedFormat");
11518             break;
11519     }
11520
11521     if (id->idDebugOnlyInfo()->idVarRefOffs)
11522     {
11523         printf("\t// ");
11524         emitDispFrameRef(id->idAddr()->iiaLclVar.lvaVarNum(), id->idAddr()->iiaLclVar.lvaOffset(),
11525                          id->idDebugOnlyInfo()->idVarRefOffs, asmfm);
11526     }
11527
11528     printf("\n");
11529 }
11530
11531 /*****************************************************************************
11532  *
11533  *  Display a stack frame reference.
11534  */
11535
11536 void emitter::emitDispFrameRef(int varx, int disp, int offs, bool asmfm)
11537 {
11538     printf("[");
11539
11540     if (varx < 0)
11541         printf("TEMP_%02u", -varx);
11542     else
11543         emitComp->gtDispLclVar(+varx, false);
11544
11545     if (disp < 0)
11546         printf("-0x%02x", -disp);
11547     else if (disp > 0)
11548         printf("+0x%02x", +disp);
11549
11550     printf("]");
11551
11552     if (varx >= 0 && emitComp->opts.varNames)
11553     {
11554         LclVarDsc*  varDsc;
11555         const char* varName;
11556
11557         assert((unsigned)varx < emitComp->lvaCount);
11558         varDsc  = emitComp->lvaTable + varx;
11559         varName = emitComp->compLocalVarName(varx, offs);
11560
11561         if (varName)
11562         {
11563             printf("'%s", varName);
11564
11565             if (disp < 0)
11566                 printf("-%d", -disp);
11567             else if (disp > 0)
11568                 printf("+%d", +disp);
11569
11570             printf("'");
11571         }
11572     }
11573 }
11574
11575 #endif // DEBUG
11576
11577 // Generate code for a load or store operation with a potentially complex addressing mode
11578 // This method handles the case of a GT_IND with contained GT_LEA op1 of the x86 form [base + index*sccale + offset]
11579 // Since Arm64 does not directly support this complex of an addressing mode
11580 // we may generates up to three instructions for this for Arm64
11581 //
11582 void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataReg, GenTreeIndir* indir)
11583 {
11584     emitAttr ldstAttr = isVectorRegister(dataReg) ? attr : emitInsAdjustLoadStoreAttr(ins, attr);
11585
11586     GenTree* addr = indir->Addr();
11587
11588     if (addr->isContained())
11589     {
11590         assert(addr->OperGet() == GT_LCL_VAR_ADDR || addr->OperGet() == GT_LEA);
11591
11592         int   offset = 0;
11593         DWORD lsl    = 0;
11594
11595         if (addr->OperGet() == GT_LEA)
11596         {
11597             offset = addr->AsAddrMode()->Offset();
11598             if (addr->AsAddrMode()->gtScale > 0)
11599             {
11600                 assert(isPow2(addr->AsAddrMode()->gtScale));
11601                 BitScanForward(&lsl, addr->AsAddrMode()->gtScale);
11602             }
11603         }
11604
11605         GenTree* memBase = indir->Base();
11606
11607         if (indir->HasIndex())
11608         {
11609             GenTree* index = indir->Index();
11610
11611             if (offset != 0)
11612             {
11613                 regNumber tmpReg = indir->GetSingleTempReg();
11614
11615                 emitAttr addType = varTypeIsGC(memBase) ? EA_BYREF : EA_PTRSIZE;
11616
11617                 if (emitIns_valid_imm_for_add(offset, EA_8BYTE))
11618                 {
11619                     if (lsl > 0)
11620                     {
11621                         // Generate code to set tmpReg = base + index*scale
11622                         emitIns_R_R_R_I(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum, lsl,
11623                                         INS_OPTS_LSL);
11624                     }
11625                     else // no scale
11626                     {
11627                         // Generate code to set tmpReg = base + index
11628                         emitIns_R_R_R(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum);
11629                     }
11630
11631                     noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11632
11633                     // Then load/store dataReg from/to [tmpReg + offset]
11634                     emitIns_R_R_I(ins, ldstAttr, dataReg, tmpReg, offset);
11635                 }
11636                 else // large offset
11637                 {
11638                     // First load/store tmpReg with the large offset constant
11639                     codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11640                     // Then add the base register
11641                     //      rd = rd + base
11642                     emitIns_R_R_R(INS_add, addType, tmpReg, tmpReg, memBase->gtRegNum);
11643
11644                     noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11645                     noway_assert(tmpReg != index->gtRegNum);
11646
11647                     // Then load/store dataReg from/to [tmpReg + index*scale]
11648                     emitIns_R_R_R_I(ins, ldstAttr, dataReg, tmpReg, index->gtRegNum, lsl, INS_OPTS_LSL);
11649                 }
11650             }
11651             else // (offset == 0)
11652             {
11653                 if (lsl > 0)
11654                 {
11655                     // Then load/store dataReg from/to [memBase + index*scale]
11656                     emitIns_R_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum, lsl, INS_OPTS_LSL);
11657                 }
11658                 else // no scale
11659                 {
11660                     // Then load/store dataReg from/to [memBase + index]
11661                     emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum);
11662                 }
11663             }
11664         }
11665         else // no Index register
11666         {
11667             if (emitIns_valid_imm_for_ldst_offset(offset, EA_SIZE(attr)))
11668             {
11669                 // Then load/store dataReg from/to [memBase + offset]
11670                 emitIns_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, offset);
11671             }
11672             else
11673             {
11674                 // We require a tmpReg to hold the offset
11675                 regNumber tmpReg = indir->GetSingleTempReg();
11676
11677                 // First load/store tmpReg with the large offset constant
11678                 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11679
11680                 // Then load/store dataReg from/to [memBase + tmpReg]
11681                 emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, tmpReg);
11682             }
11683         }
11684     }
11685     else // addr is not contained, so we evaluate it into a register
11686     {
11687         // Then load/store dataReg from/to [addrReg]
11688         emitIns_R_R(ins, ldstAttr, dataReg, addr->gtRegNum);
11689     }
11690 }
11691
11692 // The callee must call genConsumeReg() for any non-contained srcs
11693 // and genProduceReg() for any non-contained dsts.
11694
11695 regNumber emitter::emitInsBinary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src)
11696 {
11697     // dst can only be a reg
11698     assert(!dst->isContained());
11699
11700     // src can be immed or reg
11701     assert(!src->isContained() || src->isContainedIntOrIImmed());
11702
11703     // find immed (if any) - it cannot be a dst
11704     GenTreeIntConCommon* intConst = nullptr;
11705     if (src->isContainedIntOrIImmed())
11706     {
11707         intConst = src->AsIntConCommon();
11708     }
11709
11710     if (intConst)
11711     {
11712         emitIns_R_I(ins, attr, dst->gtRegNum, intConst->IconValue());
11713         return dst->gtRegNum;
11714     }
11715     else
11716     {
11717         emitIns_R_R(ins, attr, dst->gtRegNum, src->gtRegNum);
11718         return dst->gtRegNum;
11719     }
11720 }
11721
11722 // The callee must call genConsumeReg() for any non-contained srcs
11723 // and genProduceReg() for any non-contained dsts.
11724
11725 regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src1, GenTree* src2)
11726 {
11727     // dst can only be a reg
11728     assert(!dst->isContained());
11729
11730     // find immed (if any) - it cannot be a dst
11731     // Only one src can be an int.
11732     GenTreeIntConCommon* intConst  = nullptr;
11733     GenTree*             nonIntReg = nullptr;
11734
11735     if (varTypeIsFloating(dst))
11736     {
11737         // src1 can only be a reg
11738         assert(!src1->isContained());
11739         // src2 can only be a reg
11740         assert(!src2->isContained());
11741     }
11742     else // not floating point
11743     {
11744         // src2 can be immed or reg
11745         assert(!src2->isContained() || src2->isContainedIntOrIImmed());
11746
11747         // Check src2 first as we can always allow it to be a contained immediate
11748         if (src2->isContainedIntOrIImmed())
11749         {
11750             intConst  = src2->AsIntConCommon();
11751             nonIntReg = src1;
11752         }
11753         // Only for commutative operations do we check src1 and allow it to be a contained immediate
11754         else if (dst->OperIsCommutative())
11755         {
11756             // src1 can be immed or reg
11757             assert(!src1->isContained() || src1->isContainedIntOrIImmed());
11758
11759             // Check src1 and allow it to be a contained immediate
11760             if (src1->isContainedIntOrIImmed())
11761             {
11762                 assert(!src2->isContainedIntOrIImmed());
11763                 intConst  = src1->AsIntConCommon();
11764                 nonIntReg = src2;
11765             }
11766         }
11767         else
11768         {
11769             // src1 can only be a reg
11770             assert(!src1->isContained());
11771         }
11772     }
11773
11774     bool isMulOverflow = false;
11775     if (dst->gtOverflowEx())
11776     {
11777         if ((ins == INS_add) || (ins == INS_adds))
11778         {
11779             ins = INS_adds;
11780         }
11781         else if ((ins == INS_sub) || (ins == INS_subs))
11782         {
11783             ins = INS_subs;
11784         }
11785         else if (ins == INS_mul)
11786         {
11787             isMulOverflow = true;
11788             assert(intConst == nullptr); // overflow format doesn't support an int constant operand
11789         }
11790         else
11791         {
11792             assert(!"Invalid ins for overflow check");
11793         }
11794     }
11795     if (intConst != nullptr)
11796     {
11797         emitIns_R_R_I(ins, attr, dst->gtRegNum, nonIntReg->gtRegNum, intConst->IconValue());
11798     }
11799     else
11800     {
11801         if (isMulOverflow)
11802         {
11803             regNumber extraReg = dst->GetSingleTempReg();
11804             assert(extraReg != dst->gtRegNum);
11805
11806             if ((dst->gtFlags & GTF_UNSIGNED) != 0)
11807             {
11808                 if (attr == EA_4BYTE)
11809                 {
11810                     // Compute 8 byte results from 4 byte by 4 byte multiplication.
11811                     emitIns_R_R_R(INS_umull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11812
11813                     // Get the high result by shifting dst.
11814                     emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11815                 }
11816                 else
11817                 {
11818                     assert(attr == EA_8BYTE);
11819                     // Compute the high result.
11820                     emitIns_R_R_R(INS_umulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11821
11822                     // Now multiply without skewing the high result.
11823                     emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11824                 }
11825
11826                 // zero-sign bit comparison to detect overflow.
11827                 emitIns_R_I(INS_cmp, attr, extraReg, 0);
11828             }
11829             else
11830             {
11831                 int bitShift = 0;
11832                 if (attr == EA_4BYTE)
11833                 {
11834                     // Compute 8 byte results from 4 byte by 4 byte multiplication.
11835                     emitIns_R_R_R(INS_smull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11836
11837                     // Get the high result by shifting dst.
11838                     emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11839
11840                     bitShift = 31;
11841                 }
11842                 else
11843                 {
11844                     assert(attr == EA_8BYTE);
11845                     // Save the high result in a temporary register.
11846                     emitIns_R_R_R(INS_smulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11847
11848                     // Now multiply without skewing the high result.
11849                     emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11850
11851                     bitShift = 63;
11852                 }
11853
11854                 // Sign bit comparison to detect overflow.
11855                 emitIns_R_R_I(INS_cmp, attr, extraReg, dst->gtRegNum, bitShift, INS_OPTS_ASR);
11856             }
11857         }
11858         else
11859         {
11860             // We can just multiply.
11861             emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11862         }
11863     }
11864
11865     if (dst->gtOverflowEx())
11866     {
11867         assert(!varTypeIsFloating(dst));
11868         codeGen->genCheckOverflow(dst);
11869     }
11870
11871     return dst->gtRegNum;
11872 }
11873
11874 #endif // defined(_TARGET_ARM64_)