Merge pull request #18011 from CarolEidt/JitOptDoc
[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_DV_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 immN == 1
2331
2332     if (bmImm.immN == 0) // find the smaller elemWidth when immN == 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     emitAttr   size = EA_SIZE(attr);
3397     insFormat  fmt  = IF_NONE;
3398     instrDesc* id   = nullptr;
3399
3400     /* Figure out the encoding format of the instruction */
3401     switch (ins)
3402     {
3403         case INS_br:
3404         case INS_ret:
3405             assert(isGeneralRegister(reg));
3406             id = emitNewInstrSmall(attr);
3407             id->idReg1(reg);
3408             fmt = IF_BR_1A;
3409             break;
3410
3411         default:
3412             unreached();
3413     }
3414
3415     assert(fmt != IF_NONE);
3416
3417     id->idIns(ins);
3418     id->idInsFmt(fmt);
3419
3420     dispIns(id);
3421     appendToCurIG(id);
3422 }
3423
3424 /*****************************************************************************
3425  *
3426  *  Add an instruction referencing a register and a constant.
3427  */
3428
3429 void emitter::emitIns_R_I(instruction ins, emitAttr attr, regNumber reg, ssize_t imm, insOpts opt /* = INS_OPTS_NONE */)
3430 {
3431     emitAttr  size      = EA_SIZE(attr);
3432     emitAttr  elemsize  = EA_UNKNOWN;
3433     insFormat fmt       = IF_NONE;
3434     bool      canEncode = false;
3435
3436     /* Figure out the encoding format of the instruction */
3437     switch (ins)
3438     {
3439         bitMaskImm     bmi;
3440         halfwordImm    hwi;
3441         byteShiftedImm bsi;
3442         ssize_t        notOfImm;
3443
3444         case INS_tst:
3445             assert(insOptsNone(opt));
3446             assert(isGeneralRegister(reg));
3447             bmi.immNRS = 0;
3448             canEncode  = canEncodeBitMaskImm(imm, size, &bmi);
3449             if (canEncode)
3450             {
3451                 imm = bmi.immNRS;
3452                 assert(isValidImmNRS(imm, size));
3453                 fmt = IF_DI_1C;
3454             }
3455             break;
3456
3457         case INS_movk:
3458         case INS_movn:
3459         case INS_movz:
3460             assert(isValidGeneralDatasize(size));
3461             assert(insOptsNone(opt)); // No LSL here (you must use emitIns_R_I_I if a shift is needed)
3462             assert(isGeneralRegister(reg));
3463             assert(isValidUimm16(imm));
3464
3465             hwi.immHW  = 0;
3466             hwi.immVal = imm;
3467             assert(imm == emitDecodeHalfwordImm(hwi, size));
3468
3469             imm       = hwi.immHWVal;
3470             canEncode = true;
3471             fmt       = IF_DI_1B;
3472             break;
3473
3474         case INS_mov:
3475             assert(isValidGeneralDatasize(size));
3476             assert(insOptsNone(opt)); // No explicit LSL here
3477             // We will automatically determine the shift based upon the imm
3478
3479             // First try the standard 'halfword immediate' imm(i16,hw)
3480             hwi.immHWVal = 0;
3481             canEncode    = canEncodeHalfwordImm(imm, size, &hwi);
3482             if (canEncode)
3483             {
3484                 // uses a movz encoding
3485                 assert(isGeneralRegister(reg));
3486                 imm = hwi.immHWVal;
3487                 assert(isValidImmHWVal(imm, size));
3488                 fmt = IF_DI_1B;
3489                 break;
3490             }
3491
3492             // Next try the ones-complement form of 'halfword immediate' imm(i16,hw)
3493             notOfImm  = NOT_helper(imm, getBitWidth(size));
3494             canEncode = canEncodeHalfwordImm(notOfImm, size, &hwi);
3495             if (canEncode)
3496             {
3497                 assert(isGeneralRegister(reg));
3498                 imm = hwi.immHWVal;
3499                 ins = INS_movn; // uses a movn encoding
3500                 assert(isValidImmHWVal(imm, size));
3501                 fmt = IF_DI_1B;
3502                 break;
3503             }
3504
3505             // Finally try the 'bitmask immediate' imm(N,r,s)
3506             bmi.immNRS = 0;
3507             canEncode  = canEncodeBitMaskImm(imm, size, &bmi);
3508             if (canEncode)
3509             {
3510                 assert(isGeneralRegisterOrSP(reg));
3511                 reg = encodingSPtoZR(reg);
3512                 imm = bmi.immNRS;
3513                 assert(isValidImmNRS(imm, size));
3514                 fmt = IF_DI_1D;
3515                 break;
3516             }
3517             else
3518             {
3519                 assert(!"Instruction cannot be encoded: mov imm");
3520             }
3521
3522             break;
3523
3524         case INS_movi:
3525             assert(isValidVectorDatasize(size));
3526             assert(isVectorRegister(reg));
3527             if (insOptsNone(opt) && (size == EA_8BYTE))
3528             {
3529                 opt = INS_OPTS_1D;
3530             }
3531             assert(isValidArrangement(size, opt));
3532             elemsize = optGetElemsize(opt);
3533
3534             if (elemsize == EA_8BYTE)
3535             {
3536                 size_t   uimm = imm;
3537                 ssize_t  imm8 = 0;
3538                 unsigned pos  = 0;
3539                 canEncode     = true;
3540                 bool failed   = false;
3541                 while (uimm != 0)
3542                 {
3543                     INT64 loByte = uimm & 0xFF;
3544                     if (((loByte == 0) || (loByte == 0xFF)) && (pos < 8))
3545                     {
3546                         if (loByte == 0xFF)
3547                         {
3548                             imm8 |= (1 << pos);
3549                         }
3550                         uimm >>= 8;
3551                         pos++;
3552                     }
3553                     else
3554                     {
3555                         canEncode = false;
3556                         break;
3557                     }
3558                 }
3559                 imm = imm8;
3560                 assert(isValidUimm8(imm));
3561                 fmt = IF_DV_1B;
3562                 break;
3563             }
3564             else
3565             {
3566                 // Vector operation
3567
3568                 // No explicit LSL/MSL is used for the immediate
3569                 // We will automatically determine the shift based upon the value of imm
3570
3571                 // First try the standard 'byteShifted immediate' imm(i8,bySh)
3572                 bsi.immBSVal = 0;
3573                 canEncode    = canEncodeByteShiftedImm(imm, elemsize, true, &bsi);
3574                 if (canEncode)
3575                 {
3576                     imm = bsi.immBSVal;
3577                     assert(isValidImmBSVal(imm, size));
3578                     fmt = IF_DV_1B;
3579                     break;
3580                 }
3581
3582                 // Next try the ones-complement form of the 'immediate' imm(i8,bySh)
3583                 if ((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE)) // Only EA_2BYTE or EA_4BYTE forms
3584                 {
3585                     notOfImm  = NOT_helper(imm, getBitWidth(elemsize));
3586                     canEncode = canEncodeByteShiftedImm(notOfImm, elemsize, true, &bsi);
3587                     if (canEncode)
3588                     {
3589                         imm = bsi.immBSVal;
3590                         ins = INS_mvni; // uses a mvni encoding
3591                         assert(isValidImmBSVal(imm, size));
3592                         fmt = IF_DV_1B;
3593                         break;
3594                     }
3595                 }
3596             }
3597             break;
3598
3599         case INS_orr:
3600         case INS_bic:
3601         case INS_mvni:
3602             assert(isValidVectorDatasize(size));
3603             assert(isVectorRegister(reg));
3604             assert(isValidArrangement(size, opt));
3605             elemsize = optGetElemsize(opt);
3606             assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE)); // Only EA_2BYTE or EA_4BYTE forms
3607
3608             // Vector operation
3609
3610             // No explicit LSL/MSL is used for the immediate
3611             // We will automatically determine the shift based upon the value of imm
3612
3613             // First try the standard 'byteShifted immediate' imm(i8,bySh)
3614             bsi.immBSVal = 0;
3615             canEncode    = canEncodeByteShiftedImm(imm, elemsize,
3616                                                 (ins == INS_mvni), // mvni supports the ones shifting variant (aka MSL)
3617                                                 &bsi);
3618             if (canEncode)
3619             {
3620                 imm = bsi.immBSVal;
3621                 assert(isValidImmBSVal(imm, size));
3622                 fmt = IF_DV_1B;
3623                 break;
3624             }
3625             break;
3626
3627         case INS_cmp:
3628         case INS_cmn:
3629             assert(insOptsNone(opt));
3630             assert(isGeneralRegister(reg));
3631
3632             if (unsigned_abs(imm) <= 0x0fff)
3633             {
3634                 if (imm < 0)
3635                 {
3636                     ins = insReverse(ins);
3637                     imm = -imm;
3638                 }
3639                 assert(isValidUimm12(imm));
3640                 canEncode = true;
3641                 fmt       = IF_DI_1A;
3642             }
3643             else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
3644             {
3645                 // Encoding will use a 12-bit left shift of the immediate
3646                 opt = INS_OPTS_LSL12;
3647                 if (imm < 0)
3648                 {
3649                     ins = insReverse(ins);
3650                     imm = -imm;
3651                 }
3652                 assert((imm & 0xfff) == 0);
3653                 imm >>= 12;
3654                 assert(isValidUimm12(imm));
3655                 canEncode = true;
3656                 fmt       = IF_DI_1A;
3657             }
3658             else
3659             {
3660                 assert(!"Instruction cannot be encoded: IF_DI_1A");
3661             }
3662             break;
3663
3664         default:
3665             unreached();
3666             break;
3667
3668     } // end switch (ins)
3669
3670     assert(canEncode);
3671     assert(fmt != IF_NONE);
3672
3673     instrDesc* id = emitNewInstrSC(attr, imm);
3674
3675     id->idIns(ins);
3676     id->idInsFmt(fmt);
3677     id->idInsOpt(opt);
3678
3679     id->idReg1(reg);
3680
3681     dispIns(id);
3682     appendToCurIG(id);
3683 }
3684
3685 /*****************************************************************************
3686  *
3687  *  Add an instruction referencing a register and a floating point constant.
3688  */
3689
3690 void emitter::emitIns_R_F(
3691     instruction ins, emitAttr attr, regNumber reg, double immDbl, insOpts opt /* = INS_OPTS_NONE */)
3692
3693 {
3694     emitAttr  size      = EA_SIZE(attr);
3695     emitAttr  elemsize  = EA_UNKNOWN;
3696     insFormat fmt       = IF_NONE;
3697     ssize_t   imm       = 0;
3698     bool      canEncode = false;
3699
3700     /* Figure out the encoding format of the instruction */
3701     switch (ins)
3702     {
3703         floatImm8 fpi;
3704
3705         case INS_fcmp:
3706         case INS_fcmpe:
3707             assert(insOptsNone(opt));
3708             assert(isValidVectorElemsizeFloat(size));
3709             assert(isVectorRegister(reg));
3710             if (immDbl == 0.0)
3711             {
3712                 canEncode = true;
3713                 fmt       = IF_DV_1C;
3714             }
3715             break;
3716
3717         case INS_fmov:
3718             assert(isVectorRegister(reg));
3719             fpi.immFPIVal = 0;
3720             canEncode     = canEncodeFloatImm8(immDbl, &fpi);
3721
3722             if (insOptsAnyArrangement(opt))
3723             {
3724                 // Vector operation
3725                 assert(isValidVectorDatasize(size));
3726                 assert(isValidArrangement(size, opt));
3727                 elemsize = optGetElemsize(opt);
3728                 assert(isValidVectorElemsizeFloat(elemsize));
3729                 assert(opt != INS_OPTS_1D); // Reserved encoding
3730
3731                 if (canEncode)
3732                 {
3733                     imm = fpi.immFPIVal;
3734                     assert((imm >= 0) && (imm <= 0xff));
3735                     fmt = IF_DV_1B;
3736                 }
3737             }
3738             else
3739             {
3740                 // Scalar operation
3741                 assert(insOptsNone(opt));
3742                 assert(isValidVectorElemsizeFloat(size));
3743
3744                 if (canEncode)
3745                 {
3746                     imm = fpi.immFPIVal;
3747                     assert((imm >= 0) && (imm <= 0xff));
3748                     fmt = IF_DV_1A;
3749                 }
3750             }
3751             break;
3752
3753         default:
3754             unreached();
3755             break;
3756
3757     } // end switch (ins)
3758
3759     assert(canEncode);
3760     assert(fmt != IF_NONE);
3761
3762     instrDesc* id = emitNewInstrSC(attr, imm);
3763
3764     id->idIns(ins);
3765     id->idInsFmt(fmt);
3766     id->idInsOpt(opt);
3767
3768     id->idReg1(reg);
3769
3770     dispIns(id);
3771     appendToCurIG(id);
3772 }
3773
3774 /*****************************************************************************
3775  *
3776  *  Add an instruction referencing two registers
3777  */
3778
3779 void emitter::emitIns_R_R(
3780     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insOpts opt /* = INS_OPTS_NONE */)
3781 {
3782     emitAttr  size     = EA_SIZE(attr);
3783     emitAttr  elemsize = EA_UNKNOWN;
3784     insFormat fmt      = IF_NONE;
3785
3786     /* Figure out the encoding format of the instruction */
3787     switch (ins)
3788     {
3789         case INS_mov:
3790             assert(insOptsNone(opt));
3791             // Is the mov even necessary?
3792             if (reg1 == reg2)
3793             {
3794                 // A mov with a EA_4BYTE has the side-effect of clearing the upper bits
3795                 // So only eliminate mov instructions that are not clearing the upper bits
3796                 //
3797                 if (isGeneralRegisterOrSP(reg1) && (size == EA_8BYTE))
3798                 {
3799                     return;
3800                 }
3801                 else if (isVectorRegister(reg1) && (size == EA_16BYTE))
3802                 {
3803                     return;
3804                 }
3805             }
3806
3807             // Check for the 'mov' aliases for the vector registers
3808             if (isVectorRegister(reg1))
3809             {
3810                 if (isVectorRegister(reg2) && isValidVectorDatasize(size))
3811                 {
3812                     return emitIns_R_R_R(INS_mov, size, reg1, reg2, reg2);
3813                 }
3814                 else
3815                 {
3816                     return emitIns_R_R_I(INS_mov, size, reg1, reg2, 0);
3817                 }
3818             }
3819             else
3820             {
3821                 if (isVectorRegister(reg2))
3822                 {
3823                     assert(isGeneralRegister(reg1));
3824                     return emitIns_R_R_I(INS_mov, size, reg1, reg2, 0);
3825                 }
3826             }
3827
3828             // Is this a MOV to/from SP instruction?
3829             if ((reg1 == REG_SP) || (reg2 == REG_SP))
3830             {
3831                 assert(isGeneralRegisterOrSP(reg1));
3832                 assert(isGeneralRegisterOrSP(reg2));
3833                 reg1 = encodingSPtoZR(reg1);
3834                 reg2 = encodingSPtoZR(reg2);
3835                 fmt  = IF_DR_2G;
3836             }
3837             else
3838             {
3839                 assert(insOptsNone(opt));
3840                 assert(isGeneralRegister(reg1));
3841                 assert(isGeneralRegisterOrZR(reg2));
3842                 fmt = IF_DR_2E;
3843             }
3844             break;
3845
3846         case INS_dup:
3847             // Vector operation
3848             assert(insOptsAnyArrangement(opt));
3849             assert(isVectorRegister(reg1));
3850             assert(isGeneralRegisterOrZR(reg2));
3851             assert(isValidVectorDatasize(size));
3852             assert(isValidArrangement(size, opt));
3853             fmt = IF_DV_2C;
3854             break;
3855
3856         case INS_abs:
3857         case INS_not:
3858             assert(isVectorRegister(reg1));
3859             assert(isVectorRegister(reg2));
3860             if (ins == INS_not)
3861             {
3862                 assert(isValidVectorDatasize(size));
3863                 // Bitwise behavior is independent of element size, but is always encoded as 1 Byte
3864                 opt = optMakeArrangement(size, EA_1BYTE);
3865             }
3866             if (insOptsNone(opt))
3867             {
3868                 // Scalar operation
3869                 assert(size == EA_8BYTE); // Only type D is supported
3870                 fmt = IF_DV_2L;
3871             }
3872             else
3873             {
3874                 // Vector operation
3875                 assert(insOptsAnyArrangement(opt));
3876                 assert(isValidVectorDatasize(size));
3877                 assert(isValidArrangement(size, opt));
3878                 elemsize = optGetElemsize(opt);
3879                 fmt      = IF_DV_2M;
3880             }
3881             break;
3882
3883         case INS_mvn:
3884         case INS_neg:
3885             if (isVectorRegister(reg1))
3886             {
3887                 assert(isVectorRegister(reg2));
3888                 if (ins == INS_mvn)
3889                 {
3890                     assert(isValidVectorDatasize(size));
3891                     // Bitwise behavior is independent of element size, but is always encoded as 1 Byte
3892                     opt = optMakeArrangement(size, EA_1BYTE);
3893                 }
3894                 if (insOptsNone(opt))
3895                 {
3896                     // Scalar operation
3897                     assert(size == EA_8BYTE); // Only type D is supported
3898                     fmt = IF_DV_2L;
3899                 }
3900                 else
3901                 {
3902                     // Vector operation
3903                     assert(isValidVectorDatasize(size));
3904                     assert(isValidArrangement(size, opt));
3905                     elemsize = optGetElemsize(opt);
3906                     fmt      = IF_DV_2M;
3907                 }
3908                 break;
3909             }
3910             __fallthrough;
3911
3912         case INS_negs:
3913             assert(insOptsNone(opt));
3914             assert(isGeneralRegister(reg1));
3915             assert(isGeneralRegisterOrZR(reg2));
3916             fmt = IF_DR_2E;
3917             break;
3918
3919         case INS_sxtw:
3920             assert(size == EA_8BYTE);
3921             __fallthrough;
3922
3923         case INS_sxtb:
3924         case INS_sxth:
3925         case INS_uxtb:
3926         case INS_uxth:
3927             assert(insOptsNone(opt));
3928             assert(isValidGeneralDatasize(size));
3929             assert(isGeneralRegister(reg1));
3930             assert(isGeneralRegister(reg2));
3931             fmt = IF_DR_2H;
3932             break;
3933
3934         case INS_sxtl:
3935         case INS_sxtl2:
3936         case INS_uxtl:
3937         case INS_uxtl2:
3938             return emitIns_R_R_I(ins, size, reg1, reg2, 0, opt);
3939
3940         case INS_cls:
3941         case INS_clz:
3942         case INS_rbit:
3943         case INS_rev16:
3944         case INS_rev32:
3945         case INS_cnt:
3946             if (isVectorRegister(reg1))
3947             {
3948                 assert(isVectorRegister(reg2));
3949                 assert(isValidVectorDatasize(size));
3950                 assert(isValidArrangement(size, opt));
3951                 elemsize = optGetElemsize(opt);
3952                 if ((ins == INS_cls) || (ins == INS_clz))
3953                 {
3954                     assert(elemsize != EA_8BYTE); // No encoding for type D
3955                 }
3956                 else if (ins == INS_rev32)
3957                 {
3958                     assert((elemsize == EA_2BYTE) || (elemsize == EA_1BYTE));
3959                 }
3960                 else
3961                 {
3962                     assert(elemsize == EA_1BYTE); // Only supports 8B or 16B
3963                 }
3964                 fmt = IF_DV_2M;
3965                 break;
3966             }
3967             if (ins == INS_cnt)
3968             {
3969                 // Doesn't have general register version(s)
3970                 break;
3971             }
3972
3973             __fallthrough;
3974
3975         case INS_rev:
3976             assert(insOptsNone(opt));
3977             assert(isGeneralRegister(reg1));
3978             assert(isGeneralRegister(reg2));
3979             if (ins == INS_rev32)
3980             {
3981                 assert(size == EA_8BYTE);
3982             }
3983             else
3984             {
3985                 assert(isValidGeneralDatasize(size));
3986             }
3987             fmt = IF_DR_2G;
3988             break;
3989
3990         case INS_addv:
3991         case INS_saddlv:
3992         case INS_smaxv:
3993         case INS_sminv:
3994         case INS_uaddlv:
3995         case INS_umaxv:
3996         case INS_uminv:
3997         case INS_rev64:
3998             assert(isVectorRegister(reg1));
3999             assert(isVectorRegister(reg2));
4000             assert(isValidVectorDatasize(size));
4001             assert(isValidArrangement(size, opt));
4002             elemsize = optGetElemsize(opt);
4003             assert(elemsize != EA_8BYTE); // No encoding for type D
4004             fmt = IF_DV_2M;
4005             break;
4006
4007         case INS_xtn:
4008         case INS_xtn2:
4009             assert(isVectorRegister(reg1));
4010             assert(isVectorRegister(reg2));
4011             assert(isValidVectorDatasize(size));
4012             assert(isValidArrangement(size, opt));
4013             elemsize = optGetElemsize(opt);
4014             // size is determined by instruction
4015             if (ins == INS_xtn)
4016             {
4017                 assert(size == EA_8BYTE);
4018             }
4019             else // ins == INS_xtn2
4020             {
4021                 assert(size == EA_16BYTE);
4022             }
4023             assert(elemsize != EA_8BYTE); // Narrowing must not end with 8 byte data
4024             fmt = IF_DV_2M;
4025             break;
4026
4027         case INS_ldar:
4028         case INS_ldaxr:
4029         case INS_ldxr:
4030         case INS_stlr:
4031             assert(isValidGeneralDatasize(size));
4032
4033             __fallthrough;
4034
4035         case INS_ldarb:
4036         case INS_ldaxrb:
4037         case INS_ldxrb:
4038         case INS_ldarh:
4039         case INS_ldaxrh:
4040         case INS_ldxrh:
4041         case INS_stlrb:
4042         case INS_stlrh:
4043             assert(isValidGeneralLSDatasize(size));
4044             assert(isGeneralRegisterOrZR(reg1));
4045             assert(isGeneralRegisterOrSP(reg2));
4046             assert(insOptsNone(opt));
4047
4048             reg2 = encodingSPtoZR(reg2);
4049
4050             fmt = IF_LS_2A;
4051             break;
4052
4053         case INS_ldr:
4054         case INS_ldrb:
4055         case INS_ldrh:
4056         case INS_ldrsb:
4057         case INS_ldrsh:
4058         case INS_ldrsw:
4059         case INS_str:
4060         case INS_strb:
4061         case INS_strh:
4062
4063         case INS_cmp:
4064         case INS_cmn:
4065         case INS_tst:
4066             assert(insOptsNone(opt));
4067             emitIns_R_R_I(ins, attr, reg1, reg2, 0, INS_OPTS_NONE);
4068             return;
4069
4070         case INS_staddb:
4071             emitIns_R_R_R(INS_ldaddb, attr, reg1, REG_ZR, reg2);
4072             return;
4073         case INS_staddlb:
4074             emitIns_R_R_R(INS_ldaddlb, attr, reg1, REG_ZR, reg2);
4075             return;
4076         case INS_staddh:
4077             emitIns_R_R_R(INS_ldaddh, attr, reg1, REG_ZR, reg2);
4078             return;
4079         case INS_staddlh:
4080             emitIns_R_R_R(INS_ldaddlh, attr, reg1, REG_ZR, reg2);
4081             return;
4082         case INS_stadd:
4083             emitIns_R_R_R(INS_ldadd, attr, reg1, REG_ZR, reg2);
4084             return;
4085         case INS_staddl:
4086             emitIns_R_R_R(INS_ldaddl, attr, reg1, REG_ZR, reg2);
4087             return;
4088
4089         case INS_fmov:
4090             assert(isValidVectorElemsizeFloat(size));
4091
4092             // Is the mov even necessary?
4093             if (reg1 == reg2)
4094             {
4095                 return;
4096             }
4097
4098             if (isVectorRegister(reg1))
4099             {
4100                 if (isVectorRegister(reg2))
4101                 {
4102                     assert(insOptsNone(opt));
4103                     fmt = IF_DV_2G;
4104                 }
4105                 else
4106                 {
4107                     assert(isGeneralRegister(reg2));
4108
4109                     // if the optional conversion specifier is not present we calculate it
4110                     if (opt == INS_OPTS_NONE)
4111                     {
4112                         opt = (size == EA_4BYTE) ? INS_OPTS_4BYTE_TO_S : INS_OPTS_8BYTE_TO_D;
4113                     }
4114                     assert(insOptsConvertIntToFloat(opt));
4115
4116                     fmt = IF_DV_2I;
4117                 }
4118             }
4119             else
4120             {
4121                 assert(isGeneralRegister(reg1));
4122                 assert(isVectorRegister(reg2));
4123
4124                 // if the optional conversion specifier is not present we calculate it
4125                 if (opt == INS_OPTS_NONE)
4126                 {
4127                     opt = (size == EA_4BYTE) ? INS_OPTS_S_TO_4BYTE : INS_OPTS_D_TO_8BYTE;
4128                 }
4129                 assert(insOptsConvertFloatToInt(opt));
4130
4131                 fmt = IF_DV_2H;
4132             }
4133             break;
4134
4135         case INS_fcmp:
4136         case INS_fcmpe:
4137             assert(insOptsNone(opt));
4138             assert(isValidVectorElemsizeFloat(size));
4139             assert(isVectorRegister(reg1));
4140             assert(isVectorRegister(reg2));
4141             fmt = IF_DV_2K;
4142             break;
4143
4144         case INS_fcvtns:
4145         case INS_fcvtnu:
4146         case INS_fcvtas:
4147         case INS_fcvtau:
4148         case INS_fcvtps:
4149         case INS_fcvtpu:
4150         case INS_fcvtms:
4151         case INS_fcvtmu:
4152         case INS_fcvtzs:
4153         case INS_fcvtzu:
4154             if (insOptsAnyArrangement(opt))
4155             {
4156                 // Vector operation
4157                 assert(isVectorRegister(reg1));
4158                 assert(isVectorRegister(reg2));
4159                 assert(isValidVectorDatasize(size));
4160                 assert(isValidArrangement(size, opt));
4161                 elemsize = optGetElemsize(opt);
4162                 assert(isValidVectorElemsizeFloat(elemsize));
4163                 assert(opt != INS_OPTS_1D); // Reserved encoding
4164                 fmt = IF_DV_2A;
4165             }
4166             else
4167             {
4168                 // Scalar operation
4169                 assert(isVectorRegister(reg2));
4170                 if (isVectorRegister(reg1))
4171                 {
4172                     assert(insOptsNone(opt));
4173                     assert(isValidVectorElemsizeFloat(size));
4174                     fmt = IF_DV_2G;
4175                 }
4176                 else
4177                 {
4178                     assert(isGeneralRegister(reg1));
4179                     assert(insOptsConvertFloatToInt(opt));
4180                     assert(isValidVectorElemsizeFloat(size));
4181                     fmt = IF_DV_2H;
4182                 }
4183             }
4184             break;
4185
4186         case INS_fcvtl:
4187         case INS_fcvtl2:
4188         case INS_fcvtn:
4189         case INS_fcvtn2:
4190             assert(isVectorRegister(reg1));
4191             assert(isVectorRegister(reg2));
4192             assert(isValidVectorDatasize(size));
4193             assert(insOptsNone(opt));
4194             assert(size == EA_8BYTE); // Narrowing from Double or Widening to Double (Half not supported)
4195             fmt = IF_DV_2G;
4196             break;
4197
4198         case INS_scvtf:
4199         case INS_ucvtf:
4200             if (insOptsAnyArrangement(opt))
4201             {
4202                 // Vector operation
4203                 assert(isVectorRegister(reg1));
4204                 assert(isVectorRegister(reg2));
4205                 assert(isValidVectorDatasize(size));
4206                 assert(isValidArrangement(size, opt));
4207                 elemsize = optGetElemsize(opt);
4208                 assert(isValidVectorElemsizeFloat(elemsize));
4209                 assert(opt != INS_OPTS_1D); // Reserved encoding
4210                 fmt = IF_DV_2A;
4211             }
4212             else
4213             {
4214                 // Scalar operation
4215                 assert(isVectorRegister(reg1));
4216                 if (isVectorRegister(reg2))
4217                 {
4218                     assert(insOptsNone(opt));
4219                     assert(isValidVectorElemsizeFloat(size));
4220                     fmt = IF_DV_2G;
4221                 }
4222                 else
4223                 {
4224                     assert(isGeneralRegister(reg2));
4225                     assert(insOptsConvertIntToFloat(opt));
4226                     assert(isValidVectorElemsizeFloat(size));
4227                     fmt = IF_DV_2I;
4228                 }
4229             }
4230             break;
4231
4232         case INS_fabs:
4233         case INS_fneg:
4234         case INS_fsqrt:
4235         case INS_frinta:
4236         case INS_frinti:
4237         case INS_frintm:
4238         case INS_frintn:
4239         case INS_frintp:
4240         case INS_frintx:
4241         case INS_frintz:
4242             if (insOptsAnyArrangement(opt))
4243             {
4244                 // Vector operation
4245                 assert(isVectorRegister(reg1));
4246                 assert(isVectorRegister(reg2));
4247                 assert(isValidVectorDatasize(size));
4248                 assert(isValidArrangement(size, opt));
4249                 elemsize = optGetElemsize(opt);
4250                 assert(isValidVectorElemsizeFloat(elemsize));
4251                 assert(opt != INS_OPTS_1D); // Reserved encoding
4252                 fmt = IF_DV_2A;
4253             }
4254             else
4255             {
4256                 // Scalar operation
4257                 assert(insOptsNone(opt));
4258                 assert(isValidVectorElemsizeFloat(size));
4259                 assert(isVectorRegister(reg1));
4260                 assert(isVectorRegister(reg2));
4261                 fmt = IF_DV_2G;
4262             }
4263             break;
4264
4265         case INS_faddp:
4266             // Scalar operation
4267             assert(insOptsNone(opt));
4268             assert(isValidVectorElemsizeFloat(size));
4269             assert(isVectorRegister(reg1));
4270             assert(isVectorRegister(reg2));
4271             fmt = IF_DV_2G;
4272             break;
4273
4274         case INS_fcvt:
4275             assert(insOptsConvertFloatToFloat(opt));
4276             assert(isValidVectorFcvtsize(size));
4277             assert(isVectorRegister(reg1));
4278             assert(isVectorRegister(reg2));
4279             fmt = IF_DV_2J;
4280             break;
4281
4282         case INS_cmeq:
4283         case INS_cmge:
4284         case INS_cmgt:
4285         case INS_cmle:
4286         case INS_cmlt:
4287             assert(isVectorRegister(reg1));
4288             assert(isVectorRegister(reg2));
4289
4290             if (isValidVectorDatasize(size))
4291             {
4292                 // Vector operation
4293                 assert(insOptsAnyArrangement(opt));
4294                 assert(isValidArrangement(size, opt));
4295                 elemsize = optGetElemsize(opt);
4296                 fmt      = IF_DV_2M;
4297             }
4298             else
4299             {
4300                 NYI("Untested");
4301                 // Scalar operation
4302                 assert(size == EA_8BYTE); // Only Double supported
4303                 fmt = IF_DV_2L;
4304             }
4305             break;
4306
4307         case INS_fcmeq:
4308         case INS_fcmge:
4309         case INS_fcmgt:
4310         case INS_fcmle:
4311         case INS_fcmlt:
4312             assert(isVectorRegister(reg1));
4313             assert(isVectorRegister(reg2));
4314
4315             if (isValidVectorDatasize(size))
4316             {
4317                 // Vector operation
4318                 assert(insOptsAnyArrangement(opt));
4319                 assert(isValidArrangement(size, opt));
4320                 elemsize = optGetElemsize(opt);
4321                 assert((elemsize == EA_8BYTE) || (elemsize == EA_4BYTE)); // Only Double/Float supported
4322                 assert(opt != INS_OPTS_1D);                               // Reserved encoding
4323                 fmt = IF_DV_2A;
4324             }
4325             else
4326             {
4327                 NYI("Untested");
4328                 // Scalar operation
4329                 assert((size == EA_8BYTE) || (size == EA_4BYTE)); // Only Double/Float supported
4330                 fmt = IF_DV_2G;
4331             }
4332             break;
4333         case INS_aesd:
4334         case INS_aese:
4335         case INS_aesmc:
4336         case INS_aesimc:
4337             assert(isVectorRegister(reg1));
4338             assert(isVectorRegister(reg2));
4339             assert(isValidVectorDatasize(size));
4340             elemsize = optGetElemsize(opt);
4341             assert(elemsize == EA_1BYTE);
4342             fmt = IF_DV_2P;
4343             break;
4344
4345         case INS_sha1h:
4346             assert(insOptsNone(opt));
4347             assert(isVectorRegister(reg1));
4348             assert(isVectorRegister(reg2));
4349             fmt = IF_DR_2J;
4350             break;
4351
4352         case INS_sha256su0:
4353         case INS_sha1su1:
4354             assert(isVectorRegister(reg1));
4355             assert(isVectorRegister(reg2));
4356             assert(isValidVectorDatasize(size));
4357             elemsize = optGetElemsize(opt);
4358             assert(elemsize == EA_4BYTE);
4359             fmt = IF_DV_2P;
4360             break;
4361
4362         default:
4363             unreached();
4364             break;
4365
4366     } // end switch (ins)
4367
4368     assert(fmt != IF_NONE);
4369
4370     instrDesc* id = emitNewInstrSmall(attr);
4371
4372     id->idIns(ins);
4373     id->idInsFmt(fmt);
4374     id->idInsOpt(opt);
4375
4376     id->idReg1(reg1);
4377     id->idReg2(reg2);
4378
4379     dispIns(id);
4380     appendToCurIG(id);
4381 }
4382
4383 /*****************************************************************************
4384  *
4385  *  Add an instruction referencing a register and two constants.
4386  */
4387
4388 void emitter::emitIns_R_I_I(
4389     instruction ins, emitAttr attr, regNumber reg, ssize_t imm1, ssize_t imm2, insOpts opt /* = INS_OPTS_NONE */)
4390 {
4391     emitAttr  size   = EA_SIZE(attr);
4392     insFormat fmt    = IF_NONE;
4393     size_t    immOut = 0; // composed from imm1 and imm2 and stored in the instrDesc
4394
4395     /* Figure out the encoding format of the instruction */
4396     switch (ins)
4397     {
4398         bool        canEncode;
4399         halfwordImm hwi;
4400
4401         case INS_mov:
4402             ins = INS_movz; // INS_mov with LSL is an alias for INS_movz LSL
4403             __fallthrough;
4404
4405         case INS_movk:
4406         case INS_movn:
4407         case INS_movz:
4408             assert(isValidGeneralDatasize(size));
4409             assert(isGeneralRegister(reg));
4410             assert(isValidUimm16(imm1));
4411             assert(insOptsLSL(opt)); // Must be INS_OPTS_LSL
4412
4413             if (size == EA_8BYTE)
4414             {
4415                 assert((imm2 == 0) || (imm2 == 16) || // shift amount: 0, 16, 32 or 48
4416                        (imm2 == 32) || (imm2 == 48));
4417             }
4418             else // EA_4BYTE
4419             {
4420                 assert((imm2 == 0) || (imm2 == 16)); // shift amount: 0 or 16
4421             }
4422
4423             hwi.immHWVal = 0;
4424
4425             switch (imm2)
4426             {
4427                 case 0:
4428                     hwi.immHW = 0;
4429                     canEncode = true;
4430                     break;
4431
4432                 case 16:
4433                     hwi.immHW = 1;
4434                     canEncode = true;
4435                     break;
4436
4437                 case 32:
4438                     hwi.immHW = 2;
4439                     canEncode = true;
4440                     break;
4441
4442                 case 48:
4443                     hwi.immHW = 3;
4444                     canEncode = true;
4445                     break;
4446
4447                 default:
4448                     canEncode = false;
4449             }
4450
4451             if (canEncode)
4452             {
4453                 hwi.immVal = imm1;
4454
4455                 immOut = hwi.immHWVal;
4456                 assert(isValidImmHWVal(immOut, size));
4457                 fmt = IF_DI_1B;
4458             }
4459             break;
4460
4461         default:
4462             unreached();
4463             break;
4464
4465     } // end switch (ins)
4466
4467     assert(fmt != IF_NONE);
4468
4469     instrDesc* id = emitNewInstrSC(attr, immOut);
4470
4471     id->idIns(ins);
4472     id->idInsFmt(fmt);
4473
4474     id->idReg1(reg);
4475
4476     dispIns(id);
4477     appendToCurIG(id);
4478 }
4479
4480 /*****************************************************************************
4481  *
4482  *  Add an instruction referencing two registers and a constant.
4483  */
4484
4485 void emitter::emitIns_R_R_I(
4486     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm, insOpts opt /* = INS_OPTS_NONE */)
4487 {
4488     emitAttr  size       = EA_SIZE(attr);
4489     emitAttr  elemsize   = EA_UNKNOWN;
4490     insFormat fmt        = IF_NONE;
4491     bool      isLdSt     = false;
4492     bool      isSIMD     = false;
4493     bool      isAddSub   = false;
4494     bool      setFlags   = false;
4495     unsigned  scale      = 0;
4496     bool      unscaledOp = false;
4497
4498     /* Figure out the encoding format of the instruction */
4499     switch (ins)
4500     {
4501         bool       canEncode;
4502         bitMaskImm bmi;
4503
4504         case INS_mov:
4505             // Check for the 'mov' aliases for the vector registers
4506             assert(insOptsNone(opt));
4507             assert(isValidVectorElemsize(size));
4508             elemsize = size;
4509             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4510
4511             if (isVectorRegister(reg1))
4512             {
4513                 if (isGeneralRegisterOrZR(reg2))
4514                 {
4515                     fmt = IF_DV_2C; // Alias for 'ins'
4516                     break;
4517                 }
4518                 else if (isVectorRegister(reg2))
4519                 {
4520                     fmt = IF_DV_2E; // Alias for 'dup'
4521                     break;
4522                 }
4523             }
4524             else // isGeneralRegister(reg1)
4525             {
4526                 assert(isGeneralRegister(reg1));
4527                 if (isVectorRegister(reg2))
4528                 {
4529                     fmt = IF_DV_2B; // Alias for 'umov'
4530                     break;
4531                 }
4532             }
4533             assert(!" invalid INS_mov operands");
4534             break;
4535
4536         case INS_lsl:
4537         case INS_lsr:
4538         case INS_asr:
4539             assert(insOptsNone(opt));
4540             assert(isValidGeneralDatasize(size));
4541             assert(isGeneralRegister(reg1));
4542             assert(isGeneralRegister(reg2));
4543             assert(isValidImmShift(imm, size));
4544             fmt = IF_DI_2D;
4545             break;
4546
4547         case INS_ror:
4548             assert(insOptsNone(opt));
4549             assert(isValidGeneralDatasize(size));
4550             assert(isGeneralRegister(reg1));
4551             assert(isGeneralRegister(reg2));
4552             assert(isValidImmShift(imm, size));
4553             fmt = IF_DI_2B;
4554             break;
4555
4556         case INS_sshr:
4557         case INS_ssra:
4558         case INS_srshr:
4559         case INS_srsra:
4560         case INS_shl:
4561         case INS_ushr:
4562         case INS_usra:
4563         case INS_urshr:
4564         case INS_ursra:
4565         case INS_sri:
4566         case INS_sli:
4567             assert(isVectorRegister(reg1));
4568             assert(isVectorRegister(reg2));
4569             if (insOptsAnyArrangement(opt))
4570             {
4571                 // Vector operation
4572                 assert(isValidVectorDatasize(size));
4573                 assert(isValidArrangement(size, opt));
4574                 elemsize = optGetElemsize(opt);
4575                 assert(isValidVectorElemsize(elemsize));
4576                 assert(isValidImmShift(imm, elemsize));
4577                 assert(opt != INS_OPTS_1D); // Reserved encoding
4578                 fmt = IF_DV_2O;
4579                 break;
4580             }
4581             else
4582             {
4583                 // Scalar operation
4584                 assert(insOptsNone(opt));
4585                 assert(size == EA_8BYTE); // only supported size
4586                 assert(isValidImmShift(imm, size));
4587                 fmt = IF_DV_2N;
4588             }
4589             break;
4590
4591         case INS_sxtl:
4592         case INS_uxtl:
4593             assert(imm == 0);
4594             __fallthrough;
4595
4596         case INS_shrn:
4597         case INS_rshrn:
4598         case INS_sshll:
4599         case INS_ushll:
4600             assert(isVectorRegister(reg1));
4601             assert(isVectorRegister(reg2));
4602             // Vector operation
4603             assert(size == EA_8BYTE);
4604             assert(isValidArrangement(size, opt));
4605             elemsize = optGetElemsize(opt);
4606             assert(elemsize != EA_8BYTE); // Reserved encodings
4607             assert(isValidVectorElemsize(elemsize));
4608             assert(isValidImmShift(imm, elemsize));
4609             fmt = IF_DV_2O;
4610             break;
4611
4612         case INS_sxtl2:
4613         case INS_uxtl2:
4614             assert(imm == 0);
4615             __fallthrough;
4616
4617         case INS_shrn2:
4618         case INS_rshrn2:
4619         case INS_sshll2:
4620         case INS_ushll2:
4621             assert(isVectorRegister(reg1));
4622             assert(isVectorRegister(reg2));
4623             // Vector operation
4624             assert(size == EA_16BYTE);
4625             assert(isValidArrangement(size, opt));
4626             elemsize = optGetElemsize(opt);
4627             assert(elemsize != EA_8BYTE); // Reserved encodings
4628             assert(isValidVectorElemsize(elemsize));
4629             assert(isValidImmShift(imm, elemsize));
4630             fmt = IF_DV_2O;
4631             break;
4632
4633         case INS_mvn:
4634         case INS_neg:
4635         case INS_negs:
4636             assert(isValidGeneralDatasize(size));
4637             assert(isGeneralRegister(reg1));
4638             assert(isGeneralRegisterOrZR(reg2));
4639
4640             if (imm == 0)
4641             {
4642                 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4643
4644                 fmt = IF_DR_2E;
4645             }
4646             else
4647             {
4648                 if (ins == INS_mvn)
4649                 {
4650                     assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
4651                 }
4652                 else // neg or negs
4653                 {
4654                     assert(insOptsAluShift(opt)); // a non-zero imm, must select shift kind, can't use ROR
4655                 }
4656                 assert(isValidImmShift(imm, size));
4657                 fmt = IF_DR_2F;
4658             }
4659             break;
4660
4661         case INS_tst:
4662             assert(isValidGeneralDatasize(size));
4663             assert(isGeneralRegisterOrZR(reg1));
4664             assert(isGeneralRegister(reg2));
4665
4666             if (insOptsAnyShift(opt))
4667             {
4668                 assert(isValidImmShift(imm, size) && (imm != 0));
4669                 fmt = IF_DR_2B;
4670             }
4671             else
4672             {
4673                 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4674                 assert(imm == 0);
4675                 fmt = IF_DR_2A;
4676             }
4677             break;
4678
4679         case INS_cmp:
4680         case INS_cmn:
4681             assert(isValidGeneralDatasize(size));
4682             assert(isGeneralRegisterOrSP(reg1));
4683             assert(isGeneralRegister(reg2));
4684
4685             reg1 = encodingSPtoZR(reg1);
4686             if (insOptsAnyExtend(opt))
4687             {
4688                 assert((imm >= 0) && (imm <= 4));
4689
4690                 fmt = IF_DR_2C;
4691             }
4692             else if (imm == 0)
4693             {
4694                 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4695
4696                 fmt = IF_DR_2A;
4697             }
4698             else
4699             {
4700                 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
4701                 assert(isValidImmShift(imm, size));
4702                 fmt = IF_DR_2B;
4703             }
4704             break;
4705
4706         case INS_ands:
4707         case INS_and:
4708         case INS_eor:
4709         case INS_orr:
4710             assert(insOptsNone(opt));
4711             assert(isGeneralRegister(reg2));
4712             if (ins == INS_ands)
4713             {
4714                 assert(isGeneralRegister(reg1));
4715             }
4716             else
4717             {
4718                 assert(isGeneralRegisterOrSP(reg1));
4719                 reg1 = encodingSPtoZR(reg1);
4720             }
4721
4722             bmi.immNRS = 0;
4723             canEncode  = canEncodeBitMaskImm(imm, size, &bmi);
4724             if (canEncode)
4725             {
4726                 imm = bmi.immNRS;
4727                 assert(isValidImmNRS(imm, size));
4728                 fmt = IF_DI_2C;
4729             }
4730             break;
4731
4732         case INS_dup: // by element, imm selects the element of reg2
4733             assert(isVectorRegister(reg1));
4734             if (isVectorRegister(reg2))
4735             {
4736                 if (insOptsAnyArrangement(opt))
4737                 {
4738                     // Vector operation
4739                     assert(isValidVectorDatasize(size));
4740                     assert(isValidArrangement(size, opt));
4741                     elemsize = optGetElemsize(opt);
4742                     assert(isValidVectorElemsize(elemsize));
4743                     assert(isValidVectorIndex(size, elemsize, imm));
4744                     assert(opt != INS_OPTS_1D); // Reserved encoding
4745                     fmt = IF_DV_2D;
4746                     break;
4747                 }
4748                 else
4749                 {
4750                     // Scalar operation
4751                     assert(insOptsNone(opt));
4752                     elemsize = size;
4753                     assert(isValidVectorElemsize(elemsize));
4754                     assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4755                     fmt = IF_DV_2E;
4756                     break;
4757                 }
4758             }
4759             __fallthrough;
4760
4761         case INS_ins: // (MOV from general)
4762             assert(insOptsNone(opt));
4763             assert(isValidVectorElemsize(size));
4764             assert(isVectorRegister(reg1));
4765             assert(isGeneralRegisterOrZR(reg2));
4766             elemsize = size;
4767             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4768             fmt = IF_DV_2C;
4769             break;
4770
4771         case INS_umov: // (MOV to general)
4772             assert(insOptsNone(opt));
4773             assert(isValidVectorElemsize(size));
4774             assert(isGeneralRegister(reg1));
4775             assert(isVectorRegister(reg2));
4776             elemsize = size;
4777             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4778             fmt = IF_DV_2B;
4779             break;
4780
4781         case INS_smov:
4782             assert(insOptsNone(opt));
4783             assert(isValidVectorElemsize(size));
4784             assert(size != EA_8BYTE); // no encoding, use INS_umov
4785             assert(isGeneralRegister(reg1));
4786             assert(isVectorRegister(reg2));
4787             elemsize = size;
4788             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4789             fmt = IF_DV_2B;
4790             break;
4791
4792         case INS_add:
4793         case INS_sub:
4794             setFlags = false;
4795             isAddSub = true;
4796             break;
4797
4798         case INS_adds:
4799         case INS_subs:
4800             setFlags = true;
4801             isAddSub = true;
4802             break;
4803
4804         case INS_ldrsb:
4805         case INS_ldursb:
4806             // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4807             assert(isValidGeneralDatasize(size));
4808             unscaledOp = (ins == INS_ldursb);
4809             scale      = 0;
4810             isLdSt     = true;
4811             break;
4812
4813         case INS_ldrsh:
4814         case INS_ldursh:
4815             // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4816             assert(isValidGeneralDatasize(size));
4817             unscaledOp = (ins == INS_ldursh);
4818             scale      = 1;
4819             isLdSt     = true;
4820             break;
4821
4822         case INS_ldrsw:
4823         case INS_ldursw:
4824             // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4825             assert(size == EA_8BYTE);
4826             unscaledOp = (ins == INS_ldursw);
4827             scale      = 2;
4828             isLdSt     = true;
4829             break;
4830
4831         case INS_ldrb:
4832         case INS_strb:
4833             // size is ignored
4834             unscaledOp = false;
4835             scale      = 0;
4836             isLdSt     = true;
4837             break;
4838
4839         case INS_ldurb:
4840         case INS_sturb:
4841             // size is ignored
4842             unscaledOp = true;
4843             scale      = 0;
4844             isLdSt     = true;
4845             break;
4846
4847         case INS_ldrh:
4848         case INS_strh:
4849             // size is ignored
4850             unscaledOp = false;
4851             scale      = 1;
4852             isLdSt     = true;
4853             break;
4854
4855         case INS_ldurh:
4856         case INS_sturh:
4857             // size is ignored
4858             unscaledOp = true;
4859             scale      = 0;
4860             isLdSt     = true;
4861             break;
4862
4863         case INS_ldr:
4864         case INS_str:
4865             // Is the target a vector register?
4866             if (isVectorRegister(reg1))
4867             {
4868                 assert(isValidVectorLSDatasize(size));
4869                 assert(isGeneralRegisterOrSP(reg2));
4870                 isSIMD = true;
4871             }
4872             else
4873             {
4874                 assert(isValidGeneralDatasize(size));
4875             }
4876             unscaledOp = false;
4877             scale      = NaturalScale_helper(size);
4878             isLdSt     = true;
4879             break;
4880
4881         case INS_ldur:
4882         case INS_stur:
4883             // Is the target a vector register?
4884             if (isVectorRegister(reg1))
4885             {
4886                 assert(isValidVectorLSDatasize(size));
4887                 assert(isGeneralRegisterOrSP(reg2));
4888                 isSIMD = true;
4889             }
4890             else
4891             {
4892                 assert(isValidGeneralDatasize(size));
4893             }
4894             unscaledOp = true;
4895             scale      = 0;
4896             isLdSt     = true;
4897             break;
4898
4899         default:
4900             unreached();
4901             break;
4902
4903     } // end switch (ins)
4904
4905     if (isLdSt)
4906     {
4907         assert(!isAddSub);
4908
4909         if (isSIMD)
4910         {
4911             assert(isValidVectorLSDatasize(size));
4912             assert(isVectorRegister(reg1));
4913             assert((scale >= 0) && (scale <= 4));
4914         }
4915         else
4916         {
4917             assert(isValidGeneralLSDatasize(size));
4918             assert(isGeneralRegisterOrZR(reg1));
4919             assert((scale >= 0) && (scale <= 3));
4920         }
4921
4922         assert(isGeneralRegisterOrSP(reg2));
4923
4924         // Load/Store reserved encodings:
4925         if (insOptsIndexed(opt))
4926         {
4927             assert(reg1 != reg2);
4928         }
4929
4930         reg2 = encodingSPtoZR(reg2);
4931
4932         ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
4933         if (imm == 0)
4934         {
4935             assert(insOptsNone(opt)); // PRE/POST Index doesn't make sense with an immediate of zero
4936
4937             fmt = IF_LS_2A;
4938         }
4939         else if (insOptsIndexed(opt) || unscaledOp || (imm < 0) || ((imm & mask) != 0))
4940         {
4941             if ((imm >= -256) && (imm <= 255))
4942             {
4943                 fmt = IF_LS_2C;
4944             }
4945             else
4946             {
4947                 assert(!"Instruction cannot be encoded: IF_LS_2C");
4948             }
4949         }
4950         else if (imm > 0)
4951         {
4952             assert(insOptsNone(opt));
4953             assert(!unscaledOp);
4954
4955             if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
4956             {
4957                 imm >>= scale; // The immediate is scaled by the size of the ld/st
4958
4959                 fmt = IF_LS_2B;
4960             }
4961             else
4962             {
4963                 assert(!"Instruction cannot be encoded: IF_LS_2B");
4964             }
4965         }
4966     }
4967     else if (isAddSub)
4968     {
4969         assert(!isLdSt);
4970         assert(insOptsNone(opt));
4971
4972         if (setFlags) // Can't encode SP with setFlags
4973         {
4974             assert(isGeneralRegister(reg1));
4975             assert(isGeneralRegister(reg2));
4976         }
4977         else
4978         {
4979             assert(isGeneralRegisterOrSP(reg1));
4980             assert(isGeneralRegisterOrSP(reg2));
4981
4982             // Is it just a mov?
4983             if (imm == 0)
4984             {
4985                 // Is the mov even necessary?
4986                 if (reg1 != reg2)
4987                 {
4988                     emitIns_R_R(INS_mov, attr, reg1, reg2);
4989                 }
4990                 return;
4991             }
4992
4993             reg1 = encodingSPtoZR(reg1);
4994             reg2 = encodingSPtoZR(reg2);
4995         }
4996
4997         if (unsigned_abs(imm) <= 0x0fff)
4998         {
4999             if (imm < 0)
5000             {
5001                 ins = insReverse(ins);
5002                 imm = -imm;
5003             }
5004             assert(isValidUimm12(imm));
5005             fmt = IF_DI_2A;
5006         }
5007         else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
5008         {
5009             // Encoding will use a 12-bit left shift of the immediate
5010             opt = INS_OPTS_LSL12;
5011             if (imm < 0)
5012             {
5013                 ins = insReverse(ins);
5014                 imm = -imm;
5015             }
5016             assert((imm & 0xfff) == 0);
5017             imm >>= 12;
5018             assert(isValidUimm12(imm));
5019             fmt = IF_DI_2A;
5020         }
5021         else
5022         {
5023             assert(!"Instruction cannot be encoded: IF_DI_2A");
5024         }
5025     }
5026
5027     assert(fmt != IF_NONE);
5028
5029     instrDesc* id = emitNewInstrSC(attr, imm);
5030
5031     id->idIns(ins);
5032     id->idInsFmt(fmt);
5033     id->idInsOpt(opt);
5034
5035     id->idReg1(reg1);
5036     id->idReg2(reg2);
5037
5038     dispIns(id);
5039     appendToCurIG(id);
5040 }
5041
5042 /*****************************************************************************
5043 *
5044 *  Add an instruction referencing two registers and a constant.
5045 *  Also checks for a large immediate that needs a second instruction
5046 *  and will load it in reg1
5047 *
5048 *  - Supports instructions: add, adds, sub, subs, and, ands, eor and orr
5049 *  - Requires that reg1 is a general register and not SP or ZR
5050 *  - Requires that reg1 != reg2
5051 */
5052 void emitter::emitIns_R_R_Imm(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm)
5053 {
5054     assert(isGeneralRegister(reg1));
5055     assert(reg1 != reg2);
5056
5057     bool immFits = true;
5058
5059     switch (ins)
5060     {
5061         case INS_add:
5062         case INS_adds:
5063         case INS_sub:
5064         case INS_subs:
5065             immFits = emitter::emitIns_valid_imm_for_add(imm, attr);
5066             break;
5067
5068         case INS_ands:
5069         case INS_and:
5070         case INS_eor:
5071         case INS_orr:
5072             immFits = emitter::emitIns_valid_imm_for_alu(imm, attr);
5073             break;
5074
5075         default:
5076             assert(!"Unsupported instruction in emitIns_R_R_Imm");
5077     }
5078
5079     if (immFits)
5080     {
5081         emitIns_R_R_I(ins, attr, reg1, reg2, imm);
5082     }
5083     else
5084     {
5085         // Load 'imm' into the reg1 register
5086         // then issue:   'ins'  reg1, reg2, reg1
5087         //
5088         codeGen->instGen_Set_Reg_To_Imm(attr, reg1, imm);
5089         emitIns_R_R_R(ins, attr, reg1, reg2, reg1);
5090     }
5091 }
5092
5093 /*****************************************************************************
5094  *
5095  *  Add an instruction referencing three registers.
5096  */
5097
5098 void emitter::emitIns_R_R_R(
5099     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insOpts opt) /* = INS_OPTS_NONE */
5100 {
5101     emitAttr  size     = EA_SIZE(attr);
5102     emitAttr  elemsize = EA_UNKNOWN;
5103     insFormat fmt      = IF_NONE;
5104
5105     /* Figure out the encoding format of the instruction */
5106     switch (ins)
5107     {
5108         case INS_lsl:
5109         case INS_lsr:
5110         case INS_asr:
5111         case INS_ror:
5112         case INS_adc:
5113         case INS_adcs:
5114         case INS_sbc:
5115         case INS_sbcs:
5116         case INS_udiv:
5117         case INS_sdiv:
5118         case INS_mneg:
5119         case INS_smull:
5120         case INS_smnegl:
5121         case INS_smulh:
5122         case INS_umull:
5123         case INS_umnegl:
5124         case INS_umulh:
5125         case INS_lslv:
5126         case INS_lsrv:
5127         case INS_asrv:
5128         case INS_rorv:
5129             assert(insOptsNone(opt));
5130             assert(isValidGeneralDatasize(size));
5131             assert(isGeneralRegister(reg1));
5132             assert(isGeneralRegister(reg2));
5133             assert(isGeneralRegister(reg3));
5134             fmt = IF_DR_3A;
5135             break;
5136
5137         case INS_mul:
5138             if (insOptsNone(opt))
5139             {
5140                 // general register
5141                 assert(isValidGeneralDatasize(size));
5142                 assert(isGeneralRegister(reg1));
5143                 assert(isGeneralRegister(reg2));
5144                 assert(isGeneralRegister(reg3));
5145                 fmt = IF_DR_3A;
5146                 break;
5147             }
5148             __fallthrough;
5149
5150         case INS_mla:
5151         case INS_mls:
5152         case INS_pmul:
5153             assert(insOptsAnyArrangement(opt));
5154             assert(isVectorRegister(reg1));
5155             assert(isVectorRegister(reg2));
5156             assert(isVectorRegister(reg3));
5157             assert(isValidVectorDatasize(size));
5158             assert(isValidArrangement(size, opt));
5159             elemsize = optGetElemsize(opt);
5160             if (ins == INS_pmul)
5161             {
5162                 assert(elemsize == EA_1BYTE); // only supports 8B or 16B
5163             }
5164             else // INS_mul, INS_mla, INS_mls
5165             {
5166                 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
5167             }
5168             fmt = IF_DV_3A;
5169             break;
5170
5171         case INS_add:
5172         case INS_sub:
5173             if (isVectorRegister(reg1))
5174             {
5175                 assert(isVectorRegister(reg2));
5176                 assert(isVectorRegister(reg3));
5177
5178                 if (insOptsAnyArrangement(opt))
5179                 {
5180                     // Vector operation
5181                     assert(opt != INS_OPTS_1D); // Reserved encoding
5182                     assert(isValidVectorDatasize(size));
5183                     assert(isValidArrangement(size, opt));
5184                     fmt = IF_DV_3A;
5185                 }
5186                 else
5187                 {
5188                     // Scalar operation
5189                     assert(insOptsNone(opt));
5190                     assert(size == EA_8BYTE);
5191                     fmt = IF_DV_3E;
5192                 }
5193                 break;
5194             }
5195             __fallthrough;
5196
5197         case INS_adds:
5198         case INS_subs:
5199             emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, INS_OPTS_NONE);
5200             return;
5201
5202         case INS_cmeq:
5203         case INS_cmge:
5204         case INS_cmgt:
5205         case INS_cmhi:
5206         case INS_cmhs:
5207         case INS_ctst:
5208             assert(isVectorRegister(reg1));
5209             assert(isVectorRegister(reg2));
5210             assert(isVectorRegister(reg3));
5211
5212             if (isValidVectorDatasize(size))
5213             {
5214                 // Vector operation
5215                 assert(insOptsAnyArrangement(opt));
5216                 assert(isValidArrangement(size, opt));
5217                 elemsize = optGetElemsize(opt);
5218                 fmt      = IF_DV_3A;
5219             }
5220             else
5221             {
5222                 NYI("Untested");
5223                 // Scalar operation
5224                 assert(size == EA_8BYTE); // Only Double supported
5225                 fmt = IF_DV_3E;
5226             }
5227             break;
5228
5229         case INS_fcmeq:
5230         case INS_fcmge:
5231         case INS_fcmgt:
5232             assert(isVectorRegister(reg1));
5233             assert(isVectorRegister(reg2));
5234             assert(isVectorRegister(reg3));
5235
5236             if (isValidVectorDatasize(size))
5237             {
5238                 // Vector operation
5239                 assert(insOptsAnyArrangement(opt));
5240                 assert(isValidArrangement(size, opt));
5241                 elemsize = optGetElemsize(opt);
5242                 assert((elemsize == EA_8BYTE) || (elemsize == EA_4BYTE)); // Only Double/Float supported
5243                 assert(opt != INS_OPTS_1D);                               // Reserved encoding
5244                 fmt = IF_DV_3B;
5245             }
5246             else
5247             {
5248                 NYI("Untested");
5249                 // Scalar operation
5250                 assert((size == EA_8BYTE) || (size == EA_4BYTE)); // Only Double/Float supported
5251                 fmt = IF_DV_3D;
5252             }
5253             break;
5254
5255         case INS_saba:
5256         case INS_sabd:
5257         case INS_smax:
5258         case INS_smin:
5259         case INS_uaba:
5260         case INS_uabd:
5261         case INS_umax:
5262         case INS_umin:
5263             assert(isVectorRegister(reg1));
5264             assert(isVectorRegister(reg2));
5265             assert(isVectorRegister(reg3));
5266             assert(insOptsAnyArrangement(opt));
5267
5268             // Vector operation
5269             assert(isValidVectorDatasize(size));
5270             assert(isValidArrangement(size, opt));
5271             elemsize = optGetElemsize(opt);
5272             assert(elemsize != EA_8BYTE); // can't use 2D or 1D
5273
5274             fmt = IF_DV_3A;
5275             break;
5276
5277         case INS_mov:
5278             assert(isVectorRegister(reg1));
5279             assert(isVectorRegister(reg2));
5280             assert(reg2 == reg3);
5281             assert(isValidVectorDatasize(size));
5282             // INS_mov is an alias for INS_orr (vector register)
5283             if (opt == INS_OPTS_NONE)
5284             {
5285                 elemsize = EA_1BYTE;
5286                 opt      = optMakeArrangement(size, elemsize);
5287             }
5288             assert(isValidArrangement(size, opt));
5289             fmt = IF_DV_3C;
5290             break;
5291
5292         case INS_and:
5293         case INS_bic:
5294         case INS_eor:
5295         case INS_orr:
5296         case INS_orn:
5297             if (isVectorRegister(reg1))
5298             {
5299                 assert(isValidVectorDatasize(size));
5300                 assert(isVectorRegister(reg2));
5301                 assert(isVectorRegister(reg3));
5302                 if (opt == INS_OPTS_NONE)
5303                 {
5304                     elemsize = EA_1BYTE;
5305                     opt      = optMakeArrangement(size, elemsize);
5306                 }
5307                 assert(isValidArrangement(size, opt));
5308                 fmt = IF_DV_3C;
5309                 break;
5310             }
5311             __fallthrough;
5312
5313         case INS_ands:
5314         case INS_bics:
5315         case INS_eon:
5316             emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, INS_OPTS_NONE);
5317             return;
5318
5319         case INS_bsl:
5320         case INS_bit:
5321         case INS_bif:
5322             assert(isValidVectorDatasize(size));
5323             assert(isVectorRegister(reg1));
5324             assert(isVectorRegister(reg2));
5325             assert(isVectorRegister(reg3));
5326             if (opt == INS_OPTS_NONE)
5327             {
5328                 elemsize = EA_1BYTE;
5329                 opt      = optMakeArrangement(size, elemsize);
5330             }
5331             assert(isValidArrangement(size, opt));
5332             fmt = IF_DV_3C;
5333             break;
5334
5335         case INS_fadd:
5336         case INS_fsub:
5337         case INS_fdiv:
5338         case INS_fmax:
5339         case INS_fmin:
5340         case INS_fabd:
5341         case INS_fmul:
5342         case INS_fmulx:
5343             assert(isVectorRegister(reg1));
5344             assert(isVectorRegister(reg2));
5345             assert(isVectorRegister(reg3));
5346             if (insOptsAnyArrangement(opt))
5347             {
5348                 // Vector operation
5349                 assert(isValidVectorDatasize(size));
5350                 assert(isValidArrangement(size, opt));
5351                 elemsize = optGetElemsize(opt);
5352                 assert(isValidVectorElemsizeFloat(elemsize));
5353                 assert(opt != INS_OPTS_1D); // Reserved encoding
5354                 fmt = IF_DV_3B;
5355             }
5356             else
5357             {
5358                 // Scalar operation
5359                 assert(insOptsNone(opt));
5360                 assert(isValidScalarDatasize(size));
5361                 fmt = IF_DV_3D;
5362             }
5363             break;
5364
5365         case INS_fnmul:
5366             // Scalar operation
5367             assert(insOptsNone(opt));
5368             assert(isVectorRegister(reg1));
5369             assert(isVectorRegister(reg2));
5370             assert(isVectorRegister(reg3));
5371             assert(isValidScalarDatasize(size));
5372             fmt = IF_DV_3D;
5373             break;
5374
5375         case INS_faddp:
5376         case INS_fmla:
5377         case INS_fmls:
5378             assert(isVectorRegister(reg1));
5379             assert(isVectorRegister(reg2));
5380             assert(isVectorRegister(reg3));
5381             assert(insOptsAnyArrangement(opt)); // no scalar encoding, use 4-operand 'fmadd' or 'fmsub'
5382
5383             // Vector operation
5384             assert(isValidVectorDatasize(size));
5385             assert(isValidArrangement(size, opt));
5386             elemsize = optGetElemsize(opt);
5387             assert(isValidVectorElemsizeFloat(elemsize));
5388             assert(opt != INS_OPTS_1D); // Reserved encoding
5389             fmt = IF_DV_3B;
5390             break;
5391
5392         case INS_ldr:
5393         case INS_ldrb:
5394         case INS_ldrh:
5395         case INS_ldrsb:
5396         case INS_ldrsh:
5397         case INS_ldrsw:
5398         case INS_str:
5399         case INS_strb:
5400         case INS_strh:
5401             emitIns_R_R_R_Ext(ins, attr, reg1, reg2, reg3, opt);
5402             return;
5403
5404         case INS_ldp:
5405         case INS_ldpsw:
5406         case INS_ldnp:
5407         case INS_stp:
5408         case INS_stnp:
5409             emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0);
5410             return;
5411
5412         case INS_stxr:
5413         case INS_stxrb:
5414         case INS_stxrh:
5415         case INS_stlxr:
5416         case INS_stlxrb:
5417         case INS_stlxrh:
5418             assert(isGeneralRegisterOrZR(reg1));
5419             assert(isGeneralRegisterOrZR(reg2));
5420             assert(isGeneralRegisterOrSP(reg3));
5421             fmt = IF_LS_3D;
5422             break;
5423
5424         case INS_casb:
5425         case INS_casab:
5426         case INS_casalb:
5427         case INS_caslb:
5428         case INS_cash:
5429         case INS_casah:
5430         case INS_casalh:
5431         case INS_caslh:
5432         case INS_cas:
5433         case INS_casa:
5434         case INS_casal:
5435         case INS_casl:
5436         case INS_ldaddb:
5437         case INS_ldaddab:
5438         case INS_ldaddalb:
5439         case INS_ldaddlb:
5440         case INS_ldaddh:
5441         case INS_ldaddah:
5442         case INS_ldaddalh:
5443         case INS_ldaddlh:
5444         case INS_ldadd:
5445         case INS_ldadda:
5446         case INS_ldaddal:
5447         case INS_ldaddl:
5448         case INS_swpb:
5449         case INS_swpab:
5450         case INS_swpalb:
5451         case INS_swplb:
5452         case INS_swph:
5453         case INS_swpah:
5454         case INS_swpalh:
5455         case INS_swplh:
5456         case INS_swp:
5457         case INS_swpa:
5458         case INS_swpal:
5459         case INS_swpl:
5460             assert(isGeneralRegisterOrZR(reg1));
5461             assert(isGeneralRegisterOrZR(reg2));
5462             assert(isGeneralRegisterOrSP(reg3));
5463             fmt = IF_LS_3E;
5464             break;
5465
5466         case INS_sha256h:
5467         case INS_sha256h2:
5468         case INS_sha256su1:
5469         case INS_sha1su0:
5470         case INS_sha1c:
5471         case INS_sha1p:
5472         case INS_sha1m:
5473             assert(isValidVectorDatasize(size));
5474             assert(isVectorRegister(reg1));
5475             assert(isVectorRegister(reg2));
5476             assert(isVectorRegister(reg3));
5477             if (opt == INS_OPTS_NONE)
5478             {
5479                 elemsize = EA_4BYTE;
5480                 opt      = optMakeArrangement(size, elemsize);
5481             }
5482             assert(isValidArrangement(size, opt));
5483             fmt = IF_DV_3F;
5484             break;
5485
5486         default:
5487             unreached();
5488             break;
5489
5490     } // end switch (ins)
5491
5492     assert(fmt != IF_NONE);
5493
5494     instrDesc* id = emitNewInstr(attr);
5495
5496     id->idIns(ins);
5497     id->idInsFmt(fmt);
5498     id->idInsOpt(opt);
5499
5500     id->idReg1(reg1);
5501     id->idReg2(reg2);
5502     id->idReg3(reg3);
5503
5504     dispIns(id);
5505     appendToCurIG(id);
5506 }
5507
5508 /*****************************************************************************
5509  *
5510  *  Add an instruction referencing three registers and a constant.
5511  */
5512
5513 void emitter::emitIns_R_R_R_I(instruction ins,
5514                               emitAttr    attr,
5515                               regNumber   reg1,
5516                               regNumber   reg2,
5517                               regNumber   reg3,
5518                               ssize_t     imm,
5519                               insOpts     opt /* = INS_OPTS_NONE */,
5520                               emitAttr    attrReg2 /* = EA_UNKNOWN */)
5521 {
5522     emitAttr  size     = EA_SIZE(attr);
5523     emitAttr  elemsize = EA_UNKNOWN;
5524     insFormat fmt      = IF_NONE;
5525     bool      isLdSt   = false;
5526     bool      isSIMD   = false;
5527     bool      isAddSub = false;
5528     bool      setFlags = false;
5529     unsigned  scale    = 0;
5530
5531     /* Figure out the encoding format of the instruction */
5532     switch (ins)
5533     {
5534         case INS_extr:
5535             assert(insOptsNone(opt));
5536             assert(isValidGeneralDatasize(size));
5537             assert(isGeneralRegister(reg1));
5538             assert(isGeneralRegister(reg2));
5539             assert(isGeneralRegister(reg3));
5540             assert(isValidImmShift(imm, size));
5541             fmt = IF_DR_3E;
5542             break;
5543
5544         case INS_and:
5545         case INS_ands:
5546         case INS_eor:
5547         case INS_orr:
5548         case INS_bic:
5549         case INS_bics:
5550         case INS_eon:
5551         case INS_orn:
5552             assert(isValidGeneralDatasize(size));
5553             assert(isGeneralRegister(reg1));
5554             assert(isGeneralRegister(reg2));
5555             assert(isGeneralRegister(reg3));
5556             assert(isValidImmShift(imm, size));
5557             if (imm == 0)
5558             {
5559                 assert(insOptsNone(opt)); // a zero imm, means no shift kind
5560                 fmt = IF_DR_3A;
5561             }
5562             else
5563             {
5564                 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
5565                 fmt = IF_DR_3B;
5566             }
5567             break;
5568
5569         case INS_fmul: // by element, imm[0..3] selects the element of reg3
5570         case INS_fmla:
5571         case INS_fmls:
5572         case INS_fmulx:
5573             assert(isVectorRegister(reg1));
5574             assert(isVectorRegister(reg2));
5575             assert(isVectorRegister(reg3));
5576             if (insOptsAnyArrangement(opt))
5577             {
5578                 // Vector operation
5579                 assert(isValidVectorDatasize(size));
5580                 assert(isValidArrangement(size, opt));
5581                 elemsize = optGetElemsize(opt);
5582                 assert(isValidVectorElemsizeFloat(elemsize));
5583                 assert(isValidVectorIndex(size, elemsize, imm));
5584                 assert(opt != INS_OPTS_1D); // Reserved encoding
5585                 fmt = IF_DV_3BI;
5586             }
5587             else
5588             {
5589                 // Scalar operation
5590                 assert(insOptsNone(opt));
5591                 assert(isValidScalarDatasize(size));
5592                 elemsize = size;
5593                 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
5594                 fmt = IF_DV_3DI;
5595             }
5596             break;
5597
5598         case INS_mul: // by element, imm[0..7] selects the element of reg3
5599         case INS_mla:
5600         case INS_mls:
5601             assert(isVectorRegister(reg1));
5602             assert(isVectorRegister(reg2));
5603             assert(isVectorRegister(reg3));
5604             // Vector operation
5605             assert(insOptsAnyArrangement(opt));
5606             assert(isValidVectorDatasize(size));
5607             assert(isValidArrangement(size, opt));
5608             elemsize = optGetElemsize(opt);
5609             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
5610             // Only has encodings for H or S elemsize
5611             assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE));
5612             // Only has encodings for V0..V15
5613             if ((elemsize == EA_2BYTE) && (reg3 >= REG_V16))
5614             {
5615                 noway_assert(!"Invalid reg3");
5616             }
5617             fmt = IF_DV_3AI;
5618             break;
5619
5620         case INS_add:
5621         case INS_sub:
5622             setFlags = false;
5623             isAddSub = true;
5624             break;
5625
5626         case INS_adds:
5627         case INS_subs:
5628             setFlags = true;
5629             isAddSub = true;
5630             break;
5631
5632         case INS_ldpsw:
5633             scale  = 2;
5634             isLdSt = true;
5635             break;
5636
5637         case INS_ldnp:
5638         case INS_stnp:
5639             assert(insOptsNone(opt)); // Can't use Pre/Post index on these two instructions
5640             __fallthrough;
5641
5642         case INS_ldp:
5643         case INS_stp:
5644             // Is the target a vector register?
5645             if (isVectorRegister(reg1))
5646             {
5647                 scale  = NaturalScale_helper(size);
5648                 isSIMD = true;
5649             }
5650             else
5651             {
5652                 scale = (size == EA_8BYTE) ? 3 : 2;
5653             }
5654             isLdSt = true;
5655             break;
5656
5657         default:
5658             unreached();
5659             break;
5660
5661     } // end switch (ins)
5662
5663     if (isLdSt)
5664     {
5665         assert(!isAddSub);
5666         assert(isGeneralRegisterOrSP(reg3));
5667         assert(insOptsNone(opt) || insOptsIndexed(opt));
5668
5669         if (isSIMD)
5670         {
5671             assert(isValidVectorLSPDatasize(size));
5672             assert(isVectorRegister(reg1));
5673             assert(isVectorRegister(reg2));
5674             assert((scale >= 2) && (scale <= 4));
5675         }
5676         else
5677         {
5678             assert(isValidGeneralDatasize(size));
5679             assert(isGeneralRegisterOrZR(reg1));
5680             assert(isGeneralRegisterOrZR(reg2));
5681             assert((scale == 2) || (scale == 3));
5682         }
5683
5684         // Load/Store Pair reserved encodings:
5685         if (emitInsIsLoad(ins))
5686         {
5687             assert(reg1 != reg2);
5688         }
5689         if (insOptsIndexed(opt))
5690         {
5691             assert(reg1 != reg3);
5692             assert(reg2 != reg3);
5693         }
5694
5695         reg3 = encodingSPtoZR(reg3);
5696
5697         ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
5698         if (imm == 0)
5699         {
5700             assert(insOptsNone(opt)); // PRE/POST Index doesn't make sense with an immediate of zero
5701
5702             fmt = IF_LS_3B;
5703         }
5704         else
5705         {
5706             if ((imm & mask) == 0)
5707             {
5708                 imm >>= scale; // The immediate is scaled by the size of the ld/st
5709
5710                 if ((imm >= -64) && (imm <= 63))
5711                 {
5712                     fmt = IF_LS_3C;
5713                 }
5714             }
5715 #ifdef DEBUG
5716             if (fmt != IF_LS_3C)
5717             {
5718                 assert(!"Instruction cannot be encoded: IF_LS_3C");
5719             }
5720 #endif
5721         }
5722     }
5723     else if (isAddSub)
5724     {
5725         bool reg2IsSP = (reg2 == REG_SP);
5726         assert(!isLdSt);
5727         assert(isValidGeneralDatasize(size));
5728         assert(isGeneralRegister(reg3));
5729
5730         if (setFlags || insOptsAluShift(opt)) // Can't encode SP in reg1 with setFlags or AluShift option
5731         {
5732             assert(isGeneralRegisterOrZR(reg1));
5733         }
5734         else
5735         {
5736             assert(isGeneralRegisterOrSP(reg1));
5737             reg1 = encodingSPtoZR(reg1);
5738         }
5739
5740         if (insOptsAluShift(opt)) // Can't encode SP in reg2 with AluShift option
5741         {
5742             assert(isGeneralRegister(reg2));
5743         }
5744         else
5745         {
5746             assert(isGeneralRegisterOrSP(reg2));
5747             reg2 = encodingSPtoZR(reg2);
5748         }
5749
5750         if (insOptsAnyExtend(opt))
5751         {
5752             assert((imm >= 0) && (imm <= 4));
5753
5754             fmt = IF_DR_3C;
5755         }
5756         else if (insOptsAluShift(opt))
5757         {
5758             // imm should be non-zero and in [1..63]
5759             assert(isValidImmShift(imm, size) && (imm != 0));
5760             fmt = IF_DR_3B;
5761         }
5762         else if (imm == 0)
5763         {
5764             assert(insOptsNone(opt));
5765
5766             if (reg2IsSP)
5767             {
5768                 // To encode the SP register as reg2 we must use the IF_DR_3C encoding
5769                 // and also specify a LSL of zero (imm == 0)
5770                 opt = INS_OPTS_LSL;
5771                 fmt = IF_DR_3C;
5772             }
5773             else
5774             {
5775                 fmt = IF_DR_3A;
5776             }
5777         }
5778         else
5779         {
5780             assert(!"Instruction cannot be encoded: Add/Sub IF_DR_3A");
5781         }
5782     }
5783     assert(fmt != IF_NONE);
5784
5785     instrDesc* id = emitNewInstrCns(attr, imm);
5786
5787     id->idIns(ins);
5788     id->idInsFmt(fmt);
5789     id->idInsOpt(opt);
5790
5791     id->idReg1(reg1);
5792     id->idReg2(reg2);
5793     id->idReg3(reg3);
5794
5795     // Record the attribute for the second register in the pair
5796     id->idGCrefReg2(GCT_NONE);
5797     if (attrReg2 != EA_UNKNOWN)
5798     {
5799         // Record the attribute for the second register in the pair
5800         assert((fmt == IF_LS_3B) || (fmt == IF_LS_3C));
5801         if (EA_IS_GCREF(attrReg2))
5802         {
5803             id->idGCrefReg2(GCT_GCREF);
5804         }
5805         else if (EA_IS_BYREF(attrReg2))
5806         {
5807             id->idGCrefReg2(GCT_BYREF);
5808         }
5809     }
5810
5811     dispIns(id);
5812     appendToCurIG(id);
5813 }
5814
5815 /*****************************************************************************
5816  *
5817  *  Add an instruction referencing three registers, with an extend option
5818  */
5819
5820 void emitter::emitIns_R_R_R_Ext(instruction ins,
5821                                 emitAttr    attr,
5822                                 regNumber   reg1,
5823                                 regNumber   reg2,
5824                                 regNumber   reg3,
5825                                 insOpts     opt,         /* = INS_OPTS_NONE */
5826                                 int         shiftAmount) /* = -1 -- unset   */
5827 {
5828     emitAttr  size   = EA_SIZE(attr);
5829     insFormat fmt    = IF_NONE;
5830     bool      isSIMD = false;
5831     int       scale  = -1;
5832
5833     /* Figure out the encoding format of the instruction */
5834     switch (ins)
5835     {
5836         case INS_ldrb:
5837         case INS_ldrsb:
5838         case INS_strb:
5839             scale = 0;
5840             break;
5841
5842         case INS_ldrh:
5843         case INS_ldrsh:
5844         case INS_strh:
5845             scale = 1;
5846             break;
5847
5848         case INS_ldrsw:
5849             scale = 2;
5850             break;
5851
5852         case INS_ldr:
5853         case INS_str:
5854             // Is the target a vector register?
5855             if (isVectorRegister(reg1))
5856             {
5857                 assert(isValidVectorLSDatasize(size));
5858                 scale  = NaturalScale_helper(size);
5859                 isSIMD = true;
5860             }
5861             else
5862             {
5863                 assert(isValidGeneralDatasize(size));
5864                 scale = (size == EA_8BYTE) ? 3 : 2;
5865             }
5866
5867             break;
5868
5869         default:
5870             unreached();
5871             break;
5872
5873     } // end switch (ins)
5874
5875     assert(scale != -1);
5876     assert(insOptsLSExtend(opt));
5877
5878     if (isSIMD)
5879     {
5880         assert(isValidVectorLSDatasize(size));
5881         assert(isVectorRegister(reg1));
5882     }
5883     else
5884     {
5885         assert(isValidGeneralLSDatasize(size));
5886         assert(isGeneralRegisterOrZR(reg1));
5887     }
5888
5889     assert(isGeneralRegisterOrSP(reg2));
5890     assert(isGeneralRegister(reg3));
5891
5892     // Load/Store reserved encodings:
5893     if (insOptsIndexed(opt))
5894     {
5895         assert(reg1 != reg2);
5896     }
5897
5898     if (shiftAmount == -1)
5899     {
5900         shiftAmount = insOptsLSL(opt) ? scale : 0;
5901     }
5902     assert((shiftAmount == scale) || (shiftAmount == 0));
5903
5904     reg2 = encodingSPtoZR(reg2);
5905     fmt  = IF_LS_3A;
5906
5907     instrDesc* id = emitNewInstr(attr);
5908
5909     id->idIns(ins);
5910     id->idInsFmt(fmt);
5911     id->idInsOpt(opt);
5912
5913     id->idReg1(reg1);
5914     id->idReg2(reg2);
5915     id->idReg3(reg3);
5916     id->idReg3Scaled(shiftAmount == scale);
5917
5918     dispIns(id);
5919     appendToCurIG(id);
5920 }
5921
5922 /*****************************************************************************
5923  *
5924  *  Add an instruction referencing two registers and two constants.
5925  */
5926
5927 void emitter::emitIns_R_R_I_I(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, int imm1, int imm2)
5928 {
5929     emitAttr  size     = EA_SIZE(attr);
5930     emitAttr  elemsize = EA_UNKNOWN;
5931     insFormat fmt      = IF_NONE;
5932     size_t    immOut   = 0; // composed from imm1 and imm2 and stored in the instrDesc
5933
5934     /* Figure out the encoding format of the instruction */
5935     switch (ins)
5936     {
5937         int        lsb;
5938         int        width;
5939         bitMaskImm bmi;
5940
5941         case INS_bfm:
5942         case INS_sbfm:
5943         case INS_ubfm:
5944             assert(isGeneralRegister(reg1));
5945             assert(isGeneralRegister(reg2));
5946             assert(isValidImmShift(imm1, size));
5947             assert(isValidImmShift(imm2, size));
5948             bmi.immNRS = 0;
5949             bmi.immN   = (size == EA_8BYTE);
5950             bmi.immR   = imm1;
5951             bmi.immS   = imm2;
5952             immOut     = bmi.immNRS;
5953             fmt        = IF_DI_2D;
5954             break;
5955
5956         case INS_bfi:
5957         case INS_sbfiz:
5958         case INS_ubfiz:
5959             assert(isGeneralRegister(reg1));
5960             assert(isGeneralRegister(reg2));
5961             lsb   = getBitWidth(size) - imm1;
5962             width = imm2 - 1;
5963             assert(isValidImmShift(lsb, size));
5964             assert(isValidImmShift(width, size));
5965             bmi.immNRS = 0;
5966             bmi.immN   = (size == EA_8BYTE);
5967             bmi.immR   = lsb;
5968             bmi.immS   = width;
5969             immOut     = bmi.immNRS;
5970             fmt        = IF_DI_2D;
5971             break;
5972
5973         case INS_bfxil:
5974         case INS_sbfx:
5975         case INS_ubfx:
5976             assert(isGeneralRegister(reg1));
5977             assert(isGeneralRegister(reg2));
5978             lsb   = imm1;
5979             width = imm2 + imm1 - 1;
5980             assert(isValidImmShift(lsb, size));
5981             assert(isValidImmShift(width, size));
5982             bmi.immNRS = 0;
5983             bmi.immN   = (size == EA_8BYTE);
5984             bmi.immR   = imm1;
5985             bmi.immS   = imm2 + imm1 - 1;
5986             immOut     = bmi.immNRS;
5987             fmt        = IF_DI_2D;
5988             break;
5989
5990         case INS_mov:
5991         case INS_ins:
5992             assert(isVectorRegister(reg1));
5993             assert(isVectorRegister(reg2));
5994             elemsize = size;
5995             assert(isValidVectorElemsize(elemsize));
5996             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm1));
5997             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm2));
5998             immOut = (imm1 << 4) + imm2;
5999             fmt    = IF_DV_2F;
6000             break;
6001
6002         default:
6003             unreached();
6004             break;
6005     }
6006     assert(fmt != IF_NONE);
6007
6008     instrDesc* id = emitNewInstrSC(attr, immOut);
6009
6010     id->idIns(ins);
6011     id->idInsFmt(fmt);
6012
6013     id->idReg1(reg1);
6014     id->idReg2(reg2);
6015
6016     dispIns(id);
6017     appendToCurIG(id);
6018 }
6019
6020 /*****************************************************************************
6021  *
6022  *  Add an instruction referencing four registers.
6023  */
6024
6025 void emitter::emitIns_R_R_R_R(
6026     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, regNumber reg4)
6027 {
6028     emitAttr  size = EA_SIZE(attr);
6029     insFormat fmt  = IF_NONE;
6030
6031     /* Figure out the encoding format of the instruction */
6032     switch (ins)
6033     {
6034         case INS_madd:
6035         case INS_msub:
6036         case INS_smaddl:
6037         case INS_smsubl:
6038         case INS_umaddl:
6039         case INS_umsubl:
6040             assert(isValidGeneralDatasize(size));
6041             assert(isGeneralRegister(reg1));
6042             assert(isGeneralRegister(reg2));
6043             assert(isGeneralRegister(reg3));
6044             assert(isGeneralRegister(reg4));
6045             fmt = IF_DR_4A;
6046             break;
6047
6048         case INS_fmadd:
6049         case INS_fmsub:
6050         case INS_fnmadd:
6051         case INS_fnmsub:
6052             // Scalar operation
6053             assert(isValidScalarDatasize(size));
6054             assert(isVectorRegister(reg1));
6055             assert(isVectorRegister(reg2));
6056             assert(isVectorRegister(reg3));
6057             assert(isVectorRegister(reg4));
6058             fmt = IF_DV_4A;
6059             break;
6060
6061         case INS_invalid:
6062             fmt = IF_NONE;
6063             break;
6064
6065         default:
6066             unreached();
6067             break;
6068     }
6069     assert(fmt != IF_NONE);
6070
6071     instrDesc* id = emitNewInstr(attr);
6072
6073     id->idIns(ins);
6074     id->idInsFmt(fmt);
6075
6076     id->idReg1(reg1);
6077     id->idReg2(reg2);
6078     id->idReg3(reg3);
6079     id->idReg4(reg4);
6080
6081     dispIns(id);
6082     appendToCurIG(id);
6083 }
6084
6085 /*****************************************************************************
6086  *
6087  *  Add an instruction referencing a register and a condition code
6088  */
6089
6090 void emitter::emitIns_R_COND(instruction ins, emitAttr attr, regNumber reg, insCond cond)
6091 {
6092     emitAttr     size = EA_SIZE(attr);
6093     insFormat    fmt  = IF_NONE;
6094     condFlagsImm cfi;
6095     cfi.immCFVal = 0;
6096
6097     /* Figure out the encoding format of the instruction */
6098     switch (ins)
6099     {
6100         case INS_cset:
6101         case INS_csetm:
6102             assert(isGeneralRegister(reg));
6103             cfi.cond = cond;
6104             fmt      = IF_DR_1D;
6105             break;
6106
6107         default:
6108             unreached();
6109             break;
6110
6111     } // end switch (ins)
6112
6113     assert(fmt != IF_NONE);
6114     assert(isValidImmCond(cfi.immCFVal));
6115
6116     instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6117
6118     id->idIns(ins);
6119     id->idInsFmt(fmt);
6120     id->idInsOpt(INS_OPTS_NONE);
6121
6122     id->idReg1(reg);
6123
6124     dispIns(id);
6125     appendToCurIG(id);
6126 }
6127
6128 /*****************************************************************************
6129  *
6130  *  Add an instruction referencing two registers and a condition code
6131  */
6132
6133 void emitter::emitIns_R_R_COND(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insCond cond)
6134 {
6135     emitAttr     size = EA_SIZE(attr);
6136     insFormat    fmt  = IF_NONE;
6137     condFlagsImm cfi;
6138     cfi.immCFVal = 0;
6139
6140     /* Figure out the encoding format of the instruction */
6141     switch (ins)
6142     {
6143         case INS_cinc:
6144         case INS_cinv:
6145         case INS_cneg:
6146             assert(isGeneralRegister(reg1));
6147             assert(isGeneralRegister(reg2));
6148             cfi.cond = cond;
6149             fmt      = IF_DR_2D;
6150             break;
6151         default:
6152             unreached();
6153             break;
6154
6155     } // end switch (ins)
6156
6157     assert(fmt != IF_NONE);
6158     assert(isValidImmCond(cfi.immCFVal));
6159
6160     instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6161
6162     id->idIns(ins);
6163     id->idInsFmt(fmt);
6164     id->idInsOpt(INS_OPTS_NONE);
6165
6166     id->idReg1(reg1);
6167     id->idReg2(reg2);
6168
6169     dispIns(id);
6170     appendToCurIG(id);
6171 }
6172
6173 /*****************************************************************************
6174  *
6175  *  Add an instruction referencing two registers and a condition code
6176  */
6177
6178 void emitter::emitIns_R_R_R_COND(
6179     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insCond cond)
6180 {
6181     emitAttr     size = EA_SIZE(attr);
6182     insFormat    fmt  = IF_NONE;
6183     condFlagsImm cfi;
6184     cfi.immCFVal = 0;
6185
6186     /* Figure out the encoding format of the instruction */
6187     switch (ins)
6188     {
6189         case INS_csel:
6190         case INS_csinc:
6191         case INS_csinv:
6192         case INS_csneg:
6193             assert(isGeneralRegister(reg1));
6194             assert(isGeneralRegister(reg2));
6195             assert(isGeneralRegister(reg3));
6196             cfi.cond = cond;
6197             fmt      = IF_DR_3D;
6198             break;
6199
6200         default:
6201             unreached();
6202             break;
6203
6204     } // end switch (ins)
6205
6206     assert(fmt != IF_NONE);
6207     assert(isValidImmCond(cfi.immCFVal));
6208
6209     instrDesc* id = emitNewInstr(attr);
6210
6211     id->idIns(ins);
6212     id->idInsFmt(fmt);
6213     id->idInsOpt(INS_OPTS_NONE);
6214
6215     id->idReg1(reg1);
6216     id->idReg2(reg2);
6217     id->idReg3(reg3);
6218     id->idSmallCns(cfi.immCFVal);
6219
6220     dispIns(id);
6221     appendToCurIG(id);
6222 }
6223
6224 /*****************************************************************************
6225  *
6226  *  Add an instruction referencing two registers the flags and a condition code
6227  */
6228
6229 void emitter::emitIns_R_R_FLAGS_COND(
6230     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insCflags flags, insCond cond)
6231 {
6232     emitAttr     size = EA_SIZE(attr);
6233     insFormat    fmt  = IF_NONE;
6234     condFlagsImm cfi;
6235     cfi.immCFVal = 0;
6236
6237     /* Figure out the encoding format of the instruction */
6238     switch (ins)
6239     {
6240         case INS_ccmp:
6241         case INS_ccmn:
6242             assert(isGeneralRegister(reg1));
6243             assert(isGeneralRegister(reg2));
6244             cfi.flags = flags;
6245             cfi.cond  = cond;
6246             fmt       = IF_DR_2I;
6247             break;
6248         default:
6249             unreached();
6250             break;
6251     } // end switch (ins)
6252
6253     assert(fmt != IF_NONE);
6254     assert(isValidImmCondFlags(cfi.immCFVal));
6255
6256     instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6257
6258     id->idIns(ins);
6259     id->idInsFmt(fmt);
6260     id->idInsOpt(INS_OPTS_NONE);
6261
6262     id->idReg1(reg1);
6263     id->idReg2(reg2);
6264
6265     dispIns(id);
6266     appendToCurIG(id);
6267 }
6268
6269 /*****************************************************************************
6270  *
6271  *  Add an instruction referencing a register, an immediate, the flags and a condition code
6272  */
6273
6274 void emitter::emitIns_R_I_FLAGS_COND(
6275     instruction ins, emitAttr attr, regNumber reg, int imm, insCflags flags, insCond cond)
6276 {
6277     emitAttr     size = EA_SIZE(attr);
6278     insFormat    fmt  = IF_NONE;
6279     condFlagsImm cfi;
6280     cfi.immCFVal = 0;
6281
6282     /* Figure out the encoding format of the instruction */
6283     switch (ins)
6284     {
6285         case INS_ccmp:
6286         case INS_ccmn:
6287             assert(isGeneralRegister(reg));
6288             if (imm < 0)
6289             {
6290                 ins = insReverse(ins);
6291                 imm = -imm;
6292             }
6293             if ((imm >= 0) && (imm <= 31))
6294             {
6295                 cfi.imm5  = imm;
6296                 cfi.flags = flags;
6297                 cfi.cond  = cond;
6298                 fmt       = IF_DI_1F;
6299             }
6300             else
6301             {
6302                 assert(!"Instruction cannot be encoded: ccmp/ccmn imm5");
6303             }
6304             break;
6305         default:
6306             unreached();
6307             break;
6308     } // end switch (ins)
6309
6310     assert(fmt != IF_NONE);
6311     assert(isValidImmCondFlagsImm5(cfi.immCFVal));
6312
6313     instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6314
6315     id->idIns(ins);
6316     id->idInsFmt(fmt);
6317     id->idInsOpt(INS_OPTS_NONE);
6318
6319     id->idReg1(reg);
6320
6321     dispIns(id);
6322     appendToCurIG(id);
6323 }
6324
6325 /*****************************************************************************
6326  *
6327  *  Add a memory barrier instruction with a 'barrier' immediate
6328  */
6329
6330 void emitter::emitIns_BARR(instruction ins, insBarrier barrier)
6331 {
6332     insFormat fmt = IF_NONE;
6333     ssize_t   imm = 0;
6334
6335     /* Figure out the encoding format of the instruction */
6336     switch (ins)
6337     {
6338         case INS_dsb:
6339         case INS_dmb:
6340         case INS_isb:
6341
6342             fmt = IF_SI_0B;
6343             imm = (ssize_t)barrier;
6344             break;
6345         default:
6346             unreached();
6347             break;
6348     } // end switch (ins)
6349
6350     assert(fmt != IF_NONE);
6351
6352     instrDesc* id = emitNewInstrSC(EA_8BYTE, imm);
6353
6354     id->idIns(ins);
6355     id->idInsFmt(fmt);
6356     id->idInsOpt(INS_OPTS_NONE);
6357
6358     dispIns(id);
6359     appendToCurIG(id);
6360 }
6361
6362 /*****************************************************************************
6363  *
6364  *  Add an instruction with a static data member operand. If 'size' is 0, the
6365  *  instruction operates on the address of the static member instead of its
6366  *  value (e.g. "push offset clsvar", rather than "push dword ptr [clsvar]").
6367  */
6368
6369 void emitter::emitIns_C(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, int offs)
6370 {
6371     NYI("emitIns_C");
6372 }
6373
6374 /*****************************************************************************
6375  *
6376  *  Add an instruction referencing stack-based local variable.
6377  */
6378
6379 void emitter::emitIns_S(instruction ins, emitAttr attr, int varx, int offs)
6380 {
6381     NYI("emitIns_S");
6382 }
6383
6384 /*****************************************************************************
6385  *
6386  *  Add an instruction referencing a register and a stack-based local variable.
6387  */
6388 void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
6389 {
6390     emitAttr  size  = EA_SIZE(attr);
6391     insFormat fmt   = IF_NONE;
6392     int       disp  = 0;
6393     unsigned  scale = 0;
6394
6395     assert(offs >= 0);
6396
6397     // TODO-ARM64-CQ: use unscaled loads?
6398     /* Figure out the encoding format of the instruction */
6399     switch (ins)
6400     {
6401         case INS_strb:
6402         case INS_ldrb:
6403         case INS_ldrsb:
6404             scale = 0;
6405             break;
6406
6407         case INS_strh:
6408         case INS_ldrh:
6409         case INS_ldrsh:
6410             scale = 1;
6411             break;
6412
6413         case INS_ldrsw:
6414             scale = 2;
6415             break;
6416
6417         case INS_str:
6418         case INS_ldr:
6419             assert(isValidGeneralDatasize(size) || isValidVectorDatasize(size));
6420             scale = genLog2(EA_SIZE_IN_BYTES(size));
6421             break;
6422
6423         case INS_lea:
6424             assert(size == EA_8BYTE);
6425             scale = 0;
6426             break;
6427
6428         default:
6429             NYI("emitIns_R_S"); // FP locals?
6430             return;
6431
6432     } // end switch (ins)
6433
6434     /* Figure out the variable's frame position */
6435     ssize_t imm;
6436     int     base;
6437     bool    FPbased;
6438
6439     base = emitComp->lvaFrameAddress(varx, &FPbased);
6440     disp = base + offs;
6441     assert((scale >= 0) && (scale <= 4));
6442
6443     regNumber reg2 = FPbased ? REG_FPBASE : REG_SPBASE;
6444     reg2           = encodingSPtoZR(reg2);
6445
6446     if (ins == INS_lea)
6447     {
6448         if (disp >= 0)
6449         {
6450             ins = INS_add;
6451             imm = disp;
6452         }
6453         else
6454         {
6455             ins = INS_sub;
6456             imm = -disp;
6457         }
6458
6459         if (imm <= 0x0fff)
6460         {
6461             fmt = IF_DI_2A; // add reg1,reg2,#disp
6462         }
6463         else
6464         {
6465             regNumber rsvdReg = codeGen->rsGetRsvdReg();
6466             codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6467             fmt = IF_DR_3A; // add reg1,reg2,rsvdReg
6468         }
6469     }
6470     else
6471     {
6472         bool    useRegForImm = false;
6473         ssize_t mask         = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6474
6475         imm = disp;
6476         if (imm == 0)
6477         {
6478             fmt = IF_LS_2A;
6479         }
6480         else if ((imm < 0) || ((imm & mask) != 0))
6481         {
6482             if ((imm >= -256) && (imm <= 255))
6483             {
6484                 fmt = IF_LS_2C;
6485             }
6486             else
6487             {
6488                 useRegForImm = true;
6489             }
6490         }
6491         else if (imm > 0)
6492         {
6493             if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
6494             {
6495                 imm >>= scale; // The immediate is scaled by the size of the ld/st
6496
6497                 fmt = IF_LS_2B;
6498             }
6499             else
6500             {
6501                 useRegForImm = true;
6502             }
6503         }
6504
6505         if (useRegForImm)
6506         {
6507             regNumber rsvdReg = codeGen->rsGetRsvdReg();
6508             codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6509             fmt = IF_LS_3A;
6510         }
6511     }
6512
6513     assert(fmt != IF_NONE);
6514
6515     instrDesc* id = emitNewInstrCns(attr, imm);
6516
6517     id->idIns(ins);
6518     id->idInsFmt(fmt);
6519     id->idInsOpt(INS_OPTS_NONE);
6520
6521     id->idReg1(reg1);
6522     id->idReg2(reg2);
6523     id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6524     id->idSetIsLclVar();
6525
6526 #ifdef DEBUG
6527     id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6528 #endif
6529
6530     dispIns(id);
6531     appendToCurIG(id);
6532 }
6533
6534 /*****************************************************************************
6535  *
6536  *  Add an instruction referencing two register and consectutive stack-based local variable slots.
6537  */
6538 void emitter::emitIns_R_R_S_S(
6539     instruction ins, emitAttr attr1, emitAttr attr2, regNumber reg1, regNumber reg2, int varx, int offs)
6540 {
6541     assert((ins == INS_ldp) || (ins == INS_ldnp));
6542     assert(EA_8BYTE == EA_SIZE(attr1));
6543     assert(EA_8BYTE == EA_SIZE(attr2));
6544     assert(isGeneralRegisterOrZR(reg1));
6545     assert(isGeneralRegisterOrZR(reg2));
6546     assert(offs >= 0);
6547
6548     insFormat      fmt   = IF_LS_3B;
6549     int            disp  = 0;
6550     const unsigned scale = 3;
6551
6552     /* Figure out the variable's frame position */
6553     int  base;
6554     bool FPbased;
6555
6556     base = emitComp->lvaFrameAddress(varx, &FPbased);
6557     disp = base + offs;
6558
6559     // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6560     regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE;
6561     reg3           = encodingSPtoZR(reg3);
6562
6563     bool    useRegForAdr = true;
6564     ssize_t imm          = disp;
6565     ssize_t mask         = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6566     if (imm == 0)
6567     {
6568         useRegForAdr = false;
6569     }
6570     else
6571     {
6572         if ((imm & mask) == 0)
6573         {
6574             ssize_t immShift = imm >> scale; // The immediate is scaled by the size of the ld/st
6575
6576             if ((immShift >= -64) && (immShift <= 63))
6577             {
6578                 fmt          = IF_LS_3C;
6579                 useRegForAdr = false;
6580                 imm          = immShift;
6581             }
6582         }
6583     }
6584
6585     if (useRegForAdr)
6586     {
6587         regNumber rsvd = codeGen->rsGetRsvdReg();
6588         emitIns_R_R_Imm(INS_add, EA_PTRSIZE, rsvd, reg3, imm);
6589         reg3 = rsvd;
6590         imm  = 0;
6591     }
6592
6593     assert(fmt != IF_NONE);
6594
6595     instrDesc* id = emitNewInstrCns(attr1, imm);
6596
6597     id->idIns(ins);
6598     id->idInsFmt(fmt);
6599     id->idInsOpt(INS_OPTS_NONE);
6600
6601     // Record the attribute for the second register in the pair
6602     if (EA_IS_GCREF(attr2))
6603     {
6604         id->idGCrefReg2(GCT_GCREF);
6605     }
6606     else if (EA_IS_BYREF(attr2))
6607     {
6608         id->idGCrefReg2(GCT_BYREF);
6609     }
6610     else
6611     {
6612         id->idGCrefReg2(GCT_NONE);
6613     }
6614
6615     id->idReg1(reg1);
6616     id->idReg2(reg2);
6617     id->idReg3(reg3);
6618     id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6619     id->idSetIsLclVar();
6620
6621 #ifdef DEBUG
6622     id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6623 #endif
6624
6625     dispIns(id);
6626     appendToCurIG(id);
6627 }
6628
6629 /*****************************************************************************
6630  *
6631  *  Add an instruction referencing a stack-based local variable and a register
6632  */
6633 void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
6634 {
6635     assert(offs >= 0);
6636     emitAttr  size          = EA_SIZE(attr);
6637     insFormat fmt           = IF_NONE;
6638     int       disp          = 0;
6639     unsigned  scale         = 0;
6640     bool      isVectorStore = false;
6641
6642     // TODO-ARM64-CQ: use unscaled loads?
6643     /* Figure out the encoding format of the instruction */
6644     switch (ins)
6645     {
6646         case INS_strb:
6647             scale = 0;
6648             assert(isGeneralRegisterOrZR(reg1));
6649             break;
6650
6651         case INS_strh:
6652             scale = 1;
6653             assert(isGeneralRegisterOrZR(reg1));
6654             break;
6655
6656         case INS_str:
6657             if (isGeneralRegisterOrZR(reg1))
6658             {
6659                 assert(isValidGeneralDatasize(size));
6660                 scale = (size == EA_8BYTE) ? 3 : 2;
6661             }
6662             else
6663             {
6664                 assert(isVectorRegister(reg1));
6665                 assert(isValidVectorLSDatasize(size));
6666                 scale         = NaturalScale_helper(size);
6667                 isVectorStore = true;
6668             }
6669             break;
6670
6671         default:
6672             NYI("emitIns_S_R"); // FP locals?
6673             return;
6674
6675     } // end switch (ins)
6676
6677     /* Figure out the variable's frame position */
6678     int  base;
6679     bool FPbased;
6680
6681     base = emitComp->lvaFrameAddress(varx, &FPbased);
6682     disp = base + offs;
6683     assert(scale >= 0);
6684     if (isVectorStore)
6685     {
6686         assert(scale <= 4);
6687     }
6688     else
6689     {
6690         assert(scale <= 3);
6691     }
6692
6693     // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6694     regNumber reg2 = FPbased ? REG_FPBASE : REG_SPBASE;
6695     reg2           = encodingSPtoZR(reg2);
6696
6697     bool    useRegForImm = false;
6698     ssize_t imm          = disp;
6699     ssize_t mask         = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6700     if (imm == 0)
6701     {
6702         fmt = IF_LS_2A;
6703     }
6704     else if ((imm < 0) || ((imm & mask) != 0))
6705     {
6706         if ((imm >= -256) && (imm <= 255))
6707         {
6708             fmt = IF_LS_2C;
6709         }
6710         else
6711         {
6712             useRegForImm = true;
6713         }
6714     }
6715     else if (imm > 0)
6716     {
6717         if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
6718         {
6719             imm >>= scale; // The immediate is scaled by the size of the ld/st
6720
6721             fmt = IF_LS_2B;
6722         }
6723         else
6724         {
6725             useRegForImm = true;
6726         }
6727     }
6728
6729     if (useRegForImm)
6730     {
6731         // The reserved register is not stored in idReg3() since that field overlaps with iiaLclVar.
6732         // It is instead implicit when idSetIsLclVar() is set, with this encoding format.
6733         regNumber rsvdReg = codeGen->rsGetRsvdReg();
6734         codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6735         fmt = IF_LS_3A;
6736     }
6737
6738     assert(fmt != IF_NONE);
6739
6740     instrDesc* id = emitNewInstrCns(attr, imm);
6741
6742     id->idIns(ins);
6743     id->idInsFmt(fmt);
6744     id->idInsOpt(INS_OPTS_NONE);
6745
6746     id->idReg1(reg1);
6747     id->idReg2(reg2);
6748     id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6749     id->idSetIsLclVar();
6750
6751 #ifdef DEBUG
6752     id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6753 #endif
6754
6755     dispIns(id);
6756     appendToCurIG(id);
6757 }
6758
6759 /*****************************************************************************
6760  *
6761  *  Add an instruction referencing consecutive stack-based local variable slots and two registers
6762  */
6763 void emitter::emitIns_S_S_R_R(
6764     instruction ins, emitAttr attr1, emitAttr attr2, regNumber reg1, regNumber reg2, int varx, int offs)
6765 {
6766     assert((ins == INS_stp) || (ins == INS_stnp));
6767     assert(EA_8BYTE == EA_SIZE(attr1));
6768     assert(EA_8BYTE == EA_SIZE(attr2));
6769     assert(isGeneralRegisterOrZR(reg1));
6770     assert(isGeneralRegisterOrZR(reg2));
6771     assert(offs >= 0);
6772
6773     insFormat      fmt   = IF_LS_3B;
6774     int            disp  = 0;
6775     const unsigned scale = 3;
6776
6777     /* Figure out the variable's frame position */
6778     int  base;
6779     bool FPbased;
6780
6781     base = emitComp->lvaFrameAddress(varx, &FPbased);
6782     disp = base + offs;
6783
6784     // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6785     regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE;
6786     reg3           = encodingSPtoZR(reg3);
6787
6788     bool    useRegForAdr = true;
6789     ssize_t imm          = disp;
6790     ssize_t mask         = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6791     if (imm == 0)
6792     {
6793         useRegForAdr = false;
6794     }
6795     else
6796     {
6797         if ((imm & mask) == 0)
6798         {
6799             ssize_t immShift = imm >> scale; // The immediate is scaled by the size of the ld/st
6800
6801             if ((immShift >= -64) && (immShift <= 63))
6802             {
6803                 fmt          = IF_LS_3C;
6804                 useRegForAdr = false;
6805                 imm          = immShift;
6806             }
6807         }
6808     }
6809
6810     if (useRegForAdr)
6811     {
6812         regNumber rsvd = codeGen->rsGetRsvdReg();
6813         emitIns_R_R_Imm(INS_add, EA_PTRSIZE, rsvd, reg3, imm);
6814         reg3 = rsvd;
6815         imm  = 0;
6816     }
6817
6818     assert(fmt != IF_NONE);
6819
6820     instrDesc* id = emitNewInstrCns(attr1, imm);
6821
6822     id->idIns(ins);
6823     id->idInsFmt(fmt);
6824     id->idInsOpt(INS_OPTS_NONE);
6825
6826     // Record the attribute for the second register in the pair
6827     if (EA_IS_GCREF(attr2))
6828     {
6829         id->idGCrefReg2(GCT_GCREF);
6830     }
6831     else if (EA_IS_BYREF(attr2))
6832     {
6833         id->idGCrefReg2(GCT_BYREF);
6834     }
6835     else
6836     {
6837         id->idGCrefReg2(GCT_NONE);
6838     }
6839
6840     id->idReg1(reg1);
6841     id->idReg2(reg2);
6842     id->idReg3(reg3);
6843     id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6844     id->idSetIsLclVar();
6845
6846 #ifdef DEBUG
6847     id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6848 #endif
6849
6850     dispIns(id);
6851     appendToCurIG(id);
6852 }
6853
6854 /*****************************************************************************
6855  *
6856  *  Add an instruction referencing stack-based local variable and an immediate
6857  */
6858 void emitter::emitIns_S_I(instruction ins, emitAttr attr, int varx, int offs, int val)
6859 {
6860     NYI("emitIns_S_I");
6861 }
6862
6863 /*****************************************************************************
6864  *
6865  *  Add an instruction with a register + static member operands.
6866  *  Constant is stored into JIT data which is adjacent to code.
6867  *  No relocation is needed. PC-relative offset will be encoded directly into instruction.
6868  *
6869  */
6870 void emitter::emitIns_R_C(
6871     instruction ins, emitAttr attr, regNumber reg, regNumber addrReg, CORINFO_FIELD_HANDLE fldHnd, int offs)
6872 {
6873     assert(offs >= 0);
6874     assert(instrDesc::fitsInSmallCns(offs));
6875
6876     emitAttr      size = EA_SIZE(attr);
6877     insFormat     fmt  = IF_NONE;
6878     int           disp = 0;
6879     instrDescJmp* id   = emitNewInstrJmp();
6880
6881     switch (ins)
6882     {
6883         case INS_adr:
6884             // This is case to get address to the constant data.
6885             fmt = IF_LARGEADR;
6886             assert(isGeneralRegister(reg));
6887             assert(isValidGeneralDatasize(size));
6888             break;
6889
6890         case INS_ldr:
6891             fmt = IF_LARGELDC;
6892             if (isVectorRegister(reg))
6893             {
6894                 assert(isValidScalarDatasize(size));
6895                 // For vector (float/double) register, we should have an integer address reg to
6896                 // compute long address which consists of page address and page offset.
6897                 // For integer constant, this is not needed since the dest reg can be used to
6898                 // compute address as well as contain the final contents.
6899                 assert(isGeneralRegister(reg) || (addrReg != REG_NA));
6900             }
6901             else
6902             {
6903                 assert(isGeneralRegister(reg));
6904                 assert(isValidGeneralDatasize(size));
6905             }
6906             break;
6907         default:
6908             unreached();
6909     }
6910
6911     assert(fmt != IF_NONE);
6912
6913     id->idIns(ins);
6914     id->idInsFmt(fmt);
6915     id->idInsOpt(INS_OPTS_NONE);
6916     id->idSmallCns(offs);
6917     id->idOpSize(size);
6918     id->idAddr()->iiaFieldHnd = fldHnd;
6919     id->idSetIsBound(); // We won't patch address since we will know the exact distance once JIT code and data are
6920                         // allocated together.
6921
6922     id->idReg1(reg); // destination register that will get the constant value.
6923     if (addrReg != REG_NA)
6924     {
6925         id->idReg2(addrReg); // integer register to compute long address (used for vector dest when we end up with long
6926                              // address)
6927     }
6928     id->idjShort = false; // Assume loading constant from long address
6929
6930     // Keep it long if it's in cold code.
6931     id->idjKeepLong = emitComp->fgIsBlockCold(emitComp->compCurBB);
6932
6933 #ifdef DEBUG
6934     if (emitComp->opts.compLongAddress)
6935         id->idjKeepLong = 1;
6936 #endif // DEBUG
6937
6938     // If it's possible to be shortened, then put it in jump list
6939     // to be revisited by emitJumpDistBind.
6940     if (!id->idjKeepLong)
6941     {
6942         /* Record the jump's IG and offset within it */
6943         id->idjIG   = emitCurIG;
6944         id->idjOffs = emitCurIGsize;
6945
6946         /* Append this jump to this IG's jump list */
6947         id->idjNext      = emitCurIGjmpList;
6948         emitCurIGjmpList = id;
6949
6950 #if EMITTER_STATS
6951         emitTotalIGjmps++;
6952 #endif
6953     }
6954
6955     dispIns(id);
6956     appendToCurIG(id);
6957 }
6958
6959 /*****************************************************************************
6960  *
6961  *  Add an instruction with a static member + constant.
6962  */
6963
6964 void emitter::emitIns_C_I(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, ssize_t offs, ssize_t val)
6965 {
6966     NYI("emitIns_C_I");
6967 }
6968
6969 /*****************************************************************************
6970  *
6971  *  Add an instruction with a static member + register operands.
6972  */
6973
6974 void emitter::emitIns_C_R(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, regNumber reg, int offs)
6975 {
6976     assert(!"emitIns_C_R not supported for RyuJIT backend");
6977 }
6978
6979 void emitter::emitIns_R_AR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
6980 {
6981     NYI("emitIns_R_AR");
6982 }
6983
6984 // This computes address from the immediate which is relocatable.
6985 void emitter::emitIns_R_AI(instruction ins, emitAttr attr, regNumber ireg, ssize_t addr)
6986 {
6987     assert(EA_IS_RELOC(attr));
6988     emitAttr      size    = EA_SIZE(attr);
6989     insFormat     fmt     = IF_DI_1E;
6990     bool          needAdd = false;
6991     instrDescJmp* id      = emitNewInstrJmp();
6992
6993     switch (ins)
6994     {
6995         case INS_adrp:
6996             // This computes page address.
6997             // page offset is needed using add.
6998             needAdd = true;
6999             break;
7000         case INS_adr:
7001             break;
7002         default:
7003             unreached();
7004     }
7005
7006     id->idIns(ins);
7007     id->idInsFmt(fmt);
7008     id->idInsOpt(INS_OPTS_NONE);
7009     id->idOpSize(size);
7010     id->idAddr()->iiaAddr = (BYTE*)addr;
7011     id->idReg1(ireg);
7012     id->idSetIsDspReloc();
7013
7014     dispIns(id);
7015     appendToCurIG(id);
7016
7017     if (needAdd)
7018     {
7019         // add reg, reg, imm
7020         ins           = INS_add;
7021         fmt           = IF_DI_2A;
7022         instrDesc* id = emitAllocInstr(attr);
7023         assert(id->idIsReloc());
7024
7025         id->idIns(ins);
7026         id->idInsFmt(fmt);
7027         id->idInsOpt(INS_OPTS_NONE);
7028         id->idOpSize(size);
7029         id->idAddr()->iiaAddr = (BYTE*)addr;
7030         id->idReg1(ireg);
7031         id->idReg2(ireg);
7032
7033         dispIns(id);
7034         appendToCurIG(id);
7035     }
7036 }
7037
7038 void emitter::emitIns_AR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
7039 {
7040     NYI("emitIns_AR_R");
7041 }
7042
7043 void emitter::emitIns_R_ARR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
7044 {
7045     NYI("emitIns_R_ARR");
7046 }
7047
7048 void emitter::emitIns_ARR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
7049 {
7050     NYI("emitIns_R_ARR");
7051 }
7052
7053 void emitter::emitIns_R_ARX(
7054     instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, unsigned mul, int disp)
7055 {
7056     NYI("emitIns_R_ARR");
7057 }
7058
7059 /*****************************************************************************
7060  *
7061  *  Record that a jump instruction uses the short encoding
7062  *
7063  */
7064 void emitter::emitSetShortJump(instrDescJmp* id)
7065 {
7066     if (id->idjKeepLong)
7067         return;
7068
7069     insFormat fmt = IF_NONE;
7070     if (emitIsCondJump(id))
7071     {
7072         switch (id->idIns())
7073         {
7074             case INS_cbz:
7075             case INS_cbnz:
7076                 fmt = IF_BI_1A;
7077                 break;
7078             case INS_tbz:
7079             case INS_tbnz:
7080                 fmt = IF_BI_1B;
7081                 break;
7082             default:
7083                 fmt = IF_BI_0B;
7084                 break;
7085         }
7086     }
7087     else if (emitIsLoadLabel(id))
7088     {
7089         fmt = IF_DI_1E;
7090     }
7091     else if (emitIsLoadConstant(id))
7092     {
7093         fmt = IF_LS_1A;
7094     }
7095     else
7096     {
7097         unreached();
7098     }
7099
7100     id->idInsFmt(fmt);
7101     id->idjShort = true;
7102 }
7103
7104 /*****************************************************************************
7105  *
7106  *  Add a label instruction.
7107  */
7108
7109 void emitter::emitIns_R_L(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
7110 {
7111     assert(dst->bbFlags & BBF_JMP_TARGET);
7112
7113     insFormat fmt = IF_NONE;
7114
7115     switch (ins)
7116     {
7117         case INS_adr:
7118             fmt = IF_LARGEADR;
7119             break;
7120         default:
7121             unreached();
7122     }
7123
7124     instrDescJmp* id = emitNewInstrJmp();
7125
7126     id->idIns(ins);
7127     id->idInsFmt(fmt);
7128     id->idjShort             = false;
7129     id->idAddr()->iiaBBlabel = dst;
7130     id->idReg1(reg);
7131     id->idOpSize(EA_PTRSIZE);
7132
7133 #ifdef DEBUG
7134     // Mark the catch return
7135     if (emitComp->compCurBB->bbJumpKind == BBJ_EHCATCHRET)
7136     {
7137         id->idDebugOnlyInfo()->idCatchRet = true;
7138     }
7139 #endif // DEBUG
7140
7141     id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7142
7143 #ifdef DEBUG
7144     if (emitComp->opts.compLongAddress)
7145         id->idjKeepLong = 1;
7146 #endif // DEBUG
7147
7148     /* Record the jump's IG and offset within it */
7149
7150     id->idjIG   = emitCurIG;
7151     id->idjOffs = emitCurIGsize;
7152
7153     /* Append this jump to this IG's jump list */
7154
7155     id->idjNext      = emitCurIGjmpList;
7156     emitCurIGjmpList = id;
7157
7158 #if EMITTER_STATS
7159     emitTotalIGjmps++;
7160 #endif
7161
7162     dispIns(id);
7163     appendToCurIG(id);
7164 }
7165
7166 /*****************************************************************************
7167  *
7168  *  Add a data label instruction.
7169  */
7170
7171 void emitter::emitIns_R_D(instruction ins, emitAttr attr, unsigned offs, regNumber reg)
7172 {
7173     NYI("emitIns_R_D");
7174 }
7175
7176 void emitter::emitIns_J_R(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
7177 {
7178     assert((ins == INS_cbz) || (ins == INS_cbnz));
7179
7180     assert(dst != nullptr);
7181     assert((dst->bbFlags & BBF_JMP_TARGET) != 0);
7182
7183     insFormat fmt = IF_LARGEJMP;
7184
7185     instrDescJmp* id = emitNewInstrJmp();
7186
7187     id->idIns(ins);
7188     id->idInsFmt(fmt);
7189     id->idReg1(reg);
7190     id->idjShort = false;
7191     id->idOpSize(EA_SIZE(attr));
7192
7193     id->idAddr()->iiaBBlabel = dst;
7194     id->idjKeepLong          = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7195
7196     /* Record the jump's IG and offset within it */
7197
7198     id->idjIG   = emitCurIG;
7199     id->idjOffs = emitCurIGsize;
7200
7201     /* Append this jump to this IG's jump list */
7202
7203     id->idjNext      = emitCurIGjmpList;
7204     emitCurIGjmpList = id;
7205
7206 #if EMITTER_STATS
7207     emitTotalIGjmps++;
7208 #endif
7209
7210     dispIns(id);
7211     appendToCurIG(id);
7212 }
7213
7214 void emitter::emitIns_J_R_I(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg, int imm)
7215 {
7216     assert((ins == INS_tbz) || (ins == INS_tbnz));
7217
7218     assert(dst != nullptr);
7219     assert((dst->bbFlags & BBF_JMP_TARGET) != 0);
7220     assert((EA_SIZE(attr) == EA_4BYTE) || (EA_SIZE(attr) == EA_8BYTE));
7221     assert(imm < ((EA_SIZE(attr) == EA_4BYTE) ? 32 : 64));
7222
7223     insFormat fmt = IF_LARGEJMP;
7224
7225     instrDescJmp* id = emitNewInstrJmp();
7226
7227     id->idIns(ins);
7228     id->idInsFmt(fmt);
7229     id->idReg1(reg);
7230     id->idjShort = false;
7231     id->idSmallCns(imm);
7232     id->idOpSize(EA_SIZE(attr));
7233
7234     id->idAddr()->iiaBBlabel = dst;
7235     id->idjKeepLong          = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7236
7237     /* Record the jump's IG and offset within it */
7238
7239     id->idjIG   = emitCurIG;
7240     id->idjOffs = emitCurIGsize;
7241
7242     /* Append this jump to this IG's jump list */
7243
7244     id->idjNext      = emitCurIGjmpList;
7245     emitCurIGjmpList = id;
7246
7247 #if EMITTER_STATS
7248     emitTotalIGjmps++;
7249 #endif
7250
7251     dispIns(id);
7252     appendToCurIG(id);
7253 }
7254
7255 void emitter::emitIns_J(instruction ins, BasicBlock* dst, int instrCount)
7256 {
7257     insFormat fmt = IF_NONE;
7258
7259     if (dst != nullptr)
7260     {
7261         assert(dst->bbFlags & BBF_JMP_TARGET);
7262     }
7263     else
7264     {
7265         assert(instrCount != 0);
7266     }
7267
7268     /* Figure out the encoding format of the instruction */
7269
7270     bool idjShort = false;
7271     switch (ins)
7272     {
7273         case INS_bl_local:
7274         case INS_b:
7275             // Unconditional jump is a single form.
7276             idjShort = true;
7277             fmt      = IF_BI_0A;
7278             break;
7279
7280         case INS_beq:
7281         case INS_bne:
7282         case INS_bhs:
7283         case INS_blo:
7284         case INS_bmi:
7285         case INS_bpl:
7286         case INS_bvs:
7287         case INS_bvc:
7288         case INS_bhi:
7289         case INS_bls:
7290         case INS_bge:
7291         case INS_blt:
7292         case INS_bgt:
7293         case INS_ble:
7294             // Assume conditional jump is long.
7295             fmt = IF_LARGEJMP;
7296             break;
7297
7298         default:
7299             unreached();
7300             break;
7301     }
7302
7303     instrDescJmp* id = emitNewInstrJmp();
7304
7305     id->idIns(ins);
7306     id->idInsFmt(fmt);
7307     id->idjShort = idjShort;
7308
7309 #ifdef DEBUG
7310     // Mark the finally call
7311     if (ins == INS_bl_local && emitComp->compCurBB->bbJumpKind == BBJ_CALLFINALLY)
7312     {
7313         id->idDebugOnlyInfo()->idFinallyCall = true;
7314     }
7315 #endif // DEBUG
7316
7317     if (dst != nullptr)
7318     {
7319         id->idAddr()->iiaBBlabel = dst;
7320
7321         // Skip unconditional jump that has a single form.
7322         // TODO-ARM64-NYI: enable hot/cold splittingNYI.
7323         // The target needs to be relocated.
7324         if (!idjShort)
7325         {
7326             id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7327
7328 #ifdef DEBUG
7329             if (emitComp->opts.compLongAddress) // Force long branches
7330                 id->idjKeepLong = 1;
7331 #endif // DEBUG
7332         }
7333     }
7334     else
7335     {
7336         id->idAddr()->iiaSetInstrCount(instrCount);
7337         id->idjKeepLong = false;
7338         /* This jump must be short */
7339         emitSetShortJump(id);
7340         id->idSetIsBound();
7341     }
7342
7343     /* Record the jump's IG and offset within it */
7344
7345     id->idjIG   = emitCurIG;
7346     id->idjOffs = emitCurIGsize;
7347
7348     /* Append this jump to this IG's jump list */
7349
7350     id->idjNext      = emitCurIGjmpList;
7351     emitCurIGjmpList = id;
7352
7353 #if EMITTER_STATS
7354     emitTotalIGjmps++;
7355 #endif
7356
7357     dispIns(id);
7358     appendToCurIG(id);
7359 }
7360
7361 /*****************************************************************************
7362  *
7363  *  Add a call instruction (direct or indirect).
7364  *      argSize<0 means that the caller will pop the arguments
7365  *
7366  * The other arguments are interpreted depending on callType as shown:
7367  * Unless otherwise specified, ireg,xreg,xmul,disp should have default values.
7368  *
7369  * EC_FUNC_TOKEN       : addr is the method address
7370  * EC_FUNC_ADDR        : addr is the absolute address of the function
7371  *
7372  * If callType is one of these emitCallTypes, addr has to be NULL.
7373  * EC_INDIR_R          : "call ireg".
7374  *
7375  * For ARM xreg, xmul and disp are never used and should always be 0/REG_NA.
7376  *
7377  *  Please consult the "debugger team notification" comment in genFnProlog().
7378  */
7379
7380 void emitter::emitIns_Call(EmitCallType          callType,
7381                            CORINFO_METHOD_HANDLE methHnd,
7382                            INDEBUG_LDISASM_COMMA(CORINFO_SIG_INFO* sigInfo) // used to report call sites to the EE
7383                            void*            addr,
7384                            ssize_t          argSize,
7385                            emitAttr         retSize,
7386                            emitAttr         secondRetSize,
7387                            VARSET_VALARG_TP ptrVars,
7388                            regMaskTP        gcrefRegs,
7389                            regMaskTP        byrefRegs,
7390                            IL_OFFSETX       ilOffset /* = BAD_IL_OFFSET */,
7391                            regNumber        ireg /* = REG_NA */,
7392                            regNumber        xreg /* = REG_NA */,
7393                            unsigned         xmul /* = 0     */,
7394                            ssize_t          disp /* = 0     */,
7395                            bool             isJump /* = false */,
7396                            bool             isNoGC /* = false */,
7397                            bool             isProfLeaveCB /* = false */)
7398 {
7399     /* Sanity check the arguments depending on callType */
7400
7401     assert(callType < EC_COUNT);
7402     assert((callType != EC_FUNC_TOKEN && callType != EC_FUNC_ADDR) ||
7403            (ireg == REG_NA && xreg == REG_NA && xmul == 0 && disp == 0));
7404     assert(callType < EC_INDIR_R || addr == NULL);
7405     assert(callType != EC_INDIR_R || (ireg < REG_COUNT && xreg == REG_NA && xmul == 0 && disp == 0));
7406
7407     // ARM never uses these
7408     assert(xreg == REG_NA && xmul == 0 && disp == 0);
7409
7410     // Our stack level should be always greater than the bytes of arguments we push. Just
7411     // a sanity test.
7412     assert((unsigned)abs(argSize) <= codeGen->genStackLevel);
7413
7414     int        argCnt;
7415     instrDesc* id;
7416
7417     /* This is the saved set of registers after a normal call */
7418     regMaskTP savedSet = RBM_CALLEE_SAVED;
7419
7420     /* some special helper calls have a different saved set registers */
7421
7422     if (isNoGC)
7423     {
7424         assert(emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
7425
7426         // Get the set of registers that this call kills and remove it from the saved set.
7427         savedSet = RBM_ALLINT & ~emitComp->compNoGCHelperCallKillSet(Compiler::eeGetHelperNum(methHnd));
7428
7429         // In case of Leave profiler callback, we need to preserve liveness of REG_PROFILER_RET_SCRATCH
7430         if (isProfLeaveCB)
7431         {
7432             savedSet |= RBM_PROFILER_RET_SCRATCH;
7433         }
7434
7435 #ifdef DEBUG
7436         if (emitComp->verbose)
7437         {
7438             printf("NOGC Call: savedSet=");
7439             printRegMaskInt(savedSet);
7440             emitDispRegSet(savedSet);
7441             printf("\n");
7442         }
7443 #endif
7444     }
7445     else
7446     {
7447         assert(!emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
7448     }
7449
7450     /* Trim out any callee-trashed registers from the live set */
7451
7452     gcrefRegs &= savedSet;
7453     byrefRegs &= savedSet;
7454
7455 #ifdef DEBUG
7456     if (EMIT_GC_VERBOSE)
7457     {
7458         printf("Call: GCvars=%s ", VarSetOps::ToString(emitComp, ptrVars));
7459         dumpConvertedVarSet(emitComp, ptrVars);
7460         printf(", gcrefRegs=");
7461         printRegMaskInt(gcrefRegs);
7462         emitDispRegSet(gcrefRegs);
7463         printf(", byrefRegs=");
7464         printRegMaskInt(byrefRegs);
7465         emitDispRegSet(byrefRegs);
7466         printf("\n");
7467     }
7468 #endif
7469
7470     assert(argSize % REGSIZE_BYTES == 0);
7471     argCnt = (int)(argSize / (int)REGSIZE_BYTES);
7472
7473     /* Managed RetVal: emit sequence point for the call */
7474     if (emitComp->opts.compDbgInfo && ilOffset != BAD_IL_OFFSET)
7475     {
7476         codeGen->genIPmappingAdd(ilOffset, false);
7477     }
7478
7479     /*
7480         We need to allocate the appropriate instruction descriptor based
7481         on whether this is a direct/indirect call, and whether we need to
7482         record an updated set of live GC variables.
7483      */
7484
7485     if (callType >= EC_INDIR_R)
7486     {
7487         /* Indirect call, virtual calls */
7488
7489         assert(callType == EC_INDIR_R);
7490
7491         id = emitNewInstrCallInd(argCnt, disp, ptrVars, gcrefRegs, byrefRegs, retSize, secondRetSize);
7492     }
7493     else
7494     {
7495         /* Helper/static/nonvirtual/function calls (direct or through handle),
7496            and calls to an absolute addr. */
7497
7498         assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
7499
7500         id = emitNewInstrCallDir(argCnt, ptrVars, gcrefRegs, byrefRegs, retSize, secondRetSize);
7501     }
7502
7503     /* Update the emitter's live GC ref sets */
7504
7505     VarSetOps::Assign(emitComp, emitThisGCrefVars, ptrVars);
7506     emitThisGCrefRegs = gcrefRegs;
7507     emitThisByrefRegs = byrefRegs;
7508
7509     /* Set the instruction - special case jumping a function */
7510     instruction ins;
7511     insFormat   fmt = IF_NONE;
7512
7513     id->idSetIsNoGC(isNoGC);
7514
7515     /* Record the address: method, indirection, or funcptr */
7516
7517     if (callType > EC_FUNC_ADDR)
7518     {
7519         /* This is an indirect call (either a virtual call or func ptr call) */
7520
7521         switch (callType)
7522         {
7523             case EC_INDIR_R: // the address is in a register
7524
7525                 id->idSetIsCallRegPtr();
7526
7527                 if (isJump)
7528                 {
7529                     ins = INS_br_tail; // INS_br_tail  Reg
7530                 }
7531                 else
7532                 {
7533                     ins = INS_blr; // INS_blr Reg
7534                 }
7535                 fmt = IF_BR_1B;
7536
7537                 id->idIns(ins);
7538                 id->idInsFmt(fmt);
7539
7540                 id->idReg3(ireg);
7541                 assert(xreg == REG_NA);
7542                 break;
7543
7544             default:
7545                 NO_WAY("unexpected instruction");
7546                 break;
7547         }
7548     }
7549     else
7550     {
7551         /* This is a simple direct call: "call helper/method/addr" */
7552
7553         assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
7554
7555         assert(addr != NULL);
7556
7557         if (isJump)
7558         {
7559             ins = INS_b_tail; // INS_b_tail imm28
7560         }
7561         else
7562         {
7563             ins = INS_bl; // INS_bl imm28
7564         }
7565         fmt = IF_BI_0C;
7566
7567         id->idIns(ins);
7568         id->idInsFmt(fmt);
7569
7570         id->idAddr()->iiaAddr = (BYTE*)addr;
7571
7572         if (callType == EC_FUNC_ADDR)
7573         {
7574             id->idSetIsCallAddr();
7575         }
7576
7577         if (emitComp->opts.compReloc)
7578         {
7579             id->idSetIsDspReloc();
7580         }
7581     }
7582
7583 #ifdef DEBUG
7584     if (EMIT_GC_VERBOSE)
7585     {
7586         if (id->idIsLargeCall())
7587         {
7588             printf("[%02u] Rec call GC vars = %s\n", id->idDebugOnlyInfo()->idNum,
7589                    VarSetOps::ToString(emitComp, ((instrDescCGCA*)id)->idcGCvars));
7590         }
7591     }
7592
7593     id->idDebugOnlyInfo()->idMemCookie = (size_t)methHnd; // method token
7594     id->idDebugOnlyInfo()->idCallSig   = sigInfo;
7595 #endif // DEBUG
7596
7597 #ifdef LATE_DISASM
7598     if (addr != nullptr)
7599     {
7600         codeGen->getDisAssembler().disSetMethod((size_t)addr, methHnd);
7601     }
7602 #endif // LATE_DISASM
7603
7604     dispIns(id);
7605     appendToCurIG(id);
7606 }
7607
7608 /*****************************************************************************
7609  *
7610  *  Returns true if 'imm' is valid Cond encoding
7611  */
7612
7613 /*static*/ bool emitter::isValidImmCond(ssize_t imm)
7614 {
7615     // range check the ssize_t value, to make sure it is a small unsigned value
7616     // and that only the bits in the cfi.cond are set
7617     if ((imm < 0) || (imm > 0xF))
7618         return false;
7619
7620     condFlagsImm cfi;
7621     cfi.immCFVal = (unsigned)imm;
7622
7623     return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7624 }
7625
7626 /*****************************************************************************
7627  *
7628  *  Returns true if 'imm' is valid Cond/Flags encoding
7629  */
7630
7631 /*static*/ bool emitter::isValidImmCondFlags(ssize_t imm)
7632 {
7633     // range check the ssize_t value, to make sure it is a small unsigned value
7634     // and that only the bits in the cfi.cond or cfi.flags are set
7635     if ((imm < 0) || (imm > 0xFF))
7636         return false;
7637
7638     condFlagsImm cfi;
7639     cfi.immCFVal = (unsigned)imm;
7640
7641     return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7642 }
7643
7644 /*****************************************************************************
7645  *
7646  *  Returns true if 'imm' is valid Cond/Flags/Imm5 encoding
7647  */
7648
7649 /*static*/ bool emitter::isValidImmCondFlagsImm5(ssize_t imm)
7650 {
7651     // range check the ssize_t value, to make sure it is a small unsigned value
7652     // and that only the bits in the cfi.cond, cfi.flags or cfi.imm5 are set
7653     if ((imm < 0) || (imm > 0x1FFF))
7654         return false;
7655
7656     condFlagsImm cfi;
7657     cfi.immCFVal = (unsigned)imm;
7658
7659     return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7660 }
7661
7662 /*****************************************************************************
7663  *
7664  *  Returns an encoding for the specified register used in the 'Rd' position
7665  */
7666
7667 /*static*/ emitter::code_t emitter::insEncodeReg_Rd(regNumber reg)
7668 {
7669     assert(isIntegerRegister(reg));
7670     emitter::code_t ureg = (emitter::code_t)reg;
7671     assert((ureg >= 0) && (ureg <= 31));
7672     return ureg;
7673 }
7674
7675 /*****************************************************************************
7676  *
7677  *  Returns an encoding for the specified register used in the 'Rt' position
7678  */
7679
7680 /*static*/ emitter::code_t emitter::insEncodeReg_Rt(regNumber reg)
7681 {
7682     assert(isIntegerRegister(reg));
7683     emitter::code_t ureg = (emitter::code_t)reg;
7684     assert((ureg >= 0) && (ureg <= 31));
7685     return ureg;
7686 }
7687
7688 /*****************************************************************************
7689  *
7690  *  Returns an encoding for the specified register used in the 'Rn' position
7691  */
7692
7693 /*static*/ emitter::code_t emitter::insEncodeReg_Rn(regNumber reg)
7694 {
7695     assert(isIntegerRegister(reg));
7696     emitter::code_t ureg = (emitter::code_t)reg;
7697     assert((ureg >= 0) && (ureg <= 31));
7698     return ureg << 5;
7699 }
7700
7701 /*****************************************************************************
7702  *
7703  *  Returns an encoding for the specified register used in the 'Rm' position
7704  */
7705
7706 /*static*/ emitter::code_t emitter::insEncodeReg_Rm(regNumber reg)
7707 {
7708     assert(isIntegerRegister(reg));
7709     emitter::code_t ureg = (emitter::code_t)reg;
7710     assert((ureg >= 0) && (ureg <= 31));
7711     return ureg << 16;
7712 }
7713
7714 /*****************************************************************************
7715  *
7716  *  Returns an encoding for the specified register used in the 'Ra' position
7717  */
7718
7719 /*static*/ emitter::code_t emitter::insEncodeReg_Ra(regNumber reg)
7720 {
7721     assert(isIntegerRegister(reg));
7722     emitter::code_t ureg = (emitter::code_t)reg;
7723     assert((ureg >= 0) && (ureg <= 31));
7724     return ureg << 10;
7725 }
7726
7727 /*****************************************************************************
7728  *
7729  *  Returns an encoding for the specified register used in the 'Vd' position
7730  */
7731
7732 /*static*/ emitter::code_t emitter::insEncodeReg_Vd(regNumber reg)
7733 {
7734     assert(emitter::isVectorRegister(reg));
7735     emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7736     assert((ureg >= 0) && (ureg <= 31));
7737     return ureg;
7738 }
7739
7740 /*****************************************************************************
7741  *
7742  *  Returns an encoding for the specified register used in the 'Vt' position
7743  */
7744
7745 /*static*/ emitter::code_t emitter::insEncodeReg_Vt(regNumber reg)
7746 {
7747     assert(emitter::isVectorRegister(reg));
7748     emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7749     assert((ureg >= 0) && (ureg <= 31));
7750     return ureg;
7751 }
7752
7753 /*****************************************************************************
7754  *
7755  *  Returns an encoding for the specified register used in the 'Vn' position
7756  */
7757
7758 /*static*/ emitter::code_t emitter::insEncodeReg_Vn(regNumber reg)
7759 {
7760     assert(emitter::isVectorRegister(reg));
7761     emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7762     assert((ureg >= 0) && (ureg <= 31));
7763     return ureg << 5;
7764 }
7765
7766 /*****************************************************************************
7767  *
7768  *  Returns an encoding for the specified register used in the 'Vm' position
7769  */
7770
7771 /*static*/ emitter::code_t emitter::insEncodeReg_Vm(regNumber reg)
7772 {
7773     assert(emitter::isVectorRegister(reg));
7774     emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7775     assert((ureg >= 0) && (ureg <= 31));
7776     return ureg << 16;
7777 }
7778
7779 /*****************************************************************************
7780  *
7781  *  Returns an encoding for the specified register used in the 'Va' position
7782  */
7783
7784 /*static*/ emitter::code_t emitter::insEncodeReg_Va(regNumber reg)
7785 {
7786     assert(emitter::isVectorRegister(reg));
7787     emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7788     assert((ureg >= 0) && (ureg <= 31));
7789     return ureg << 10;
7790 }
7791
7792 /*****************************************************************************
7793  *
7794  *  Returns an encoding for the specified condition code.
7795  */
7796
7797 /*static*/ emitter::code_t emitter::insEncodeCond(insCond cond)
7798 {
7799     emitter::code_t uimm = (emitter::code_t)cond;
7800     return uimm << 12;
7801 }
7802
7803 /*****************************************************************************
7804  *
7805  *  Returns an encoding for the condition code with the lowest bit inverted (marked by invert(<cond>) in the
7806  *  architecture manual).
7807  */
7808
7809 /*static*/ emitter::code_t emitter::insEncodeInvertedCond(insCond cond)
7810 {
7811     emitter::code_t uimm = (emitter::code_t)cond;
7812     uimm ^= 1; // invert the lowest bit
7813     return uimm << 12;
7814 }
7815
7816 /*****************************************************************************
7817  *
7818  *  Returns an encoding for the specified flags.
7819  */
7820
7821 /*static*/ emitter::code_t emitter::insEncodeFlags(insCflags flags)
7822 {
7823     emitter::code_t uimm = (emitter::code_t)flags;
7824     return uimm;
7825 }
7826
7827 /*****************************************************************************
7828  *
7829  *  Returns the encoding for the Shift Count bits to be used for Arm64 encodings
7830  */
7831
7832 /*static*/ emitter::code_t emitter::insEncodeShiftCount(ssize_t imm, emitAttr size)
7833 {
7834     assert((imm & 0x003F) == imm);
7835     assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
7836
7837     return (emitter::code_t)imm << 10;
7838 }
7839
7840 /*****************************************************************************
7841  *
7842  *  Returns the encoding to select a 64-bit datasize for an Arm64 instruction
7843  */
7844
7845 /*static*/ emitter::code_t emitter::insEncodeDatasize(emitAttr size)
7846 {
7847     if (size == EA_8BYTE)
7848     {
7849         return 0x80000000; // set the bit at location 31
7850     }
7851     else
7852     {
7853         assert(size == EA_4BYTE);
7854         return 0;
7855     }
7856 }
7857
7858 /*****************************************************************************
7859  *
7860  *  Returns the encoding to select the datasize for the general load/store Arm64 instructions
7861  *
7862  */
7863
7864 /*static*/ emitter::code_t emitter::insEncodeDatasizeLS(emitter::code_t code, emitAttr size)
7865 {
7866     bool exclusive = ((code & 0x35000000) == 0);
7867     bool atomic    = ((code & 0x31200C00) == 0x30200000);
7868
7869     if ((code & 0x00800000) && !exclusive && !atomic) // Is this a sign-extending opcode? (i.e. ldrsw, ldrsh, ldrsb)
7870     {
7871         if ((code & 0x80000000) == 0) // Is it a ldrsh or ldrsb and not ldrsw ?
7872         {
7873             if (EA_SIZE(size) != EA_8BYTE) // Do we need to encode the 32-bit Rt size bit?
7874             {
7875                 return 0x00400000; // set the bit at location 22
7876             }
7877         }
7878     }
7879     else if (code & 0x80000000) // Is this a ldr/str/ldur/stur opcode?
7880     {
7881         if (EA_SIZE(size) == EA_8BYTE) // Do we need to encode the 64-bit size bit?
7882         {
7883             return 0x40000000; // set the bit at location 30
7884         }
7885     }
7886     return 0;
7887 }
7888
7889 /*****************************************************************************
7890  *
7891  *  Returns the encoding to select the datasize for the vector load/store Arm64 instructions
7892  *
7893  */
7894
7895 /*static*/ emitter::code_t emitter::insEncodeDatasizeVLS(emitter::code_t code, emitAttr size)
7896 {
7897     code_t result = 0;
7898
7899     // Check bit 29
7900     if ((code & 0x20000000) == 0)
7901     {
7902         // LDR literal
7903
7904         if (size == EA_16BYTE)
7905         {
7906             // set the operation size in bit 31
7907             result = 0x80000000;
7908         }
7909         else if (size == EA_8BYTE)
7910         {
7911             // set the operation size in bit 30
7912             result = 0x40000000;
7913         }
7914         else
7915         {
7916             assert(size == EA_4BYTE);
7917             // no bits are set
7918             result = 0x00000000;
7919         }
7920     }
7921     else
7922     {
7923         // LDR non-literal
7924
7925         if (size == EA_16BYTE)
7926         {
7927             // The operation size in bits 31 and 30 are zero
7928             // Bit 23 specifies a 128-bit Load/Store
7929             result = 0x00800000;
7930         }
7931         else if (size == EA_8BYTE)
7932         {
7933             // set the operation size in bits 31 and 30
7934             result = 0xC0000000;
7935         }
7936         else if (size == EA_4BYTE)
7937         {
7938             // set the operation size in bit 31
7939             result = 0x80000000;
7940         }
7941         else if (size == EA_2BYTE)
7942         {
7943             // set the operation size in bit 30
7944             result = 0x40000000;
7945         }
7946         else
7947         {
7948             assert(size == EA_1BYTE);
7949             // The operation size in bits 31 and 30 are zero
7950             result = 0x00000000;
7951         }
7952     }
7953
7954     // Or in bit 26 to indicate a Vector register is used as 'target'
7955     result |= 0x04000000;
7956
7957     return result;
7958 }
7959
7960 /*****************************************************************************
7961  *
7962  *  Returns the encoding to select the datasize for the vector load/store Arm64 instructions
7963  *
7964  */
7965
7966 /*static*/ emitter::code_t emitter::insEncodeDatasizeVPLS(emitter::code_t code, emitAttr size)
7967 {
7968     code_t result = 0;
7969
7970     if (size == EA_16BYTE)
7971     {
7972         // The operation size in bits 31 and 30 are zero
7973         // Bit 23 specifies a 128-bit Load/Store
7974         result = 0x80000000;
7975     }
7976     else if (size == EA_8BYTE)
7977     {
7978         // set the operation size in bits 31 and 30
7979         result = 0x40000000;
7980     }
7981     else if (size == EA_4BYTE)
7982     {
7983         // set the operation size in bit 31
7984         result = 0x00000000;
7985     }
7986
7987     // Or in bit 26 to indicate a Vector register is used as 'target'
7988     result |= 0x04000000;
7989
7990     return result;
7991 }
7992
7993 /*****************************************************************************
7994  *
7995  *  Returns the encoding to set the size bit and the N bits for a 'bitfield' instruction
7996  *
7997  */
7998
7999 /*static*/ emitter::code_t emitter::insEncodeDatasizeBF(emitter::code_t code, emitAttr size)
8000 {
8001     // is bit 30 equal to 0?
8002     if ((code & 0x40000000) == 0) // is the opcode one of extr, sxtb, sxth or sxtw
8003     {
8004         if (size == EA_8BYTE) // Do we need to set the sf and N bits?
8005         {
8006             return 0x80400000; // set the sf-bit at location 31 and the N-bit at location 22
8007         }
8008     }
8009     return 0; // don't set any bits
8010 }
8011
8012 /*****************************************************************************
8013  *
8014  *  Returns the encoding to select the 64/128-bit datasize for an Arm64 vector instruction
8015  */
8016
8017 /*static*/ emitter::code_t emitter::insEncodeVectorsize(emitAttr size)
8018 {
8019     if (size == EA_16BYTE)
8020     {
8021         return 0x40000000; // set the bit at location 30
8022     }
8023     else
8024     {
8025         assert(size == EA_8BYTE);
8026         return 0;
8027     }
8028 }
8029
8030 /*****************************************************************************
8031  *
8032  *  Returns the encoding to select 'index' for an Arm64 vector elem instruction
8033  */
8034 /*static*/ emitter::code_t emitter::insEncodeVectorIndex(emitAttr elemsize, ssize_t index)
8035 {
8036     code_t bits = (code_t)index;
8037     if (elemsize == EA_1BYTE)
8038     {
8039         bits <<= 1;
8040         bits |= 1;
8041     }
8042     else if (elemsize == EA_2BYTE)
8043     {
8044         bits <<= 2;
8045         bits |= 2;
8046     }
8047     else if (elemsize == EA_4BYTE)
8048     {
8049         bits <<= 3;
8050         bits |= 4;
8051     }
8052     else
8053     {
8054         assert(elemsize == EA_8BYTE);
8055         bits <<= 4;
8056         bits |= 8;
8057     }
8058     assert((bits >= 1) && (bits <= 0x1f));
8059
8060     return (bits << 16); // bits at locations [20,19,18,17,16]
8061 }
8062
8063 /*****************************************************************************
8064  *
8065  *  Returns the encoding to select 'index2' for an Arm64 'ins' elem instruction
8066  */
8067 /*static*/ emitter::code_t emitter::insEncodeVectorIndex2(emitAttr elemsize, ssize_t index2)
8068 {
8069     code_t bits = (code_t)index2;
8070     if (elemsize == EA_1BYTE)
8071     {
8072         // bits are correct
8073     }
8074     else if (elemsize == EA_2BYTE)
8075     {
8076         bits <<= 1;
8077     }
8078     else if (elemsize == EA_4BYTE)
8079     {
8080         bits <<= 2;
8081     }
8082     else
8083     {
8084         assert(elemsize == EA_8BYTE);
8085         bits <<= 3;
8086     }
8087     assert((bits >= 0) && (bits <= 0xf));
8088
8089     return (bits << 11); // bits at locations [14,13,12,11]
8090 }
8091
8092 /*****************************************************************************
8093  *
8094  *  Returns the encoding to select the 'index' for an Arm64 'mul' by elem instruction
8095  */
8096 /*static*/ emitter::code_t emitter::insEncodeVectorIndexLMH(emitAttr elemsize, ssize_t index)
8097 {
8098     code_t bits = 0;
8099
8100     if (elemsize == EA_2BYTE)
8101     {
8102         assert((index >= 0) && (index <= 7));
8103         if (index & 0x4)
8104         {
8105             bits |= (1 << 11); // set bit 11 'H'
8106         }
8107         if (index & 0x2)
8108         {
8109             bits |= (1 << 21); // set bit 21 'L'
8110         }
8111         if (index & 0x1)
8112         {
8113             bits |= (1 << 20); // set bit 20 'M'
8114         }
8115     }
8116     else if (elemsize == EA_4BYTE)
8117     {
8118         assert((index >= 0) && (index <= 3));
8119         if (index & 0x2)
8120         {
8121             bits |= (1 << 11); // set bit 11 'H'
8122         }
8123         if (index & 0x1)
8124         {
8125             bits |= (1 << 21); // set bit 21 'L'
8126         }
8127     }
8128     else
8129     {
8130         assert(!"Invalid 'elemsize' value");
8131     }
8132
8133     return bits;
8134 }
8135
8136 /*****************************************************************************
8137  *
8138  *   Returns the encoding to shift by 'shift' for an Arm64 vector or scalar instruction
8139  */
8140
8141 /*static*/ emitter::code_t emitter::insEncodeVectorShift(emitAttr size, ssize_t shift)
8142 {
8143     assert(shift < getBitWidth(size));
8144
8145     code_t imm = (code_t)(getBitWidth(size) + shift);
8146
8147     return imm << 16;
8148 }
8149
8150 /*****************************************************************************
8151  *
8152  *  Returns the encoding to select the 1/2/4/8 byte elemsize for an Arm64 vector instruction
8153  */
8154
8155 /*static*/ emitter::code_t emitter::insEncodeElemsize(emitAttr size)
8156 {
8157     if (size == EA_8BYTE)
8158     {
8159         return 0x00C00000; // set the bit at location 23 and 22
8160     }
8161     else if (size == EA_4BYTE)
8162     {
8163         return 0x00800000; // set the bit at location 23
8164     }
8165     else if (size == EA_2BYTE)
8166     {
8167         return 0x00400000; // set the bit at location 22
8168     }
8169     assert(size == EA_1BYTE);
8170     return 0x00000000;
8171 }
8172
8173 /*****************************************************************************
8174  *
8175  *  Returns the encoding to select the 4/8 byte elemsize for an Arm64 float vector instruction
8176  */
8177
8178 /*static*/ emitter::code_t emitter::insEncodeFloatElemsize(emitAttr size)
8179 {
8180     if (size == EA_8BYTE)
8181     {
8182         return 0x00400000; // set the bit at location 22
8183     }
8184     assert(size == EA_4BYTE);
8185     return 0x00000000;
8186 }
8187
8188 // Returns the encoding to select the index for an Arm64 float vector by elem instruction
8189 /*static*/ emitter::code_t emitter::insEncodeFloatIndex(emitAttr elemsize, ssize_t index)
8190 {
8191     code_t result = 0x00000000;
8192     if (elemsize == EA_8BYTE)
8193     {
8194         assert((index >= 0) && (index <= 1));
8195         if (index == 1)
8196         {
8197             result |= 0x00000800; // 'H' - set the bit at location 11
8198         }
8199     }
8200     else
8201     {
8202         assert(elemsize == EA_4BYTE);
8203         assert((index >= 0) && (index <= 3));
8204         if (index & 2)
8205         {
8206             result |= 0x00000800; // 'H' - set the bit at location 11
8207         }
8208         if (index & 1)
8209         {
8210             result |= 0x00200000; // 'L' - set the bit at location 21
8211         }
8212     }
8213     return result;
8214 }
8215
8216 /*****************************************************************************
8217  *
8218  *  Returns the encoding to select the fcvt operation for Arm64 instructions
8219  */
8220 /*static*/ emitter::code_t emitter::insEncodeConvertOpt(insFormat fmt, insOpts conversion)
8221 {
8222     code_t result = 0;
8223     switch (conversion)
8224     {
8225         case INS_OPTS_S_TO_D: // Single to Double
8226             assert(fmt == IF_DV_2J);
8227             result = 0x00008000; // type=00, opc=01
8228             break;
8229
8230         case INS_OPTS_D_TO_S: // Double to Single
8231             assert(fmt == IF_DV_2J);
8232             result = 0x00400000; // type=01, opc=00
8233             break;
8234
8235         case INS_OPTS_H_TO_S: // Half to Single
8236             assert(fmt == IF_DV_2J);
8237             result = 0x00C00000; // type=11, opc=00
8238             break;
8239
8240         case INS_OPTS_H_TO_D: // Half to Double
8241             assert(fmt == IF_DV_2J);
8242             result = 0x00C08000; // type=11, opc=01
8243             break;
8244
8245         case INS_OPTS_S_TO_H: // Single to Half
8246             assert(fmt == IF_DV_2J);
8247             result = 0x00018000; // type=00, opc=11
8248             break;
8249
8250         case INS_OPTS_D_TO_H: // Double to Half
8251             assert(fmt == IF_DV_2J);
8252             result = 0x00418000; // type=01, opc=11
8253             break;
8254
8255         case INS_OPTS_S_TO_4BYTE: // Single to INT32
8256             assert(fmt == IF_DV_2H);
8257             result = 0x00000000; // sf=0, type=00
8258             break;
8259
8260         case INS_OPTS_D_TO_4BYTE: // Double to INT32
8261             assert(fmt == IF_DV_2H);
8262             result = 0x00400000; // sf=0, type=01
8263             break;
8264
8265         case INS_OPTS_S_TO_8BYTE: // Single to INT64
8266             assert(fmt == IF_DV_2H);
8267             result = 0x80000000; // sf=1, type=00
8268             break;
8269
8270         case INS_OPTS_D_TO_8BYTE: // Double to INT64
8271             assert(fmt == IF_DV_2H);
8272             result = 0x80400000; // sf=1, type=01
8273             break;
8274
8275         case INS_OPTS_4BYTE_TO_S: // INT32 to Single
8276             assert(fmt == IF_DV_2I);
8277             result = 0x00000000; // sf=0, type=00
8278             break;
8279
8280         case INS_OPTS_4BYTE_TO_D: // INT32 to Double
8281             assert(fmt == IF_DV_2I);
8282             result = 0x00400000; // sf=0, type=01
8283             break;
8284
8285         case INS_OPTS_8BYTE_TO_S: // INT64 to Single
8286             assert(fmt == IF_DV_2I);
8287             result = 0x80000000; // sf=1, type=00
8288             break;
8289
8290         case INS_OPTS_8BYTE_TO_D: // INT64 to Double
8291             assert(fmt == IF_DV_2I);
8292             result = 0x80400000; // sf=1, type=01
8293             break;
8294
8295         default:
8296             assert(!"Invalid 'conversion' value");
8297             break;
8298     }
8299     return result;
8300 }
8301
8302 /*****************************************************************************
8303  *
8304  *  Returns the encoding to have the Rn register be updated Pre/Post indexed
8305  *  or not updated
8306  */
8307
8308 /*static*/ emitter::code_t emitter::insEncodeIndexedOpt(insOpts opt)
8309 {
8310     assert(emitter::insOptsNone(opt) || emitter::insOptsIndexed(opt));
8311
8312     if (emitter::insOptsIndexed(opt))
8313     {
8314         if (emitter::insOptsPostIndex(opt))
8315         {
8316             return 0x00000400; // set the bit at location 10
8317         }
8318         else
8319         {
8320             assert(emitter::insOptsPreIndex(opt));
8321             return 0x00000C00; // set the bit at location 10 and 11
8322         }
8323     }
8324     else
8325     {
8326         assert(emitter::insOptsNone(opt));
8327         return 0; // bits 10 and 11 are zero
8328     }
8329 }
8330
8331 /*****************************************************************************
8332  *
8333  *  Returns the encoding for a ldp/stp instruction to have the Rn register
8334  *  be updated Pre/Post indexed or not updated
8335  */
8336
8337 /*static*/ emitter::code_t emitter::insEncodePairIndexedOpt(instruction ins, insOpts opt)
8338 {
8339     assert(emitter::insOptsNone(opt) || emitter::insOptsIndexed(opt));
8340
8341     if ((ins == INS_ldnp) || (ins == INS_stnp))
8342     {
8343         assert(emitter::insOptsNone(opt));
8344         return 0; // bits 23 and 24 are zero
8345     }
8346     else
8347     {
8348         if (emitter::insOptsIndexed(opt))
8349         {
8350             if (emitter::insOptsPostIndex(opt))
8351             {
8352                 return 0x00800000; // set the bit at location 23
8353             }
8354             else
8355             {
8356                 assert(emitter::insOptsPreIndex(opt));
8357                 return 0x01800000; // set the bit at location 24 and 23
8358             }
8359         }
8360         else
8361         {
8362             assert(emitter::insOptsNone(opt));
8363             return 0x01000000; // set the bit at location 24
8364         }
8365     }
8366 }
8367
8368 /*****************************************************************************
8369  *
8370  *  Returns the encoding to apply a Shift Type on the Rm register
8371  */
8372
8373 /*static*/ emitter::code_t emitter::insEncodeShiftType(insOpts opt)
8374 {
8375     if (emitter::insOptsNone(opt))
8376     {
8377         // None implies the we encode LSL (with a zero immediate)
8378         opt = INS_OPTS_LSL;
8379     }
8380     assert(emitter::insOptsAnyShift(opt));
8381
8382     emitter::code_t option = (emitter::code_t)opt - (emitter::code_t)INS_OPTS_LSL;
8383     assert(option <= 3);
8384
8385     return option << 22; // bits 23, 22
8386 }
8387
8388 /*****************************************************************************
8389  *
8390  *  Returns the encoding to apply a 12 bit left shift to the immediate
8391  */
8392
8393 /*static*/ emitter::code_t emitter::insEncodeShiftImm12(insOpts opt)
8394 {
8395     if (emitter::insOptsLSL12(opt))
8396     {
8397         return 0x00400000; // set the bit at location 22
8398     }
8399     return 0;
8400 }
8401
8402 /*****************************************************************************
8403  *
8404  *  Returns the encoding to have the Rm register use an extend operation
8405  */
8406
8407 /*static*/ emitter::code_t emitter::insEncodeExtend(insOpts opt)
8408 {
8409     if (emitter::insOptsNone(opt) || (opt == INS_OPTS_LSL))
8410     {
8411         // None or LSL implies the we encode UXTX
8412         opt = INS_OPTS_UXTX;
8413     }
8414     assert(emitter::insOptsAnyExtend(opt));
8415
8416     emitter::code_t option = (emitter::code_t)opt - (emitter::code_t)INS_OPTS_UXTB;
8417     assert(option <= 7);
8418
8419     return option << 13; // bits 15,14,13
8420 }
8421
8422 /*****************************************************************************
8423  *
8424  *  Returns the encoding to scale the Rm register by {0,1,2,3,4}
8425  *  when using an extend operation
8426  */
8427
8428 /*static*/ emitter::code_t emitter::insEncodeExtendScale(ssize_t imm)
8429 {
8430     assert((imm >= 0) && (imm <= 4));
8431
8432     return (emitter::code_t)imm << 10; // bits 12,11,10
8433 }
8434
8435 /*****************************************************************************
8436  *
8437  *  Returns the encoding to have the Rm register be auto scaled by the ld/st size
8438  */
8439
8440 /*static*/ emitter::code_t emitter::insEncodeReg3Scale(bool isScaled)
8441 {
8442     if (isScaled)
8443     {
8444         return 0x00001000; // set the bit at location 12
8445     }
8446     else
8447     {
8448         return 0;
8449     }
8450 }
8451
8452 BYTE* emitter::emitOutputLoadLabel(BYTE* dst, BYTE* srcAddr, BYTE* dstAddr, instrDescJmp* id)
8453 {
8454     instruction ins    = id->idIns();
8455     insFormat   fmt    = id->idInsFmt();
8456     regNumber   dstReg = id->idReg1();
8457     if (id->idjShort)
8458     {
8459         // adr x, [rel addr] --  compute address: current addr(ip) + rel addr.
8460         assert(ins == INS_adr);
8461         assert(fmt == IF_DI_1E);
8462         ssize_t distVal = (ssize_t)(dstAddr - srcAddr);
8463         dst             = emitOutputShortAddress(dst, ins, fmt, distVal, dstReg);
8464     }
8465     else
8466     {
8467         // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8468         assert(fmt == IF_LARGEADR);
8469         ssize_t relPageAddr =
8470             (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8471         dst = emitOutputShortAddress(dst, INS_adrp, IF_DI_1E, relPageAddr, dstReg);
8472
8473         // add x, x, page offs -- compute address = page addr + page offs
8474         ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8475         assert(isValidUimm12(imm12));
8476         code_t code =
8477             emitInsCode(INS_add, IF_DI_2A);  // DI_2A  X0010001shiiiiii iiiiiinnnnnddddd   1100 0000   imm(i12, sh)
8478         code |= insEncodeDatasize(EA_8BYTE); // X
8479         code |= ((code_t)imm12 << 10);       // iiiiiiiiiiii
8480         code |= insEncodeReg_Rd(dstReg);     // ddddd
8481         code |= insEncodeReg_Rn(dstReg);     // nnnnn
8482         dst += emitOutput_Instr(dst, code);
8483     }
8484     return dst;
8485 }
8486
8487 /*****************************************************************************
8488  *
8489  *  Output a local jump or other instruction with a pc-relative immediate.
8490  *  Note that this may be invoked to overwrite an existing jump instruction at 'dst'
8491  *  to handle forward branch patching.
8492  */
8493
8494 BYTE* emitter::emitOutputLJ(insGroup* ig, BYTE* dst, instrDesc* i)
8495 {
8496     instrDescJmp* id = (instrDescJmp*)i;
8497
8498     unsigned srcOffs;
8499     unsigned dstOffs;
8500     BYTE*    srcAddr;
8501     BYTE*    dstAddr;
8502     ssize_t  distVal;
8503     ssize_t  loBits;
8504
8505     // Set default ins/fmt from id.
8506     instruction ins = id->idIns();
8507     insFormat   fmt = id->idInsFmt();
8508
8509     bool loadLabel    = false;
8510     bool isJump       = false;
8511     bool loadConstant = false;
8512
8513     switch (ins)
8514     {
8515         default:
8516             isJump = true;
8517             break;
8518
8519         case INS_tbz:
8520         case INS_tbnz:
8521         case INS_cbz:
8522         case INS_cbnz:
8523             isJump = true;
8524             break;
8525
8526         case INS_ldr:
8527         case INS_ldrsw:
8528             loadConstant = true;
8529             break;
8530
8531         case INS_adr:
8532         case INS_adrp:
8533             loadLabel = true;
8534             break;
8535     }
8536
8537     /* Figure out the distance to the target */
8538
8539     srcOffs = emitCurCodeOffs(dst);
8540     srcAddr = emitOffsetToPtr(srcOffs);
8541
8542     if (id->idAddr()->iiaIsJitDataOffset())
8543     {
8544         assert(loadConstant || loadLabel);
8545         int doff = id->idAddr()->iiaGetJitDataOffset();
8546         assert(doff >= 0);
8547         ssize_t imm = emitGetInsSC(id);
8548         assert((imm >= 0) && (imm < 0x1000)); // 0x1000 is arbitrary, currently 'imm' is always 0
8549
8550         unsigned dataOffs = (unsigned)(doff + imm);
8551         assert(dataOffs < emitDataSize());
8552         dstAddr = emitDataOffsetToPtr(dataOffs);
8553
8554         regNumber dstReg  = id->idReg1();
8555         regNumber addrReg = dstReg; // an integer register to compute long address.
8556         emitAttr  opSize  = id->idOpSize();
8557
8558         if (loadConstant)
8559         {
8560             if (id->idjShort)
8561             {
8562                 // ldr x/v, [rel addr] -- load constant from current addr(ip) + rel addr.
8563                 assert(ins == INS_ldr);
8564                 assert(fmt == IF_LS_1A);
8565                 distVal = (ssize_t)(dstAddr - srcAddr);
8566                 dst     = emitOutputShortConstant(dst, ins, fmt, distVal, dstReg, opSize);
8567             }
8568             else
8569             {
8570                 // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8571                 assert(fmt == IF_LARGELDC);
8572                 ssize_t relPageAddr =
8573                     (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8574                 if (isVectorRegister(dstReg))
8575                 {
8576                     // Update addrReg with the reserved integer register
8577                     // since we cannot use dstReg (vector) to load constant directly from memory.
8578                     addrReg = id->idReg2();
8579                     assert(isGeneralRegister(addrReg));
8580                 }
8581                 ins = INS_adrp;
8582                 fmt = IF_DI_1E;
8583                 dst = emitOutputShortAddress(dst, ins, fmt, relPageAddr, addrReg);
8584
8585                 // ldr x, [x, page offs] -- load constant from page address + page offset into integer register.
8586                 ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8587                 assert(isValidUimm12(imm12));
8588                 ins = INS_ldr;
8589                 fmt = IF_LS_2B;
8590                 dst = emitOutputShortConstant(dst, ins, fmt, imm12, addrReg, opSize);
8591
8592                 // fmov v, d -- copy constant in integer register to vector register.
8593                 // This is needed only for vector constant.
8594                 if (addrReg != dstReg)
8595                 {
8596                     //  fmov    Vd,Rn                DV_2I  X00111100X100111 000000nnnnnddddd   1E27 0000   Vd,Rn
8597                     //  (scalar, from general)
8598                     assert(isVectorRegister(dstReg) && isGeneralRegister(addrReg));
8599                     ins         = INS_fmov;
8600                     fmt         = IF_DV_2I;
8601                     code_t code = emitInsCode(ins, fmt);
8602
8603                     code |= insEncodeReg_Vd(dstReg);  // ddddd
8604                     code |= insEncodeReg_Rn(addrReg); // nnnnn
8605                     if (id->idOpSize() == EA_8BYTE)
8606                     {
8607                         code |= 0x80400000; // X ... X
8608                     }
8609                     dst += emitOutput_Instr(dst, code);
8610                 }
8611             }
8612         }
8613         else
8614         {
8615             assert(loadLabel);
8616             dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8617         }
8618
8619         return dst;
8620     }
8621
8622     assert(loadLabel || isJump);
8623
8624     if (id->idAddr()->iiaHasInstrCount())
8625     {
8626         assert(ig != NULL);
8627         int      instrCount = id->idAddr()->iiaGetInstrCount();
8628         unsigned insNum     = emitFindInsNum(ig, id);
8629         if (instrCount < 0)
8630         {
8631             // Backward branches using instruction count must be within the same instruction group.
8632             assert(insNum + 1 >= (unsigned)(-instrCount));
8633         }
8634         dstOffs = ig->igOffs + emitFindOffset(ig, (insNum + 1 + instrCount));
8635         dstAddr = emitOffsetToPtr(dstOffs);
8636     }
8637     else
8638     {
8639         dstOffs = id->idAddr()->iiaIGlabel->igOffs;
8640         dstAddr = emitOffsetToPtr(dstOffs);
8641     }
8642
8643     distVal = (ssize_t)(dstAddr - srcAddr);
8644
8645     if (dstOffs <= srcOffs)
8646     {
8647 #if DEBUG_EMIT
8648         /* This is a backward jump - distance is known at this point */
8649
8650         if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8651         {
8652             size_t blkOffs = id->idjIG->igOffs;
8653
8654             if (INTERESTING_JUMP_NUM == 0)
8655                 printf("[3] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8656             printf("[3] Jump  block is at %08X - %02X = %08X\n", blkOffs, emitOffsAdj, blkOffs - emitOffsAdj);
8657             printf("[3] Jump        is at %08X - %02X = %08X\n", srcOffs, emitOffsAdj, srcOffs - emitOffsAdj);
8658             printf("[3] Label block is at %08X - %02X = %08X\n", dstOffs, emitOffsAdj, dstOffs - emitOffsAdj);
8659         }
8660 #endif
8661     }
8662     else
8663     {
8664         /* This is a  forward jump - distance will be an upper limit */
8665
8666         emitFwdJumps = true;
8667
8668         /* The target offset will be closer by at least 'emitOffsAdj', but only if this
8669            jump doesn't cross the hot-cold boundary. */
8670
8671         if (!emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8672         {
8673             dstOffs -= emitOffsAdj;
8674             distVal -= emitOffsAdj;
8675         }
8676
8677         /* Record the location of the jump for later patching */
8678
8679         id->idjOffs = dstOffs;
8680
8681         /* Are we overflowing the id->idjOffs bitfield? */
8682         if (id->idjOffs != dstOffs)
8683             IMPL_LIMITATION("Method is too large");
8684
8685 #if DEBUG_EMIT
8686         if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8687         {
8688             size_t blkOffs = id->idjIG->igOffs;
8689
8690             if (INTERESTING_JUMP_NUM == 0)
8691                 printf("[4] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8692             printf("[4] Jump  block is at %08X\n", blkOffs);
8693             printf("[4] Jump        is at %08X\n", srcOffs);
8694             printf("[4] Label block is at %08X - %02X = %08X\n", dstOffs + emitOffsAdj, emitOffsAdj, dstOffs);
8695         }
8696 #endif
8697     }
8698
8699 #ifdef DEBUG
8700     if (0 && emitComp->verbose)
8701     {
8702         size_t sz          = 4;
8703         int    distValSize = id->idjShort ? 4 : 8;
8704         printf("; %s jump [%08X/%03u] from %0*X to %0*X: dist = %08XH\n", (dstOffs <= srcOffs) ? "Fwd" : "Bwd",
8705                dspPtr(id), id->idDebugOnlyInfo()->idNum, distValSize, srcOffs + sz, distValSize, dstOffs, distVal);
8706     }
8707 #endif
8708
8709     /* For forward jumps, record the address of the distance value */
8710     id->idjTemp.idjAddr = (distVal > 0) ? dst : NULL;
8711
8712     if (emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8713     {
8714         assert(!id->idjShort);
8715         NYI_ARM64("Relocation Support for long address");
8716     }
8717
8718     assert(insOptsNone(id->idInsOpt()));
8719
8720     if (isJump)
8721     {
8722         if (id->idjShort)
8723         {
8724             // Short conditional/unconditional jump
8725             assert(!id->idjKeepLong);
8726             assert(emitJumpCrossHotColdBoundary(srcOffs, dstOffs) == false);
8727             assert((fmt == IF_BI_0A) || (fmt == IF_BI_0B) || (fmt == IF_BI_1A) || (fmt == IF_BI_1B));
8728         }
8729         else
8730         {
8731             // Long conditional jump
8732             assert(fmt == IF_LARGEJMP);
8733             // This is a pseudo-instruction format representing a large conditional branch, to allow
8734             // us to get a greater branch target range than we can get by using a straightforward conditional
8735             // branch. It is encoded as a short conditional branch that branches around a long unconditional
8736             // branch.
8737             //
8738             // Conceptually, we have:
8739             //
8740             //      b<cond> L_target
8741             //
8742             // The code we emit is:
8743             //
8744             //      b<!cond> L_not  // 4 bytes. Note that we reverse the condition.
8745             //      b L_target      // 4 bytes
8746             //   L_not:
8747             //
8748             // Note that we don't actually insert any blocks: we simply encode "b <!cond> L_not" as a branch with
8749             // the correct offset. Note also that this works for both integer and floating-point conditions, because
8750             // the condition inversion takes ordered/unordered into account, preserving NaN behavior. For example,
8751             // "GT" (greater than) is inverted to "LE" (less than, equal, or unordered).
8752
8753             instruction reverseIns;
8754             insFormat   reverseFmt;
8755
8756             switch (ins)
8757             {
8758                 case INS_cbz:
8759                     reverseIns = INS_cbnz;
8760                     reverseFmt = IF_BI_1A;
8761                     break;
8762                 case INS_cbnz:
8763                     reverseIns = INS_cbz;
8764                     reverseFmt = IF_BI_1A;
8765                     break;
8766                 case INS_tbz:
8767                     reverseIns = INS_tbnz;
8768                     reverseFmt = IF_BI_1B;
8769                     break;
8770                 case INS_tbnz:
8771                     reverseIns = INS_tbz;
8772                     reverseFmt = IF_BI_1B;
8773                     break;
8774                 default:
8775                     reverseIns = emitJumpKindToIns(emitReverseJumpKind(emitInsToJumpKind(ins)));
8776                     reverseFmt = IF_BI_0B;
8777             }
8778
8779             dst =
8780                 emitOutputShortBranch(dst,
8781                                       reverseIns, // reverse the conditional instruction
8782                                       reverseFmt,
8783                                       8, /* 8 bytes from start of this large conditional pseudo-instruction to L_not. */
8784                                       id);
8785
8786             // Now, pretend we've got a normal unconditional branch, and fall through to the code to emit that.
8787             ins = INS_b;
8788             fmt = IF_BI_0A;
8789
8790             // The distVal was computed based on the beginning of the pseudo-instruction,
8791             // So subtract the size of the conditional branch so that it is relative to the
8792             // unconditional branch.
8793             distVal -= 4;
8794         }
8795
8796         dst = emitOutputShortBranch(dst, ins, fmt, distVal, id);
8797     }
8798     else if (loadLabel)
8799     {
8800         dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8801     }
8802
8803     return dst;
8804 }
8805
8806 /*****************************************************************************
8807 *
8808 *  Output a short branch instruction.
8809 */
8810 BYTE* emitter::emitOutputShortBranch(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, instrDescJmp* id)
8811 {
8812     code_t code = emitInsCode(ins, fmt);
8813
8814     ssize_t loBits = (distVal & 3);
8815     noway_assert(loBits == 0);
8816     distVal >>= 2; // branch offset encodings are scaled by 4.
8817
8818     if (fmt == IF_BI_0A)
8819     {
8820         // INS_b or INS_bl_local
8821         noway_assert(isValidSimm26(distVal));
8822         distVal &= 0x3FFFFFFLL;
8823         code |= distVal;
8824     }
8825     else if (fmt == IF_BI_0B) // BI_0B   01010100iiiiiiii iiiiiiiiiiiXXXXX      simm19:00
8826     {
8827         // INS_beq, INS_bne, etc...
8828         noway_assert(isValidSimm19(distVal));
8829         distVal &= 0x7FFFFLL;
8830         code |= distVal << 5;
8831     }
8832     else if (fmt == IF_BI_1A) // BI_1A   X.......iiiiiiii iiiiiiiiiiittttt      Rt simm19:00
8833     {
8834         // INS_cbz or INS_cbnz
8835         assert(id != nullptr);
8836         code |= insEncodeDatasize(id->idOpSize()); // X
8837         code |= insEncodeReg_Rt(id->idReg1());     // ttttt
8838
8839         noway_assert(isValidSimm19(distVal));
8840         distVal &= 0x7FFFFLL; // 19 bits
8841         code |= distVal << 5;
8842     }
8843     else if (fmt == IF_BI_1B) // BI_1B   B.......bbbbbiii iiiiiiiiiiittttt      Rt imm6, simm14:00
8844     {
8845         // INS_tbz or INS_tbnz
8846         assert(id != nullptr);
8847         ssize_t imm = emitGetInsSC(id);
8848         assert(isValidImmShift(imm, id->idOpSize()));
8849
8850         if (imm & 0x20) // test bit 32-63 ?
8851         {
8852             code |= 0x80000000; // B
8853         }
8854         code |= ((imm & 0x1F) << 19);          // bbbbb
8855         code |= insEncodeReg_Rt(id->idReg1()); // ttttt
8856
8857         noway_assert(isValidSimm14(distVal));
8858         distVal &= 0x3FFFLL; // 14 bits
8859         code |= distVal << 5;
8860     }
8861     else
8862     {
8863         assert(!"Unknown fmt for emitOutputShortBranch");
8864     }
8865
8866     dst += emitOutput_Instr(dst, code);
8867
8868     return dst;
8869 }
8870
8871 /*****************************************************************************
8872 *
8873 *  Output a short address instruction.
8874 */
8875 BYTE* emitter::emitOutputShortAddress(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, regNumber reg)
8876 {
8877     ssize_t loBits = (distVal & 3);
8878     distVal >>= 2;
8879
8880     code_t code = emitInsCode(ins, fmt);
8881     if (fmt == IF_DI_1E) // DI_1E   .ii.....iiiiiiii iiiiiiiiiiiddddd      Rd simm21
8882     {
8883         // INS_adr or INS_adrp
8884         code |= insEncodeReg_Rd(reg); // ddddd
8885
8886         noway_assert(isValidSimm19(distVal));
8887         distVal &= 0x7FFFFLL; // 19 bits
8888         code |= distVal << 5;
8889         code |= loBits << 29; //  2 bits
8890     }
8891     else
8892     {
8893         assert(!"Unknown fmt for emitOutputShortAddress");
8894     }
8895
8896     dst += emitOutput_Instr(dst, code);
8897
8898     return dst;
8899 }
8900
8901 /*****************************************************************************
8902 *
8903 *  Output a short constant instruction.
8904 */
8905 BYTE* emitter::emitOutputShortConstant(
8906     BYTE* dst, instruction ins, insFormat fmt, ssize_t imm, regNumber reg, emitAttr opSize)
8907 {
8908     code_t code = emitInsCode(ins, fmt);
8909
8910     if (fmt == IF_LS_1A)
8911     {
8912         // LS_1A   XX...V..iiiiiiii iiiiiiiiiiittttt      Rt simm21
8913         // INS_ldr or INS_ldrsw (PC-Relative)
8914
8915         ssize_t loBits = (imm & 3);
8916         noway_assert(loBits == 0);
8917         ssize_t distVal = imm >>= 2; // load offset encodings are scaled by 4.
8918
8919         noway_assert(isValidSimm19(distVal));
8920
8921         // Is the target a vector register?
8922         if (isVectorRegister(reg))
8923         {
8924             code |= insEncodeDatasizeVLS(code, opSize); // XX V
8925             code |= insEncodeReg_Vt(reg);               // ttttt
8926         }
8927         else
8928         {
8929             assert(isGeneralRegister(reg));
8930             // insEncodeDatasizeLS is not quite right for this case.
8931             // So just specialize it.
8932             if ((ins == INS_ldr) && (opSize == EA_8BYTE))
8933             {
8934                 // set the operation size in bit 30
8935                 code |= 0x40000000;
8936             }
8937
8938             code |= insEncodeReg_Rt(reg); // ttttt
8939         }
8940
8941         distVal &= 0x7FFFFLL; // 19 bits
8942         code |= distVal << 5;
8943     }
8944     else if (fmt == IF_LS_2B)
8945     {
8946         //  ldr     Rt,[Xn+pimm12]       LS_2B  1X11100101iiiiii iiiiiinnnnnttttt   B940 0000   imm(0-4095<<{2,3})
8947         // INS_ldr or INS_ldrsw (PC-Relative)
8948         noway_assert(isValidUimm12(imm));
8949         assert(isGeneralRegister(reg));
8950
8951         if (opSize == EA_8BYTE)
8952         {
8953             // insEncodeDatasizeLS is not quite right for this case.
8954             // So just specialize it.
8955             if (ins == INS_ldr)
8956             {
8957                 // set the operation size in bit 30
8958                 code |= 0x40000000;
8959             }
8960             // Low 3 bits should be 0 -- 8 byte JIT data should be aligned on 8 byte.
8961             assert((imm & 7) == 0);
8962             imm >>= 3;
8963         }
8964         else
8965         {
8966             assert(opSize == EA_4BYTE);
8967             // Low 2 bits should be 0 -- 4 byte aligned data.
8968             assert((imm & 3) == 0);
8969             imm >>= 2;
8970         }
8971
8972         code |= insEncodeReg_Rt(reg); // ttttt
8973         code |= insEncodeReg_Rn(reg); // nnnnn
8974         code |= imm << 10;
8975     }
8976     else
8977     {
8978         assert(!"Unknown fmt for emitOutputShortConstant");
8979     }
8980
8981     dst += emitOutput_Instr(dst, code);
8982
8983     return dst;
8984 }
8985 /*****************************************************************************
8986  *
8987  *  Output a call instruction.
8988  */
8989
8990 unsigned emitter::emitOutputCall(insGroup* ig, BYTE* dst, instrDesc* id, code_t code)
8991 {
8992     const unsigned char callInstrSize = sizeof(code_t); // 4 bytes
8993     regMaskTP           gcrefRegs;
8994     regMaskTP           byrefRegs;
8995
8996     VARSET_TP GCvars(VarSetOps::UninitVal());
8997
8998     // Is this a "fat" call descriptor?
8999     if (id->idIsLargeCall())
9000     {
9001         instrDescCGCA* idCall = (instrDescCGCA*)id;
9002         gcrefRegs             = idCall->idcGcrefRegs;
9003         byrefRegs             = idCall->idcByrefRegs;
9004         VarSetOps::Assign(emitComp, GCvars, idCall->idcGCvars);
9005     }
9006     else
9007     {
9008         assert(!id->idIsLargeDsp());
9009         assert(!id->idIsLargeCns());
9010
9011         gcrefRegs = emitDecodeCallGCregs(id);
9012         byrefRegs = 0;
9013         VarSetOps::AssignNoCopy(emitComp, GCvars, VarSetOps::MakeEmpty(emitComp));
9014     }
9015
9016     /* We update the GC info before the call as the variables cannot be
9017         used by the call. Killing variables before the call helps with
9018         boundary conditions if the call is CORINFO_HELP_THROW - see bug 50029.
9019         If we ever track aliased variables (which could be used by the
9020         call), we would have to keep them alive past the call. */
9021
9022     emitUpdateLiveGCvars(GCvars, dst);
9023
9024     // Now output the call instruction and update the 'dst' pointer
9025     //
9026     unsigned outputInstrSize = emitOutput_Instr(dst, code);
9027     dst += outputInstrSize;
9028
9029     // All call instructions are 4-byte in size on ARM64
9030     //
9031     assert(outputInstrSize == callInstrSize);
9032
9033     // If the method returns a GC ref, mark INTRET (R0) appropriately.
9034     if (id->idGCref() == GCT_GCREF)
9035     {
9036         gcrefRegs |= RBM_INTRET;
9037     }
9038     else if (id->idGCref() == GCT_BYREF)
9039     {
9040         byrefRegs |= RBM_INTRET;
9041     }
9042
9043     // If is a multi-register return method is called, mark INTRET_1 (X1) appropriately
9044     if (id->idIsLargeCall())
9045     {
9046         instrDescCGCA* idCall = (instrDescCGCA*)id;
9047         if (idCall->idSecondGCref() == GCT_GCREF)
9048         {
9049             gcrefRegs |= RBM_INTRET_1;
9050         }
9051         else if (idCall->idSecondGCref() == GCT_BYREF)
9052         {
9053             byrefRegs |= RBM_INTRET_1;
9054         }
9055     }
9056
9057     // If the GC register set has changed, report the new set.
9058     if (gcrefRegs != emitThisGCrefRegs)
9059     {
9060         emitUpdateLiveGCregs(GCT_GCREF, gcrefRegs, dst);
9061     }
9062     // If the Byref register set has changed, report the new set.
9063     if (byrefRegs != emitThisByrefRegs)
9064     {
9065         emitUpdateLiveGCregs(GCT_BYREF, byrefRegs, dst);
9066     }
9067
9068     // Some helper calls may be marked as not requiring GC info to be recorded.
9069     if ((!id->idIsNoGC()))
9070     {
9071         // On ARM64, as on AMD64, we don't change the stack pointer to push/pop args.
9072         // So we're not really doing a "stack pop" here (note that "args" is 0), but we use this mechanism
9073         // to record the call for GC info purposes.  (It might be best to use an alternate call,
9074         // and protect "emitStackPop" under the EMIT_TRACK_STACK_DEPTH preprocessor variable.)
9075         emitStackPop(dst, /*isCall*/ true, callInstrSize, /*args*/ 0);
9076
9077         // Do we need to record a call location for GC purposes?
9078         //
9079         if (!emitFullGCinfo)
9080         {
9081             emitRecordGCcall(dst, callInstrSize);
9082         }
9083     }
9084     return callInstrSize;
9085 }
9086
9087 /*****************************************************************************
9088  *
9089  *  Emit a 32-bit Arm64 instruction
9090  */
9091
9092 /*static*/ unsigned emitter::emitOutput_Instr(BYTE* dst, code_t code)
9093 {
9094     assert(sizeof(code_t) == 4);
9095     *((code_t*)dst) = code;
9096
9097     return sizeof(code_t);
9098 }
9099
9100 /*****************************************************************************
9101 *
9102  *  Append the machine code corresponding to the given instruction descriptor
9103  *  to the code block at '*dp'; the base of the code block is 'bp', and 'ig'
9104  *  is the instruction group that contains the instruction. Updates '*dp' to
9105  *  point past the generated code, and returns the size of the instruction
9106  *  descriptor in bytes.
9107  */
9108
9109 size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
9110 {
9111     BYTE*         dst  = *dp;
9112     BYTE*         odst = dst;
9113     code_t        code = 0;
9114     size_t        sz   = emitGetInstrDescSize(id); // TODO-ARM64-Cleanup: on ARM, this is set in each case. why?
9115     instruction   ins  = id->idIns();
9116     insFormat     fmt  = id->idInsFmt();
9117     emitAttr      size = id->idOpSize();
9118     unsigned char callInstrSize = 0;
9119     unsigned      condcode;
9120
9121 #ifdef DEBUG
9122 #if DUMP_GC_TABLES
9123     bool dspOffs = emitComp->opts.dspGCtbls;
9124 #else
9125     bool dspOffs = !emitComp->opts.disDiffable;
9126 #endif
9127 #endif // DEBUG
9128
9129     assert(REG_NA == (int)REG_NA);
9130
9131     VARSET_TP GCvars(VarSetOps::UninitVal());
9132
9133     /* What instruction format have we got? */
9134
9135     switch (fmt)
9136     {
9137         ssize_t  imm;
9138         ssize_t  index;
9139         ssize_t  index2;
9140         unsigned scale;
9141         unsigned cmode;
9142         unsigned immShift;
9143         bool     hasShift;
9144         emitAttr extSize;
9145         emitAttr elemsize;
9146         emitAttr datasize;
9147
9148         case IF_BI_0A: // BI_0A   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
9149         case IF_BI_0B: // BI_0B   ......iiiiiiiiii iiiiiiiiiii.....               simm19:00
9150         case IF_LARGEJMP:
9151             assert(id->idGCref() == GCT_NONE);
9152             assert(id->idIsBound());
9153             dst = emitOutputLJ(ig, dst, id);
9154             sz  = sizeof(instrDescJmp);
9155             break;
9156
9157         case IF_BI_0C: // BI_0C   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
9158             code = emitInsCode(ins, fmt);
9159             sz   = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
9160             dst += emitOutputCall(ig, dst, id, code);
9161             // Always call RecordRelocation so that we wire in a JumpStub when we don't reach
9162             emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_BRANCH26);
9163             break;
9164
9165         case IF_BI_1A: // BI_1A   ......iiiiiiiiii iiiiiiiiiiittttt      Rt       simm19:00
9166             assert(insOptsNone(id->idInsOpt()));
9167             assert(id->idIsBound());
9168
9169             dst = emitOutputLJ(ig, dst, id);
9170             sz  = sizeof(instrDescJmp);
9171             break;
9172
9173         case IF_BI_1B: // BI_1B   B.......bbbbbiii iiiiiiiiiiittttt      Rt imm6, simm14:00
9174             assert(insOptsNone(id->idInsOpt()));
9175             assert(id->idIsBound());
9176
9177             dst = emitOutputLJ(ig, dst, id);
9178             sz  = sizeof(instrDescJmp);
9179             break;
9180
9181         case IF_BR_1A: // BR_1A   ................ ......nnnnn.....         Rn
9182             assert(insOptsNone(id->idInsOpt()));
9183             assert((ins == INS_ret) || (ins == INS_br));
9184             code = emitInsCode(ins, fmt);
9185             code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9186
9187             dst += emitOutput_Instr(dst, code);
9188             break;
9189
9190         case IF_BR_1B: // BR_1B   ................ ......nnnnn.....         Rn
9191             assert(insOptsNone(id->idInsOpt()));
9192             assert((ins == INS_br_tail) || (ins == INS_blr));
9193             code = emitInsCode(ins, fmt);
9194             code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9195
9196             sz = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
9197             dst += emitOutputCall(ig, dst, id, code);
9198             break;
9199
9200         case IF_LS_1A: // LS_1A   XX...V..iiiiiiii iiiiiiiiiiittttt      Rt    PC imm(1MB)
9201         case IF_LARGELDC:
9202             assert(insOptsNone(id->idInsOpt()));
9203             assert(id->idIsBound());
9204
9205             dst = emitOutputLJ(ig, dst, id);
9206             sz  = sizeof(instrDescJmp);
9207             break;
9208
9209         case IF_LS_2A: // LS_2A   .X.......X...... ......nnnnnttttt      Rt Rn
9210             assert(insOptsNone(id->idInsOpt()));
9211             code = emitInsCode(ins, fmt);
9212             // Is the target a vector register?
9213             if (isVectorRegister(id->idReg1()))
9214             {
9215                 code &= 0x3FFFFFFF;                                 // clear the size bits
9216                 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9217                 code |= insEncodeReg_Vt(id->idReg1());              // ttttt
9218             }
9219             else
9220             {
9221                 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9222                 code |= insEncodeReg_Rt(id->idReg1());             // ttttt
9223             }
9224             code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9225             dst += emitOutput_Instr(dst, code);
9226             break;
9227
9228         case IF_LS_2B: // LS_2B   .X.......Xiiiiii iiiiiinnnnnttttt      Rt Rn    imm(0-4095)
9229             assert(insOptsNone(id->idInsOpt()));
9230             imm = emitGetInsSC(id);
9231             assert(isValidUimm12(imm));
9232             code = emitInsCode(ins, fmt);
9233             // Is the target a vector register?
9234             if (isVectorRegister(id->idReg1()))
9235             {
9236                 code &= 0x3FFFFFFF;                                 // clear the size bits
9237                 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9238                 code |= insEncodeReg_Vt(id->idReg1());              // ttttt
9239             }
9240             else
9241             {
9242                 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9243                 code |= insEncodeReg_Rt(id->idReg1());             // ttttt
9244             }
9245             code |= ((code_t)imm << 10);           // iiiiiiiiiiii
9246             code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9247             dst += emitOutput_Instr(dst, code);
9248             break;
9249
9250         case IF_LS_2C: // LS_2C   .X.......X.iiiii iiiiPPnnnnnttttt      Rt Rn    imm(-256..+255) no/pre/post inc
9251             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9252             imm = emitGetInsSC(id);
9253             assert((imm >= -256) && (imm <= 255)); // signed 9 bits
9254             imm &= 0x1ff;                          // force into unsigned 9 bit representation
9255             code = emitInsCode(ins, fmt);
9256             // Is the target a vector register?
9257             if (isVectorRegister(id->idReg1()))
9258             {
9259                 code &= 0x3FFFFFFF;                                 // clear the size bits
9260                 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9261                 code |= insEncodeReg_Vt(id->idReg1());              // ttttt
9262             }
9263             else
9264             {
9265                 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9266                 code |= insEncodeReg_Rt(id->idReg1());             // ttttt
9267             }
9268             code |= insEncodeIndexedOpt(id->idInsOpt()); // PP
9269             code |= ((code_t)imm << 12);                 // iiiiiiiii
9270             code |= insEncodeReg_Rn(id->idReg2());       // nnnnn
9271             dst += emitOutput_Instr(dst, code);
9272             break;
9273
9274         case IF_LS_3A: // LS_3A   .X.......X.mmmmm oooS..nnnnnttttt      Rt Rn Rm ext(Rm) LSL {}
9275             assert(insOptsLSExtend(id->idInsOpt()));
9276             code = emitInsCode(ins, fmt);
9277             // Is the target a vector register?
9278             if (isVectorRegister(id->idReg1()))
9279             {
9280                 code &= 0x3FFFFFFF;                                 // clear the size bits
9281                 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9282                 code |= insEncodeReg_Vt(id->idReg1());              // ttttt
9283             }
9284             else
9285             {
9286                 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9287                 code |= insEncodeReg_Rt(id->idReg1());             // ttttt
9288             }
9289             code |= insEncodeExtend(id->idInsOpt()); // ooo
9290             code |= insEncodeReg_Rn(id->idReg2());   // nnnnn
9291             if (id->idIsLclVar())
9292             {
9293                 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9294             }
9295             else
9296             {
9297                 code |= insEncodeReg3Scale(id->idReg3Scaled()); // S
9298                 code |= insEncodeReg_Rm(id->idReg3());          // mmmmm
9299             }
9300             dst += emitOutput_Instr(dst, code);
9301             break;
9302
9303         case IF_LS_3B: // LS_3B   X............... .aaaaannnnnddddd      Rd Ra Rn
9304             assert(insOptsNone(id->idInsOpt()));
9305             code = emitInsCode(ins, fmt);
9306             // Is the target a vector register?
9307             if (isVectorRegister(id->idReg1()))
9308             {
9309                 code &= 0x3FFFFFFF;                                  // clear the size bits
9310                 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9311                 code |= insEncodeReg_Vt(id->idReg1());               // ttttt
9312                 code |= insEncodeReg_Va(id->idReg2());               // aaaaa
9313             }
9314             else
9315             {
9316                 code |= insEncodeDatasize(id->idOpSize()); // X
9317                 code |= insEncodeReg_Rt(id->idReg1());     // ttttt
9318                 code |= insEncodeReg_Ra(id->idReg2());     // aaaaa
9319             }
9320             code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9321             dst += emitOutput_Instr(dst, code);
9322             break;
9323
9324         case IF_LS_3C: // LS_3C   X......PP.iiiiii iaaaaannnnnddddd      Rd Ra Rn imm(im7,sh)
9325             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9326             imm = emitGetInsSC(id);
9327             assert((imm >= -64) && (imm <= 63)); // signed 7 bits
9328             imm &= 0x7f;                         // force into unsigned 7 bit representation
9329             code = emitInsCode(ins, fmt);
9330             // Is the target a vector register?
9331             if (isVectorRegister(id->idReg1()))
9332             {
9333                 code &= 0x3FFFFFFF;                                  // clear the size bits
9334                 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9335                 code |= insEncodeReg_Vt(id->idReg1());               // ttttt
9336                 code |= insEncodeReg_Va(id->idReg2());               // aaaaa
9337             }
9338             else
9339             {
9340                 code |= insEncodeDatasize(id->idOpSize()); // X
9341                 code |= insEncodeReg_Rt(id->idReg1());     // ttttt
9342                 code |= insEncodeReg_Ra(id->idReg2());     // aaaaa
9343             }
9344             code |= insEncodePairIndexedOpt(ins, id->idInsOpt()); // PP
9345             code |= ((code_t)imm << 15);                          // iiiiiiiii
9346             code |= insEncodeReg_Rn(id->idReg3());                // nnnnn
9347             dst += emitOutput_Instr(dst, code);
9348             break;
9349
9350         case IF_LS_3D: // LS_3D   .X.......X.mmmmm ......nnnnnttttt      Wm Rt Rn
9351             code = emitInsCode(ins, fmt);
9352             // Arm64 store exclusive unpredictable cases
9353             assert(id->idReg1() != id->idReg2());
9354             assert(id->idReg1() != id->idReg3());
9355             code |= insEncodeDatasizeLS(code, id->idOpSize()); // X
9356             code |= insEncodeReg_Rm(id->idReg1());             // mmmmm
9357             code |= insEncodeReg_Rt(id->idReg2());             // ttttt
9358             code |= insEncodeReg_Rn(id->idReg3());             // nnnnn
9359             dst += emitOutput_Instr(dst, code);
9360             break;
9361
9362         case IF_LS_3E: // LS_3E   .X.........mmmmm ......nnnnnttttt      Rm Rt Rn ARMv8.1 LSE Atomics
9363             code = emitInsCode(ins, fmt);
9364             code |= insEncodeDatasizeLS(code, id->idOpSize()); // X
9365             code |= insEncodeReg_Rm(id->idReg1());             // mmmmm
9366             code |= insEncodeReg_Rt(id->idReg2());             // ttttt
9367             code |= insEncodeReg_Rn(id->idReg3());             // nnnnn
9368             dst += emitOutput_Instr(dst, code);
9369             break;
9370
9371         case IF_DI_1A: // DI_1A   X.......shiiiiii iiiiiinnnnn.....         Rn    imm(i12,sh)
9372             assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9373             imm = emitGetInsSC(id);
9374             assert(isValidUimm12(imm));
9375             code = emitInsCode(ins, fmt);
9376             code |= insEncodeDatasize(id->idOpSize());   // X
9377             code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9378             code |= ((code_t)imm << 10);                 // iiiiiiiiiiii
9379             code |= insEncodeReg_Rn(id->idReg1());       // nnnnn
9380             dst += emitOutput_Instr(dst, code);
9381             break;
9382
9383         case IF_DI_1B: // DI_1B   X........hwiiiii iiiiiiiiiiiddddd      Rd       imm(i16,hw)
9384             imm = emitGetInsSC(id);
9385             assert(isValidImmHWVal(imm, id->idOpSize()));
9386             code = emitInsCode(ins, fmt);
9387             code |= insEncodeDatasize(id->idOpSize()); // X
9388             code |= ((code_t)imm << 5);                // hwiiiii iiiiiiiiiii
9389             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9390             dst += emitOutput_Instr(dst, code);
9391             break;
9392
9393         case IF_DI_1C: // DI_1C   X........Nrrrrrr ssssssnnnnn.....         Rn    imm(N,r,s)
9394             imm = emitGetInsSC(id);
9395             assert(isValidImmNRS(imm, id->idOpSize()));
9396             code = emitInsCode(ins, fmt);
9397             code |= ((code_t)imm << 10);               // Nrrrrrrssssss
9398             code |= insEncodeDatasize(id->idOpSize()); // X
9399             code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9400             dst += emitOutput_Instr(dst, code);
9401             break;
9402
9403         case IF_DI_1D: // DI_1D   X........Nrrrrrr ssssss.....ddddd      Rd       imm(N,r,s)
9404             imm = emitGetInsSC(id);
9405             assert(isValidImmNRS(imm, id->idOpSize()));
9406             code = emitInsCode(ins, fmt);
9407             code |= ((code_t)imm << 10);               // Nrrrrrrssssss
9408             code |= insEncodeDatasize(id->idOpSize()); // X
9409             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9410             dst += emitOutput_Instr(dst, code);
9411             break;
9412
9413         case IF_DI_1E: // DI_1E   .ii.....iiiiiiii iiiiiiiiiiiddddd      Rd       simm21
9414         case IF_LARGEADR:
9415             assert(insOptsNone(id->idInsOpt()));
9416             if (id->idIsReloc())
9417             {
9418                 code = emitInsCode(ins, fmt);
9419                 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9420                 dst += emitOutput_Instr(dst, code);
9421                 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEBASE_REL21);
9422             }
9423             else
9424             {
9425                 // Local jmp/load case which does not need a relocation.
9426                 assert(id->idIsBound());
9427                 dst = emitOutputLJ(ig, dst, id);
9428             }
9429             sz = sizeof(instrDescJmp);
9430             break;
9431
9432         case IF_DI_1F: // DI_1F   X..........iiiii cccc..nnnnn.nzcv      Rn imm5  nzcv cond
9433             imm = emitGetInsSC(id);
9434             assert(isValidImmCondFlagsImm5(imm));
9435             {
9436                 condFlagsImm cfi;
9437                 cfi.immCFVal = (unsigned)imm;
9438                 code         = emitInsCode(ins, fmt);
9439                 code |= insEncodeDatasize(id->idOpSize()); // X
9440                 code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9441                 code |= ((code_t)cfi.imm5 << 16);          // iiiii
9442                 code |= insEncodeFlags(cfi.flags);         // nzcv
9443                 code |= insEncodeCond(cfi.cond);           // cccc
9444                 dst += emitOutput_Instr(dst, code);
9445             }
9446             break;
9447
9448         case IF_DI_2A: // DI_2A   X.......shiiiiii iiiiiinnnnnddddd      Rd Rn    imm(i12,sh)
9449             assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9450             imm = emitGetInsSC(id);
9451             assert(isValidUimm12(imm));
9452             code = emitInsCode(ins, fmt);
9453             code |= insEncodeDatasize(id->idOpSize());   // X
9454             code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9455             code |= ((code_t)imm << 10);                 // iiiiiiiiiiii
9456             code |= insEncodeReg_Rd(id->idReg1());       // ddddd
9457             code |= insEncodeReg_Rn(id->idReg2());       // nnnnn
9458             dst += emitOutput_Instr(dst, code);
9459
9460             if (id->idIsReloc())
9461             {
9462                 assert(sz == sizeof(instrDesc));
9463                 assert(id->idAddr()->iiaAddr != nullptr);
9464                 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEOFFSET_12A);
9465             }
9466             break;
9467
9468         case IF_DI_2B: // DI_2B   X.........Xnnnnn ssssssnnnnnddddd      Rd Rn    imm(0-63)
9469             code = emitInsCode(ins, fmt);
9470             imm  = emitGetInsSC(id);
9471             assert(isValidImmShift(imm, id->idOpSize()));
9472             code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9473             code |= insEncodeReg_Rd(id->idReg1());             // ddddd
9474             code |= insEncodeReg_Rn(id->idReg2());             // nnnnn
9475             code |= insEncodeReg_Rm(id->idReg2());             // Reg2 also in mmmmm
9476             code |= insEncodeShiftCount(imm, id->idOpSize());  // ssssss
9477             dst += emitOutput_Instr(dst, code);
9478             break;
9479
9480         case IF_DI_2C: // DI_2C   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imm(N,r,s)
9481             imm = emitGetInsSC(id);
9482             assert(isValidImmNRS(imm, id->idOpSize()));
9483             code = emitInsCode(ins, fmt);
9484             code |= ((code_t)imm << 10);               // Nrrrrrrssssss
9485             code |= insEncodeDatasize(id->idOpSize()); // X
9486             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9487             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9488             dst += emitOutput_Instr(dst, code);
9489             break;
9490
9491         case IF_DI_2D: // DI_2D   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imr, imms   (N,r,s)
9492             if (ins == INS_asr || ins == INS_lsl || ins == INS_lsr)
9493             {
9494                 imm = emitGetInsSC(id);
9495                 assert(isValidImmShift(imm, id->idOpSize()));
9496
9497                 // Shift immediates are aliases of the SBFM/UBFM instructions
9498                 // that actually take 2 registers and 2 constants,
9499                 // Since we stored the shift immediate value
9500                 // we need to calculate the N,R and S values here.
9501
9502                 bitMaskImm bmi;
9503                 bmi.immNRS = 0;
9504
9505                 bmi.immN = (size == EA_8BYTE) ? 1 : 0;
9506                 bmi.immR = imm;
9507                 bmi.immS = (size == EA_8BYTE) ? 0x3f : 0x1f;
9508
9509                 // immR and immS are now set correctly for INS_asr and INS_lsr
9510                 // but for INS_lsl we have to adjust the values for immR and immS
9511                 //
9512                 if (ins == INS_lsl)
9513                 {
9514                     bmi.immR = -imm & bmi.immS;
9515                     bmi.immS = bmi.immS - imm;
9516                 }
9517
9518                 // setup imm with the proper 13 bit value N:R:S
9519                 //
9520                 imm = bmi.immNRS;
9521             }
9522             else
9523             {
9524                 // The other instructions have already have encoded N,R and S values
9525                 imm = emitGetInsSC(id);
9526             }
9527             assert(isValidImmNRS(imm, id->idOpSize()));
9528
9529             code = emitInsCode(ins, fmt);
9530             code |= ((code_t)imm << 10);               // Nrrrrrrssssss
9531             code |= insEncodeDatasize(id->idOpSize()); // X
9532             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9533             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9534             dst += emitOutput_Instr(dst, code);
9535             break;
9536
9537         case IF_DR_1D: // DR_1D   X............... cccc.......ddddd      Rd       cond
9538             imm = emitGetInsSC(id);
9539             assert(isValidImmCond(imm));
9540             {
9541                 condFlagsImm cfi;
9542                 cfi.immCFVal = (unsigned)imm;
9543                 code         = emitInsCode(ins, fmt);
9544                 code |= insEncodeDatasize(id->idOpSize()); // X
9545                 code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9546                 code |= insEncodeInvertedCond(cfi.cond);   // cccc
9547                 dst += emitOutput_Instr(dst, code);
9548             }
9549             break;
9550
9551         case IF_DR_2A: // DR_2A   X..........mmmmm ......nnnnn.....         Rn Rm
9552             assert(insOptsNone(id->idInsOpt()));
9553             code = emitInsCode(ins, fmt);
9554             code |= insEncodeDatasize(id->idOpSize()); // X
9555             code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9556             code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9557             dst += emitOutput_Instr(dst, code);
9558             break;
9559
9560         case IF_DR_2B: // DR_2B   X.......sh.mmmmm ssssssnnnnn.....         Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
9561             code = emitInsCode(ins, fmt);
9562             imm  = emitGetInsSC(id);
9563             assert(isValidImmShift(imm, id->idOpSize()));
9564             code |= insEncodeDatasize(id->idOpSize());        // X
9565             code |= insEncodeShiftType(id->idInsOpt());       // sh
9566             code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9567             code |= insEncodeReg_Rn(id->idReg1());            // nnnnn
9568             code |= insEncodeReg_Rm(id->idReg2());            // mmmmm
9569             dst += emitOutput_Instr(dst, code);
9570             break;
9571
9572         case IF_DR_2C: // DR_2C   X..........mmmmm ooosssnnnnn.....         Rn Rm ext(Rm) LSL imm(0-4)
9573             code = emitInsCode(ins, fmt);
9574             imm  = emitGetInsSC(id);
9575             assert((imm >= 0) && (imm <= 4));          // imm [0..4]
9576             code |= insEncodeDatasize(id->idOpSize()); // X
9577             code |= insEncodeExtend(id->idInsOpt());   // ooo
9578             code |= insEncodeExtendScale(imm);         // sss
9579             code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9580             code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9581             dst += emitOutput_Instr(dst, code);
9582             break;
9583
9584         case IF_DR_2D: // DR_2D   X..........nnnnn cccc..nnnnnddddd      Rd Rn    cond
9585             imm = emitGetInsSC(id);
9586             assert(isValidImmCond(imm));
9587             {
9588                 condFlagsImm cfi;
9589                 cfi.immCFVal = (unsigned)imm;
9590                 code         = emitInsCode(ins, fmt);
9591                 code |= insEncodeDatasize(id->idOpSize()); // X
9592                 code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9593                 code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9594                 code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9595                 code |= insEncodeInvertedCond(cfi.cond);   // cccc
9596                 dst += emitOutput_Instr(dst, code);
9597             }
9598             break;
9599
9600         case IF_DR_2E: // DR_2E   X..........mmmmm ...........ddddd      Rd    Rm
9601             code = emitInsCode(ins, fmt);
9602             code |= insEncodeDatasize(id->idOpSize()); // X
9603             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9604             code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9605             dst += emitOutput_Instr(dst, code);
9606             break;
9607
9608         case IF_DR_2F: // DR_2F   X.......sh.mmmmm ssssss.....ddddd      Rd    Rm {LSL,LSR,ASR} imm(0-63)
9609             code = emitInsCode(ins, fmt);
9610             imm  = emitGetInsSC(id);
9611             assert(isValidImmShift(imm, id->idOpSize()));
9612             code |= insEncodeDatasize(id->idOpSize());        // X
9613             code |= insEncodeShiftType(id->idInsOpt());       // sh
9614             code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9615             code |= insEncodeReg_Rd(id->idReg1());            // ddddd
9616             code |= insEncodeReg_Rm(id->idReg2());            // mmmmm
9617             dst += emitOutput_Instr(dst, code);
9618             break;
9619
9620         case IF_DR_2G: // DR_2G   X............... .....xnnnnnddddd      Rd Rn
9621             code = emitInsCode(ins, fmt);
9622             code |= insEncodeDatasize(id->idOpSize()); // X
9623             if (ins == INS_rev)
9624             {
9625                 if (size == EA_8BYTE)
9626                 {
9627                     code |= 0x00000400; // x - bit at location 10
9628                 }
9629             }
9630             code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9631             code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9632             dst += emitOutput_Instr(dst, code);
9633             break;
9634
9635         case IF_DR_2H: // DR_2H   X........X...... ......nnnnnddddd      Rd Rn
9636             code = emitInsCode(ins, fmt);
9637             code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9638             code |= insEncodeReg_Rd(id->idReg1());             // ddddd
9639             code |= insEncodeReg_Rn(id->idReg2());             // nnnnn
9640             dst += emitOutput_Instr(dst, code);
9641             break;
9642
9643         case IF_DR_2I: // DR_2I   X..........mmmmm cccc..nnnnn.nzcv      Rn Rm    nzcv cond
9644             imm = emitGetInsSC(id);
9645             assert(isValidImmCondFlags(imm));
9646             {
9647                 condFlagsImm cfi;
9648                 cfi.immCFVal = (unsigned)imm;
9649                 code         = emitInsCode(ins, fmt);
9650                 code |= insEncodeDatasize(id->idOpSize()); // X
9651                 code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9652                 code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9653                 code |= insEncodeFlags(cfi.flags);         // nzcv
9654                 code |= insEncodeCond(cfi.cond);           // cccc
9655                 dst += emitOutput_Instr(dst, code);
9656             }
9657             break;
9658
9659         case IF_DR_2J: // DR_2J   ................ ......nnnnnddddd      Sd Sn   (sha1h)
9660             code = emitInsCode(ins, fmt);
9661             code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9662             code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9663             dst += emitOutput_Instr(dst, code);
9664             break;
9665
9666         case IF_DR_3A: // DR_3A   X..........mmmmm ......nnnnnmmmmm      Rd Rn Rm
9667             code = emitInsCode(ins, fmt);
9668             code |= insEncodeDatasize(id->idOpSize()); // X
9669             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9670             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9671             if (id->idIsLclVar())
9672             {
9673                 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9674             }
9675             else
9676             {
9677                 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9678             }
9679             dst += emitOutput_Instr(dst, code);
9680             break;
9681
9682         case IF_DR_3B: // DR_3B   X.......sh.mmmmm ssssssnnnnnddddd      Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
9683             code = emitInsCode(ins, fmt);
9684             imm  = emitGetInsSC(id);
9685             assert(isValidImmShift(imm, id->idOpSize()));
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 |= insEncodeShiftType(id->idInsOpt());       // sh
9691             code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9692             dst += emitOutput_Instr(dst, code);
9693             break;
9694
9695         case IF_DR_3C: // DR_3C   X..........mmmmm ooosssnnnnnddddd      Rd Rn Rm ext(Rm) LSL imm(0-4)
9696             code = emitInsCode(ins, fmt);
9697             imm  = emitGetInsSC(id);
9698             assert((imm >= 0) && (imm <= 4));          // imm [0..4]
9699             code |= insEncodeDatasize(id->idOpSize()); // X
9700             code |= insEncodeExtend(id->idInsOpt());   // ooo
9701             code |= insEncodeExtendScale(imm);         // sss
9702             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9703             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9704             code |= insEncodeReg_Rm(id->idReg3());     // mmmmm
9705             dst += emitOutput_Instr(dst, code);
9706             break;
9707
9708         case IF_DR_3D: // DR_3D   X..........mmmmm cccc..nnnnnddddd      Rd Rn Rm cond
9709             imm = emitGetInsSC(id);
9710             assert(isValidImmCond(imm));
9711             {
9712                 condFlagsImm cfi;
9713                 cfi.immCFVal = (unsigned)imm;
9714                 code         = emitInsCode(ins, fmt);
9715                 code |= insEncodeDatasize(id->idOpSize()); // X
9716                 code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9717                 code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9718                 code |= insEncodeReg_Rm(id->idReg3());     // mmmmm
9719                 code |= insEncodeCond(cfi.cond);           // cccc
9720                 dst += emitOutput_Instr(dst, code);
9721             }
9722             break;
9723
9724         case IF_DR_3E: // DR_3E   X........X.mmmmm ssssssnnnnnddddd      Rd Rn Rm imm(0-63)
9725             code = emitInsCode(ins, fmt);
9726             imm  = emitGetInsSC(id);
9727             assert(isValidImmShift(imm, id->idOpSize()));
9728             code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9729             code |= insEncodeReg_Rd(id->idReg1());             // ddddd
9730             code |= insEncodeReg_Rn(id->idReg2());             // nnnnn
9731             code |= insEncodeReg_Rm(id->idReg3());             // mmmmm
9732             code |= insEncodeShiftCount(imm, id->idOpSize());  // ssssss
9733             dst += emitOutput_Instr(dst, code);
9734             break;
9735
9736         case IF_DR_4A: // DR_4A   X..........mmmmm .aaaaannnnnmmmmm      Rd Rn Rm Ra
9737             code = emitInsCode(ins, fmt);
9738             code |= insEncodeDatasize(id->idOpSize()); // X
9739             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9740             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9741             code |= insEncodeReg_Rm(id->idReg3());     // mmmmm
9742             code |= insEncodeReg_Ra(id->idReg4());     // aaaaa
9743             dst += emitOutput_Instr(dst, code);
9744             break;
9745
9746         case IF_DV_1A: // DV_1A   .........X.iiiii iii........ddddd      Vd imm8    (fmov - immediate scalar)
9747             imm      = emitGetInsSC(id);
9748             elemsize = id->idOpSize();
9749             code     = emitInsCode(ins, fmt);
9750             code |= insEncodeFloatElemsize(elemsize); // X
9751             code |= ((code_t)imm << 13);              // iiiii iii
9752             code |= insEncodeReg_Vd(id->idReg1());    // ddddd
9753             dst += emitOutput_Instr(dst, code);
9754             break;
9755
9756         case IF_DV_1B: // DV_1B   .QX..........iii cmod..iiiiiddddd      Vd imm8    (immediate vector)
9757             imm      = emitGetInsSC(id) & 0x0ff;
9758             immShift = (emitGetInsSC(id) & 0x700) >> 8;
9759             elemsize = optGetElemsize(id->idInsOpt());
9760             cmode    = 0;
9761             switch (elemsize)
9762             { // cmode
9763                 case EA_1BYTE:
9764                     cmode = 0xE; // 1110
9765                     break;
9766                 case EA_2BYTE:
9767                     cmode = 0x8;
9768                     cmode |= (immShift << 1); // 10x0
9769                     break;
9770                 case EA_4BYTE:
9771                     if (immShift < 4)
9772                     {
9773                         cmode = 0x0;
9774                         cmode |= (immShift << 1); // 0xx0
9775                     }
9776                     else // MSL
9777                     {
9778                         cmode = 0xC;
9779                         if (immShift & 2)
9780                             cmode |= 1; // 110x
9781                     }
9782                     break;
9783                 case EA_8BYTE:
9784                     cmode = 0xE; // 1110
9785                     break;
9786                 default:
9787                     unreached();
9788                     break;
9789             }
9790
9791             code = emitInsCode(ins, fmt);
9792             code |= insEncodeVectorsize(id->idOpSize()); // Q
9793             if ((ins == INS_fmov) || (ins == INS_movi))
9794             {
9795                 if (elemsize == EA_8BYTE)
9796                 {
9797                     code |= 0x20000000; // X
9798                 }
9799             }
9800             if (ins != INS_fmov)
9801             {
9802                 assert((cmode >= 0) && (cmode <= 0xF));
9803                 code |= (cmode << 12); // cmod
9804             }
9805             code |= (((code_t)imm >> 5) << 16);    // iii
9806             code |= (((code_t)imm & 0x1f) << 5);   // iiiii
9807             code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9808             dst += emitOutput_Instr(dst, code);
9809             break;
9810
9811         case IF_DV_1C: // DV_1C   .........X...... ......nnnnn.....      Vn #0.0    (fcmp - with zero)
9812             elemsize = id->idOpSize();
9813             code     = emitInsCode(ins, fmt);
9814             code |= insEncodeFloatElemsize(elemsize); // X
9815             code |= insEncodeReg_Vn(id->idReg1());    // nnnnn
9816             dst += emitOutput_Instr(dst, code);
9817             break;
9818
9819         case IF_DV_2A: // DV_2A   .Q.......X...... ......nnnnnddddd      Vd Vn      (fabs, fcvt - vector)
9820             elemsize = optGetElemsize(id->idInsOpt());
9821             code     = emitInsCode(ins, fmt);
9822             code |= insEncodeVectorsize(id->idOpSize()); // Q
9823             code |= insEncodeFloatElemsize(elemsize);    // X
9824             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9825             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9826             dst += emitOutput_Instr(dst, code);
9827             break;
9828
9829         case IF_DV_2B: // DV_2B   .Q.........iiiii ......nnnnnddddd      Rd Vn[] (umov/smov    - to general)
9830             elemsize = id->idOpSize();
9831             index    = emitGetInsSC(id);
9832             datasize = (elemsize == EA_8BYTE) ? EA_16BYTE : EA_8BYTE;
9833             if (ins == INS_smov)
9834             {
9835                 datasize = EA_16BYTE;
9836             }
9837             code = emitInsCode(ins, fmt);
9838             code |= insEncodeVectorsize(datasize);         // Q
9839             code |= insEncodeVectorIndex(elemsize, index); // iiiii
9840             code |= insEncodeReg_Rd(id->idReg1());         // ddddd
9841             code |= insEncodeReg_Vn(id->idReg2());         // nnnnn
9842             dst += emitOutput_Instr(dst, code);
9843             break;
9844
9845         case IF_DV_2C: // DV_2C   .Q.........iiiii ......nnnnnddddd      Vd Rn   (dup/ins - vector from general)
9846             if (ins == INS_dup)
9847             {
9848                 datasize = id->idOpSize();
9849                 elemsize = optGetElemsize(id->idInsOpt());
9850                 index    = 0;
9851             }
9852             else // INS_ins
9853             {
9854                 datasize = EA_16BYTE;
9855                 elemsize = id->idOpSize();
9856                 index    = emitGetInsSC(id);
9857             }
9858             code = emitInsCode(ins, fmt);
9859             code |= insEncodeVectorsize(datasize);         // Q
9860             code |= insEncodeVectorIndex(elemsize, index); // iiiii
9861             code |= insEncodeReg_Vd(id->idReg1());         // ddddd
9862             code |= insEncodeReg_Rn(id->idReg2());         // nnnnn
9863             dst += emitOutput_Instr(dst, code);
9864             break;
9865
9866         case IF_DV_2D: // DV_2D   .Q.........iiiii ......nnnnnddddd      Vd Vn[]   (dup - vector)
9867             index    = emitGetInsSC(id);
9868             elemsize = optGetElemsize(id->idInsOpt());
9869             code     = emitInsCode(ins, fmt);
9870             code |= insEncodeVectorsize(id->idOpSize());   // Q
9871             code |= insEncodeVectorIndex(elemsize, index); // iiiii
9872             code |= insEncodeReg_Vd(id->idReg1());         // ddddd
9873             code |= insEncodeReg_Vn(id->idReg2());         // nnnnn
9874             dst += emitOutput_Instr(dst, code);
9875             break;
9876
9877         case IF_DV_2E: // DV_2E   ...........iiiii ......nnnnnddddd      Vd Vn[]   (dup - scalar)
9878             index    = emitGetInsSC(id);
9879             elemsize = id->idOpSize();
9880             code     = emitInsCode(ins, fmt);
9881             code |= insEncodeVectorIndex(elemsize, index); // iiiii
9882             code |= insEncodeReg_Vd(id->idReg1());         // ddddd
9883             code |= insEncodeReg_Vn(id->idReg2());         // nnnnn
9884             dst += emitOutput_Instr(dst, code);
9885             break;
9886
9887         case IF_DV_2F: // DV_2F   ...........iiiii .jjjj.nnnnnddddd      Vd[] Vn[] (ins - element)
9888             elemsize = id->idOpSize();
9889             imm      = emitGetInsSC(id);
9890             index    = (imm >> 4) & 0xf;
9891             index2   = imm & 0xf;
9892             code     = emitInsCode(ins, fmt);
9893             code |= insEncodeVectorIndex(elemsize, index);   // iiiii
9894             code |= insEncodeVectorIndex2(elemsize, index2); // jjjj
9895             code |= insEncodeReg_Vd(id->idReg1());           // ddddd
9896             code |= insEncodeReg_Vn(id->idReg2());           // nnnnn
9897             dst += emitOutput_Instr(dst, code);
9898             break;
9899
9900         case IF_DV_2G: // DV_2G   .........X...... ......nnnnnddddd      Vd Vn      (fmov,fcvtXX - register)
9901             elemsize = id->idOpSize();
9902             code     = emitInsCode(ins, fmt);
9903             code |= insEncodeFloatElemsize(elemsize); // X
9904             code |= insEncodeReg_Vd(id->idReg1());    // ddddd
9905             code |= insEncodeReg_Vn(id->idReg2());    // nnnnn
9906             dst += emitOutput_Instr(dst, code);
9907             break;
9908
9909         case IF_DV_2H: // DV_2H   X........X...... ......nnnnnddddd      Rd Vn      (fmov - to general)
9910             elemsize = id->idOpSize();
9911             code     = emitInsCode(ins, fmt);
9912             code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X   X
9913             code |= insEncodeReg_Rd(id->idReg1());            // ddddd
9914             code |= insEncodeReg_Vn(id->idReg2());            // nnnnn
9915             dst += emitOutput_Instr(dst, code);
9916             break;
9917
9918         case IF_DV_2I: // DV_2I   X........X...... ......nnnnnddddd      Vd Rn      (fmov - from general)
9919             elemsize = id->idOpSize();
9920             code     = emitInsCode(ins, fmt);
9921             code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X   X
9922             code |= insEncodeReg_Vd(id->idReg1());            // ddddd
9923             code |= insEncodeReg_Rn(id->idReg2());            // nnnnn
9924             dst += emitOutput_Instr(dst, code);
9925             break;
9926
9927         case IF_DV_2J: // DV_2J   ........SS.....D D.....nnnnnddddd      Vd Vn      (fcvt)
9928             code = emitInsCode(ins, fmt);
9929             code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // SS DD
9930             code |= insEncodeReg_Vd(id->idReg1());            // ddddd
9931             code |= insEncodeReg_Vn(id->idReg2());            // nnnnn
9932             dst += emitOutput_Instr(dst, code);
9933             break;
9934
9935         case IF_DV_2K: // DV_2K   .........X.mmmmm ......nnnnn.....      Vn Vm      (fcmp)
9936             elemsize = id->idOpSize();
9937             code     = emitInsCode(ins, fmt);
9938             code |= insEncodeFloatElemsize(elemsize); // X
9939             code |= insEncodeReg_Vn(id->idReg1());    // nnnnn
9940             code |= insEncodeReg_Vm(id->idReg2());    // mmmmm
9941             dst += emitOutput_Instr(dst, code);
9942             break;
9943
9944         case IF_DV_2L: // DV_2L   ........XX...... ......nnnnnddddd      Vd Vn      (abs, neg - scalar)
9945             elemsize = id->idOpSize();
9946             code     = emitInsCode(ins, fmt);
9947             code |= insEncodeElemsize(elemsize);   // XX
9948             code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9949             code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9950             dst += emitOutput_Instr(dst, code);
9951             break;
9952
9953         case IF_DV_2M: // DV_2M   .Q......XX...... ......nnnnnddddd      Vd Vn      (abs, neg   - vector)
9954             elemsize = optGetElemsize(id->idInsOpt());
9955             code     = emitInsCode(ins, fmt);
9956             code |= insEncodeVectorsize(id->idOpSize()); // Q
9957             code |= insEncodeElemsize(elemsize);         // XX
9958             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9959             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9960             dst += emitOutput_Instr(dst, code);
9961             break;
9962
9963         case IF_DV_2N: // DV_2N   .........iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - scalar)
9964             imm  = emitGetInsSC(id);
9965             code = emitInsCode(ins, fmt);
9966             code |= insEncodeVectorShift(EA_8BYTE, imm); // iiiiiii
9967             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9968             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9969             dst += emitOutput_Instr(dst, code);
9970             break;
9971
9972         case IF_DV_2O: // DV_2O   .Q.......iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - vector)
9973             imm      = emitGetInsSC(id);
9974             elemsize = optGetElemsize(id->idInsOpt());
9975             code     = emitInsCode(ins, fmt);
9976             code |= insEncodeVectorsize(id->idOpSize()); // Q
9977             code |= insEncodeVectorShift(elemsize, imm); // iiiiiii
9978             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9979             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9980             dst += emitOutput_Instr(dst, code);
9981             break;
9982
9983         case IF_DV_2P: // DV_2P   ............... ......nnnnnddddd      Vd Vn      (aes*, sha1su1)
9984             elemsize = optGetElemsize(id->idInsOpt());
9985             code     = emitInsCode(ins, fmt);
9986             code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9987             code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9988             dst += emitOutput_Instr(dst, code);
9989             break;
9990
9991         case IF_DV_3A: // DV_3A   .Q......XX.mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
9992             code     = emitInsCode(ins, fmt);
9993             elemsize = optGetElemsize(id->idInsOpt());
9994             code |= insEncodeVectorsize(id->idOpSize()); // Q
9995             code |= insEncodeElemsize(elemsize);         // XX
9996             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9997             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9998             code |= insEncodeReg_Vm(id->idReg3());       // mmmmm
9999             dst += emitOutput_Instr(dst, code);
10000             break;
10001
10002         case IF_DV_3AI: // DV_3AI  .Q......XXLMmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector)
10003             code     = emitInsCode(ins, fmt);
10004             imm      = emitGetInsSC(id);
10005             elemsize = optGetElemsize(id->idInsOpt());
10006             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
10007             code |= insEncodeVectorsize(id->idOpSize());    // Q
10008             code |= insEncodeElemsize(elemsize);            // XX
10009             code |= insEncodeVectorIndexLMH(elemsize, imm); // LM H
10010             code |= insEncodeReg_Vd(id->idReg1());          // ddddd
10011             code |= insEncodeReg_Vn(id->idReg2());          // nnnnn
10012             code |= insEncodeReg_Vm(id->idReg3());          // mmmmm
10013             dst += emitOutput_Instr(dst, code);
10014             break;
10015
10016         case IF_DV_3B: // DV_3B   .Q.......X.mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
10017             code     = emitInsCode(ins, fmt);
10018             elemsize = optGetElemsize(id->idInsOpt());
10019             code |= insEncodeVectorsize(id->idOpSize()); // Q
10020             code |= insEncodeFloatElemsize(elemsize);    // X
10021             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
10022             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
10023             code |= insEncodeReg_Vm(id->idReg3());       // mmmmm
10024             dst += emitOutput_Instr(dst, code);
10025             break;
10026
10027         case IF_DV_3BI: // DV_3BI  .Q.......XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector by elem)
10028             code     = emitInsCode(ins, fmt);
10029             imm      = emitGetInsSC(id);
10030             elemsize = optGetElemsize(id->idInsOpt());
10031             assert(isValidVectorIndex(id->idOpSize(), elemsize, imm));
10032             code |= insEncodeVectorsize(id->idOpSize()); // Q
10033             code |= insEncodeFloatElemsize(elemsize);    // X
10034             code |= insEncodeFloatIndex(elemsize, imm);  // L H
10035             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
10036             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
10037             code |= insEncodeReg_Vm(id->idReg3());       // mmmmm
10038             dst += emitOutput_Instr(dst, code);
10039             break;
10040
10041         case IF_DV_3C: // DV_3C   .Q.........mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
10042             code = emitInsCode(ins, fmt);
10043             code |= insEncodeVectorsize(id->idOpSize()); // Q
10044             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
10045             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
10046             code |= insEncodeReg_Vm(id->idReg3());       // mmmmm
10047             dst += emitOutput_Instr(dst, code);
10048             break;
10049
10050         case IF_DV_3D: // DV_3D   .........X.mmmmm ......nnnnnddddd      Vd Vn Vm   (scalar)
10051             code = emitInsCode(ins, fmt);
10052             code |= insEncodeFloatElemsize(id->idOpSize()); // X
10053             code |= insEncodeReg_Vd(id->idReg1());          // ddddd
10054             code |= insEncodeReg_Vn(id->idReg2());          // nnnnn
10055             code |= insEncodeReg_Vm(id->idReg3());          // mmmmm
10056             dst += emitOutput_Instr(dst, code);
10057             break;
10058
10059         case IF_DV_3DI: // DV_3DI  .........XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (scalar by elem)
10060             code     = emitInsCode(ins, fmt);
10061             imm      = emitGetInsSC(id);
10062             elemsize = id->idOpSize();
10063             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
10064             code |= insEncodeFloatElemsize(elemsize);   // X
10065             code |= insEncodeFloatIndex(elemsize, imm); // L H
10066             code |= insEncodeReg_Vd(id->idReg1());      // ddddd
10067             code |= insEncodeReg_Vn(id->idReg2());      // nnnnn
10068             code |= insEncodeReg_Vm(id->idReg3());      // mmmmm
10069             dst += emitOutput_Instr(dst, code);
10070             break;
10071
10072         case IF_DV_3E: // DV_3E   ...........mmmmm ......nnnnnddddd      Vd Vn Vm   (scalar)
10073         case IF_DV_3F: // DV_3F   ...........mmmmm ......nnnnnddddd      Vd Vn Vm   (vector) - source dest regs overlap
10074             code = emitInsCode(ins, fmt);
10075             code |= insEncodeReg_Vd(id->idReg1()); // ddddd
10076             code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
10077             code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
10078             dst += emitOutput_Instr(dst, code);
10079             break;
10080
10081         case IF_DV_4A: // DV_4A   .........X.mmmmm .aaaaannnnnddddd      Vd Va Vn Vm (scalar)
10082             code     = emitInsCode(ins, fmt);
10083             elemsize = id->idOpSize();
10084             code |= insEncodeFloatElemsize(elemsize); // X
10085             code |= insEncodeReg_Vd(id->idReg1());    // ddddd
10086             code |= insEncodeReg_Vn(id->idReg2());    // nnnnn
10087             code |= insEncodeReg_Vm(id->idReg3());    // mmmmm
10088             code |= insEncodeReg_Va(id->idReg4());    // aaaaa
10089             dst += emitOutput_Instr(dst, code);
10090             break;
10091
10092         case IF_SN_0A: // SN_0A   ................ ................
10093             code = emitInsCode(ins, fmt);
10094             dst += emitOutput_Instr(dst, code);
10095             break;
10096
10097         case IF_SI_0A: // SI_0A   ...........iiiii iiiiiiiiiii.....               imm16
10098             imm = emitGetInsSC(id);
10099             assert(isValidUimm16(imm));
10100             code = emitInsCode(ins, fmt);
10101             code |= ((code_t)imm << 5); // iiiii iiiiiiiiiii
10102             dst += emitOutput_Instr(dst, code);
10103             break;
10104
10105         case IF_SI_0B: // SI_0B   ................ ....bbbb........               imm4 - barrier
10106             imm = emitGetInsSC(id);
10107             assert((imm >= 0) && (imm <= 15));
10108             code = emitInsCode(ins, fmt);
10109             code |= ((code_t)imm << 8); // bbbb
10110             dst += emitOutput_Instr(dst, code);
10111             break;
10112
10113         default:
10114             assert(!"Unexpected format");
10115             break;
10116     }
10117
10118     // Determine if any registers now hold GC refs, or whether a register that was overwritten held a GC ref.
10119     // We assume here that "id->idGCref()" is not GC_NONE only if the instruction described by "id" writes a
10120     // GC ref to register "id->idReg1()".  (It may, apparently, also not be GC_NONE in other cases, such as
10121     // for stores, but we ignore those cases here.)
10122     if (emitInsMayWriteToGCReg(id)) // True if "id->idIns()" writes to a register than can hold GC ref.
10123     {
10124         // We assume that "idReg1" is the primary destination register for all instructions
10125         if (id->idGCref() != GCT_NONE)
10126         {
10127             emitGCregLiveUpd(id->idGCref(), id->idReg1(), dst);
10128         }
10129         else
10130         {
10131             emitGCregDeadUpd(id->idReg1(), dst);
10132         }
10133
10134         if (emitInsMayWriteMultipleRegs(id))
10135         {
10136             // INS_ldp etc...
10137             // "idReg2" is the secondary destination register
10138             if (id->idGCrefReg2() != GCT_NONE)
10139             {
10140                 emitGCregLiveUpd(id->idGCrefReg2(), id->idReg2(), dst);
10141             }
10142             else
10143             {
10144                 emitGCregDeadUpd(id->idReg2(), dst);
10145             }
10146         }
10147     }
10148
10149     // Now we determine if the instruction has written to a (local variable) stack location, and either written a GC
10150     // ref or overwritten one.
10151     if (emitInsWritesToLclVarStackLoc(id) || emitInsWritesToLclVarStackLocPair(id))
10152     {
10153         int      varNum = id->idAddr()->iiaLclVar.lvaVarNum();
10154         unsigned ofs    = AlignDown(id->idAddr()->iiaLclVar.lvaOffset(), TARGET_POINTER_SIZE);
10155         bool     FPbased;
10156         int      adr = emitComp->lvaFrameAddress(varNum, &FPbased);
10157         if (id->idGCref() != GCT_NONE)
10158         {
10159             emitGCvarLiveUpd(adr + ofs, varNum, id->idGCref(), dst);
10160         }
10161         else
10162         {
10163             // If the type of the local is a gc ref type, update the liveness.
10164             var_types vt;
10165             if (varNum >= 0)
10166             {
10167                 // "Regular" (non-spill-temp) local.
10168                 vt = var_types(emitComp->lvaTable[varNum].lvType);
10169             }
10170             else
10171             {
10172                 TempDsc* tmpDsc = emitComp->tmpFindNum(varNum);
10173                 vt              = tmpDsc->tdTempType();
10174             }
10175             if (vt == TYP_REF || vt == TYP_BYREF)
10176                 emitGCvarDeadUpd(adr + ofs, dst);
10177         }
10178         if (emitInsWritesToLclVarStackLocPair(id))
10179         {
10180             unsigned ofs2 = ofs + TARGET_POINTER_SIZE;
10181             if (id->idGCrefReg2() != GCT_NONE)
10182             {
10183                 emitGCvarLiveUpd(adr + ofs2, varNum, id->idGCrefReg2(), dst);
10184             }
10185             else
10186             {
10187                 // If the type of the local is a gc ref type, update the liveness.
10188                 var_types vt;
10189                 if (varNum >= 0)
10190                 {
10191                     // "Regular" (non-spill-temp) local.
10192                     vt = var_types(emitComp->lvaTable[varNum].lvType);
10193                 }
10194                 else
10195                 {
10196                     TempDsc* tmpDsc = emitComp->tmpFindNum(varNum);
10197                     vt              = tmpDsc->tdTempType();
10198                 }
10199                 if (vt == TYP_REF || vt == TYP_BYREF)
10200                     emitGCvarDeadUpd(adr + ofs2, dst);
10201             }
10202         }
10203     }
10204
10205 #ifdef DEBUG
10206     /* Make sure we set the instruction descriptor size correctly */
10207
10208     size_t expected = emitSizeOfInsDsc(id);
10209     assert(sz == expected);
10210
10211     if (emitComp->opts.disAsm || emitComp->opts.dspEmit || emitComp->verbose)
10212     {
10213         emitDispIns(id, false, dspOffs, true, emitCurCodeOffs(odst), *dp, (dst - *dp), ig);
10214     }
10215
10216     if (emitComp->compDebugBreak)
10217     {
10218         // For example, set JitBreakEmitOutputInstr=a6 will break when this method is called for
10219         // emitting instruction a6, (i.e. IN00a6 in jitdump).
10220         if ((unsigned)JitConfig.JitBreakEmitOutputInstr() == id->idDebugOnlyInfo()->idNum)
10221         {
10222             assert(!"JitBreakEmitOutputInstr reached");
10223         }
10224     }
10225 #endif
10226
10227     /* All instructions are expected to generate code */
10228
10229     assert(*dp != dst);
10230
10231     *dp = dst;
10232
10233     return sz;
10234 }
10235
10236 /*****************************************************************************/
10237 /*****************************************************************************/
10238
10239 #ifdef DEBUG
10240
10241 /*****************************************************************************
10242  *
10243  *  Display the instruction name
10244  */
10245 void emitter::emitDispInst(instruction ins)
10246 {
10247     const char* insstr = codeGen->genInsName(ins);
10248     size_t      len    = strlen(insstr);
10249
10250     /* Display the instruction name */
10251
10252     printf("%s", insstr);
10253
10254     //
10255     // Add at least one space after the instruction name
10256     // and add spaces until we have reach the normal size of 8
10257     do
10258     {
10259         printf(" ");
10260         len++;
10261     } while (len < 8);
10262 }
10263
10264 /*****************************************************************************
10265  *
10266  *  Display an reloc value
10267  *  If we are formatting for an assembly listing don't print the hex value
10268  *  since it will prevent us from doing assembly diffs
10269  */
10270 void emitter::emitDispReloc(int value, bool addComma)
10271 {
10272     if (emitComp->opts.disAsm)
10273     {
10274         printf("(reloc)");
10275     }
10276     else
10277     {
10278         printf("(reloc 0x%x)", dspPtr(value));
10279     }
10280
10281     if (addComma)
10282         printf(", ");
10283 }
10284
10285 /*****************************************************************************
10286  *
10287  *  Display an immediate value
10288  */
10289 void emitter::emitDispImm(ssize_t imm, bool addComma, bool alwaysHex /* =false */)
10290 {
10291     if (strictArmAsm)
10292     {
10293         printf("#");
10294     }
10295
10296     // Munge any pointers if we want diff-able disassembly.
10297     // Since some may be emitted as partial words, print as diffable anything that has
10298     // significant bits beyond the lowest 8-bits.
10299     if (emitComp->opts.disDiffable)
10300     {
10301         ssize_t top56bits = (imm >> 8);
10302         if ((top56bits != 0) && (top56bits != -1))
10303             imm = 0xD1FFAB1E;
10304     }
10305
10306     if (!alwaysHex && (imm > -1000) && (imm < 1000))
10307     {
10308         printf("%d", imm);
10309     }
10310     else
10311     {
10312         if ((imm < 0) && ((imm & 0xFFFFFFFF00000000LL) == 0xFFFFFFFF00000000LL))
10313         {
10314             printf("-");
10315             imm = -imm;
10316         }
10317
10318         if ((imm & 0xFFFFFFFF00000000LL) != 0)
10319         {
10320             printf("0x%llx", imm);
10321         }
10322         else
10323         {
10324             printf("0x%02x", imm);
10325         }
10326     }
10327
10328     if (addComma)
10329         printf(", ");
10330 }
10331
10332 /*****************************************************************************
10333  *
10334  *  Display a float zero constant
10335  */
10336 void emitter::emitDispFloatZero()
10337 {
10338     if (strictArmAsm)
10339     {
10340         printf("#");
10341     }
10342     printf("0.0");
10343 }
10344
10345 /*****************************************************************************
10346  *
10347  *  Display an encoded float constant value
10348  */
10349 void emitter::emitDispFloatImm(ssize_t imm8)
10350 {
10351     assert((0 <= imm8) && (imm8 <= 0x0ff));
10352     if (strictArmAsm)
10353     {
10354         printf("#");
10355     }
10356
10357     floatImm8 fpImm;
10358     fpImm.immFPIVal = (unsigned)imm8;
10359     double result   = emitDecodeFloatImm8(fpImm);
10360
10361     printf("%.4f", result);
10362 }
10363
10364 /*****************************************************************************
10365  *
10366  *  Display an immediate that is optionally LSL12.
10367  */
10368 void emitter::emitDispImmOptsLSL12(ssize_t imm, insOpts opt)
10369 {
10370     if (!strictArmAsm && insOptsLSL12(opt))
10371     {
10372         imm <<= 12;
10373     }
10374     emitDispImm(imm, false);
10375     if (strictArmAsm && insOptsLSL12(opt))
10376     {
10377         printf(", LSL #12");
10378     }
10379 }
10380
10381 /*****************************************************************************
10382  *
10383  *  Display an ARM64 condition code for the conditional instructions
10384  */
10385 void emitter::emitDispCond(insCond cond)
10386 {
10387     const static char* armCond[16] = {"eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc",
10388                                       "hi", "ls", "ge", "lt", "gt", "le", "AL", "NV"}; // The last two are invalid
10389     unsigned imm = (unsigned)cond;
10390     assert((0 <= imm) && (imm < ArrLen(armCond)));
10391     printf(armCond[imm]);
10392 }
10393
10394 /*****************************************************************************
10395  *
10396  *  Display an ARM64 flags for the conditional instructions
10397  */
10398 void emitter::emitDispFlags(insCflags flags)
10399 {
10400     const static char* armFlags[16] = {"0", "v",  "c",  "cv",  "z",  "zv",  "zc",  "zcv",
10401                                        "n", "nv", "nc", "ncv", "nz", "nzv", "nzc", "nzcv"};
10402     unsigned imm = (unsigned)flags;
10403     assert((0 <= imm) && (imm < ArrLen(armFlags)));
10404     printf(armFlags[imm]);
10405 }
10406
10407 /*****************************************************************************
10408  *
10409  *  Display an ARM64 'barrier' for the memory barrier instructions
10410  */
10411 void emitter::emitDispBarrier(insBarrier barrier)
10412 {
10413     const static char* armBarriers[16] = {"#0", "oshld", "oshst", "osh", "#4",  "nshld", "nshst", "nsh",
10414                                           "#8", "ishld", "ishst", "ish", "#12", "ld",    "st",    "sy"};
10415     unsigned imm = (unsigned)barrier;
10416     assert((0 <= imm) && (imm < ArrLen(armBarriers)));
10417     printf(armBarriers[imm]);
10418 }
10419
10420 /*****************************************************************************
10421  *
10422  *  Prints the encoding for the Shift Type encoding
10423  */
10424
10425 void emitter::emitDispShiftOpts(insOpts opt)
10426 {
10427     if (opt == INS_OPTS_LSL)
10428         printf(" LSL ");
10429     else if (opt == INS_OPTS_LSR)
10430         printf(" LSR ");
10431     else if (opt == INS_OPTS_ASR)
10432         printf(" ASR ");
10433     else if (opt == INS_OPTS_ROR)
10434         printf(" ROR ");
10435     else if (opt == INS_OPTS_MSL)
10436         printf(" MSL ");
10437     else
10438         assert(!"Bad value");
10439 }
10440
10441 /*****************************************************************************
10442  *
10443  *  Prints the encoding for the Extend Type encoding
10444  */
10445
10446 void emitter::emitDispExtendOpts(insOpts opt)
10447 {
10448     if (opt == INS_OPTS_UXTB)
10449         printf("UXTB");
10450     else if (opt == INS_OPTS_UXTH)
10451         printf("UXTH");
10452     else if (opt == INS_OPTS_UXTW)
10453         printf("UXTW");
10454     else if (opt == INS_OPTS_UXTX)
10455         printf("UXTX");
10456     else if (opt == INS_OPTS_SXTB)
10457         printf("SXTB");
10458     else if (opt == INS_OPTS_SXTH)
10459         printf("SXTH");
10460     else if (opt == INS_OPTS_SXTW)
10461         printf("SXTW");
10462     else if (opt == INS_OPTS_SXTX)
10463         printf("SXTX");
10464     else
10465         assert(!"Bad value");
10466 }
10467
10468 /*****************************************************************************
10469  *
10470  *  Prints the encoding for the Extend Type encoding in loads/stores
10471  */
10472
10473 void emitter::emitDispLSExtendOpts(insOpts opt)
10474 {
10475     if (opt == INS_OPTS_LSL)
10476         printf("LSL");
10477     else if (opt == INS_OPTS_UXTW)
10478         printf("UXTW");
10479     else if (opt == INS_OPTS_UXTX)
10480         printf("UXTX");
10481     else if (opt == INS_OPTS_SXTW)
10482         printf("SXTW");
10483     else if (opt == INS_OPTS_SXTX)
10484         printf("SXTX");
10485     else
10486         assert(!"Bad value");
10487 }
10488
10489 /*****************************************************************************
10490  *
10491  *  Display a register
10492  */
10493 void emitter::emitDispReg(regNumber reg, emitAttr attr, bool addComma)
10494 {
10495     emitAttr size = EA_SIZE(attr);
10496     printf(emitRegName(reg, size));
10497
10498     if (addComma)
10499         printf(", ");
10500 }
10501
10502 /*****************************************************************************
10503  *
10504  *  Display a vector register with an arrangement suffix
10505  */
10506 void emitter::emitDispVectorReg(regNumber reg, insOpts opt, bool addComma)
10507 {
10508     assert(isVectorRegister(reg));
10509     printf(emitVectorRegName(reg));
10510     emitDispArrangement(opt);
10511
10512     if (addComma)
10513         printf(", ");
10514 }
10515
10516 /*****************************************************************************
10517  *
10518  *  Display an vector register index suffix
10519  */
10520 void emitter::emitDispVectorRegIndex(regNumber reg, emitAttr elemsize, ssize_t index, bool addComma)
10521 {
10522     assert(isVectorRegister(reg));
10523     printf(emitVectorRegName(reg));
10524
10525     switch (elemsize)
10526     {
10527         case EA_1BYTE:
10528             printf(".b");
10529             break;
10530         case EA_2BYTE:
10531             printf(".h");
10532             break;
10533         case EA_4BYTE:
10534             printf(".s");
10535             break;
10536         case EA_8BYTE:
10537             printf(".d");
10538             break;
10539         default:
10540             assert(!"invalid elemsize");
10541             break;
10542     }
10543
10544     printf("[%d]", index);
10545
10546     if (addComma)
10547         printf(", ");
10548 }
10549
10550 /*****************************************************************************
10551  *
10552  *  Display an arrangement suffix
10553  */
10554 void emitter::emitDispArrangement(insOpts opt)
10555 {
10556     const char* str = "???";
10557
10558     switch (opt)
10559     {
10560         case INS_OPTS_8B:
10561             str = "8b";
10562             break;
10563         case INS_OPTS_16B:
10564             str = "16b";
10565             break;
10566         case INS_OPTS_4H:
10567             str = "4h";
10568             break;
10569         case INS_OPTS_8H:
10570             str = "8h";
10571             break;
10572         case INS_OPTS_2S:
10573             str = "2s";
10574             break;
10575         case INS_OPTS_4S:
10576             str = "4s";
10577             break;
10578         case INS_OPTS_1D:
10579             str = "1d";
10580             break;
10581         case INS_OPTS_2D:
10582             str = "2d";
10583             break;
10584
10585         default:
10586             assert(!"Invalid insOpt for vector register");
10587     }
10588     printf(".");
10589     printf(str);
10590 }
10591
10592 /*****************************************************************************
10593  *
10594  *  Display a register with an optional shift operation
10595  */
10596 void emitter::emitDispShiftedReg(regNumber reg, insOpts opt, ssize_t imm, emitAttr attr)
10597 {
10598     emitAttr size = EA_SIZE(attr);
10599     assert((imm & 0x003F) == imm);
10600     assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
10601
10602     printf(emitRegName(reg, size));
10603
10604     if (imm > 0)
10605     {
10606         if (strictArmAsm)
10607         {
10608             printf(",");
10609         }
10610         emitDispShiftOpts(opt);
10611         emitDispImm(imm, false);
10612     }
10613 }
10614
10615 /*****************************************************************************
10616  *
10617  *  Display a register with an optional extend and scale operations
10618  */
10619 void emitter::emitDispExtendReg(regNumber reg, insOpts opt, ssize_t imm)
10620 {
10621     assert((imm >= 0) && (imm <= 4));
10622     assert(insOptsNone(opt) || insOptsAnyExtend(opt) || (opt == INS_OPTS_LSL));
10623
10624     // size is based on the extend option, not the instr size.
10625     emitAttr size = insOpts32BitExtend(opt) ? EA_4BYTE : EA_8BYTE;
10626
10627     if (strictArmAsm)
10628     {
10629         if (insOptsNone(opt))
10630         {
10631             emitDispReg(reg, size, false);
10632         }
10633         else
10634         {
10635             emitDispReg(reg, size, true);
10636             if (opt == INS_OPTS_LSL)
10637                 printf("LSL");
10638             else
10639                 emitDispExtendOpts(opt);
10640             if ((imm > 0) || (opt == INS_OPTS_LSL))
10641             {
10642                 printf(" ");
10643                 emitDispImm(imm, false);
10644             }
10645         }
10646     }
10647     else // !strictArmAsm
10648     {
10649         if (insOptsNone(opt))
10650         {
10651             emitDispReg(reg, size, false);
10652         }
10653         else
10654         {
10655             if (opt != INS_OPTS_LSL)
10656             {
10657                 emitDispExtendOpts(opt);
10658                 printf("(");
10659                 emitDispReg(reg, size, false);
10660                 printf(")");
10661             }
10662         }
10663         if (imm > 0)
10664         {
10665             printf("*");
10666             emitDispImm(1 << imm, false);
10667         }
10668     }
10669 }
10670
10671 /*****************************************************************************
10672  *
10673  *  Display an addressing operand [reg + imm]
10674  */
10675 void emitter::emitDispAddrRI(regNumber reg, insOpts opt, ssize_t imm)
10676 {
10677     reg = encodingZRtoSP(reg); // ZR (R31) encodes the SP register
10678
10679     if (strictArmAsm)
10680     {
10681         printf("[");
10682
10683         emitDispReg(reg, EA_8BYTE, false);
10684
10685         if (!insOptsPostIndex(opt) && (imm != 0))
10686         {
10687             printf(",");
10688             emitDispImm(imm, false);
10689         }
10690         printf("]");
10691
10692         if (insOptsPreIndex(opt))
10693         {
10694             printf("!");
10695         }
10696         else if (insOptsPostIndex(opt))
10697         {
10698             printf(",");
10699             emitDispImm(imm, false);
10700         }
10701     }
10702     else // !strictArmAsm
10703     {
10704         printf("[");
10705
10706         const char* operStr = "++";
10707         if (imm < 0)
10708         {
10709             operStr = "--";
10710             imm     = -imm;
10711         }
10712
10713         if (insOptsPreIndex(opt))
10714         {
10715             printf(operStr);
10716         }
10717
10718         emitDispReg(reg, EA_8BYTE, false);
10719
10720         if (insOptsPostIndex(opt))
10721         {
10722             printf(operStr);
10723         }
10724
10725         if (insOptsIndexed(opt))
10726         {
10727             printf(", ");
10728         }
10729         else
10730         {
10731             printf("%c", operStr[1]);
10732         }
10733         emitDispImm(imm, false);
10734         printf("]");
10735     }
10736 }
10737
10738 /*****************************************************************************
10739  *
10740  *  Display an addressing operand [reg + extended reg]
10741  */
10742 void emitter::emitDispAddrRRExt(regNumber reg1, regNumber reg2, insOpts opt, bool isScaled, emitAttr size)
10743 {
10744     reg1 = encodingZRtoSP(reg1); // ZR (R31) encodes the SP register
10745
10746     unsigned scale = 0;
10747     if (isScaled)
10748     {
10749         scale = NaturalScale_helper(size);
10750     }
10751
10752     printf("[");
10753
10754     if (strictArmAsm)
10755     {
10756         emitDispReg(reg1, EA_8BYTE, true);
10757         emitDispExtendReg(reg2, opt, scale);
10758     }
10759     else // !strictArmAsm
10760     {
10761         emitDispReg(reg1, EA_8BYTE, false);
10762         printf("+");
10763         emitDispExtendReg(reg2, opt, scale);
10764     }
10765
10766     printf("]");
10767 }
10768
10769 /*****************************************************************************
10770  *
10771  *  Display (optionally) the instruction encoding in hex
10772  */
10773
10774 void emitter::emitDispInsHex(BYTE* code, size_t sz)
10775 {
10776     // We do not display the instruction hex if we want diff-able disassembly
10777     if (!emitComp->opts.disDiffable)
10778     {
10779         if (sz == 4)
10780         {
10781             printf("  %08X    ", (*((code_t*)code)));
10782         }
10783         else
10784         {
10785             printf("              ");
10786         }
10787     }
10788 }
10789
10790 /****************************************************************************
10791  *
10792  *  Display the given instruction.
10793  */
10794
10795 void emitter::emitDispIns(
10796     instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* pCode, size_t sz, insGroup* ig)
10797 {
10798     if (EMITVERBOSE)
10799     {
10800         unsigned idNum =
10801             id->idDebugOnlyInfo()->idNum; // Do not remove this!  It is needed for VisualStudio conditional breakpoints
10802
10803         printf("IN%04x: ", idNum);
10804     }
10805
10806     if (pCode == NULL)
10807         sz = 0;
10808
10809     if (!emitComp->opts.dspEmit && !isNew && !asmfm && sz)
10810         doffs = true;
10811
10812     /* Display the instruction offset */
10813
10814     emitDispInsOffs(offset, doffs);
10815
10816     /* Display the instruction hex code */
10817
10818     emitDispInsHex(pCode, sz);
10819
10820     printf("      ");
10821
10822     /* Get the instruction and format */
10823
10824     instruction ins = id->idIns();
10825     insFormat   fmt = id->idInsFmt();
10826
10827     emitDispInst(ins);
10828
10829     /* If this instruction has just been added, check its size */
10830
10831     assert(isNew == false || (int)emitSizeOfInsDsc(id) == emitCurIGfreeNext - (BYTE*)id);
10832
10833     /* Figure out the operand size */
10834     emitAttr size = id->idOpSize();
10835     emitAttr attr = size;
10836     if (id->idGCref() == GCT_GCREF)
10837         attr = EA_GCREF;
10838     else if (id->idGCref() == GCT_BYREF)
10839         attr = EA_BYREF;
10840
10841     switch (fmt)
10842     {
10843         code_t       code;
10844         ssize_t      imm;
10845         int          doffs;
10846         bool         isExtendAlias;
10847         bool         canEncode;
10848         bitMaskImm   bmi;
10849         halfwordImm  hwi;
10850         condFlagsImm cfi;
10851         unsigned     scale;
10852         unsigned     immShift;
10853         bool         hasShift;
10854         ssize_t      offs;
10855         const char*  methodName;
10856         emitAttr     elemsize;
10857         emitAttr     datasize;
10858         emitAttr     srcsize;
10859         emitAttr     dstsize;
10860         ssize_t      index;
10861         ssize_t      index2;
10862
10863         case IF_BI_0A: // BI_0A   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
10864         case IF_BI_0B: // BI_0B   ......iiiiiiiiii iiiiiiiiiii.....               simm19:00
10865         case IF_LARGEJMP:
10866         {
10867             if (fmt == IF_LARGEJMP)
10868             {
10869                 printf("(LARGEJMP)");
10870             }
10871             if (id->idAddr()->iiaHasInstrCount())
10872             {
10873                 int instrCount = id->idAddr()->iiaGetInstrCount();
10874
10875                 if (ig == nullptr)
10876                 {
10877                     printf("pc%s%d instructions", (instrCount >= 0) ? "+" : "", instrCount);
10878                 }
10879                 else
10880                 {
10881                     unsigned       insNum  = emitFindInsNum(ig, id);
10882                     UNATIVE_OFFSET srcOffs = ig->igOffs + emitFindOffset(ig, insNum + 1);
10883                     UNATIVE_OFFSET dstOffs = ig->igOffs + emitFindOffset(ig, insNum + 1 + instrCount);
10884                     ssize_t        relOffs = (ssize_t)(emitOffsetToPtr(dstOffs) - emitOffsetToPtr(srcOffs));
10885                     printf("pc%s%d (%d instructions)", (relOffs >= 0) ? "+" : "", relOffs, instrCount);
10886                 }
10887             }
10888             else if (id->idIsBound())
10889             {
10890                 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10891             }
10892             else
10893             {
10894                 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10895             }
10896         }
10897         break;
10898
10899         case IF_BI_0C: // BI_0C   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
10900             if (id->idIsCallAddr())
10901             {
10902                 offs       = (ssize_t)id->idAddr()->iiaAddr;
10903                 methodName = "";
10904             }
10905             else
10906             {
10907                 offs       = 0;
10908                 methodName = emitComp->eeGetMethodFullName((CORINFO_METHOD_HANDLE)id->idDebugOnlyInfo()->idMemCookie);
10909             }
10910
10911             if (offs)
10912             {
10913                 if (id->idIsDspReloc())
10914                     printf("reloc ");
10915                 printf("%08X", offs);
10916             }
10917             else
10918             {
10919                 printf("%s", methodName);
10920             }
10921             break;
10922
10923         case IF_BI_1A: // BI_1A   ......iiiiiiiiii iiiiiiiiiiittttt      Rt       simm19:00
10924             assert(insOptsNone(id->idInsOpt()));
10925             emitDispReg(id->idReg1(), size, true);
10926             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_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10933             }
10934             break;
10935
10936         case IF_BI_1B: // BI_1B   B.......bbbbbiii iiiiiiiiiiittttt      Rt imm6, simm14:00
10937             assert(insOptsNone(id->idInsOpt()));
10938             emitDispReg(id->idReg1(), size, true);
10939             emitDispImm(emitGetInsSC(id), true);
10940             if (id->idIsBound())
10941             {
10942                 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10943             }
10944             else
10945             {
10946                 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10947             }
10948             break;
10949
10950         case IF_BR_1A: // BR_1A   ................ ......nnnnn.....         Rn
10951             assert(insOptsNone(id->idInsOpt()));
10952             emitDispReg(id->idReg1(), size, false);
10953             break;
10954
10955         case IF_BR_1B: // BR_1B   ................ ......nnnnn.....         Rn
10956             assert(insOptsNone(id->idInsOpt()));
10957             emitDispReg(id->idReg3(), size, false);
10958             break;
10959
10960         case IF_LS_1A: // LS_1A   XX...V..iiiiiiii iiiiiiiiiiittttt      Rt    PC imm(1MB)
10961         case IF_DI_1E: // DI_1E   .ii.....iiiiiiii iiiiiiiiiiiddddd      Rd       simm21
10962         case IF_LARGELDC:
10963         case IF_LARGEADR:
10964             assert(insOptsNone(id->idInsOpt()));
10965             emitDispReg(id->idReg1(), size, true);
10966             imm = emitGetInsSC(id);
10967
10968             /* Is this actually a reference to a data section? */
10969             if (fmt == IF_LARGEADR)
10970             {
10971                 printf("(LARGEADR)");
10972             }
10973             else if (fmt == IF_LARGELDC)
10974             {
10975                 printf("(LARGELDC)");
10976             }
10977
10978             printf("[");
10979             if (id->idAddr()->iiaIsJitDataOffset())
10980             {
10981                 doffs = Compiler::eeGetJitDataOffs(id->idAddr()->iiaFieldHnd);
10982                 /* Display a data section reference */
10983
10984                 if (doffs & 1)
10985                     printf("@CNS%02u", doffs - 1);
10986                 else
10987                     printf("@RWD%02u", doffs);
10988
10989                 if (imm != 0)
10990                     printf("%+Id", imm);
10991             }
10992             else
10993             {
10994                 assert(imm == 0);
10995                 if (id->idIsReloc())
10996                 {
10997                     printf("RELOC ");
10998                     emitDispImm((ssize_t)id->idAddr()->iiaAddr, false);
10999                 }
11000                 else if (id->idIsBound())
11001                 {
11002                     printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
11003                 }
11004                 else
11005                 {
11006                     printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
11007                 }
11008             }
11009             printf("]");
11010             break;
11011
11012         case IF_LS_2A: // LS_2A   .X.......X...... ......nnnnnttttt      Rt Rn
11013             assert(insOptsNone(id->idInsOpt()));
11014             assert(emitGetInsSC(id) == 0);
11015             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
11016             emitDispAddrRI(id->idReg2(), id->idInsOpt(), 0);
11017             break;
11018
11019         case IF_LS_2B: // LS_2B   .X.......Xiiiiii iiiiiinnnnnttttt      Rt Rn    imm(0-4095)
11020             assert(insOptsNone(id->idInsOpt()));
11021             imm   = emitGetInsSC(id);
11022             scale = NaturalScale_helper(emitInsLoadStoreSize(id));
11023             imm <<= scale; // The immediate is scaled by the size of the ld/st
11024             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
11025             emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
11026             break;
11027
11028         case IF_LS_2C: // LS_2C   .X.......X.iiiii iiiiPPnnnnnttttt      Rt Rn    imm(-256..+255) no/pre/post inc
11029             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
11030             imm = emitGetInsSC(id);
11031             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
11032             emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
11033             break;
11034
11035         case IF_LS_3A: // LS_3A   .X.......X.mmmmm oooS..nnnnnttttt      Rt Rn Rm ext(Rm) LSL {}
11036             assert(insOptsLSExtend(id->idInsOpt()));
11037             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
11038             if (id->idIsLclVar())
11039             {
11040                 emitDispAddrRRExt(id->idReg2(), codeGen->rsGetRsvdReg(), id->idInsOpt(), false, size);
11041             }
11042             else
11043             {
11044                 emitDispAddrRRExt(id->idReg2(), id->idReg3(), id->idInsOpt(), id->idReg3Scaled(), size);
11045             }
11046             break;
11047
11048         case IF_LS_3B: // LS_3B   X............... .aaaaannnnnddddd      Rt Ra Rn
11049             assert(insOptsNone(id->idInsOpt()));
11050             assert(emitGetInsSC(id) == 0);
11051             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
11052             emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
11053             emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
11054             break;
11055
11056         case IF_LS_3C: // LS_3C   X.........iiiiii iaaaaannnnnddddd      Rt Ra Rn imm(im7,sh)
11057             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
11058             imm   = emitGetInsSC(id);
11059             scale = NaturalScale_helper(emitInsLoadStoreSize(id));
11060             imm <<= scale;
11061             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
11062             emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
11063             emitDispAddrRI(id->idReg3(), id->idInsOpt(), imm);
11064             break;
11065
11066         case IF_LS_3D: // LS_3D   .X.......X.mmmmm ......nnnnnttttt      Wm Rt Rn
11067             assert(insOptsNone(id->idInsOpt()));
11068             emitDispReg(id->idReg1(), EA_4BYTE, true);
11069             emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
11070             emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
11071             break;
11072
11073         case IF_LS_3E: // LS_3E   .X.........mmmmm ......nnnnnttttt      Rm Rt Rn ARMv8.1 LSE Atomics
11074             assert(insOptsNone(id->idInsOpt()));
11075             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
11076             emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
11077             emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
11078             break;
11079
11080         case IF_DI_1A: // DI_1A   X.......shiiiiii iiiiiinnnnn.....      Rn       imm(i12,sh)
11081             emitDispReg(id->idReg1(), size, true);
11082             emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
11083             break;
11084
11085         case IF_DI_1B: // DI_1B   X........hwiiiii iiiiiiiiiiiddddd      Rd       imm(i16,hw)
11086             emitDispReg(id->idReg1(), size, true);
11087             hwi.immHWVal = (unsigned)emitGetInsSC(id);
11088             if (ins == INS_mov)
11089             {
11090                 emitDispImm(emitDecodeHalfwordImm(hwi, size), false);
11091             }
11092             else // movz, movn, movk
11093             {
11094                 emitDispImm(hwi.immVal, false);
11095                 if (hwi.immHW != 0)
11096                 {
11097                     emitDispShiftOpts(INS_OPTS_LSL);
11098                     emitDispImm(hwi.immHW * 16, false);
11099                 }
11100             }
11101             break;
11102
11103         case IF_DI_1C: // DI_1C   X........Nrrrrrr ssssssnnnnn.....         Rn    imm(N,r,s)
11104             emitDispReg(id->idReg1(), size, true);
11105             bmi.immNRS = (unsigned)emitGetInsSC(id);
11106             emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
11107             break;
11108
11109         case IF_DI_1D: // DI_1D   X........Nrrrrrr ssssss.....ddddd      Rd       imm(N,r,s)
11110             emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11111             bmi.immNRS = (unsigned)emitGetInsSC(id);
11112             emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
11113             break;
11114
11115         case IF_DI_2A: // DI_2A   X.......shiiiiii iiiiiinnnnnddddd      Rd Rn    imm(i12,sh)
11116             if ((ins == INS_add) || (ins == INS_sub))
11117             {
11118                 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11119                 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11120             }
11121             else
11122             {
11123                 emitDispReg(id->idReg1(), size, true);
11124                 emitDispReg(id->idReg2(), size, true);
11125             }
11126             emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
11127             break;
11128
11129         case IF_DI_2B: // DI_2B   X........X.nnnnn ssssssnnnnnddddd      Rd Rn    imm(0-63)
11130             emitDispReg(id->idReg1(), size, true);
11131             emitDispReg(id->idReg2(), size, true);
11132             emitDispImm(emitGetInsSC(id), false);
11133             break;
11134
11135         case IF_DI_2C: // DI_2C   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imm(N,r,s)
11136             if (ins == INS_ands)
11137             {
11138                 emitDispReg(id->idReg1(), size, true);
11139             }
11140             else
11141             {
11142                 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11143             }
11144             emitDispReg(id->idReg2(), size, true);
11145             bmi.immNRS = (unsigned)emitGetInsSC(id);
11146             emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
11147             break;
11148
11149         case IF_DI_2D: // DI_2D   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imr, ims   (N,r,s)
11150             emitDispReg(id->idReg1(), size, true);
11151             emitDispReg(id->idReg2(), size, true);
11152
11153             imm        = emitGetInsSC(id);
11154             bmi.immNRS = (unsigned)imm;
11155
11156             switch (ins)
11157             {
11158                 case INS_bfm:
11159                 case INS_sbfm:
11160                 case INS_ubfm:
11161                     emitDispImm(bmi.immR, true);
11162                     emitDispImm(bmi.immS, false);
11163                     break;
11164
11165                 case INS_bfi:
11166                 case INS_sbfiz:
11167                 case INS_ubfiz:
11168                     emitDispImm(getBitWidth(size) - bmi.immR, true);
11169                     emitDispImm(bmi.immS + 1, false);
11170                     break;
11171
11172                 case INS_bfxil:
11173                 case INS_sbfx:
11174                 case INS_ubfx:
11175                     emitDispImm(bmi.immR, true);
11176                     emitDispImm(bmi.immS - bmi.immR + 1, false);
11177                     break;
11178
11179                 case INS_asr:
11180                 case INS_lsr:
11181                 case INS_lsl:
11182                     emitDispImm(imm, false);
11183                     break;
11184
11185                 default:
11186                     assert(!"Unexpected instruction in IF_DI_2D");
11187             }
11188
11189             break;
11190
11191         case IF_DI_1F: // DI_1F   X..........iiiii cccc..nnnnn.nzcv      Rn imm5  nzcv cond
11192             emitDispReg(id->idReg1(), size, true);
11193             cfi.immCFVal = (unsigned)emitGetInsSC(id);
11194             emitDispImm(cfi.imm5, true);
11195             emitDispFlags(cfi.flags);
11196             printf(",");
11197             emitDispCond(cfi.cond);
11198             break;
11199
11200         case IF_DR_1D: // DR_1D   X............... cccc.......mmmmm      Rd       cond
11201             emitDispReg(id->idReg1(), size, true);
11202             cfi.immCFVal = (unsigned)emitGetInsSC(id);
11203             emitDispCond(cfi.cond);
11204             break;
11205
11206         case IF_DR_2A: // DR_2A   X..........mmmmm ......nnnnn.....         Rn Rm
11207             emitDispReg(id->idReg1(), size, true);
11208             emitDispReg(id->idReg2(), size, false);
11209             break;
11210
11211         case IF_DR_2B: // DR_2B   X.......sh.mmmmm ssssssnnnnn.....         Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
11212             emitDispReg(id->idReg1(), size, true);
11213             emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
11214             break;
11215
11216         case IF_DR_2C: // DR_2C   X..........mmmmm ooosssnnnnn.....         Rn Rm ext(Rm) LSL imm(0-4)
11217             emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11218             imm = emitGetInsSC(id);
11219             emitDispExtendReg(id->idReg2(), id->idInsOpt(), imm);
11220             break;
11221
11222         case IF_DR_2D: // DR_2D   X..........nnnnn cccc..nnnnnddddd      Rd Rn    cond
11223             emitDispReg(id->idReg1(), size, true);
11224             emitDispReg(id->idReg2(), size, true);
11225             cfi.immCFVal = (unsigned)emitGetInsSC(id);
11226             emitDispCond(cfi.cond);
11227             break;
11228
11229         case IF_DR_2E: // DR_2E   X..........mmmmm ...........ddddd      Rd    Rm
11230         case IF_DR_2J: // DR_2J   ................ ......nnnnnddddd      Sd    Sn
11231             emitDispReg(id->idReg1(), size, true);
11232             emitDispReg(id->idReg2(), size, false);
11233             break;
11234
11235         case IF_DR_2F: // DR_2F   X.......sh.mmmmm ssssss.....ddddd      Rd    Rm {LSL,LSR,ASR} imm(0-63)
11236             emitDispReg(id->idReg1(), size, true);
11237             emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
11238             break;
11239
11240         case IF_DR_2G: // DR_2G   X............... ......nnnnnddddd      Rd Rn
11241             emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11242             emitDispReg(encodingZRtoSP(id->idReg2()), size, false);
11243             break;
11244
11245         case IF_DR_2H: // DR_2H   X........X...... ......nnnnnddddd      Rd Rn
11246             emitDispReg(id->idReg1(), size, true);
11247             emitDispReg(id->idReg2(), size, false);
11248             break;
11249
11250         case IF_DR_2I: // DR_2I   X..........mmmmm cccc..nnnnn.nzcv      Rn Rm    nzcv cond
11251             emitDispReg(id->idReg1(), size, true);
11252             emitDispReg(id->idReg2(), size, true);
11253             cfi.immCFVal = (unsigned)emitGetInsSC(id);
11254             emitDispFlags(cfi.flags);
11255             printf(",");
11256             emitDispCond(cfi.cond);
11257             break;
11258
11259         case IF_DR_3A: // DR_3A   X..........mmmmm ......nnnnnmmmmm      Rd Rn Rm
11260             if ((ins == INS_add) || (ins == INS_sub))
11261             {
11262                 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11263                 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11264             }
11265             else if ((ins == INS_smull) || (ins == INS_smulh))
11266             {
11267                 // Rd is always 8 bytes
11268                 emitDispReg(id->idReg1(), EA_8BYTE, true);
11269
11270                 // Rn, Rm effective size depends on instruction type
11271                 size = (ins == INS_smulh) ? EA_8BYTE : EA_4BYTE;
11272                 emitDispReg(id->idReg2(), size, true);
11273             }
11274             else
11275             {
11276                 emitDispReg(id->idReg1(), size, true);
11277                 emitDispReg(id->idReg2(), size, true);
11278             }
11279             if (id->idIsLclVar())
11280             {
11281                 emitDispReg(codeGen->rsGetRsvdReg(), size, false);
11282             }
11283             else
11284             {
11285                 emitDispReg(id->idReg3(), size, false);
11286             }
11287
11288             break;
11289
11290         case IF_DR_3B: // DR_3B   X.......sh.mmmmm ssssssnnnnnddddd      Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
11291             emitDispReg(id->idReg1(), size, true);
11292             emitDispReg(id->idReg2(), size, true);
11293             emitDispShiftedReg(id->idReg3(), id->idInsOpt(), emitGetInsSC(id), size);
11294             break;
11295
11296         case IF_DR_3C: // DR_3C   X..........mmmmm ooosssnnnnnddddd      Rd Rn Rm ext(Rm) LSL imm(0-4)
11297             emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11298             emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11299             imm = emitGetInsSC(id);
11300             emitDispExtendReg(id->idReg3(), id->idInsOpt(), imm);
11301             break;
11302
11303         case IF_DR_3D: // DR_3D   X..........mmmmm cccc..nnnnnmmmmm      Rd Rn Rm cond
11304             emitDispReg(id->idReg1(), size, true);
11305             emitDispReg(id->idReg2(), size, true);
11306             emitDispReg(id->idReg3(), size, true);
11307             cfi.immCFVal = (unsigned)emitGetInsSC(id);
11308             emitDispCond(cfi.cond);
11309             break;
11310
11311         case IF_DR_3E: // DR_3E   X........X.mmmmm ssssssnnnnnddddd      Rd Rn Rm imm(0-63)
11312             emitDispReg(id->idReg1(), size, true);
11313             emitDispReg(id->idReg2(), size, true);
11314             emitDispReg(id->idReg3(), size, true);
11315             emitDispImm(emitGetInsSC(id), false);
11316             break;
11317
11318         case IF_DR_4A: // DR_4A   X..........mmmmm .aaaaannnnnmmmmm      Rd Rn Rm Ra
11319             emitDispReg(id->idReg1(), size, true);
11320             emitDispReg(id->idReg2(), size, true);
11321             emitDispReg(id->idReg3(), size, true);
11322             emitDispReg(id->idReg4(), size, false);
11323             break;
11324
11325         case IF_DV_1A: // DV_1A   .........X.iiiii iii........ddddd      Vd imm8 (fmov - immediate scalar)
11326             elemsize = id->idOpSize();
11327             emitDispReg(id->idReg1(), elemsize, true);
11328             emitDispFloatImm(emitGetInsSC(id));
11329             break;
11330
11331         case IF_DV_1B: // DV_1B   .QX..........iii cmod..iiiiiddddd      Vd imm8 (immediate vector)
11332             imm      = emitGetInsSC(id) & 0x0ff;
11333             immShift = (emitGetInsSC(id) & 0x700) >> 8;
11334             hasShift = (immShift != 0);
11335             elemsize = optGetElemsize(id->idInsOpt());
11336             if (id->idInsOpt() == INS_OPTS_1D)
11337             {
11338                 assert(elemsize == size);
11339                 emitDispReg(id->idReg1(), size, true);
11340             }
11341             else
11342             {
11343                 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11344             }
11345             if (ins == INS_fmov)
11346             {
11347                 emitDispFloatImm(imm);
11348                 assert(hasShift == false);
11349             }
11350             else
11351             {
11352                 if (elemsize == EA_8BYTE)
11353                 {
11354                     assert(ins == INS_movi);
11355                     ssize_t       imm64 = 0;
11356                     const ssize_t mask8 = 0xFF;
11357                     for (unsigned b = 0; b < 8; b++)
11358                     {
11359                         if (imm & (1 << b))
11360                         {
11361                             imm64 |= (mask8 << (b * 8));
11362                         }
11363                     }
11364                     emitDispImm(imm64, hasShift, true);
11365                 }
11366                 else
11367                 {
11368                     emitDispImm(imm, hasShift, true);
11369                 }
11370                 if (hasShift)
11371                 {
11372                     insOpts  opt   = (immShift & 0x4) ? INS_OPTS_MSL : INS_OPTS_LSL;
11373                     unsigned shift = (immShift & 0x3) * 8;
11374                     emitDispShiftOpts(opt);
11375                     emitDispImm(shift, false);
11376                 }
11377             }
11378             break;
11379
11380         case IF_DV_1C: // DV_1C   .........X...... ......nnnnn.....      Vn #0.0 (fcmp - with zero)
11381             elemsize = id->idOpSize();
11382             emitDispReg(id->idReg1(), elemsize, true);
11383             emitDispFloatZero();
11384             break;
11385
11386         case IF_DV_2A: // DV_2A   .Q.......X...... ......nnnnnddddd      Vd Vn   (fabs, fcvt - vector)
11387         case IF_DV_2M: // DV_2M   .Q......XX...... ......nnnnnddddd      Vd Vn   (abs, neg   - vector)
11388         case IF_DV_2P: // DV_2P   ................ ......nnnnnddddd      Vd Vn   (aes*, sha1su1)
11389             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11390             emitDispVectorReg(id->idReg2(), id->idInsOpt(), false);
11391             break;
11392
11393         case IF_DV_2N: // DV_2N   .........iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - scalar)
11394             elemsize = id->idOpSize();
11395             emitDispReg(id->idReg1(), elemsize, true);
11396             emitDispReg(id->idReg2(), elemsize, true);
11397             emitDispImm(emitGetInsSC(id), false);
11398             break;
11399
11400         case IF_DV_2O: // DV_2O   .Q.......iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - vector)
11401             imm = emitGetInsSC(id);
11402             // Do we have a sxtl or uxtl instruction?
11403             isExtendAlias = ((ins == INS_sxtl) || (ins == INS_sxtl2) || (ins == INS_uxtl) || (ins == INS_uxtl2));
11404             code          = emitInsCode(ins, fmt);
11405             if (code & 0x00008000) // widen/narrow opcodes
11406             {
11407                 if (code & 0x00002000) // SHL opcodes
11408                 {
11409                     emitDispVectorReg(id->idReg1(), optWidenElemsize(id->idInsOpt()), true);
11410                     emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11411                 }
11412                 else // SHR opcodes
11413                 {
11414                     emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11415                     emitDispVectorReg(id->idReg2(), optWidenElemsize(id->idInsOpt()), !isExtendAlias);
11416                 }
11417             }
11418             else
11419             {
11420                 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11421                 emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11422             }
11423             // Print the immediate unless we have a sxtl or uxtl instruction
11424             if (!isExtendAlias)
11425             {
11426                 emitDispImm(imm, false);
11427             }
11428             break;
11429
11430         case IF_DV_2B: // DV_2B   .Q.........iiiii ......nnnnnddddd      Rd Vn[] (umov/smov    - to general)
11431             srcsize = id->idOpSize();
11432             index   = emitGetInsSC(id);
11433             if (ins == INS_smov)
11434             {
11435                 dstsize = EA_8BYTE;
11436             }
11437             else // INS_umov or INS_mov
11438             {
11439                 dstsize = (srcsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE;
11440             }
11441             emitDispReg(id->idReg1(), dstsize, true);
11442             emitDispVectorRegIndex(id->idReg2(), srcsize, index, false);
11443             break;
11444
11445         case IF_DV_2C: // DV_2C   .Q.........iiiii ......nnnnnddddd      Vd Rn   (dup/ins - vector from general)
11446             if (ins == INS_dup)
11447             {
11448                 datasize = id->idOpSize();
11449                 assert(isValidVectorDatasize(datasize));
11450                 assert(isValidArrangement(datasize, id->idInsOpt()));
11451                 elemsize = optGetElemsize(id->idInsOpt());
11452                 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11453             }
11454             else // INS_ins
11455             {
11456                 elemsize = id->idOpSize();
11457                 index    = emitGetInsSC(id);
11458                 assert(isValidVectorElemsize(elemsize));
11459                 emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11460             }
11461             emitDispReg(id->idReg2(), (elemsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE, false);
11462             break;
11463
11464         case IF_DV_2D: // DV_2D   .Q.........iiiii ......nnnnnddddd      Vd Vn[]   (dup - vector)
11465             datasize = id->idOpSize();
11466             assert(isValidVectorDatasize(datasize));
11467             assert(isValidArrangement(datasize, id->idInsOpt()));
11468             elemsize = optGetElemsize(id->idInsOpt());
11469             index    = emitGetInsSC(id);
11470             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11471             emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11472             break;
11473
11474         case IF_DV_2E: // DV_2E   ...........iiiii ......nnnnnddddd      Vd Vn[]   (dup - scalar)
11475             elemsize = id->idOpSize();
11476             index    = emitGetInsSC(id);
11477             emitDispReg(id->idReg1(), elemsize, true);
11478             emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11479             break;
11480
11481         case IF_DV_2F: // DV_2F   ...........iiiii .jjjj.nnnnnddddd      Vd[] Vn[] (ins - element)
11482             imm      = emitGetInsSC(id);
11483             index    = (imm >> 4) & 0xf;
11484             index2   = imm & 0xf;
11485             elemsize = id->idOpSize();
11486             emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11487             emitDispVectorRegIndex(id->idReg2(), elemsize, index2, false);
11488             break;
11489
11490         case IF_DV_2G: // DV_2G   .........X...... ......nnnnnddddd      Vd Vn      (fmov, fcvtXX - register)
11491         case IF_DV_2K: // DV_2K   .........X.mmmmm ......nnnnn.....      Vn Vm      (fcmp)
11492         case IF_DV_2L: // DV_2L   ........XX...... ......nnnnnddddd      Vd Vn      (abs, neg - scalar)
11493             elemsize = id->idOpSize();
11494             emitDispReg(id->idReg1(), elemsize, true);
11495             emitDispReg(id->idReg2(), elemsize, false);
11496             break;
11497
11498         case IF_DV_2H: // DV_2H   X........X...... ......nnnnnddddd      Rd Vn      (fmov, fcvtXX - to general)
11499         case IF_DV_2I: // DV_2I   X........X...... ......nnnnnddddd      Vd Rn      (fmov, Xcvtf - from general)
11500         case IF_DV_2J: // DV_2J   ........SS.....D D.....nnnnnddddd      Vd Vn      (fcvt)
11501             dstsize = optGetDstsize(id->idInsOpt());
11502             srcsize = optGetSrcsize(id->idInsOpt());
11503
11504             emitDispReg(id->idReg1(), dstsize, true);
11505             emitDispReg(id->idReg2(), srcsize, false);
11506             break;
11507
11508         case IF_DV_3A: // DV_3A   .Q......XX.mmmmm ......nnnnnddddd      Vd Vn Vm  (vector)
11509         case IF_DV_3B: // DV_3B   .Q.........mmmmm ......nnnnnddddd      Vd Vn Vm  (vector)
11510             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11511             emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11512             emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11513             break;
11514
11515         case IF_DV_3C: // DV_3C   .Q.........mmmmm ......nnnnnddddd      Vd Vn Vm  (vector)
11516             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11517             if (ins != INS_mov)
11518             {
11519                 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11520             }
11521             emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11522             break;
11523
11524         case IF_DV_3AI: // DV_3AI  .Q......XXLMmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector by elem)
11525         case IF_DV_3BI: // DV_3BI  .Q........Lmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector by elem)
11526             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11527             emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11528             elemsize = optGetElemsize(id->idInsOpt());
11529             emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11530             break;
11531
11532         case IF_DV_3D: // DV_3D   .........X.mmmmm ......nnnnnddddd      Vd Vn Vm  (scalar)
11533         case IF_DV_3E: // DV_3E   ...........mmmmm ......nnnnnddddd      Vd Vn Vm  (scalar)
11534             emitDispReg(id->idReg1(), size, true);
11535             emitDispReg(id->idReg2(), size, true);
11536             emitDispReg(id->idReg3(), size, false);
11537             break;
11538
11539         case IF_DV_3F: // DV_3F   ..........mmmmm ......nnnnnddddd       Vd Vn Vm (vector)
11540             if ((ins == INS_sha1c) || (ins == INS_sha1m) || (ins == INS_sha1p))
11541             {
11542                 // Qd, Sn, Vm (vector)
11543                 emitDispReg(id->idReg1(), size, true);
11544                 emitDispReg(id->idReg2(), EA_4BYTE, true);
11545                 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11546             }
11547             else if ((ins == INS_sha256h) || (ins == INS_sha256h2))
11548             {
11549                 // Qd Qn Vm (vector)
11550                 emitDispReg(id->idReg1(), size, true);
11551                 emitDispReg(id->idReg2(), size, true);
11552                 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11553             }
11554             else // INS_sha1su0, INS_sha256su1
11555             {
11556                 // Vd, Vn, Vm   (vector)
11557                 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11558                 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11559                 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11560             }
11561             break;
11562
11563         case IF_DV_3DI: // DV_3DI  .........XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (scalar by elem)
11564             emitDispReg(id->idReg1(), size, true);
11565             emitDispReg(id->idReg2(), size, true);
11566             elemsize = size;
11567             emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11568             break;
11569
11570         case IF_DV_4A: // DV_4A   .........X.mmmmm .aaaaannnnnddddd      Vd Va Vn Vm (scalar)
11571             emitDispReg(id->idReg1(), size, true);
11572             emitDispReg(id->idReg2(), size, true);
11573             emitDispReg(id->idReg3(), size, true);
11574             emitDispReg(id->idReg4(), size, false);
11575             break;
11576
11577         case IF_SN_0A: // SN_0A   ................ ................
11578             break;
11579
11580         case IF_SI_0A: // SI_0A   ...........iiiii iiiiiiiiiii.....               imm16
11581             emitDispImm(emitGetInsSC(id), false);
11582             break;
11583
11584         case IF_SI_0B: // SI_0B   ................ ....bbbb........               imm4 - barrier
11585             emitDispBarrier((insBarrier)emitGetInsSC(id));
11586             break;
11587
11588         default:
11589             printf("unexpected format %s", emitIfName(id->idInsFmt()));
11590             assert(!"unexpectedFormat");
11591             break;
11592     }
11593
11594     if (id->idDebugOnlyInfo()->idVarRefOffs)
11595     {
11596         printf("\t// ");
11597         emitDispFrameRef(id->idAddr()->iiaLclVar.lvaVarNum(), id->idAddr()->iiaLclVar.lvaOffset(),
11598                          id->idDebugOnlyInfo()->idVarRefOffs, asmfm);
11599     }
11600
11601     printf("\n");
11602 }
11603
11604 /*****************************************************************************
11605  *
11606  *  Display a stack frame reference.
11607  */
11608
11609 void emitter::emitDispFrameRef(int varx, int disp, int offs, bool asmfm)
11610 {
11611     printf("[");
11612
11613     if (varx < 0)
11614         printf("TEMP_%02u", -varx);
11615     else
11616         emitComp->gtDispLclVar(+varx, false);
11617
11618     if (disp < 0)
11619         printf("-0x%02x", -disp);
11620     else if (disp > 0)
11621         printf("+0x%02x", +disp);
11622
11623     printf("]");
11624
11625     if (varx >= 0 && emitComp->opts.varNames)
11626     {
11627         LclVarDsc*  varDsc;
11628         const char* varName;
11629
11630         assert((unsigned)varx < emitComp->lvaCount);
11631         varDsc  = emitComp->lvaTable + varx;
11632         varName = emitComp->compLocalVarName(varx, offs);
11633
11634         if (varName)
11635         {
11636             printf("'%s", varName);
11637
11638             if (disp < 0)
11639                 printf("-%d", -disp);
11640             else if (disp > 0)
11641                 printf("+%d", +disp);
11642
11643             printf("'");
11644         }
11645     }
11646 }
11647
11648 #endif // DEBUG
11649
11650 // Generate code for a load or store operation with a potentially complex addressing mode
11651 // This method handles the case of a GT_IND with contained GT_LEA op1 of the x86 form [base + index*sccale + offset]
11652 // Since Arm64 does not directly support this complex of an addressing mode
11653 // we may generates up to three instructions for this for Arm64
11654 //
11655 void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataReg, GenTreeIndir* indir)
11656 {
11657     emitAttr ldstAttr = isVectorRegister(dataReg) ? attr : emitInsAdjustLoadStoreAttr(ins, attr);
11658
11659     GenTree* addr = indir->Addr();
11660
11661     if (addr->isContained())
11662     {
11663         assert(addr->OperGet() == GT_LCL_VAR_ADDR || addr->OperGet() == GT_LEA);
11664
11665         int   offset = 0;
11666         DWORD lsl    = 0;
11667
11668         if (addr->OperGet() == GT_LEA)
11669         {
11670             offset = addr->AsAddrMode()->Offset();
11671             if (addr->AsAddrMode()->gtScale > 0)
11672             {
11673                 assert(isPow2(addr->AsAddrMode()->gtScale));
11674                 BitScanForward(&lsl, addr->AsAddrMode()->gtScale);
11675             }
11676         }
11677
11678         GenTree* memBase = indir->Base();
11679
11680         if (indir->HasIndex())
11681         {
11682             GenTree* index = indir->Index();
11683
11684             if (offset != 0)
11685             {
11686                 regNumber tmpReg = indir->GetSingleTempReg();
11687
11688                 emitAttr addType = varTypeIsGC(memBase) ? EA_BYREF : EA_PTRSIZE;
11689
11690                 if (emitIns_valid_imm_for_add(offset, EA_8BYTE))
11691                 {
11692                     if (lsl > 0)
11693                     {
11694                         // Generate code to set tmpReg = base + index*scale
11695                         emitIns_R_R_R_I(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum, lsl,
11696                                         INS_OPTS_LSL);
11697                     }
11698                     else // no scale
11699                     {
11700                         // Generate code to set tmpReg = base + index
11701                         emitIns_R_R_R(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum);
11702                     }
11703
11704                     noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11705
11706                     // Then load/store dataReg from/to [tmpReg + offset]
11707                     emitIns_R_R_I(ins, ldstAttr, dataReg, tmpReg, offset);
11708                 }
11709                 else // large offset
11710                 {
11711                     // First load/store tmpReg with the large offset constant
11712                     codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11713                     // Then add the base register
11714                     //      rd = rd + base
11715                     emitIns_R_R_R(INS_add, addType, tmpReg, tmpReg, memBase->gtRegNum);
11716
11717                     noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11718                     noway_assert(tmpReg != index->gtRegNum);
11719
11720                     // Then load/store dataReg from/to [tmpReg + index*scale]
11721                     emitIns_R_R_R_I(ins, ldstAttr, dataReg, tmpReg, index->gtRegNum, lsl, INS_OPTS_LSL);
11722                 }
11723             }
11724             else // (offset == 0)
11725             {
11726                 if (lsl > 0)
11727                 {
11728                     // Then load/store dataReg from/to [memBase + index*scale]
11729                     emitIns_R_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum, lsl, INS_OPTS_LSL);
11730                 }
11731                 else // no scale
11732                 {
11733                     // Then load/store dataReg from/to [memBase + index]
11734                     emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum);
11735                 }
11736             }
11737         }
11738         else // no Index register
11739         {
11740             if (emitIns_valid_imm_for_ldst_offset(offset, EA_SIZE(attr)))
11741             {
11742                 // Then load/store dataReg from/to [memBase + offset]
11743                 emitIns_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, offset);
11744             }
11745             else
11746             {
11747                 // We require a tmpReg to hold the offset
11748                 regNumber tmpReg = indir->GetSingleTempReg();
11749
11750                 // First load/store tmpReg with the large offset constant
11751                 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11752
11753                 // Then load/store dataReg from/to [memBase + tmpReg]
11754                 emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, tmpReg);
11755             }
11756         }
11757     }
11758     else // addr is not contained, so we evaluate it into a register
11759     {
11760         // Then load/store dataReg from/to [addrReg]
11761         emitIns_R_R(ins, ldstAttr, dataReg, addr->gtRegNum);
11762     }
11763 }
11764
11765 // The callee must call genConsumeReg() for any non-contained srcs
11766 // and genProduceReg() for any non-contained dsts.
11767
11768 regNumber emitter::emitInsBinary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src)
11769 {
11770     regNumber result = REG_NA;
11771
11772     // dst can only be a reg
11773     assert(!dst->isContained());
11774
11775     // src can be immed or reg
11776     assert(!src->isContained() || src->isContainedIntOrIImmed());
11777
11778     // find immed (if any) - it cannot be a dst
11779     GenTreeIntConCommon* intConst = nullptr;
11780     if (src->isContainedIntOrIImmed())
11781     {
11782         intConst = src->AsIntConCommon();
11783     }
11784
11785     if (intConst)
11786     {
11787         emitIns_R_I(ins, attr, dst->gtRegNum, intConst->IconValue());
11788         return dst->gtRegNum;
11789     }
11790     else
11791     {
11792         emitIns_R_R(ins, attr, dst->gtRegNum, src->gtRegNum);
11793         return dst->gtRegNum;
11794     }
11795 }
11796
11797 // The callee must call genConsumeReg() for any non-contained srcs
11798 // and genProduceReg() for any non-contained dsts.
11799
11800 regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src1, GenTree* src2)
11801 {
11802     regNumber result = REG_NA;
11803
11804     // dst can only be a reg
11805     assert(!dst->isContained());
11806
11807     // find immed (if any) - it cannot be a dst
11808     // Only one src can be an int.
11809     GenTreeIntConCommon* intConst  = nullptr;
11810     GenTree*             nonIntReg = nullptr;
11811
11812     if (varTypeIsFloating(dst))
11813     {
11814         // src1 can only be a reg
11815         assert(!src1->isContained());
11816         // src2 can only be a reg
11817         assert(!src2->isContained());
11818     }
11819     else // not floating point
11820     {
11821         // src2 can be immed or reg
11822         assert(!src2->isContained() || src2->isContainedIntOrIImmed());
11823
11824         // Check src2 first as we can always allow it to be a contained immediate
11825         if (src2->isContainedIntOrIImmed())
11826         {
11827             intConst  = src2->AsIntConCommon();
11828             nonIntReg = src1;
11829         }
11830         // Only for commutative operations do we check src1 and allow it to be a contained immediate
11831         else if (dst->OperIsCommutative())
11832         {
11833             // src1 can be immed or reg
11834             assert(!src1->isContained() || src1->isContainedIntOrIImmed());
11835
11836             // Check src1 and allow it to be a contained immediate
11837             if (src1->isContainedIntOrIImmed())
11838             {
11839                 assert(!src2->isContainedIntOrIImmed());
11840                 intConst  = src1->AsIntConCommon();
11841                 nonIntReg = src2;
11842             }
11843         }
11844         else
11845         {
11846             // src1 can only be a reg
11847             assert(!src1->isContained());
11848         }
11849     }
11850
11851     bool isMulOverflow = false;
11852     if (dst->gtOverflowEx())
11853     {
11854         if ((ins == INS_add) || (ins == INS_adds))
11855         {
11856             ins = INS_adds;
11857         }
11858         else if ((ins == INS_sub) || (ins == INS_subs))
11859         {
11860             ins = INS_subs;
11861         }
11862         else if (ins == INS_mul)
11863         {
11864             isMulOverflow = true;
11865             assert(intConst == nullptr); // overflow format doesn't support an int constant operand
11866         }
11867         else
11868         {
11869             assert(!"Invalid ins for overflow check");
11870         }
11871     }
11872     if (intConst != nullptr)
11873     {
11874         emitIns_R_R_I(ins, attr, dst->gtRegNum, nonIntReg->gtRegNum, intConst->IconValue());
11875     }
11876     else
11877     {
11878         if (isMulOverflow)
11879         {
11880             regNumber extraReg = dst->GetSingleTempReg();
11881             assert(extraReg != dst->gtRegNum);
11882
11883             if ((dst->gtFlags & GTF_UNSIGNED) != 0)
11884             {
11885                 if (attr == EA_4BYTE)
11886                 {
11887                     // Compute 8 byte results from 4 byte by 4 byte multiplication.
11888                     emitIns_R_R_R(INS_umull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11889
11890                     // Get the high result by shifting dst.
11891                     emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11892                 }
11893                 else
11894                 {
11895                     assert(attr == EA_8BYTE);
11896                     // Compute the high result.
11897                     emitIns_R_R_R(INS_umulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11898
11899                     // Now multiply without skewing the high result.
11900                     emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11901                 }
11902
11903                 // zero-sign bit comparison to detect overflow.
11904                 emitIns_R_I(INS_cmp, attr, extraReg, 0);
11905             }
11906             else
11907             {
11908                 int bitShift = 0;
11909                 if (attr == EA_4BYTE)
11910                 {
11911                     // Compute 8 byte results from 4 byte by 4 byte multiplication.
11912                     emitIns_R_R_R(INS_smull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11913
11914                     // Get the high result by shifting dst.
11915                     emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11916
11917                     bitShift = 31;
11918                 }
11919                 else
11920                 {
11921                     assert(attr == EA_8BYTE);
11922                     // Save the high result in a temporary register.
11923                     emitIns_R_R_R(INS_smulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11924
11925                     // Now multiply without skewing the high result.
11926                     emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11927
11928                     bitShift = 63;
11929                 }
11930
11931                 // Sign bit comparison to detect overflow.
11932                 emitIns_R_R_I(INS_cmp, attr, extraReg, dst->gtRegNum, bitShift, INS_OPTS_ASR);
11933             }
11934         }
11935         else
11936         {
11937             // We can just multiply.
11938             emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11939         }
11940     }
11941
11942     if (dst->gtOverflowEx())
11943     {
11944         assert(!varTypeIsFloating(dst));
11945         codeGen->genCheckOverflow(dst);
11946     }
11947
11948     return dst->gtRegNum;
11949 }
11950
11951 #endif // defined(_TARGET_ARM64_)