Handle MovRelocatableImmediate on ARM32 as a special case (IF_T2_N3) (#19013)
[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 |= (ssize_t{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
8504     // Set default ins/fmt from id.
8505     instruction ins = id->idIns();
8506     insFormat   fmt = id->idInsFmt();
8507
8508     bool loadLabel    = false;
8509     bool isJump       = false;
8510     bool loadConstant = false;
8511
8512     switch (ins)
8513     {
8514         default:
8515             isJump = true;
8516             break;
8517
8518         case INS_tbz:
8519         case INS_tbnz:
8520         case INS_cbz:
8521         case INS_cbnz:
8522             isJump = true;
8523             break;
8524
8525         case INS_ldr:
8526         case INS_ldrsw:
8527             loadConstant = true;
8528             break;
8529
8530         case INS_adr:
8531         case INS_adrp:
8532             loadLabel = true;
8533             break;
8534     }
8535
8536     /* Figure out the distance to the target */
8537
8538     srcOffs = emitCurCodeOffs(dst);
8539     srcAddr = emitOffsetToPtr(srcOffs);
8540
8541     if (id->idAddr()->iiaIsJitDataOffset())
8542     {
8543         assert(loadConstant || loadLabel);
8544         int doff = id->idAddr()->iiaGetJitDataOffset();
8545         assert(doff >= 0);
8546         ssize_t imm = emitGetInsSC(id);
8547         assert((imm >= 0) && (imm < 0x1000)); // 0x1000 is arbitrary, currently 'imm' is always 0
8548
8549         unsigned dataOffs = (unsigned)(doff + imm);
8550         assert(dataOffs < emitDataSize());
8551         dstAddr = emitDataOffsetToPtr(dataOffs);
8552
8553         regNumber dstReg  = id->idReg1();
8554         regNumber addrReg = dstReg; // an integer register to compute long address.
8555         emitAttr  opSize  = id->idOpSize();
8556
8557         if (loadConstant)
8558         {
8559             if (id->idjShort)
8560             {
8561                 // ldr x/v, [rel addr] -- load constant from current addr(ip) + rel addr.
8562                 assert(ins == INS_ldr);
8563                 assert(fmt == IF_LS_1A);
8564                 distVal = (ssize_t)(dstAddr - srcAddr);
8565                 dst     = emitOutputShortConstant(dst, ins, fmt, distVal, dstReg, opSize);
8566             }
8567             else
8568             {
8569                 // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8570                 assert(fmt == IF_LARGELDC);
8571                 ssize_t relPageAddr =
8572                     (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8573                 if (isVectorRegister(dstReg))
8574                 {
8575                     // Update addrReg with the reserved integer register
8576                     // since we cannot use dstReg (vector) to load constant directly from memory.
8577                     addrReg = id->idReg2();
8578                     assert(isGeneralRegister(addrReg));
8579                 }
8580                 ins = INS_adrp;
8581                 fmt = IF_DI_1E;
8582                 dst = emitOutputShortAddress(dst, ins, fmt, relPageAddr, addrReg);
8583
8584                 // ldr x, [x, page offs] -- load constant from page address + page offset into integer register.
8585                 ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8586                 assert(isValidUimm12(imm12));
8587                 ins = INS_ldr;
8588                 fmt = IF_LS_2B;
8589                 dst = emitOutputShortConstant(dst, ins, fmt, imm12, addrReg, opSize);
8590
8591                 // fmov v, d -- copy constant in integer register to vector register.
8592                 // This is needed only for vector constant.
8593                 if (addrReg != dstReg)
8594                 {
8595                     //  fmov    Vd,Rn                DV_2I  X00111100X100111 000000nnnnnddddd   1E27 0000   Vd,Rn
8596                     //  (scalar, from general)
8597                     assert(isVectorRegister(dstReg) && isGeneralRegister(addrReg));
8598                     ins         = INS_fmov;
8599                     fmt         = IF_DV_2I;
8600                     code_t code = emitInsCode(ins, fmt);
8601
8602                     code |= insEncodeReg_Vd(dstReg);  // ddddd
8603                     code |= insEncodeReg_Rn(addrReg); // nnnnn
8604                     if (id->idOpSize() == EA_8BYTE)
8605                     {
8606                         code |= 0x80400000; // X ... X
8607                     }
8608                     dst += emitOutput_Instr(dst, code);
8609                 }
8610             }
8611         }
8612         else
8613         {
8614             assert(loadLabel);
8615             dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8616         }
8617
8618         return dst;
8619     }
8620
8621     assert(loadLabel || isJump);
8622
8623     if (id->idAddr()->iiaHasInstrCount())
8624     {
8625         assert(ig != NULL);
8626         int      instrCount = id->idAddr()->iiaGetInstrCount();
8627         unsigned insNum     = emitFindInsNum(ig, id);
8628         if (instrCount < 0)
8629         {
8630             // Backward branches using instruction count must be within the same instruction group.
8631             assert(insNum + 1 >= (unsigned)(-instrCount));
8632         }
8633         dstOffs = ig->igOffs + emitFindOffset(ig, (insNum + 1 + instrCount));
8634         dstAddr = emitOffsetToPtr(dstOffs);
8635     }
8636     else
8637     {
8638         dstOffs = id->idAddr()->iiaIGlabel->igOffs;
8639         dstAddr = emitOffsetToPtr(dstOffs);
8640     }
8641
8642     distVal = (ssize_t)(dstAddr - srcAddr);
8643
8644     if (dstOffs <= srcOffs)
8645     {
8646 #if DEBUG_EMIT
8647         /* This is a backward jump - distance is known at this point */
8648
8649         if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8650         {
8651             size_t blkOffs = id->idjIG->igOffs;
8652
8653             if (INTERESTING_JUMP_NUM == 0)
8654                 printf("[3] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8655             printf("[3] Jump  block is at %08X - %02X = %08X\n", blkOffs, emitOffsAdj, blkOffs - emitOffsAdj);
8656             printf("[3] Jump        is at %08X - %02X = %08X\n", srcOffs, emitOffsAdj, srcOffs - emitOffsAdj);
8657             printf("[3] Label block is at %08X - %02X = %08X\n", dstOffs, emitOffsAdj, dstOffs - emitOffsAdj);
8658         }
8659 #endif
8660     }
8661     else
8662     {
8663         /* This is a  forward jump - distance will be an upper limit */
8664
8665         emitFwdJumps = true;
8666
8667         /* The target offset will be closer by at least 'emitOffsAdj', but only if this
8668            jump doesn't cross the hot-cold boundary. */
8669
8670         if (!emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8671         {
8672             dstOffs -= emitOffsAdj;
8673             distVal -= emitOffsAdj;
8674         }
8675
8676         /* Record the location of the jump for later patching */
8677
8678         id->idjOffs = dstOffs;
8679
8680         /* Are we overflowing the id->idjOffs bitfield? */
8681         if (id->idjOffs != dstOffs)
8682             IMPL_LIMITATION("Method is too large");
8683
8684 #if DEBUG_EMIT
8685         if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8686         {
8687             size_t blkOffs = id->idjIG->igOffs;
8688
8689             if (INTERESTING_JUMP_NUM == 0)
8690                 printf("[4] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8691             printf("[4] Jump  block is at %08X\n", blkOffs);
8692             printf("[4] Jump        is at %08X\n", srcOffs);
8693             printf("[4] Label block is at %08X - %02X = %08X\n", dstOffs + emitOffsAdj, emitOffsAdj, dstOffs);
8694         }
8695 #endif
8696     }
8697
8698 #ifdef DEBUG
8699     if (0 && emitComp->verbose)
8700     {
8701         size_t sz          = 4;
8702         int    distValSize = id->idjShort ? 4 : 8;
8703         printf("; %s jump [%08X/%03u] from %0*X to %0*X: dist = %08XH\n", (dstOffs <= srcOffs) ? "Fwd" : "Bwd",
8704                dspPtr(id), id->idDebugOnlyInfo()->idNum, distValSize, srcOffs + sz, distValSize, dstOffs, distVal);
8705     }
8706 #endif
8707
8708     /* For forward jumps, record the address of the distance value */
8709     id->idjTemp.idjAddr = (distVal > 0) ? dst : NULL;
8710
8711     if (emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8712     {
8713         assert(!id->idjShort);
8714         NYI_ARM64("Relocation Support for long address");
8715     }
8716
8717     assert(insOptsNone(id->idInsOpt()));
8718
8719     if (isJump)
8720     {
8721         if (id->idjShort)
8722         {
8723             // Short conditional/unconditional jump
8724             assert(!id->idjKeepLong);
8725             assert(emitJumpCrossHotColdBoundary(srcOffs, dstOffs) == false);
8726             assert((fmt == IF_BI_0A) || (fmt == IF_BI_0B) || (fmt == IF_BI_1A) || (fmt == IF_BI_1B));
8727         }
8728         else
8729         {
8730             // Long conditional jump
8731             assert(fmt == IF_LARGEJMP);
8732             // This is a pseudo-instruction format representing a large conditional branch, to allow
8733             // us to get a greater branch target range than we can get by using a straightforward conditional
8734             // branch. It is encoded as a short conditional branch that branches around a long unconditional
8735             // branch.
8736             //
8737             // Conceptually, we have:
8738             //
8739             //      b<cond> L_target
8740             //
8741             // The code we emit is:
8742             //
8743             //      b<!cond> L_not  // 4 bytes. Note that we reverse the condition.
8744             //      b L_target      // 4 bytes
8745             //   L_not:
8746             //
8747             // Note that we don't actually insert any blocks: we simply encode "b <!cond> L_not" as a branch with
8748             // the correct offset. Note also that this works for both integer and floating-point conditions, because
8749             // the condition inversion takes ordered/unordered into account, preserving NaN behavior. For example,
8750             // "GT" (greater than) is inverted to "LE" (less than, equal, or unordered).
8751
8752             instruction reverseIns;
8753             insFormat   reverseFmt;
8754
8755             switch (ins)
8756             {
8757                 case INS_cbz:
8758                     reverseIns = INS_cbnz;
8759                     reverseFmt = IF_BI_1A;
8760                     break;
8761                 case INS_cbnz:
8762                     reverseIns = INS_cbz;
8763                     reverseFmt = IF_BI_1A;
8764                     break;
8765                 case INS_tbz:
8766                     reverseIns = INS_tbnz;
8767                     reverseFmt = IF_BI_1B;
8768                     break;
8769                 case INS_tbnz:
8770                     reverseIns = INS_tbz;
8771                     reverseFmt = IF_BI_1B;
8772                     break;
8773                 default:
8774                     reverseIns = emitJumpKindToIns(emitReverseJumpKind(emitInsToJumpKind(ins)));
8775                     reverseFmt = IF_BI_0B;
8776             }
8777
8778             dst =
8779                 emitOutputShortBranch(dst,
8780                                       reverseIns, // reverse the conditional instruction
8781                                       reverseFmt,
8782                                       8, /* 8 bytes from start of this large conditional pseudo-instruction to L_not. */
8783                                       id);
8784
8785             // Now, pretend we've got a normal unconditional branch, and fall through to the code to emit that.
8786             ins = INS_b;
8787             fmt = IF_BI_0A;
8788
8789             // The distVal was computed based on the beginning of the pseudo-instruction,
8790             // So subtract the size of the conditional branch so that it is relative to the
8791             // unconditional branch.
8792             distVal -= 4;
8793         }
8794
8795         dst = emitOutputShortBranch(dst, ins, fmt, distVal, id);
8796     }
8797     else if (loadLabel)
8798     {
8799         dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8800     }
8801
8802     return dst;
8803 }
8804
8805 /*****************************************************************************
8806 *
8807 *  Output a short branch instruction.
8808 */
8809 BYTE* emitter::emitOutputShortBranch(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, instrDescJmp* id)
8810 {
8811     code_t code = emitInsCode(ins, fmt);
8812
8813     ssize_t loBits = (distVal & 3);
8814     noway_assert(loBits == 0);
8815     distVal >>= 2; // branch offset encodings are scaled by 4.
8816
8817     if (fmt == IF_BI_0A)
8818     {
8819         // INS_b or INS_bl_local
8820         noway_assert(isValidSimm26(distVal));
8821         distVal &= 0x3FFFFFFLL;
8822         code |= distVal;
8823     }
8824     else if (fmt == IF_BI_0B) // BI_0B   01010100iiiiiiii iiiiiiiiiiiXXXXX      simm19:00
8825     {
8826         // INS_beq, INS_bne, etc...
8827         noway_assert(isValidSimm19(distVal));
8828         distVal &= 0x7FFFFLL;
8829         code |= distVal << 5;
8830     }
8831     else if (fmt == IF_BI_1A) // BI_1A   X.......iiiiiiii iiiiiiiiiiittttt      Rt simm19:00
8832     {
8833         // INS_cbz or INS_cbnz
8834         assert(id != nullptr);
8835         code |= insEncodeDatasize(id->idOpSize()); // X
8836         code |= insEncodeReg_Rt(id->idReg1());     // ttttt
8837
8838         noway_assert(isValidSimm19(distVal));
8839         distVal &= 0x7FFFFLL; // 19 bits
8840         code |= distVal << 5;
8841     }
8842     else if (fmt == IF_BI_1B) // BI_1B   B.......bbbbbiii iiiiiiiiiiittttt      Rt imm6, simm14:00
8843     {
8844         // INS_tbz or INS_tbnz
8845         assert(id != nullptr);
8846         ssize_t imm = emitGetInsSC(id);
8847         assert(isValidImmShift(imm, id->idOpSize()));
8848
8849         if (imm & 0x20) // test bit 32-63 ?
8850         {
8851             code |= 0x80000000; // B
8852         }
8853         code |= ((imm & 0x1F) << 19);          // bbbbb
8854         code |= insEncodeReg_Rt(id->idReg1()); // ttttt
8855
8856         noway_assert(isValidSimm14(distVal));
8857         distVal &= 0x3FFFLL; // 14 bits
8858         code |= distVal << 5;
8859     }
8860     else
8861     {
8862         assert(!"Unknown fmt for emitOutputShortBranch");
8863     }
8864
8865     dst += emitOutput_Instr(dst, code);
8866
8867     return dst;
8868 }
8869
8870 /*****************************************************************************
8871 *
8872 *  Output a short address instruction.
8873 */
8874 BYTE* emitter::emitOutputShortAddress(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, regNumber reg)
8875 {
8876     ssize_t loBits = (distVal & 3);
8877     distVal >>= 2;
8878
8879     code_t code = emitInsCode(ins, fmt);
8880     if (fmt == IF_DI_1E) // DI_1E   .ii.....iiiiiiii iiiiiiiiiiiddddd      Rd simm21
8881     {
8882         // INS_adr or INS_adrp
8883         code |= insEncodeReg_Rd(reg); // ddddd
8884
8885         noway_assert(isValidSimm19(distVal));
8886         distVal &= 0x7FFFFLL; // 19 bits
8887         code |= distVal << 5;
8888         code |= loBits << 29; //  2 bits
8889     }
8890     else
8891     {
8892         assert(!"Unknown fmt for emitOutputShortAddress");
8893     }
8894
8895     dst += emitOutput_Instr(dst, code);
8896
8897     return dst;
8898 }
8899
8900 /*****************************************************************************
8901 *
8902 *  Output a short constant instruction.
8903 */
8904 BYTE* emitter::emitOutputShortConstant(
8905     BYTE* dst, instruction ins, insFormat fmt, ssize_t imm, regNumber reg, emitAttr opSize)
8906 {
8907     code_t code = emitInsCode(ins, fmt);
8908
8909     if (fmt == IF_LS_1A)
8910     {
8911         // LS_1A   XX...V..iiiiiiii iiiiiiiiiiittttt      Rt simm21
8912         // INS_ldr or INS_ldrsw (PC-Relative)
8913
8914         ssize_t loBits = (imm & 3);
8915         noway_assert(loBits == 0);
8916         ssize_t distVal = imm >>= 2; // load offset encodings are scaled by 4.
8917
8918         noway_assert(isValidSimm19(distVal));
8919
8920         // Is the target a vector register?
8921         if (isVectorRegister(reg))
8922         {
8923             code |= insEncodeDatasizeVLS(code, opSize); // XX V
8924             code |= insEncodeReg_Vt(reg);               // ttttt
8925         }
8926         else
8927         {
8928             assert(isGeneralRegister(reg));
8929             // insEncodeDatasizeLS is not quite right for this case.
8930             // So just specialize it.
8931             if ((ins == INS_ldr) && (opSize == EA_8BYTE))
8932             {
8933                 // set the operation size in bit 30
8934                 code |= 0x40000000;
8935             }
8936
8937             code |= insEncodeReg_Rt(reg); // ttttt
8938         }
8939
8940         distVal &= 0x7FFFFLL; // 19 bits
8941         code |= distVal << 5;
8942     }
8943     else if (fmt == IF_LS_2B)
8944     {
8945         //  ldr     Rt,[Xn+pimm12]       LS_2B  1X11100101iiiiii iiiiiinnnnnttttt   B940 0000   imm(0-4095<<{2,3})
8946         // INS_ldr or INS_ldrsw (PC-Relative)
8947         noway_assert(isValidUimm12(imm));
8948         assert(isGeneralRegister(reg));
8949
8950         if (opSize == EA_8BYTE)
8951         {
8952             // insEncodeDatasizeLS is not quite right for this case.
8953             // So just specialize it.
8954             if (ins == INS_ldr)
8955             {
8956                 // set the operation size in bit 30
8957                 code |= 0x40000000;
8958             }
8959             // Low 3 bits should be 0 -- 8 byte JIT data should be aligned on 8 byte.
8960             assert((imm & 7) == 0);
8961             imm >>= 3;
8962         }
8963         else
8964         {
8965             assert(opSize == EA_4BYTE);
8966             // Low 2 bits should be 0 -- 4 byte aligned data.
8967             assert((imm & 3) == 0);
8968             imm >>= 2;
8969         }
8970
8971         code |= insEncodeReg_Rt(reg); // ttttt
8972         code |= insEncodeReg_Rn(reg); // nnnnn
8973         code |= imm << 10;
8974     }
8975     else
8976     {
8977         assert(!"Unknown fmt for emitOutputShortConstant");
8978     }
8979
8980     dst += emitOutput_Instr(dst, code);
8981
8982     return dst;
8983 }
8984 /*****************************************************************************
8985  *
8986  *  Output a call instruction.
8987  */
8988
8989 unsigned emitter::emitOutputCall(insGroup* ig, BYTE* dst, instrDesc* id, code_t code)
8990 {
8991     const unsigned char callInstrSize = sizeof(code_t); // 4 bytes
8992     regMaskTP           gcrefRegs;
8993     regMaskTP           byrefRegs;
8994
8995     VARSET_TP GCvars(VarSetOps::UninitVal());
8996
8997     // Is this a "fat" call descriptor?
8998     if (id->idIsLargeCall())
8999     {
9000         instrDescCGCA* idCall = (instrDescCGCA*)id;
9001         gcrefRegs             = idCall->idcGcrefRegs;
9002         byrefRegs             = idCall->idcByrefRegs;
9003         VarSetOps::Assign(emitComp, GCvars, idCall->idcGCvars);
9004     }
9005     else
9006     {
9007         assert(!id->idIsLargeDsp());
9008         assert(!id->idIsLargeCns());
9009
9010         gcrefRegs = emitDecodeCallGCregs(id);
9011         byrefRegs = 0;
9012         VarSetOps::AssignNoCopy(emitComp, GCvars, VarSetOps::MakeEmpty(emitComp));
9013     }
9014
9015     /* We update the GC info before the call as the variables cannot be
9016         used by the call. Killing variables before the call helps with
9017         boundary conditions if the call is CORINFO_HELP_THROW - see bug 50029.
9018         If we ever track aliased variables (which could be used by the
9019         call), we would have to keep them alive past the call. */
9020
9021     emitUpdateLiveGCvars(GCvars, dst);
9022
9023     // Now output the call instruction and update the 'dst' pointer
9024     //
9025     unsigned outputInstrSize = emitOutput_Instr(dst, code);
9026     dst += outputInstrSize;
9027
9028     // All call instructions are 4-byte in size on ARM64
9029     //
9030     assert(outputInstrSize == callInstrSize);
9031
9032     // If the method returns a GC ref, mark INTRET (R0) appropriately.
9033     if (id->idGCref() == GCT_GCREF)
9034     {
9035         gcrefRegs |= RBM_INTRET;
9036     }
9037     else if (id->idGCref() == GCT_BYREF)
9038     {
9039         byrefRegs |= RBM_INTRET;
9040     }
9041
9042     // If is a multi-register return method is called, mark INTRET_1 (X1) appropriately
9043     if (id->idIsLargeCall())
9044     {
9045         instrDescCGCA* idCall = (instrDescCGCA*)id;
9046         if (idCall->idSecondGCref() == GCT_GCREF)
9047         {
9048             gcrefRegs |= RBM_INTRET_1;
9049         }
9050         else if (idCall->idSecondGCref() == GCT_BYREF)
9051         {
9052             byrefRegs |= RBM_INTRET_1;
9053         }
9054     }
9055
9056     // If the GC register set has changed, report the new set.
9057     if (gcrefRegs != emitThisGCrefRegs)
9058     {
9059         emitUpdateLiveGCregs(GCT_GCREF, gcrefRegs, dst);
9060     }
9061     // If the Byref register set has changed, report the new set.
9062     if (byrefRegs != emitThisByrefRegs)
9063     {
9064         emitUpdateLiveGCregs(GCT_BYREF, byrefRegs, dst);
9065     }
9066
9067     // Some helper calls may be marked as not requiring GC info to be recorded.
9068     if ((!id->idIsNoGC()))
9069     {
9070         // On ARM64, as on AMD64, we don't change the stack pointer to push/pop args.
9071         // So we're not really doing a "stack pop" here (note that "args" is 0), but we use this mechanism
9072         // to record the call for GC info purposes.  (It might be best to use an alternate call,
9073         // and protect "emitStackPop" under the EMIT_TRACK_STACK_DEPTH preprocessor variable.)
9074         emitStackPop(dst, /*isCall*/ true, callInstrSize, /*args*/ 0);
9075
9076         // Do we need to record a call location for GC purposes?
9077         //
9078         if (!emitFullGCinfo)
9079         {
9080             emitRecordGCcall(dst, callInstrSize);
9081         }
9082     }
9083     return callInstrSize;
9084 }
9085
9086 /*****************************************************************************
9087  *
9088  *  Emit a 32-bit Arm64 instruction
9089  */
9090
9091 /*static*/ unsigned emitter::emitOutput_Instr(BYTE* dst, code_t code)
9092 {
9093     assert(sizeof(code_t) == 4);
9094     *((code_t*)dst) = code;
9095
9096     return sizeof(code_t);
9097 }
9098
9099 /*****************************************************************************
9100 *
9101  *  Append the machine code corresponding to the given instruction descriptor
9102  *  to the code block at '*dp'; the base of the code block is 'bp', and 'ig'
9103  *  is the instruction group that contains the instruction. Updates '*dp' to
9104  *  point past the generated code, and returns the size of the instruction
9105  *  descriptor in bytes.
9106  */
9107
9108 size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
9109 {
9110     BYTE*         dst  = *dp;
9111     BYTE*         odst = dst;
9112     code_t        code = 0;
9113     size_t        sz   = emitGetInstrDescSize(id); // TODO-ARM64-Cleanup: on ARM, this is set in each case. why?
9114     instruction   ins  = id->idIns();
9115     insFormat     fmt  = id->idInsFmt();
9116     emitAttr      size = id->idOpSize();
9117     unsigned char callInstrSize = 0;
9118
9119 #ifdef DEBUG
9120 #if DUMP_GC_TABLES
9121     bool dspOffs = emitComp->opts.dspGCtbls;
9122 #else
9123     bool dspOffs = !emitComp->opts.disDiffable;
9124 #endif
9125 #endif // DEBUG
9126
9127     assert(REG_NA == (int)REG_NA);
9128
9129     VARSET_TP GCvars(VarSetOps::UninitVal());
9130
9131     /* What instruction format have we got? */
9132
9133     switch (fmt)
9134     {
9135         ssize_t  imm;
9136         ssize_t  index;
9137         ssize_t  index2;
9138         unsigned cmode;
9139         unsigned immShift;
9140         emitAttr elemsize;
9141         emitAttr datasize;
9142
9143         case IF_BI_0A: // BI_0A   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
9144         case IF_BI_0B: // BI_0B   ......iiiiiiiiii iiiiiiiiiii.....               simm19:00
9145         case IF_LARGEJMP:
9146             assert(id->idGCref() == GCT_NONE);
9147             assert(id->idIsBound());
9148             dst = emitOutputLJ(ig, dst, id);
9149             sz  = sizeof(instrDescJmp);
9150             break;
9151
9152         case IF_BI_0C: // BI_0C   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
9153             code = emitInsCode(ins, fmt);
9154             sz   = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
9155             dst += emitOutputCall(ig, dst, id, code);
9156             // Always call RecordRelocation so that we wire in a JumpStub when we don't reach
9157             emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_BRANCH26);
9158             break;
9159
9160         case IF_BI_1A: // BI_1A   ......iiiiiiiiii iiiiiiiiiiittttt      Rt       simm19:00
9161             assert(insOptsNone(id->idInsOpt()));
9162             assert(id->idIsBound());
9163
9164             dst = emitOutputLJ(ig, dst, id);
9165             sz  = sizeof(instrDescJmp);
9166             break;
9167
9168         case IF_BI_1B: // BI_1B   B.......bbbbbiii iiiiiiiiiiittttt      Rt imm6, simm14:00
9169             assert(insOptsNone(id->idInsOpt()));
9170             assert(id->idIsBound());
9171
9172             dst = emitOutputLJ(ig, dst, id);
9173             sz  = sizeof(instrDescJmp);
9174             break;
9175
9176         case IF_BR_1A: // BR_1A   ................ ......nnnnn.....         Rn
9177             assert(insOptsNone(id->idInsOpt()));
9178             assert((ins == INS_ret) || (ins == INS_br));
9179             code = emitInsCode(ins, fmt);
9180             code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9181
9182             dst += emitOutput_Instr(dst, code);
9183             break;
9184
9185         case IF_BR_1B: // BR_1B   ................ ......nnnnn.....         Rn
9186             assert(insOptsNone(id->idInsOpt()));
9187             assert((ins == INS_br_tail) || (ins == INS_blr));
9188             code = emitInsCode(ins, fmt);
9189             code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9190
9191             sz = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
9192             dst += emitOutputCall(ig, dst, id, code);
9193             break;
9194
9195         case IF_LS_1A: // LS_1A   XX...V..iiiiiiii iiiiiiiiiiittttt      Rt    PC imm(1MB)
9196         case IF_LARGELDC:
9197             assert(insOptsNone(id->idInsOpt()));
9198             assert(id->idIsBound());
9199
9200             dst = emitOutputLJ(ig, dst, id);
9201             sz  = sizeof(instrDescJmp);
9202             break;
9203
9204         case IF_LS_2A: // LS_2A   .X.......X...... ......nnnnnttttt      Rt Rn
9205             assert(insOptsNone(id->idInsOpt()));
9206             code = emitInsCode(ins, fmt);
9207             // Is the target a vector register?
9208             if (isVectorRegister(id->idReg1()))
9209             {
9210                 code &= 0x3FFFFFFF;                                 // clear the size bits
9211                 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9212                 code |= insEncodeReg_Vt(id->idReg1());              // ttttt
9213             }
9214             else
9215             {
9216                 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9217                 code |= insEncodeReg_Rt(id->idReg1());             // ttttt
9218             }
9219             code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9220             dst += emitOutput_Instr(dst, code);
9221             break;
9222
9223         case IF_LS_2B: // LS_2B   .X.......Xiiiiii iiiiiinnnnnttttt      Rt Rn    imm(0-4095)
9224             assert(insOptsNone(id->idInsOpt()));
9225             imm = emitGetInsSC(id);
9226             assert(isValidUimm12(imm));
9227             code = emitInsCode(ins, fmt);
9228             // Is the target a vector register?
9229             if (isVectorRegister(id->idReg1()))
9230             {
9231                 code &= 0x3FFFFFFF;                                 // clear the size bits
9232                 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9233                 code |= insEncodeReg_Vt(id->idReg1());              // ttttt
9234             }
9235             else
9236             {
9237                 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9238                 code |= insEncodeReg_Rt(id->idReg1());             // ttttt
9239             }
9240             code |= ((code_t)imm << 10);           // iiiiiiiiiiii
9241             code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9242             dst += emitOutput_Instr(dst, code);
9243             break;
9244
9245         case IF_LS_2C: // LS_2C   .X.......X.iiiii iiiiPPnnnnnttttt      Rt Rn    imm(-256..+255) no/pre/post inc
9246             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9247             imm = emitGetInsSC(id);
9248             assert((imm >= -256) && (imm <= 255)); // signed 9 bits
9249             imm &= 0x1ff;                          // force into unsigned 9 bit representation
9250             code = emitInsCode(ins, fmt);
9251             // Is the target a vector register?
9252             if (isVectorRegister(id->idReg1()))
9253             {
9254                 code &= 0x3FFFFFFF;                                 // clear the size bits
9255                 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9256                 code |= insEncodeReg_Vt(id->idReg1());              // ttttt
9257             }
9258             else
9259             {
9260                 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9261                 code |= insEncodeReg_Rt(id->idReg1());             // ttttt
9262             }
9263             code |= insEncodeIndexedOpt(id->idInsOpt()); // PP
9264             code |= ((code_t)imm << 12);                 // iiiiiiiii
9265             code |= insEncodeReg_Rn(id->idReg2());       // nnnnn
9266             dst += emitOutput_Instr(dst, code);
9267             break;
9268
9269         case IF_LS_3A: // LS_3A   .X.......X.mmmmm oooS..nnnnnttttt      Rt Rn Rm ext(Rm) LSL {}
9270             assert(insOptsLSExtend(id->idInsOpt()));
9271             code = emitInsCode(ins, fmt);
9272             // Is the target a vector register?
9273             if (isVectorRegister(id->idReg1()))
9274             {
9275                 code &= 0x3FFFFFFF;                                 // clear the size bits
9276                 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9277                 code |= insEncodeReg_Vt(id->idReg1());              // ttttt
9278             }
9279             else
9280             {
9281                 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9282                 code |= insEncodeReg_Rt(id->idReg1());             // ttttt
9283             }
9284             code |= insEncodeExtend(id->idInsOpt()); // ooo
9285             code |= insEncodeReg_Rn(id->idReg2());   // nnnnn
9286             if (id->idIsLclVar())
9287             {
9288                 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9289             }
9290             else
9291             {
9292                 code |= insEncodeReg3Scale(id->idReg3Scaled()); // S
9293                 code |= insEncodeReg_Rm(id->idReg3());          // mmmmm
9294             }
9295             dst += emitOutput_Instr(dst, code);
9296             break;
9297
9298         case IF_LS_3B: // LS_3B   X............... .aaaaannnnnddddd      Rd Ra Rn
9299             assert(insOptsNone(id->idInsOpt()));
9300             code = emitInsCode(ins, fmt);
9301             // Is the target a vector register?
9302             if (isVectorRegister(id->idReg1()))
9303             {
9304                 code &= 0x3FFFFFFF;                                  // clear the size bits
9305                 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9306                 code |= insEncodeReg_Vt(id->idReg1());               // ttttt
9307                 code |= insEncodeReg_Va(id->idReg2());               // aaaaa
9308             }
9309             else
9310             {
9311                 code |= insEncodeDatasize(id->idOpSize()); // X
9312                 code |= insEncodeReg_Rt(id->idReg1());     // ttttt
9313                 code |= insEncodeReg_Ra(id->idReg2());     // aaaaa
9314             }
9315             code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9316             dst += emitOutput_Instr(dst, code);
9317             break;
9318
9319         case IF_LS_3C: // LS_3C   X......PP.iiiiii iaaaaannnnnddddd      Rd Ra Rn imm(im7,sh)
9320             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9321             imm = emitGetInsSC(id);
9322             assert((imm >= -64) && (imm <= 63)); // signed 7 bits
9323             imm &= 0x7f;                         // force into unsigned 7 bit representation
9324             code = emitInsCode(ins, fmt);
9325             // Is the target a vector register?
9326             if (isVectorRegister(id->idReg1()))
9327             {
9328                 code &= 0x3FFFFFFF;                                  // clear the size bits
9329                 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9330                 code |= insEncodeReg_Vt(id->idReg1());               // ttttt
9331                 code |= insEncodeReg_Va(id->idReg2());               // aaaaa
9332             }
9333             else
9334             {
9335                 code |= insEncodeDatasize(id->idOpSize()); // X
9336                 code |= insEncodeReg_Rt(id->idReg1());     // ttttt
9337                 code |= insEncodeReg_Ra(id->idReg2());     // aaaaa
9338             }
9339             code |= insEncodePairIndexedOpt(ins, id->idInsOpt()); // PP
9340             code |= ((code_t)imm << 15);                          // iiiiiiiii
9341             code |= insEncodeReg_Rn(id->idReg3());                // nnnnn
9342             dst += emitOutput_Instr(dst, code);
9343             break;
9344
9345         case IF_LS_3D: // LS_3D   .X.......X.mmmmm ......nnnnnttttt      Wm Rt Rn
9346             code = emitInsCode(ins, fmt);
9347             // Arm64 store exclusive unpredictable cases
9348             assert(id->idReg1() != id->idReg2());
9349             assert(id->idReg1() != id->idReg3());
9350             code |= insEncodeDatasizeLS(code, id->idOpSize()); // X
9351             code |= insEncodeReg_Rm(id->idReg1());             // mmmmm
9352             code |= insEncodeReg_Rt(id->idReg2());             // ttttt
9353             code |= insEncodeReg_Rn(id->idReg3());             // nnnnn
9354             dst += emitOutput_Instr(dst, code);
9355             break;
9356
9357         case IF_LS_3E: // LS_3E   .X.........mmmmm ......nnnnnttttt      Rm Rt Rn ARMv8.1 LSE Atomics
9358             code = emitInsCode(ins, fmt);
9359             code |= insEncodeDatasizeLS(code, id->idOpSize()); // X
9360             code |= insEncodeReg_Rm(id->idReg1());             // mmmmm
9361             code |= insEncodeReg_Rt(id->idReg2());             // ttttt
9362             code |= insEncodeReg_Rn(id->idReg3());             // nnnnn
9363             dst += emitOutput_Instr(dst, code);
9364             break;
9365
9366         case IF_DI_1A: // DI_1A   X.......shiiiiii iiiiiinnnnn.....         Rn    imm(i12,sh)
9367             assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9368             imm = emitGetInsSC(id);
9369             assert(isValidUimm12(imm));
9370             code = emitInsCode(ins, fmt);
9371             code |= insEncodeDatasize(id->idOpSize());   // X
9372             code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9373             code |= ((code_t)imm << 10);                 // iiiiiiiiiiii
9374             code |= insEncodeReg_Rn(id->idReg1());       // nnnnn
9375             dst += emitOutput_Instr(dst, code);
9376             break;
9377
9378         case IF_DI_1B: // DI_1B   X........hwiiiii iiiiiiiiiiiddddd      Rd       imm(i16,hw)
9379             imm = emitGetInsSC(id);
9380             assert(isValidImmHWVal(imm, id->idOpSize()));
9381             code = emitInsCode(ins, fmt);
9382             code |= insEncodeDatasize(id->idOpSize()); // X
9383             code |= ((code_t)imm << 5);                // hwiiiii iiiiiiiiiii
9384             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9385             dst += emitOutput_Instr(dst, code);
9386             break;
9387
9388         case IF_DI_1C: // DI_1C   X........Nrrrrrr ssssssnnnnn.....         Rn    imm(N,r,s)
9389             imm = emitGetInsSC(id);
9390             assert(isValidImmNRS(imm, id->idOpSize()));
9391             code = emitInsCode(ins, fmt);
9392             code |= ((code_t)imm << 10);               // Nrrrrrrssssss
9393             code |= insEncodeDatasize(id->idOpSize()); // X
9394             code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9395             dst += emitOutput_Instr(dst, code);
9396             break;
9397
9398         case IF_DI_1D: // DI_1D   X........Nrrrrrr ssssss.....ddddd      Rd       imm(N,r,s)
9399             imm = emitGetInsSC(id);
9400             assert(isValidImmNRS(imm, id->idOpSize()));
9401             code = emitInsCode(ins, fmt);
9402             code |= ((code_t)imm << 10);               // Nrrrrrrssssss
9403             code |= insEncodeDatasize(id->idOpSize()); // X
9404             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9405             dst += emitOutput_Instr(dst, code);
9406             break;
9407
9408         case IF_DI_1E: // DI_1E   .ii.....iiiiiiii iiiiiiiiiiiddddd      Rd       simm21
9409         case IF_LARGEADR:
9410             assert(insOptsNone(id->idInsOpt()));
9411             if (id->idIsReloc())
9412             {
9413                 code = emitInsCode(ins, fmt);
9414                 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9415                 dst += emitOutput_Instr(dst, code);
9416                 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEBASE_REL21);
9417             }
9418             else
9419             {
9420                 // Local jmp/load case which does not need a relocation.
9421                 assert(id->idIsBound());
9422                 dst = emitOutputLJ(ig, dst, id);
9423             }
9424             sz = sizeof(instrDescJmp);
9425             break;
9426
9427         case IF_DI_1F: // DI_1F   X..........iiiii cccc..nnnnn.nzcv      Rn imm5  nzcv cond
9428             imm = emitGetInsSC(id);
9429             assert(isValidImmCondFlagsImm5(imm));
9430             {
9431                 condFlagsImm cfi;
9432                 cfi.immCFVal = (unsigned)imm;
9433                 code         = emitInsCode(ins, fmt);
9434                 code |= insEncodeDatasize(id->idOpSize()); // X
9435                 code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9436                 code |= ((code_t)cfi.imm5 << 16);          // iiiii
9437                 code |= insEncodeFlags(cfi.flags);         // nzcv
9438                 code |= insEncodeCond(cfi.cond);           // cccc
9439                 dst += emitOutput_Instr(dst, code);
9440             }
9441             break;
9442
9443         case IF_DI_2A: // DI_2A   X.......shiiiiii iiiiiinnnnnddddd      Rd Rn    imm(i12,sh)
9444             assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9445             imm = emitGetInsSC(id);
9446             assert(isValidUimm12(imm));
9447             code = emitInsCode(ins, fmt);
9448             code |= insEncodeDatasize(id->idOpSize());   // X
9449             code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9450             code |= ((code_t)imm << 10);                 // iiiiiiiiiiii
9451             code |= insEncodeReg_Rd(id->idReg1());       // ddddd
9452             code |= insEncodeReg_Rn(id->idReg2());       // nnnnn
9453             dst += emitOutput_Instr(dst, code);
9454
9455             if (id->idIsReloc())
9456             {
9457                 assert(sz == sizeof(instrDesc));
9458                 assert(id->idAddr()->iiaAddr != nullptr);
9459                 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEOFFSET_12A);
9460             }
9461             break;
9462
9463         case IF_DI_2B: // DI_2B   X.........Xnnnnn ssssssnnnnnddddd      Rd Rn    imm(0-63)
9464             code = emitInsCode(ins, fmt);
9465             imm  = emitGetInsSC(id);
9466             assert(isValidImmShift(imm, id->idOpSize()));
9467             code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9468             code |= insEncodeReg_Rd(id->idReg1());             // ddddd
9469             code |= insEncodeReg_Rn(id->idReg2());             // nnnnn
9470             code |= insEncodeReg_Rm(id->idReg2());             // Reg2 also in mmmmm
9471             code |= insEncodeShiftCount(imm, id->idOpSize());  // ssssss
9472             dst += emitOutput_Instr(dst, code);
9473             break;
9474
9475         case IF_DI_2C: // DI_2C   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imm(N,r,s)
9476             imm = emitGetInsSC(id);
9477             assert(isValidImmNRS(imm, id->idOpSize()));
9478             code = emitInsCode(ins, fmt);
9479             code |= ((code_t)imm << 10);               // Nrrrrrrssssss
9480             code |= insEncodeDatasize(id->idOpSize()); // X
9481             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9482             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9483             dst += emitOutput_Instr(dst, code);
9484             break;
9485
9486         case IF_DI_2D: // DI_2D   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imr, imms   (N,r,s)
9487             if (ins == INS_asr || ins == INS_lsl || ins == INS_lsr)
9488             {
9489                 imm = emitGetInsSC(id);
9490                 assert(isValidImmShift(imm, id->idOpSize()));
9491
9492                 // Shift immediates are aliases of the SBFM/UBFM instructions
9493                 // that actually take 2 registers and 2 constants,
9494                 // Since we stored the shift immediate value
9495                 // we need to calculate the N,R and S values here.
9496
9497                 bitMaskImm bmi;
9498                 bmi.immNRS = 0;
9499
9500                 bmi.immN = (size == EA_8BYTE) ? 1 : 0;
9501                 bmi.immR = imm;
9502                 bmi.immS = (size == EA_8BYTE) ? 0x3f : 0x1f;
9503
9504                 // immR and immS are now set correctly for INS_asr and INS_lsr
9505                 // but for INS_lsl we have to adjust the values for immR and immS
9506                 //
9507                 if (ins == INS_lsl)
9508                 {
9509                     bmi.immR = -imm & bmi.immS;
9510                     bmi.immS = bmi.immS - imm;
9511                 }
9512
9513                 // setup imm with the proper 13 bit value N:R:S
9514                 //
9515                 imm = bmi.immNRS;
9516             }
9517             else
9518             {
9519                 // The other instructions have already have encoded N,R and S values
9520                 imm = emitGetInsSC(id);
9521             }
9522             assert(isValidImmNRS(imm, id->idOpSize()));
9523
9524             code = emitInsCode(ins, fmt);
9525             code |= ((code_t)imm << 10);               // Nrrrrrrssssss
9526             code |= insEncodeDatasize(id->idOpSize()); // X
9527             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9528             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9529             dst += emitOutput_Instr(dst, code);
9530             break;
9531
9532         case IF_DR_1D: // DR_1D   X............... cccc.......ddddd      Rd       cond
9533             imm = emitGetInsSC(id);
9534             assert(isValidImmCond(imm));
9535             {
9536                 condFlagsImm cfi;
9537                 cfi.immCFVal = (unsigned)imm;
9538                 code         = emitInsCode(ins, fmt);
9539                 code |= insEncodeDatasize(id->idOpSize()); // X
9540                 code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9541                 code |= insEncodeInvertedCond(cfi.cond);   // cccc
9542                 dst += emitOutput_Instr(dst, code);
9543             }
9544             break;
9545
9546         case IF_DR_2A: // DR_2A   X..........mmmmm ......nnnnn.....         Rn Rm
9547             assert(insOptsNone(id->idInsOpt()));
9548             code = emitInsCode(ins, fmt);
9549             code |= insEncodeDatasize(id->idOpSize()); // X
9550             code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9551             code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9552             dst += emitOutput_Instr(dst, code);
9553             break;
9554
9555         case IF_DR_2B: // DR_2B   X.......sh.mmmmm ssssssnnnnn.....         Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
9556             code = emitInsCode(ins, fmt);
9557             imm  = emitGetInsSC(id);
9558             assert(isValidImmShift(imm, id->idOpSize()));
9559             code |= insEncodeDatasize(id->idOpSize());        // X
9560             code |= insEncodeShiftType(id->idInsOpt());       // sh
9561             code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9562             code |= insEncodeReg_Rn(id->idReg1());            // nnnnn
9563             code |= insEncodeReg_Rm(id->idReg2());            // mmmmm
9564             dst += emitOutput_Instr(dst, code);
9565             break;
9566
9567         case IF_DR_2C: // DR_2C   X..........mmmmm ooosssnnnnn.....         Rn Rm ext(Rm) LSL imm(0-4)
9568             code = emitInsCode(ins, fmt);
9569             imm  = emitGetInsSC(id);
9570             assert((imm >= 0) && (imm <= 4));          // imm [0..4]
9571             code |= insEncodeDatasize(id->idOpSize()); // X
9572             code |= insEncodeExtend(id->idInsOpt());   // ooo
9573             code |= insEncodeExtendScale(imm);         // sss
9574             code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9575             code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9576             dst += emitOutput_Instr(dst, code);
9577             break;
9578
9579         case IF_DR_2D: // DR_2D   X..........nnnnn cccc..nnnnnddddd      Rd Rn    cond
9580             imm = emitGetInsSC(id);
9581             assert(isValidImmCond(imm));
9582             {
9583                 condFlagsImm cfi;
9584                 cfi.immCFVal = (unsigned)imm;
9585                 code         = emitInsCode(ins, fmt);
9586                 code |= insEncodeDatasize(id->idOpSize()); // X
9587                 code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9588                 code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9589                 code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9590                 code |= insEncodeInvertedCond(cfi.cond);   // cccc
9591                 dst += emitOutput_Instr(dst, code);
9592             }
9593             break;
9594
9595         case IF_DR_2E: // DR_2E   X..........mmmmm ...........ddddd      Rd    Rm
9596             code = emitInsCode(ins, fmt);
9597             code |= insEncodeDatasize(id->idOpSize()); // X
9598             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9599             code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9600             dst += emitOutput_Instr(dst, code);
9601             break;
9602
9603         case IF_DR_2F: // DR_2F   X.......sh.mmmmm ssssss.....ddddd      Rd    Rm {LSL,LSR,ASR} imm(0-63)
9604             code = emitInsCode(ins, fmt);
9605             imm  = emitGetInsSC(id);
9606             assert(isValidImmShift(imm, id->idOpSize()));
9607             code |= insEncodeDatasize(id->idOpSize());        // X
9608             code |= insEncodeShiftType(id->idInsOpt());       // sh
9609             code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9610             code |= insEncodeReg_Rd(id->idReg1());            // ddddd
9611             code |= insEncodeReg_Rm(id->idReg2());            // mmmmm
9612             dst += emitOutput_Instr(dst, code);
9613             break;
9614
9615         case IF_DR_2G: // DR_2G   X............... .....xnnnnnddddd      Rd Rn
9616             code = emitInsCode(ins, fmt);
9617             code |= insEncodeDatasize(id->idOpSize()); // X
9618             if (ins == INS_rev)
9619             {
9620                 if (size == EA_8BYTE)
9621                 {
9622                     code |= 0x00000400; // x - bit at location 10
9623                 }
9624             }
9625             code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9626             code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9627             dst += emitOutput_Instr(dst, code);
9628             break;
9629
9630         case IF_DR_2H: // DR_2H   X........X...... ......nnnnnddddd      Rd Rn
9631             code = emitInsCode(ins, fmt);
9632             code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9633             code |= insEncodeReg_Rd(id->idReg1());             // ddddd
9634             code |= insEncodeReg_Rn(id->idReg2());             // nnnnn
9635             dst += emitOutput_Instr(dst, code);
9636             break;
9637
9638         case IF_DR_2I: // DR_2I   X..........mmmmm cccc..nnnnn.nzcv      Rn Rm    nzcv cond
9639             imm = emitGetInsSC(id);
9640             assert(isValidImmCondFlags(imm));
9641             {
9642                 condFlagsImm cfi;
9643                 cfi.immCFVal = (unsigned)imm;
9644                 code         = emitInsCode(ins, fmt);
9645                 code |= insEncodeDatasize(id->idOpSize()); // X
9646                 code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9647                 code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9648                 code |= insEncodeFlags(cfi.flags);         // nzcv
9649                 code |= insEncodeCond(cfi.cond);           // cccc
9650                 dst += emitOutput_Instr(dst, code);
9651             }
9652             break;
9653
9654         case IF_DR_2J: // DR_2J   ................ ......nnnnnddddd      Sd Sn   (sha1h)
9655             code = emitInsCode(ins, fmt);
9656             code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9657             code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9658             dst += emitOutput_Instr(dst, code);
9659             break;
9660
9661         case IF_DR_3A: // DR_3A   X..........mmmmm ......nnnnnmmmmm      Rd Rn Rm
9662             code = emitInsCode(ins, fmt);
9663             code |= insEncodeDatasize(id->idOpSize()); // X
9664             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9665             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9666             if (id->idIsLclVar())
9667             {
9668                 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9669             }
9670             else
9671             {
9672                 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9673             }
9674             dst += emitOutput_Instr(dst, code);
9675             break;
9676
9677         case IF_DR_3B: // DR_3B   X.......sh.mmmmm ssssssnnnnnddddd      Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
9678             code = emitInsCode(ins, fmt);
9679             imm  = emitGetInsSC(id);
9680             assert(isValidImmShift(imm, id->idOpSize()));
9681             code |= insEncodeDatasize(id->idOpSize());        // X
9682             code |= insEncodeReg_Rd(id->idReg1());            // ddddd
9683             code |= insEncodeReg_Rn(id->idReg2());            // nnnnn
9684             code |= insEncodeReg_Rm(id->idReg3());            // mmmmm
9685             code |= insEncodeShiftType(id->idInsOpt());       // sh
9686             code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9687             dst += emitOutput_Instr(dst, code);
9688             break;
9689
9690         case IF_DR_3C: // DR_3C   X..........mmmmm ooosssnnnnnddddd      Rd Rn Rm ext(Rm) LSL imm(0-4)
9691             code = emitInsCode(ins, fmt);
9692             imm  = emitGetInsSC(id);
9693             assert((imm >= 0) && (imm <= 4));          // imm [0..4]
9694             code |= insEncodeDatasize(id->idOpSize()); // X
9695             code |= insEncodeExtend(id->idInsOpt());   // ooo
9696             code |= insEncodeExtendScale(imm);         // sss
9697             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9698             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9699             code |= insEncodeReg_Rm(id->idReg3());     // mmmmm
9700             dst += emitOutput_Instr(dst, code);
9701             break;
9702
9703         case IF_DR_3D: // DR_3D   X..........mmmmm cccc..nnnnnddddd      Rd Rn Rm cond
9704             imm = emitGetInsSC(id);
9705             assert(isValidImmCond(imm));
9706             {
9707                 condFlagsImm cfi;
9708                 cfi.immCFVal = (unsigned)imm;
9709                 code         = emitInsCode(ins, fmt);
9710                 code |= insEncodeDatasize(id->idOpSize()); // X
9711                 code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9712                 code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9713                 code |= insEncodeReg_Rm(id->idReg3());     // mmmmm
9714                 code |= insEncodeCond(cfi.cond);           // cccc
9715                 dst += emitOutput_Instr(dst, code);
9716             }
9717             break;
9718
9719         case IF_DR_3E: // DR_3E   X........X.mmmmm ssssssnnnnnddddd      Rd Rn Rm imm(0-63)
9720             code = emitInsCode(ins, fmt);
9721             imm  = emitGetInsSC(id);
9722             assert(isValidImmShift(imm, id->idOpSize()));
9723             code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9724             code |= insEncodeReg_Rd(id->idReg1());             // ddddd
9725             code |= insEncodeReg_Rn(id->idReg2());             // nnnnn
9726             code |= insEncodeReg_Rm(id->idReg3());             // mmmmm
9727             code |= insEncodeShiftCount(imm, id->idOpSize());  // ssssss
9728             dst += emitOutput_Instr(dst, code);
9729             break;
9730
9731         case IF_DR_4A: // DR_4A   X..........mmmmm .aaaaannnnnmmmmm      Rd Rn Rm Ra
9732             code = emitInsCode(ins, fmt);
9733             code |= insEncodeDatasize(id->idOpSize()); // X
9734             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9735             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9736             code |= insEncodeReg_Rm(id->idReg3());     // mmmmm
9737             code |= insEncodeReg_Ra(id->idReg4());     // aaaaa
9738             dst += emitOutput_Instr(dst, code);
9739             break;
9740
9741         case IF_DV_1A: // DV_1A   .........X.iiiii iii........ddddd      Vd imm8    (fmov - immediate scalar)
9742             imm      = emitGetInsSC(id);
9743             elemsize = id->idOpSize();
9744             code     = emitInsCode(ins, fmt);
9745             code |= insEncodeFloatElemsize(elemsize); // X
9746             code |= ((code_t)imm << 13);              // iiiii iii
9747             code |= insEncodeReg_Vd(id->idReg1());    // ddddd
9748             dst += emitOutput_Instr(dst, code);
9749             break;
9750
9751         case IF_DV_1B: // DV_1B   .QX..........iii cmod..iiiiiddddd      Vd imm8    (immediate vector)
9752             imm      = emitGetInsSC(id) & 0x0ff;
9753             immShift = (emitGetInsSC(id) & 0x700) >> 8;
9754             elemsize = optGetElemsize(id->idInsOpt());
9755             cmode    = 0;
9756             switch (elemsize)
9757             { // cmode
9758                 case EA_1BYTE:
9759                     cmode = 0xE; // 1110
9760                     break;
9761                 case EA_2BYTE:
9762                     cmode = 0x8;
9763                     cmode |= (immShift << 1); // 10x0
9764                     break;
9765                 case EA_4BYTE:
9766                     if (immShift < 4)
9767                     {
9768                         cmode = 0x0;
9769                         cmode |= (immShift << 1); // 0xx0
9770                     }
9771                     else // MSL
9772                     {
9773                         cmode = 0xC;
9774                         if (immShift & 2)
9775                             cmode |= 1; // 110x
9776                     }
9777                     break;
9778                 case EA_8BYTE:
9779                     cmode = 0xE; // 1110
9780                     break;
9781                 default:
9782                     unreached();
9783                     break;
9784             }
9785
9786             code = emitInsCode(ins, fmt);
9787             code |= insEncodeVectorsize(id->idOpSize()); // Q
9788             if ((ins == INS_fmov) || (ins == INS_movi))
9789             {
9790                 if (elemsize == EA_8BYTE)
9791                 {
9792                     code |= 0x20000000; // X
9793                 }
9794             }
9795             if (ins != INS_fmov)
9796             {
9797                 assert((cmode >= 0) && (cmode <= 0xF));
9798                 code |= (cmode << 12); // cmod
9799             }
9800             code |= (((code_t)imm >> 5) << 16);    // iii
9801             code |= (((code_t)imm & 0x1f) << 5);   // iiiii
9802             code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9803             dst += emitOutput_Instr(dst, code);
9804             break;
9805
9806         case IF_DV_1C: // DV_1C   .........X...... ......nnnnn.....      Vn #0.0    (fcmp - with zero)
9807             elemsize = id->idOpSize();
9808             code     = emitInsCode(ins, fmt);
9809             code |= insEncodeFloatElemsize(elemsize); // X
9810             code |= insEncodeReg_Vn(id->idReg1());    // nnnnn
9811             dst += emitOutput_Instr(dst, code);
9812             break;
9813
9814         case IF_DV_2A: // DV_2A   .Q.......X...... ......nnnnnddddd      Vd Vn      (fabs, fcvt - vector)
9815             elemsize = optGetElemsize(id->idInsOpt());
9816             code     = emitInsCode(ins, fmt);
9817             code |= insEncodeVectorsize(id->idOpSize()); // Q
9818             code |= insEncodeFloatElemsize(elemsize);    // X
9819             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9820             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9821             dst += emitOutput_Instr(dst, code);
9822             break;
9823
9824         case IF_DV_2B: // DV_2B   .Q.........iiiii ......nnnnnddddd      Rd Vn[] (umov/smov    - to general)
9825             elemsize = id->idOpSize();
9826             index    = emitGetInsSC(id);
9827             datasize = (elemsize == EA_8BYTE) ? EA_16BYTE : EA_8BYTE;
9828             if (ins == INS_smov)
9829             {
9830                 datasize = EA_16BYTE;
9831             }
9832             code = emitInsCode(ins, fmt);
9833             code |= insEncodeVectorsize(datasize);         // Q
9834             code |= insEncodeVectorIndex(elemsize, index); // iiiii
9835             code |= insEncodeReg_Rd(id->idReg1());         // ddddd
9836             code |= insEncodeReg_Vn(id->idReg2());         // nnnnn
9837             dst += emitOutput_Instr(dst, code);
9838             break;
9839
9840         case IF_DV_2C: // DV_2C   .Q.........iiiii ......nnnnnddddd      Vd Rn   (dup/ins - vector from general)
9841             if (ins == INS_dup)
9842             {
9843                 datasize = id->idOpSize();
9844                 elemsize = optGetElemsize(id->idInsOpt());
9845                 index    = 0;
9846             }
9847             else // INS_ins
9848             {
9849                 datasize = EA_16BYTE;
9850                 elemsize = id->idOpSize();
9851                 index    = emitGetInsSC(id);
9852             }
9853             code = emitInsCode(ins, fmt);
9854             code |= insEncodeVectorsize(datasize);         // Q
9855             code |= insEncodeVectorIndex(elemsize, index); // iiiii
9856             code |= insEncodeReg_Vd(id->idReg1());         // ddddd
9857             code |= insEncodeReg_Rn(id->idReg2());         // nnnnn
9858             dst += emitOutput_Instr(dst, code);
9859             break;
9860
9861         case IF_DV_2D: // DV_2D   .Q.........iiiii ......nnnnnddddd      Vd Vn[]   (dup - vector)
9862             index    = emitGetInsSC(id);
9863             elemsize = optGetElemsize(id->idInsOpt());
9864             code     = emitInsCode(ins, fmt);
9865             code |= insEncodeVectorsize(id->idOpSize());   // Q
9866             code |= insEncodeVectorIndex(elemsize, index); // iiiii
9867             code |= insEncodeReg_Vd(id->idReg1());         // ddddd
9868             code |= insEncodeReg_Vn(id->idReg2());         // nnnnn
9869             dst += emitOutput_Instr(dst, code);
9870             break;
9871
9872         case IF_DV_2E: // DV_2E   ...........iiiii ......nnnnnddddd      Vd Vn[]   (dup - scalar)
9873             index    = emitGetInsSC(id);
9874             elemsize = id->idOpSize();
9875             code     = emitInsCode(ins, fmt);
9876             code |= insEncodeVectorIndex(elemsize, index); // iiiii
9877             code |= insEncodeReg_Vd(id->idReg1());         // ddddd
9878             code |= insEncodeReg_Vn(id->idReg2());         // nnnnn
9879             dst += emitOutput_Instr(dst, code);
9880             break;
9881
9882         case IF_DV_2F: // DV_2F   ...........iiiii .jjjj.nnnnnddddd      Vd[] Vn[] (ins - element)
9883             elemsize = id->idOpSize();
9884             imm      = emitGetInsSC(id);
9885             index    = (imm >> 4) & 0xf;
9886             index2   = imm & 0xf;
9887             code     = emitInsCode(ins, fmt);
9888             code |= insEncodeVectorIndex(elemsize, index);   // iiiii
9889             code |= insEncodeVectorIndex2(elemsize, index2); // jjjj
9890             code |= insEncodeReg_Vd(id->idReg1());           // ddddd
9891             code |= insEncodeReg_Vn(id->idReg2());           // nnnnn
9892             dst += emitOutput_Instr(dst, code);
9893             break;
9894
9895         case IF_DV_2G: // DV_2G   .........X...... ......nnnnnddddd      Vd Vn      (fmov,fcvtXX - register)
9896             elemsize = id->idOpSize();
9897             code     = emitInsCode(ins, fmt);
9898             code |= insEncodeFloatElemsize(elemsize); // X
9899             code |= insEncodeReg_Vd(id->idReg1());    // ddddd
9900             code |= insEncodeReg_Vn(id->idReg2());    // nnnnn
9901             dst += emitOutput_Instr(dst, code);
9902             break;
9903
9904         case IF_DV_2H: // DV_2H   X........X...... ......nnnnnddddd      Rd Vn      (fmov - to general)
9905             elemsize = id->idOpSize();
9906             code     = emitInsCode(ins, fmt);
9907             code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X   X
9908             code |= insEncodeReg_Rd(id->idReg1());            // ddddd
9909             code |= insEncodeReg_Vn(id->idReg2());            // nnnnn
9910             dst += emitOutput_Instr(dst, code);
9911             break;
9912
9913         case IF_DV_2I: // DV_2I   X........X...... ......nnnnnddddd      Vd Rn      (fmov - from general)
9914             elemsize = id->idOpSize();
9915             code     = emitInsCode(ins, fmt);
9916             code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X   X
9917             code |= insEncodeReg_Vd(id->idReg1());            // ddddd
9918             code |= insEncodeReg_Rn(id->idReg2());            // nnnnn
9919             dst += emitOutput_Instr(dst, code);
9920             break;
9921
9922         case IF_DV_2J: // DV_2J   ........SS.....D D.....nnnnnddddd      Vd Vn      (fcvt)
9923             code = emitInsCode(ins, fmt);
9924             code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // SS DD
9925             code |= insEncodeReg_Vd(id->idReg1());            // ddddd
9926             code |= insEncodeReg_Vn(id->idReg2());            // nnnnn
9927             dst += emitOutput_Instr(dst, code);
9928             break;
9929
9930         case IF_DV_2K: // DV_2K   .........X.mmmmm ......nnnnn.....      Vn Vm      (fcmp)
9931             elemsize = id->idOpSize();
9932             code     = emitInsCode(ins, fmt);
9933             code |= insEncodeFloatElemsize(elemsize); // X
9934             code |= insEncodeReg_Vn(id->idReg1());    // nnnnn
9935             code |= insEncodeReg_Vm(id->idReg2());    // mmmmm
9936             dst += emitOutput_Instr(dst, code);
9937             break;
9938
9939         case IF_DV_2L: // DV_2L   ........XX...... ......nnnnnddddd      Vd Vn      (abs, neg - scalar)
9940             elemsize = id->idOpSize();
9941             code     = emitInsCode(ins, fmt);
9942             code |= insEncodeElemsize(elemsize);   // XX
9943             code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9944             code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9945             dst += emitOutput_Instr(dst, code);
9946             break;
9947
9948         case IF_DV_2M: // DV_2M   .Q......XX...... ......nnnnnddddd      Vd Vn      (abs, neg   - vector)
9949             elemsize = optGetElemsize(id->idInsOpt());
9950             code     = emitInsCode(ins, fmt);
9951             code |= insEncodeVectorsize(id->idOpSize()); // Q
9952             code |= insEncodeElemsize(elemsize);         // XX
9953             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9954             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9955             dst += emitOutput_Instr(dst, code);
9956             break;
9957
9958         case IF_DV_2N: // DV_2N   .........iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - scalar)
9959             imm  = emitGetInsSC(id);
9960             code = emitInsCode(ins, fmt);
9961             code |= insEncodeVectorShift(EA_8BYTE, imm); // iiiiiii
9962             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9963             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9964             dst += emitOutput_Instr(dst, code);
9965             break;
9966
9967         case IF_DV_2O: // DV_2O   .Q.......iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - vector)
9968             imm      = emitGetInsSC(id);
9969             elemsize = optGetElemsize(id->idInsOpt());
9970             code     = emitInsCode(ins, fmt);
9971             code |= insEncodeVectorsize(id->idOpSize()); // Q
9972             code |= insEncodeVectorShift(elemsize, imm); // iiiiiii
9973             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9974             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9975             dst += emitOutput_Instr(dst, code);
9976             break;
9977
9978         case IF_DV_2P: // DV_2P   ............... ......nnnnnddddd      Vd Vn      (aes*, sha1su1)
9979             elemsize = optGetElemsize(id->idInsOpt());
9980             code     = emitInsCode(ins, fmt);
9981             code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9982             code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9983             dst += emitOutput_Instr(dst, code);
9984             break;
9985
9986         case IF_DV_3A: // DV_3A   .Q......XX.mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
9987             code     = emitInsCode(ins, fmt);
9988             elemsize = optGetElemsize(id->idInsOpt());
9989             code |= insEncodeVectorsize(id->idOpSize()); // Q
9990             code |= insEncodeElemsize(elemsize);         // XX
9991             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9992             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9993             code |= insEncodeReg_Vm(id->idReg3());       // mmmmm
9994             dst += emitOutput_Instr(dst, code);
9995             break;
9996
9997         case IF_DV_3AI: // DV_3AI  .Q......XXLMmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector)
9998             code     = emitInsCode(ins, fmt);
9999             imm      = emitGetInsSC(id);
10000             elemsize = optGetElemsize(id->idInsOpt());
10001             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
10002             code |= insEncodeVectorsize(id->idOpSize());    // Q
10003             code |= insEncodeElemsize(elemsize);            // XX
10004             code |= insEncodeVectorIndexLMH(elemsize, imm); // LM H
10005             code |= insEncodeReg_Vd(id->idReg1());          // ddddd
10006             code |= insEncodeReg_Vn(id->idReg2());          // nnnnn
10007             code |= insEncodeReg_Vm(id->idReg3());          // mmmmm
10008             dst += emitOutput_Instr(dst, code);
10009             break;
10010
10011         case IF_DV_3B: // DV_3B   .Q.......X.mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
10012             code     = emitInsCode(ins, fmt);
10013             elemsize = optGetElemsize(id->idInsOpt());
10014             code |= insEncodeVectorsize(id->idOpSize()); // Q
10015             code |= insEncodeFloatElemsize(elemsize);    // X
10016             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
10017             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
10018             code |= insEncodeReg_Vm(id->idReg3());       // mmmmm
10019             dst += emitOutput_Instr(dst, code);
10020             break;
10021
10022         case IF_DV_3BI: // DV_3BI  .Q.......XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector by elem)
10023             code     = emitInsCode(ins, fmt);
10024             imm      = emitGetInsSC(id);
10025             elemsize = optGetElemsize(id->idInsOpt());
10026             assert(isValidVectorIndex(id->idOpSize(), elemsize, imm));
10027             code |= insEncodeVectorsize(id->idOpSize()); // Q
10028             code |= insEncodeFloatElemsize(elemsize);    // X
10029             code |= insEncodeFloatIndex(elemsize, imm);  // L H
10030             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
10031             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
10032             code |= insEncodeReg_Vm(id->idReg3());       // mmmmm
10033             dst += emitOutput_Instr(dst, code);
10034             break;
10035
10036         case IF_DV_3C: // DV_3C   .Q.........mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
10037             code = emitInsCode(ins, fmt);
10038             code |= insEncodeVectorsize(id->idOpSize()); // Q
10039             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
10040             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
10041             code |= insEncodeReg_Vm(id->idReg3());       // mmmmm
10042             dst += emitOutput_Instr(dst, code);
10043             break;
10044
10045         case IF_DV_3D: // DV_3D   .........X.mmmmm ......nnnnnddddd      Vd Vn Vm   (scalar)
10046             code = emitInsCode(ins, fmt);
10047             code |= insEncodeFloatElemsize(id->idOpSize()); // X
10048             code |= insEncodeReg_Vd(id->idReg1());          // ddddd
10049             code |= insEncodeReg_Vn(id->idReg2());          // nnnnn
10050             code |= insEncodeReg_Vm(id->idReg3());          // mmmmm
10051             dst += emitOutput_Instr(dst, code);
10052             break;
10053
10054         case IF_DV_3DI: // DV_3DI  .........XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (scalar by elem)
10055             code     = emitInsCode(ins, fmt);
10056             imm      = emitGetInsSC(id);
10057             elemsize = id->idOpSize();
10058             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
10059             code |= insEncodeFloatElemsize(elemsize);   // X
10060             code |= insEncodeFloatIndex(elemsize, imm); // L H
10061             code |= insEncodeReg_Vd(id->idReg1());      // ddddd
10062             code |= insEncodeReg_Vn(id->idReg2());      // nnnnn
10063             code |= insEncodeReg_Vm(id->idReg3());      // mmmmm
10064             dst += emitOutput_Instr(dst, code);
10065             break;
10066
10067         case IF_DV_3E: // DV_3E   ...........mmmmm ......nnnnnddddd      Vd Vn Vm   (scalar)
10068         case IF_DV_3F: // DV_3F   ...........mmmmm ......nnnnnddddd      Vd Vn Vm   (vector) - source dest regs overlap
10069             code = emitInsCode(ins, fmt);
10070             code |= insEncodeReg_Vd(id->idReg1()); // ddddd
10071             code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
10072             code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
10073             dst += emitOutput_Instr(dst, code);
10074             break;
10075
10076         case IF_DV_4A: // DV_4A   .........X.mmmmm .aaaaannnnnddddd      Vd Va Vn Vm (scalar)
10077             code     = emitInsCode(ins, fmt);
10078             elemsize = id->idOpSize();
10079             code |= insEncodeFloatElemsize(elemsize); // X
10080             code |= insEncodeReg_Vd(id->idReg1());    // ddddd
10081             code |= insEncodeReg_Vn(id->idReg2());    // nnnnn
10082             code |= insEncodeReg_Vm(id->idReg3());    // mmmmm
10083             code |= insEncodeReg_Va(id->idReg4());    // aaaaa
10084             dst += emitOutput_Instr(dst, code);
10085             break;
10086
10087         case IF_SN_0A: // SN_0A   ................ ................
10088             code = emitInsCode(ins, fmt);
10089             dst += emitOutput_Instr(dst, code);
10090             break;
10091
10092         case IF_SI_0A: // SI_0A   ...........iiiii iiiiiiiiiii.....               imm16
10093             imm = emitGetInsSC(id);
10094             assert(isValidUimm16(imm));
10095             code = emitInsCode(ins, fmt);
10096             code |= ((code_t)imm << 5); // iiiii iiiiiiiiiii
10097             dst += emitOutput_Instr(dst, code);
10098             break;
10099
10100         case IF_SI_0B: // SI_0B   ................ ....bbbb........               imm4 - barrier
10101             imm = emitGetInsSC(id);
10102             assert((imm >= 0) && (imm <= 15));
10103             code = emitInsCode(ins, fmt);
10104             code |= ((code_t)imm << 8); // bbbb
10105             dst += emitOutput_Instr(dst, code);
10106             break;
10107
10108         default:
10109             assert(!"Unexpected format");
10110             break;
10111     }
10112
10113     // Determine if any registers now hold GC refs, or whether a register that was overwritten held a GC ref.
10114     // We assume here that "id->idGCref()" is not GC_NONE only if the instruction described by "id" writes a
10115     // GC ref to register "id->idReg1()".  (It may, apparently, also not be GC_NONE in other cases, such as
10116     // for stores, but we ignore those cases here.)
10117     if (emitInsMayWriteToGCReg(id)) // True if "id->idIns()" writes to a register than can hold GC ref.
10118     {
10119         // We assume that "idReg1" is the primary destination register for all instructions
10120         if (id->idGCref() != GCT_NONE)
10121         {
10122             emitGCregLiveUpd(id->idGCref(), id->idReg1(), dst);
10123         }
10124         else
10125         {
10126             emitGCregDeadUpd(id->idReg1(), dst);
10127         }
10128
10129         if (emitInsMayWriteMultipleRegs(id))
10130         {
10131             // INS_ldp etc...
10132             // "idReg2" is the secondary destination register
10133             if (id->idGCrefReg2() != GCT_NONE)
10134             {
10135                 emitGCregLiveUpd(id->idGCrefReg2(), id->idReg2(), dst);
10136             }
10137             else
10138             {
10139                 emitGCregDeadUpd(id->idReg2(), dst);
10140             }
10141         }
10142     }
10143
10144     // Now we determine if the instruction has written to a (local variable) stack location, and either written a GC
10145     // ref or overwritten one.
10146     if (emitInsWritesToLclVarStackLoc(id) || emitInsWritesToLclVarStackLocPair(id))
10147     {
10148         int      varNum = id->idAddr()->iiaLclVar.lvaVarNum();
10149         unsigned ofs    = AlignDown(id->idAddr()->iiaLclVar.lvaOffset(), TARGET_POINTER_SIZE);
10150         bool     FPbased;
10151         int      adr = emitComp->lvaFrameAddress(varNum, &FPbased);
10152         if (id->idGCref() != GCT_NONE)
10153         {
10154             emitGCvarLiveUpd(adr + ofs, varNum, id->idGCref(), dst);
10155         }
10156         else
10157         {
10158             // If the type of the local is a gc ref type, update the liveness.
10159             var_types vt;
10160             if (varNum >= 0)
10161             {
10162                 // "Regular" (non-spill-temp) local.
10163                 vt = var_types(emitComp->lvaTable[varNum].lvType);
10164             }
10165             else
10166             {
10167                 TempDsc* tmpDsc = codeGen->regSet.tmpFindNum(varNum);
10168                 vt              = tmpDsc->tdTempType();
10169             }
10170             if (vt == TYP_REF || vt == TYP_BYREF)
10171                 emitGCvarDeadUpd(adr + ofs, dst);
10172         }
10173         if (emitInsWritesToLclVarStackLocPair(id))
10174         {
10175             unsigned ofs2 = ofs + TARGET_POINTER_SIZE;
10176             if (id->idGCrefReg2() != GCT_NONE)
10177             {
10178                 emitGCvarLiveUpd(adr + ofs2, varNum, id->idGCrefReg2(), dst);
10179             }
10180             else
10181             {
10182                 // If the type of the local is a gc ref type, update the liveness.
10183                 var_types vt;
10184                 if (varNum >= 0)
10185                 {
10186                     // "Regular" (non-spill-temp) local.
10187                     vt = var_types(emitComp->lvaTable[varNum].lvType);
10188                 }
10189                 else
10190                 {
10191                     TempDsc* tmpDsc = codeGen->regSet.tmpFindNum(varNum);
10192                     vt              = tmpDsc->tdTempType();
10193                 }
10194                 if (vt == TYP_REF || vt == TYP_BYREF)
10195                     emitGCvarDeadUpd(adr + ofs2, dst);
10196             }
10197         }
10198     }
10199
10200 #ifdef DEBUG
10201     /* Make sure we set the instruction descriptor size correctly */
10202
10203     size_t expected = emitSizeOfInsDsc(id);
10204     assert(sz == expected);
10205
10206     if (emitComp->opts.disAsm || emitComp->opts.dspEmit || emitComp->verbose)
10207     {
10208         emitDispIns(id, false, dspOffs, true, emitCurCodeOffs(odst), *dp, (dst - *dp), ig);
10209     }
10210
10211     if (emitComp->compDebugBreak)
10212     {
10213         // For example, set JitBreakEmitOutputInstr=a6 will break when this method is called for
10214         // emitting instruction a6, (i.e. IN00a6 in jitdump).
10215         if ((unsigned)JitConfig.JitBreakEmitOutputInstr() == id->idDebugOnlyInfo()->idNum)
10216         {
10217             assert(!"JitBreakEmitOutputInstr reached");
10218         }
10219     }
10220 #endif
10221
10222     /* All instructions are expected to generate code */
10223
10224     assert(*dp != dst);
10225
10226     *dp = dst;
10227
10228     return sz;
10229 }
10230
10231 /*****************************************************************************/
10232 /*****************************************************************************/
10233
10234 #ifdef DEBUG
10235
10236 /*****************************************************************************
10237  *
10238  *  Display the instruction name
10239  */
10240 void emitter::emitDispInst(instruction ins)
10241 {
10242     const char* insstr = codeGen->genInsName(ins);
10243     size_t      len    = strlen(insstr);
10244
10245     /* Display the instruction name */
10246
10247     printf("%s", insstr);
10248
10249     //
10250     // Add at least one space after the instruction name
10251     // and add spaces until we have reach the normal size of 8
10252     do
10253     {
10254         printf(" ");
10255         len++;
10256     } while (len < 8);
10257 }
10258
10259 /*****************************************************************************
10260  *
10261  *  Display an immediate value
10262  */
10263 void emitter::emitDispImm(ssize_t imm, bool addComma, bool alwaysHex /* =false */)
10264 {
10265     if (strictArmAsm)
10266     {
10267         printf("#");
10268     }
10269
10270     // Munge any pointers if we want diff-able disassembly.
10271     // Since some may be emitted as partial words, print as diffable anything that has
10272     // significant bits beyond the lowest 8-bits.
10273     if (emitComp->opts.disDiffable)
10274     {
10275         ssize_t top56bits = (imm >> 8);
10276         if ((top56bits != 0) && (top56bits != -1))
10277             imm = 0xD1FFAB1E;
10278     }
10279
10280     if (!alwaysHex && (imm > -1000) && (imm < 1000))
10281     {
10282         printf("%d", imm);
10283     }
10284     else
10285     {
10286         if ((imm < 0) && ((imm & 0xFFFFFFFF00000000LL) == 0xFFFFFFFF00000000LL))
10287         {
10288             printf("-");
10289             imm = -imm;
10290         }
10291
10292         if ((imm & 0xFFFFFFFF00000000LL) != 0)
10293         {
10294             printf("0x%llx", imm);
10295         }
10296         else
10297         {
10298             printf("0x%02x", imm);
10299         }
10300     }
10301
10302     if (addComma)
10303         printf(", ");
10304 }
10305
10306 /*****************************************************************************
10307  *
10308  *  Display a float zero constant
10309  */
10310 void emitter::emitDispFloatZero()
10311 {
10312     if (strictArmAsm)
10313     {
10314         printf("#");
10315     }
10316     printf("0.0");
10317 }
10318
10319 /*****************************************************************************
10320  *
10321  *  Display an encoded float constant value
10322  */
10323 void emitter::emitDispFloatImm(ssize_t imm8)
10324 {
10325     assert((0 <= imm8) && (imm8 <= 0x0ff));
10326     if (strictArmAsm)
10327     {
10328         printf("#");
10329     }
10330
10331     floatImm8 fpImm;
10332     fpImm.immFPIVal = (unsigned)imm8;
10333     double result   = emitDecodeFloatImm8(fpImm);
10334
10335     printf("%.4f", result);
10336 }
10337
10338 /*****************************************************************************
10339  *
10340  *  Display an immediate that is optionally LSL12.
10341  */
10342 void emitter::emitDispImmOptsLSL12(ssize_t imm, insOpts opt)
10343 {
10344     if (!strictArmAsm && insOptsLSL12(opt))
10345     {
10346         imm <<= 12;
10347     }
10348     emitDispImm(imm, false);
10349     if (strictArmAsm && insOptsLSL12(opt))
10350     {
10351         printf(", LSL #12");
10352     }
10353 }
10354
10355 /*****************************************************************************
10356  *
10357  *  Display an ARM64 condition code for the conditional instructions
10358  */
10359 void emitter::emitDispCond(insCond cond)
10360 {
10361     const static char* armCond[16] = {"eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc",
10362                                       "hi", "ls", "ge", "lt", "gt", "le", "AL", "NV"}; // The last two are invalid
10363     unsigned imm = (unsigned)cond;
10364     assert((0 <= imm) && (imm < ArrLen(armCond)));
10365     printf(armCond[imm]);
10366 }
10367
10368 /*****************************************************************************
10369  *
10370  *  Display an ARM64 flags for the conditional instructions
10371  */
10372 void emitter::emitDispFlags(insCflags flags)
10373 {
10374     const static char* armFlags[16] = {"0", "v",  "c",  "cv",  "z",  "zv",  "zc",  "zcv",
10375                                        "n", "nv", "nc", "ncv", "nz", "nzv", "nzc", "nzcv"};
10376     unsigned imm = (unsigned)flags;
10377     assert((0 <= imm) && (imm < ArrLen(armFlags)));
10378     printf(armFlags[imm]);
10379 }
10380
10381 /*****************************************************************************
10382  *
10383  *  Display an ARM64 'barrier' for the memory barrier instructions
10384  */
10385 void emitter::emitDispBarrier(insBarrier barrier)
10386 {
10387     const static char* armBarriers[16] = {"#0", "oshld", "oshst", "osh", "#4",  "nshld", "nshst", "nsh",
10388                                           "#8", "ishld", "ishst", "ish", "#12", "ld",    "st",    "sy"};
10389     unsigned imm = (unsigned)barrier;
10390     assert((0 <= imm) && (imm < ArrLen(armBarriers)));
10391     printf(armBarriers[imm]);
10392 }
10393
10394 /*****************************************************************************
10395  *
10396  *  Prints the encoding for the Shift Type encoding
10397  */
10398
10399 void emitter::emitDispShiftOpts(insOpts opt)
10400 {
10401     if (opt == INS_OPTS_LSL)
10402         printf(" LSL ");
10403     else if (opt == INS_OPTS_LSR)
10404         printf(" LSR ");
10405     else if (opt == INS_OPTS_ASR)
10406         printf(" ASR ");
10407     else if (opt == INS_OPTS_ROR)
10408         printf(" ROR ");
10409     else if (opt == INS_OPTS_MSL)
10410         printf(" MSL ");
10411     else
10412         assert(!"Bad value");
10413 }
10414
10415 /*****************************************************************************
10416  *
10417  *  Prints the encoding for the Extend Type encoding
10418  */
10419
10420 void emitter::emitDispExtendOpts(insOpts opt)
10421 {
10422     if (opt == INS_OPTS_UXTB)
10423         printf("UXTB");
10424     else if (opt == INS_OPTS_UXTH)
10425         printf("UXTH");
10426     else if (opt == INS_OPTS_UXTW)
10427         printf("UXTW");
10428     else if (opt == INS_OPTS_UXTX)
10429         printf("UXTX");
10430     else if (opt == INS_OPTS_SXTB)
10431         printf("SXTB");
10432     else if (opt == INS_OPTS_SXTH)
10433         printf("SXTH");
10434     else if (opt == INS_OPTS_SXTW)
10435         printf("SXTW");
10436     else if (opt == INS_OPTS_SXTX)
10437         printf("SXTX");
10438     else
10439         assert(!"Bad value");
10440 }
10441
10442 /*****************************************************************************
10443  *
10444  *  Prints the encoding for the Extend Type encoding in loads/stores
10445  */
10446
10447 void emitter::emitDispLSExtendOpts(insOpts opt)
10448 {
10449     if (opt == INS_OPTS_LSL)
10450         printf("LSL");
10451     else if (opt == INS_OPTS_UXTW)
10452         printf("UXTW");
10453     else if (opt == INS_OPTS_UXTX)
10454         printf("UXTX");
10455     else if (opt == INS_OPTS_SXTW)
10456         printf("SXTW");
10457     else if (opt == INS_OPTS_SXTX)
10458         printf("SXTX");
10459     else
10460         assert(!"Bad value");
10461 }
10462
10463 /*****************************************************************************
10464  *
10465  *  Display a register
10466  */
10467 void emitter::emitDispReg(regNumber reg, emitAttr attr, bool addComma)
10468 {
10469     emitAttr size = EA_SIZE(attr);
10470     printf(emitRegName(reg, size));
10471
10472     if (addComma)
10473         printf(", ");
10474 }
10475
10476 /*****************************************************************************
10477  *
10478  *  Display a vector register with an arrangement suffix
10479  */
10480 void emitter::emitDispVectorReg(regNumber reg, insOpts opt, bool addComma)
10481 {
10482     assert(isVectorRegister(reg));
10483     printf(emitVectorRegName(reg));
10484     emitDispArrangement(opt);
10485
10486     if (addComma)
10487         printf(", ");
10488 }
10489
10490 /*****************************************************************************
10491  *
10492  *  Display an vector register index suffix
10493  */
10494 void emitter::emitDispVectorRegIndex(regNumber reg, emitAttr elemsize, ssize_t index, bool addComma)
10495 {
10496     assert(isVectorRegister(reg));
10497     printf(emitVectorRegName(reg));
10498
10499     switch (elemsize)
10500     {
10501         case EA_1BYTE:
10502             printf(".b");
10503             break;
10504         case EA_2BYTE:
10505             printf(".h");
10506             break;
10507         case EA_4BYTE:
10508             printf(".s");
10509             break;
10510         case EA_8BYTE:
10511             printf(".d");
10512             break;
10513         default:
10514             assert(!"invalid elemsize");
10515             break;
10516     }
10517
10518     printf("[%d]", index);
10519
10520     if (addComma)
10521         printf(", ");
10522 }
10523
10524 /*****************************************************************************
10525  *
10526  *  Display an arrangement suffix
10527  */
10528 void emitter::emitDispArrangement(insOpts opt)
10529 {
10530     const char* str = "???";
10531
10532     switch (opt)
10533     {
10534         case INS_OPTS_8B:
10535             str = "8b";
10536             break;
10537         case INS_OPTS_16B:
10538             str = "16b";
10539             break;
10540         case INS_OPTS_4H:
10541             str = "4h";
10542             break;
10543         case INS_OPTS_8H:
10544             str = "8h";
10545             break;
10546         case INS_OPTS_2S:
10547             str = "2s";
10548             break;
10549         case INS_OPTS_4S:
10550             str = "4s";
10551             break;
10552         case INS_OPTS_1D:
10553             str = "1d";
10554             break;
10555         case INS_OPTS_2D:
10556             str = "2d";
10557             break;
10558
10559         default:
10560             assert(!"Invalid insOpt for vector register");
10561     }
10562     printf(".");
10563     printf(str);
10564 }
10565
10566 /*****************************************************************************
10567  *
10568  *  Display a register with an optional shift operation
10569  */
10570 void emitter::emitDispShiftedReg(regNumber reg, insOpts opt, ssize_t imm, emitAttr attr)
10571 {
10572     emitAttr size = EA_SIZE(attr);
10573     assert((imm & 0x003F) == imm);
10574     assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
10575
10576     printf(emitRegName(reg, size));
10577
10578     if (imm > 0)
10579     {
10580         if (strictArmAsm)
10581         {
10582             printf(",");
10583         }
10584         emitDispShiftOpts(opt);
10585         emitDispImm(imm, false);
10586     }
10587 }
10588
10589 /*****************************************************************************
10590  *
10591  *  Display a register with an optional extend and scale operations
10592  */
10593 void emitter::emitDispExtendReg(regNumber reg, insOpts opt, ssize_t imm)
10594 {
10595     assert((imm >= 0) && (imm <= 4));
10596     assert(insOptsNone(opt) || insOptsAnyExtend(opt) || (opt == INS_OPTS_LSL));
10597
10598     // size is based on the extend option, not the instr size.
10599     emitAttr size = insOpts32BitExtend(opt) ? EA_4BYTE : EA_8BYTE;
10600
10601     if (strictArmAsm)
10602     {
10603         if (insOptsNone(opt))
10604         {
10605             emitDispReg(reg, size, false);
10606         }
10607         else
10608         {
10609             emitDispReg(reg, size, true);
10610             if (opt == INS_OPTS_LSL)
10611                 printf("LSL");
10612             else
10613                 emitDispExtendOpts(opt);
10614             if ((imm > 0) || (opt == INS_OPTS_LSL))
10615             {
10616                 printf(" ");
10617                 emitDispImm(imm, false);
10618             }
10619         }
10620     }
10621     else // !strictArmAsm
10622     {
10623         if (insOptsNone(opt))
10624         {
10625             emitDispReg(reg, size, false);
10626         }
10627         else
10628         {
10629             if (opt != INS_OPTS_LSL)
10630             {
10631                 emitDispExtendOpts(opt);
10632                 printf("(");
10633                 emitDispReg(reg, size, false);
10634                 printf(")");
10635             }
10636         }
10637         if (imm > 0)
10638         {
10639             printf("*");
10640             emitDispImm(ssize_t{1} << imm, false);
10641         }
10642     }
10643 }
10644
10645 /*****************************************************************************
10646  *
10647  *  Display an addressing operand [reg + imm]
10648  */
10649 void emitter::emitDispAddrRI(regNumber reg, insOpts opt, ssize_t imm)
10650 {
10651     reg = encodingZRtoSP(reg); // ZR (R31) encodes the SP register
10652
10653     if (strictArmAsm)
10654     {
10655         printf("[");
10656
10657         emitDispReg(reg, EA_8BYTE, false);
10658
10659         if (!insOptsPostIndex(opt) && (imm != 0))
10660         {
10661             printf(",");
10662             emitDispImm(imm, false);
10663         }
10664         printf("]");
10665
10666         if (insOptsPreIndex(opt))
10667         {
10668             printf("!");
10669         }
10670         else if (insOptsPostIndex(opt))
10671         {
10672             printf(",");
10673             emitDispImm(imm, false);
10674         }
10675     }
10676     else // !strictArmAsm
10677     {
10678         printf("[");
10679
10680         const char* operStr = "++";
10681         if (imm < 0)
10682         {
10683             operStr = "--";
10684             imm     = -imm;
10685         }
10686
10687         if (insOptsPreIndex(opt))
10688         {
10689             printf(operStr);
10690         }
10691
10692         emitDispReg(reg, EA_8BYTE, false);
10693
10694         if (insOptsPostIndex(opt))
10695         {
10696             printf(operStr);
10697         }
10698
10699         if (insOptsIndexed(opt))
10700         {
10701             printf(", ");
10702         }
10703         else
10704         {
10705             printf("%c", operStr[1]);
10706         }
10707         emitDispImm(imm, false);
10708         printf("]");
10709     }
10710 }
10711
10712 /*****************************************************************************
10713  *
10714  *  Display an addressing operand [reg + extended reg]
10715  */
10716 void emitter::emitDispAddrRRExt(regNumber reg1, regNumber reg2, insOpts opt, bool isScaled, emitAttr size)
10717 {
10718     reg1 = encodingZRtoSP(reg1); // ZR (R31) encodes the SP register
10719
10720     unsigned scale = 0;
10721     if (isScaled)
10722     {
10723         scale = NaturalScale_helper(size);
10724     }
10725
10726     printf("[");
10727
10728     if (strictArmAsm)
10729     {
10730         emitDispReg(reg1, EA_8BYTE, true);
10731         emitDispExtendReg(reg2, opt, scale);
10732     }
10733     else // !strictArmAsm
10734     {
10735         emitDispReg(reg1, EA_8BYTE, false);
10736         printf("+");
10737         emitDispExtendReg(reg2, opt, scale);
10738     }
10739
10740     printf("]");
10741 }
10742
10743 /*****************************************************************************
10744  *
10745  *  Display (optionally) the instruction encoding in hex
10746  */
10747
10748 void emitter::emitDispInsHex(BYTE* code, size_t sz)
10749 {
10750     // We do not display the instruction hex if we want diff-able disassembly
10751     if (!emitComp->opts.disDiffable)
10752     {
10753         if (sz == 4)
10754         {
10755             printf("  %08X    ", (*((code_t*)code)));
10756         }
10757         else
10758         {
10759             printf("              ");
10760         }
10761     }
10762 }
10763
10764 /****************************************************************************
10765  *
10766  *  Display the given instruction.
10767  */
10768
10769 void emitter::emitDispIns(
10770     instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* pCode, size_t sz, insGroup* ig)
10771 {
10772     if (EMITVERBOSE)
10773     {
10774         unsigned idNum =
10775             id->idDebugOnlyInfo()->idNum; // Do not remove this!  It is needed for VisualStudio conditional breakpoints
10776
10777         printf("IN%04x: ", idNum);
10778     }
10779
10780     if (pCode == NULL)
10781         sz = 0;
10782
10783     if (!emitComp->opts.dspEmit && !isNew && !asmfm && sz)
10784         doffs = true;
10785
10786     /* Display the instruction offset */
10787
10788     emitDispInsOffs(offset, doffs);
10789
10790     /* Display the instruction hex code */
10791
10792     emitDispInsHex(pCode, sz);
10793
10794     printf("      ");
10795
10796     /* Get the instruction and format */
10797
10798     instruction ins = id->idIns();
10799     insFormat   fmt = id->idInsFmt();
10800
10801     emitDispInst(ins);
10802
10803     /* If this instruction has just been added, check its size */
10804
10805     assert(isNew == false || (int)emitSizeOfInsDsc(id) == emitCurIGfreeNext - (BYTE*)id);
10806
10807     /* Figure out the operand size */
10808     emitAttr size = id->idOpSize();
10809     emitAttr attr = size;
10810     if (id->idGCref() == GCT_GCREF)
10811         attr = EA_GCREF;
10812     else if (id->idGCref() == GCT_BYREF)
10813         attr = EA_BYREF;
10814
10815     switch (fmt)
10816     {
10817         code_t       code;
10818         ssize_t      imm;
10819         int          doffs;
10820         bool         isExtendAlias;
10821         bitMaskImm   bmi;
10822         halfwordImm  hwi;
10823         condFlagsImm cfi;
10824         unsigned     scale;
10825         unsigned     immShift;
10826         bool         hasShift;
10827         ssize_t      offs;
10828         const char*  methodName;
10829         emitAttr     elemsize;
10830         emitAttr     datasize;
10831         emitAttr     srcsize;
10832         emitAttr     dstsize;
10833         ssize_t      index;
10834         ssize_t      index2;
10835
10836         case IF_BI_0A: // BI_0A   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
10837         case IF_BI_0B: // BI_0B   ......iiiiiiiiii iiiiiiiiiii.....               simm19:00
10838         case IF_LARGEJMP:
10839         {
10840             if (fmt == IF_LARGEJMP)
10841             {
10842                 printf("(LARGEJMP)");
10843             }
10844             if (id->idAddr()->iiaHasInstrCount())
10845             {
10846                 int instrCount = id->idAddr()->iiaGetInstrCount();
10847
10848                 if (ig == nullptr)
10849                 {
10850                     printf("pc%s%d instructions", (instrCount >= 0) ? "+" : "", instrCount);
10851                 }
10852                 else
10853                 {
10854                     unsigned       insNum  = emitFindInsNum(ig, id);
10855                     UNATIVE_OFFSET srcOffs = ig->igOffs + emitFindOffset(ig, insNum + 1);
10856                     UNATIVE_OFFSET dstOffs = ig->igOffs + emitFindOffset(ig, insNum + 1 + instrCount);
10857                     ssize_t        relOffs = (ssize_t)(emitOffsetToPtr(dstOffs) - emitOffsetToPtr(srcOffs));
10858                     printf("pc%s%d (%d instructions)", (relOffs >= 0) ? "+" : "", relOffs, instrCount);
10859                 }
10860             }
10861             else if (id->idIsBound())
10862             {
10863                 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10864             }
10865             else
10866             {
10867                 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10868             }
10869         }
10870         break;
10871
10872         case IF_BI_0C: // BI_0C   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
10873             if (id->idIsCallAddr())
10874             {
10875                 offs       = (ssize_t)id->idAddr()->iiaAddr;
10876                 methodName = "";
10877             }
10878             else
10879             {
10880                 offs       = 0;
10881                 methodName = emitComp->eeGetMethodFullName((CORINFO_METHOD_HANDLE)id->idDebugOnlyInfo()->idMemCookie);
10882             }
10883
10884             if (offs)
10885             {
10886                 if (id->idIsDspReloc())
10887                     printf("reloc ");
10888                 printf("%08X", offs);
10889             }
10890             else
10891             {
10892                 printf("%s", methodName);
10893             }
10894             break;
10895
10896         case IF_BI_1A: // BI_1A   ......iiiiiiiiii iiiiiiiiiiittttt      Rt       simm19:00
10897             assert(insOptsNone(id->idInsOpt()));
10898             emitDispReg(id->idReg1(), size, true);
10899             if (id->idIsBound())
10900             {
10901                 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10902             }
10903             else
10904             {
10905                 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10906             }
10907             break;
10908
10909         case IF_BI_1B: // BI_1B   B.......bbbbbiii iiiiiiiiiiittttt      Rt imm6, simm14:00
10910             assert(insOptsNone(id->idInsOpt()));
10911             emitDispReg(id->idReg1(), size, true);
10912             emitDispImm(emitGetInsSC(id), true);
10913             if (id->idIsBound())
10914             {
10915                 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10916             }
10917             else
10918             {
10919                 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10920             }
10921             break;
10922
10923         case IF_BR_1A: // BR_1A   ................ ......nnnnn.....         Rn
10924             assert(insOptsNone(id->idInsOpt()));
10925             emitDispReg(id->idReg1(), size, false);
10926             break;
10927
10928         case IF_BR_1B: // BR_1B   ................ ......nnnnn.....         Rn
10929             assert(insOptsNone(id->idInsOpt()));
10930             emitDispReg(id->idReg3(), size, false);
10931             break;
10932
10933         case IF_LS_1A: // LS_1A   XX...V..iiiiiiii iiiiiiiiiiittttt      Rt    PC imm(1MB)
10934         case IF_DI_1E: // DI_1E   .ii.....iiiiiiii iiiiiiiiiiiddddd      Rd       simm21
10935         case IF_LARGELDC:
10936         case IF_LARGEADR:
10937             assert(insOptsNone(id->idInsOpt()));
10938             emitDispReg(id->idReg1(), size, true);
10939             imm = emitGetInsSC(id);
10940
10941             /* Is this actually a reference to a data section? */
10942             if (fmt == IF_LARGEADR)
10943             {
10944                 printf("(LARGEADR)");
10945             }
10946             else if (fmt == IF_LARGELDC)
10947             {
10948                 printf("(LARGELDC)");
10949             }
10950
10951             printf("[");
10952             if (id->idAddr()->iiaIsJitDataOffset())
10953             {
10954                 doffs = Compiler::eeGetJitDataOffs(id->idAddr()->iiaFieldHnd);
10955                 /* Display a data section reference */
10956
10957                 if (doffs & 1)
10958                     printf("@CNS%02u", doffs - 1);
10959                 else
10960                     printf("@RWD%02u", doffs);
10961
10962                 if (imm != 0)
10963                     printf("%+Id", imm);
10964             }
10965             else
10966             {
10967                 assert(imm == 0);
10968                 if (id->idIsReloc())
10969                 {
10970                     printf("RELOC ");
10971                     emitDispImm((ssize_t)id->idAddr()->iiaAddr, false);
10972                 }
10973                 else if (id->idIsBound())
10974                 {
10975                     printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10976                 }
10977                 else
10978                 {
10979                     printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10980                 }
10981             }
10982             printf("]");
10983             break;
10984
10985         case IF_LS_2A: // LS_2A   .X.......X...... ......nnnnnttttt      Rt Rn
10986             assert(insOptsNone(id->idInsOpt()));
10987             assert(emitGetInsSC(id) == 0);
10988             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10989             emitDispAddrRI(id->idReg2(), id->idInsOpt(), 0);
10990             break;
10991
10992         case IF_LS_2B: // LS_2B   .X.......Xiiiiii iiiiiinnnnnttttt      Rt Rn    imm(0-4095)
10993             assert(insOptsNone(id->idInsOpt()));
10994             imm   = emitGetInsSC(id);
10995             scale = NaturalScale_helper(emitInsLoadStoreSize(id));
10996             imm <<= scale; // The immediate is scaled by the size of the ld/st
10997             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10998             emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
10999             break;
11000
11001         case IF_LS_2C: // LS_2C   .X.......X.iiiii iiiiPPnnnnnttttt      Rt Rn    imm(-256..+255) no/pre/post inc
11002             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
11003             imm = emitGetInsSC(id);
11004             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
11005             emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
11006             break;
11007
11008         case IF_LS_3A: // LS_3A   .X.......X.mmmmm oooS..nnnnnttttt      Rt Rn Rm ext(Rm) LSL {}
11009             assert(insOptsLSExtend(id->idInsOpt()));
11010             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
11011             if (id->idIsLclVar())
11012             {
11013                 emitDispAddrRRExt(id->idReg2(), codeGen->rsGetRsvdReg(), id->idInsOpt(), false, size);
11014             }
11015             else
11016             {
11017                 emitDispAddrRRExt(id->idReg2(), id->idReg3(), id->idInsOpt(), id->idReg3Scaled(), size);
11018             }
11019             break;
11020
11021         case IF_LS_3B: // LS_3B   X............... .aaaaannnnnddddd      Rt Ra Rn
11022             assert(insOptsNone(id->idInsOpt()));
11023             assert(emitGetInsSC(id) == 0);
11024             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
11025             emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
11026             emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
11027             break;
11028
11029         case IF_LS_3C: // LS_3C   X.........iiiiii iaaaaannnnnddddd      Rt Ra Rn imm(im7,sh)
11030             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
11031             imm   = emitGetInsSC(id);
11032             scale = NaturalScale_helper(emitInsLoadStoreSize(id));
11033             imm <<= scale;
11034             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
11035             emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
11036             emitDispAddrRI(id->idReg3(), id->idInsOpt(), imm);
11037             break;
11038
11039         case IF_LS_3D: // LS_3D   .X.......X.mmmmm ......nnnnnttttt      Wm Rt Rn
11040             assert(insOptsNone(id->idInsOpt()));
11041             emitDispReg(id->idReg1(), EA_4BYTE, true);
11042             emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
11043             emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
11044             break;
11045
11046         case IF_LS_3E: // LS_3E   .X.........mmmmm ......nnnnnttttt      Rm Rt Rn ARMv8.1 LSE Atomics
11047             assert(insOptsNone(id->idInsOpt()));
11048             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
11049             emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
11050             emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
11051             break;
11052
11053         case IF_DI_1A: // DI_1A   X.......shiiiiii iiiiiinnnnn.....      Rn       imm(i12,sh)
11054             emitDispReg(id->idReg1(), size, true);
11055             emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
11056             break;
11057
11058         case IF_DI_1B: // DI_1B   X........hwiiiii iiiiiiiiiiiddddd      Rd       imm(i16,hw)
11059             emitDispReg(id->idReg1(), size, true);
11060             hwi.immHWVal = (unsigned)emitGetInsSC(id);
11061             if (ins == INS_mov)
11062             {
11063                 emitDispImm(emitDecodeHalfwordImm(hwi, size), false);
11064             }
11065             else // movz, movn, movk
11066             {
11067                 emitDispImm(hwi.immVal, false);
11068                 if (hwi.immHW != 0)
11069                 {
11070                     emitDispShiftOpts(INS_OPTS_LSL);
11071                     emitDispImm(hwi.immHW * 16, false);
11072                 }
11073             }
11074             break;
11075
11076         case IF_DI_1C: // DI_1C   X........Nrrrrrr ssssssnnnnn.....         Rn    imm(N,r,s)
11077             emitDispReg(id->idReg1(), size, true);
11078             bmi.immNRS = (unsigned)emitGetInsSC(id);
11079             emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
11080             break;
11081
11082         case IF_DI_1D: // DI_1D   X........Nrrrrrr ssssss.....ddddd      Rd       imm(N,r,s)
11083             emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11084             bmi.immNRS = (unsigned)emitGetInsSC(id);
11085             emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
11086             break;
11087
11088         case IF_DI_2A: // DI_2A   X.......shiiiiii iiiiiinnnnnddddd      Rd Rn    imm(i12,sh)
11089             if ((ins == INS_add) || (ins == INS_sub))
11090             {
11091                 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11092                 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11093             }
11094             else
11095             {
11096                 emitDispReg(id->idReg1(), size, true);
11097                 emitDispReg(id->idReg2(), size, true);
11098             }
11099             emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
11100             break;
11101
11102         case IF_DI_2B: // DI_2B   X........X.nnnnn ssssssnnnnnddddd      Rd Rn    imm(0-63)
11103             emitDispReg(id->idReg1(), size, true);
11104             emitDispReg(id->idReg2(), size, true);
11105             emitDispImm(emitGetInsSC(id), false);
11106             break;
11107
11108         case IF_DI_2C: // DI_2C   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imm(N,r,s)
11109             if (ins == INS_ands)
11110             {
11111                 emitDispReg(id->idReg1(), size, true);
11112             }
11113             else
11114             {
11115                 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11116             }
11117             emitDispReg(id->idReg2(), size, true);
11118             bmi.immNRS = (unsigned)emitGetInsSC(id);
11119             emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
11120             break;
11121
11122         case IF_DI_2D: // DI_2D   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imr, ims   (N,r,s)
11123             emitDispReg(id->idReg1(), size, true);
11124             emitDispReg(id->idReg2(), size, true);
11125
11126             imm        = emitGetInsSC(id);
11127             bmi.immNRS = (unsigned)imm;
11128
11129             switch (ins)
11130             {
11131                 case INS_bfm:
11132                 case INS_sbfm:
11133                 case INS_ubfm:
11134                     emitDispImm(bmi.immR, true);
11135                     emitDispImm(bmi.immS, false);
11136                     break;
11137
11138                 case INS_bfi:
11139                 case INS_sbfiz:
11140                 case INS_ubfiz:
11141                     emitDispImm(getBitWidth(size) - bmi.immR, true);
11142                     emitDispImm(bmi.immS + 1, false);
11143                     break;
11144
11145                 case INS_bfxil:
11146                 case INS_sbfx:
11147                 case INS_ubfx:
11148                     emitDispImm(bmi.immR, true);
11149                     emitDispImm(bmi.immS - bmi.immR + 1, false);
11150                     break;
11151
11152                 case INS_asr:
11153                 case INS_lsr:
11154                 case INS_lsl:
11155                     emitDispImm(imm, false);
11156                     break;
11157
11158                 default:
11159                     assert(!"Unexpected instruction in IF_DI_2D");
11160             }
11161
11162             break;
11163
11164         case IF_DI_1F: // DI_1F   X..........iiiii cccc..nnnnn.nzcv      Rn imm5  nzcv cond
11165             emitDispReg(id->idReg1(), size, true);
11166             cfi.immCFVal = (unsigned)emitGetInsSC(id);
11167             emitDispImm(cfi.imm5, true);
11168             emitDispFlags(cfi.flags);
11169             printf(",");
11170             emitDispCond(cfi.cond);
11171             break;
11172
11173         case IF_DR_1D: // DR_1D   X............... cccc.......mmmmm      Rd       cond
11174             emitDispReg(id->idReg1(), size, true);
11175             cfi.immCFVal = (unsigned)emitGetInsSC(id);
11176             emitDispCond(cfi.cond);
11177             break;
11178
11179         case IF_DR_2A: // DR_2A   X..........mmmmm ......nnnnn.....         Rn Rm
11180             emitDispReg(id->idReg1(), size, true);
11181             emitDispReg(id->idReg2(), size, false);
11182             break;
11183
11184         case IF_DR_2B: // DR_2B   X.......sh.mmmmm ssssssnnnnn.....         Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
11185             emitDispReg(id->idReg1(), size, true);
11186             emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
11187             break;
11188
11189         case IF_DR_2C: // DR_2C   X..........mmmmm ooosssnnnnn.....         Rn Rm ext(Rm) LSL imm(0-4)
11190             emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11191             imm = emitGetInsSC(id);
11192             emitDispExtendReg(id->idReg2(), id->idInsOpt(), imm);
11193             break;
11194
11195         case IF_DR_2D: // DR_2D   X..........nnnnn cccc..nnnnnddddd      Rd Rn    cond
11196             emitDispReg(id->idReg1(), size, true);
11197             emitDispReg(id->idReg2(), size, true);
11198             cfi.immCFVal = (unsigned)emitGetInsSC(id);
11199             emitDispCond(cfi.cond);
11200             break;
11201
11202         case IF_DR_2E: // DR_2E   X..........mmmmm ...........ddddd      Rd    Rm
11203         case IF_DR_2J: // DR_2J   ................ ......nnnnnddddd      Sd    Sn
11204             emitDispReg(id->idReg1(), size, true);
11205             emitDispReg(id->idReg2(), size, false);
11206             break;
11207
11208         case IF_DR_2F: // DR_2F   X.......sh.mmmmm ssssss.....ddddd      Rd    Rm {LSL,LSR,ASR} imm(0-63)
11209             emitDispReg(id->idReg1(), size, true);
11210             emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
11211             break;
11212
11213         case IF_DR_2G: // DR_2G   X............... ......nnnnnddddd      Rd Rn
11214             emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11215             emitDispReg(encodingZRtoSP(id->idReg2()), size, false);
11216             break;
11217
11218         case IF_DR_2H: // DR_2H   X........X...... ......nnnnnddddd      Rd Rn
11219             emitDispReg(id->idReg1(), size, true);
11220             emitDispReg(id->idReg2(), size, false);
11221             break;
11222
11223         case IF_DR_2I: // DR_2I   X..........mmmmm cccc..nnnnn.nzcv      Rn Rm    nzcv cond
11224             emitDispReg(id->idReg1(), size, true);
11225             emitDispReg(id->idReg2(), size, true);
11226             cfi.immCFVal = (unsigned)emitGetInsSC(id);
11227             emitDispFlags(cfi.flags);
11228             printf(",");
11229             emitDispCond(cfi.cond);
11230             break;
11231
11232         case IF_DR_3A: // DR_3A   X..........mmmmm ......nnnnnmmmmm      Rd Rn Rm
11233             if ((ins == INS_add) || (ins == INS_sub))
11234             {
11235                 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11236                 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11237             }
11238             else if ((ins == INS_smull) || (ins == INS_smulh))
11239             {
11240                 // Rd is always 8 bytes
11241                 emitDispReg(id->idReg1(), EA_8BYTE, true);
11242
11243                 // Rn, Rm effective size depends on instruction type
11244                 size = (ins == INS_smulh) ? EA_8BYTE : EA_4BYTE;
11245                 emitDispReg(id->idReg2(), size, true);
11246             }
11247             else
11248             {
11249                 emitDispReg(id->idReg1(), size, true);
11250                 emitDispReg(id->idReg2(), size, true);
11251             }
11252             if (id->idIsLclVar())
11253             {
11254                 emitDispReg(codeGen->rsGetRsvdReg(), size, false);
11255             }
11256             else
11257             {
11258                 emitDispReg(id->idReg3(), size, false);
11259             }
11260
11261             break;
11262
11263         case IF_DR_3B: // DR_3B   X.......sh.mmmmm ssssssnnnnnddddd      Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
11264             emitDispReg(id->idReg1(), size, true);
11265             emitDispReg(id->idReg2(), size, true);
11266             emitDispShiftedReg(id->idReg3(), id->idInsOpt(), emitGetInsSC(id), size);
11267             break;
11268
11269         case IF_DR_3C: // DR_3C   X..........mmmmm ooosssnnnnnddddd      Rd Rn Rm ext(Rm) LSL imm(0-4)
11270             emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11271             emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11272             imm = emitGetInsSC(id);
11273             emitDispExtendReg(id->idReg3(), id->idInsOpt(), imm);
11274             break;
11275
11276         case IF_DR_3D: // DR_3D   X..........mmmmm cccc..nnnnnmmmmm      Rd Rn Rm cond
11277             emitDispReg(id->idReg1(), size, true);
11278             emitDispReg(id->idReg2(), size, true);
11279             emitDispReg(id->idReg3(), size, true);
11280             cfi.immCFVal = (unsigned)emitGetInsSC(id);
11281             emitDispCond(cfi.cond);
11282             break;
11283
11284         case IF_DR_3E: // DR_3E   X........X.mmmmm ssssssnnnnnddddd      Rd Rn Rm imm(0-63)
11285             emitDispReg(id->idReg1(), size, true);
11286             emitDispReg(id->idReg2(), size, true);
11287             emitDispReg(id->idReg3(), size, true);
11288             emitDispImm(emitGetInsSC(id), false);
11289             break;
11290
11291         case IF_DR_4A: // DR_4A   X..........mmmmm .aaaaannnnnmmmmm      Rd Rn Rm Ra
11292             emitDispReg(id->idReg1(), size, true);
11293             emitDispReg(id->idReg2(), size, true);
11294             emitDispReg(id->idReg3(), size, true);
11295             emitDispReg(id->idReg4(), size, false);
11296             break;
11297
11298         case IF_DV_1A: // DV_1A   .........X.iiiii iii........ddddd      Vd imm8 (fmov - immediate scalar)
11299             elemsize = id->idOpSize();
11300             emitDispReg(id->idReg1(), elemsize, true);
11301             emitDispFloatImm(emitGetInsSC(id));
11302             break;
11303
11304         case IF_DV_1B: // DV_1B   .QX..........iii cmod..iiiiiddddd      Vd imm8 (immediate vector)
11305             imm      = emitGetInsSC(id) & 0x0ff;
11306             immShift = (emitGetInsSC(id) & 0x700) >> 8;
11307             hasShift = (immShift != 0);
11308             elemsize = optGetElemsize(id->idInsOpt());
11309             if (id->idInsOpt() == INS_OPTS_1D)
11310             {
11311                 assert(elemsize == size);
11312                 emitDispReg(id->idReg1(), size, true);
11313             }
11314             else
11315             {
11316                 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11317             }
11318             if (ins == INS_fmov)
11319             {
11320                 emitDispFloatImm(imm);
11321                 assert(hasShift == false);
11322             }
11323             else
11324             {
11325                 if (elemsize == EA_8BYTE)
11326                 {
11327                     assert(ins == INS_movi);
11328                     ssize_t       imm64 = 0;
11329                     const ssize_t mask8 = 0xFF;
11330                     for (unsigned b = 0; b < 8; b++)
11331                     {
11332                         if (imm & (ssize_t{1} << b))
11333                         {
11334                             imm64 |= (mask8 << (b * 8));
11335                         }
11336                     }
11337                     emitDispImm(imm64, hasShift, true);
11338                 }
11339                 else
11340                 {
11341                     emitDispImm(imm, hasShift, true);
11342                 }
11343                 if (hasShift)
11344                 {
11345                     insOpts  opt   = (immShift & 0x4) ? INS_OPTS_MSL : INS_OPTS_LSL;
11346                     unsigned shift = (immShift & 0x3) * 8;
11347                     emitDispShiftOpts(opt);
11348                     emitDispImm(shift, false);
11349                 }
11350             }
11351             break;
11352
11353         case IF_DV_1C: // DV_1C   .........X...... ......nnnnn.....      Vn #0.0 (fcmp - with zero)
11354             elemsize = id->idOpSize();
11355             emitDispReg(id->idReg1(), elemsize, true);
11356             emitDispFloatZero();
11357             break;
11358
11359         case IF_DV_2A: // DV_2A   .Q.......X...... ......nnnnnddddd      Vd Vn   (fabs, fcvt - vector)
11360         case IF_DV_2M: // DV_2M   .Q......XX...... ......nnnnnddddd      Vd Vn   (abs, neg   - vector)
11361         case IF_DV_2P: // DV_2P   ................ ......nnnnnddddd      Vd Vn   (aes*, sha1su1)
11362             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11363             emitDispVectorReg(id->idReg2(), id->idInsOpt(), false);
11364             break;
11365
11366         case IF_DV_2N: // DV_2N   .........iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - scalar)
11367             elemsize = id->idOpSize();
11368             emitDispReg(id->idReg1(), elemsize, true);
11369             emitDispReg(id->idReg2(), elemsize, true);
11370             emitDispImm(emitGetInsSC(id), false);
11371             break;
11372
11373         case IF_DV_2O: // DV_2O   .Q.......iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - vector)
11374             imm = emitGetInsSC(id);
11375             // Do we have a sxtl or uxtl instruction?
11376             isExtendAlias = ((ins == INS_sxtl) || (ins == INS_sxtl2) || (ins == INS_uxtl) || (ins == INS_uxtl2));
11377             code          = emitInsCode(ins, fmt);
11378             if (code & 0x00008000) // widen/narrow opcodes
11379             {
11380                 if (code & 0x00002000) // SHL opcodes
11381                 {
11382                     emitDispVectorReg(id->idReg1(), optWidenElemsize(id->idInsOpt()), true);
11383                     emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11384                 }
11385                 else // SHR opcodes
11386                 {
11387                     emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11388                     emitDispVectorReg(id->idReg2(), optWidenElemsize(id->idInsOpt()), !isExtendAlias);
11389                 }
11390             }
11391             else
11392             {
11393                 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11394                 emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11395             }
11396             // Print the immediate unless we have a sxtl or uxtl instruction
11397             if (!isExtendAlias)
11398             {
11399                 emitDispImm(imm, false);
11400             }
11401             break;
11402
11403         case IF_DV_2B: // DV_2B   .Q.........iiiii ......nnnnnddddd      Rd Vn[] (umov/smov    - to general)
11404             srcsize = id->idOpSize();
11405             index   = emitGetInsSC(id);
11406             if (ins == INS_smov)
11407             {
11408                 dstsize = EA_8BYTE;
11409             }
11410             else // INS_umov or INS_mov
11411             {
11412                 dstsize = (srcsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE;
11413             }
11414             emitDispReg(id->idReg1(), dstsize, true);
11415             emitDispVectorRegIndex(id->idReg2(), srcsize, index, false);
11416             break;
11417
11418         case IF_DV_2C: // DV_2C   .Q.........iiiii ......nnnnnddddd      Vd Rn   (dup/ins - vector from general)
11419             if (ins == INS_dup)
11420             {
11421                 datasize = id->idOpSize();
11422                 assert(isValidVectorDatasize(datasize));
11423                 assert(isValidArrangement(datasize, id->idInsOpt()));
11424                 elemsize = optGetElemsize(id->idInsOpt());
11425                 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11426             }
11427             else // INS_ins
11428             {
11429                 elemsize = id->idOpSize();
11430                 index    = emitGetInsSC(id);
11431                 assert(isValidVectorElemsize(elemsize));
11432                 emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11433             }
11434             emitDispReg(id->idReg2(), (elemsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE, false);
11435             break;
11436
11437         case IF_DV_2D: // DV_2D   .Q.........iiiii ......nnnnnddddd      Vd Vn[]   (dup - vector)
11438             datasize = id->idOpSize();
11439             assert(isValidVectorDatasize(datasize));
11440             assert(isValidArrangement(datasize, id->idInsOpt()));
11441             elemsize = optGetElemsize(id->idInsOpt());
11442             index    = emitGetInsSC(id);
11443             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11444             emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11445             break;
11446
11447         case IF_DV_2E: // DV_2E   ...........iiiii ......nnnnnddddd      Vd Vn[]   (dup - scalar)
11448             elemsize = id->idOpSize();
11449             index    = emitGetInsSC(id);
11450             emitDispReg(id->idReg1(), elemsize, true);
11451             emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11452             break;
11453
11454         case IF_DV_2F: // DV_2F   ...........iiiii .jjjj.nnnnnddddd      Vd[] Vn[] (ins - element)
11455             imm      = emitGetInsSC(id);
11456             index    = (imm >> 4) & 0xf;
11457             index2   = imm & 0xf;
11458             elemsize = id->idOpSize();
11459             emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11460             emitDispVectorRegIndex(id->idReg2(), elemsize, index2, false);
11461             break;
11462
11463         case IF_DV_2G: // DV_2G   .........X...... ......nnnnnddddd      Vd Vn      (fmov, fcvtXX - register)
11464         case IF_DV_2K: // DV_2K   .........X.mmmmm ......nnnnn.....      Vn Vm      (fcmp)
11465         case IF_DV_2L: // DV_2L   ........XX...... ......nnnnnddddd      Vd Vn      (abs, neg - scalar)
11466             elemsize = id->idOpSize();
11467             emitDispReg(id->idReg1(), elemsize, true);
11468             emitDispReg(id->idReg2(), elemsize, false);
11469             break;
11470
11471         case IF_DV_2H: // DV_2H   X........X...... ......nnnnnddddd      Rd Vn      (fmov, fcvtXX - to general)
11472         case IF_DV_2I: // DV_2I   X........X...... ......nnnnnddddd      Vd Rn      (fmov, Xcvtf - from general)
11473         case IF_DV_2J: // DV_2J   ........SS.....D D.....nnnnnddddd      Vd Vn      (fcvt)
11474             dstsize = optGetDstsize(id->idInsOpt());
11475             srcsize = optGetSrcsize(id->idInsOpt());
11476
11477             emitDispReg(id->idReg1(), dstsize, true);
11478             emitDispReg(id->idReg2(), srcsize, false);
11479             break;
11480
11481         case IF_DV_3A: // DV_3A   .Q......XX.mmmmm ......nnnnnddddd      Vd Vn Vm  (vector)
11482         case IF_DV_3B: // DV_3B   .Q.........mmmmm ......nnnnnddddd      Vd Vn Vm  (vector)
11483             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11484             emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11485             emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11486             break;
11487
11488         case IF_DV_3C: // DV_3C   .Q.........mmmmm ......nnnnnddddd      Vd Vn Vm  (vector)
11489             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11490             if (ins != INS_mov)
11491             {
11492                 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11493             }
11494             emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11495             break;
11496
11497         case IF_DV_3AI: // DV_3AI  .Q......XXLMmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector by elem)
11498         case IF_DV_3BI: // DV_3BI  .Q........Lmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector by elem)
11499             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11500             emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11501             elemsize = optGetElemsize(id->idInsOpt());
11502             emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11503             break;
11504
11505         case IF_DV_3D: // DV_3D   .........X.mmmmm ......nnnnnddddd      Vd Vn Vm  (scalar)
11506         case IF_DV_3E: // DV_3E   ...........mmmmm ......nnnnnddddd      Vd Vn Vm  (scalar)
11507             emitDispReg(id->idReg1(), size, true);
11508             emitDispReg(id->idReg2(), size, true);
11509             emitDispReg(id->idReg3(), size, false);
11510             break;
11511
11512         case IF_DV_3F: // DV_3F   ..........mmmmm ......nnnnnddddd       Vd Vn Vm (vector)
11513             if ((ins == INS_sha1c) || (ins == INS_sha1m) || (ins == INS_sha1p))
11514             {
11515                 // Qd, Sn, Vm (vector)
11516                 emitDispReg(id->idReg1(), size, true);
11517                 emitDispReg(id->idReg2(), EA_4BYTE, true);
11518                 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11519             }
11520             else if ((ins == INS_sha256h) || (ins == INS_sha256h2))
11521             {
11522                 // Qd Qn Vm (vector)
11523                 emitDispReg(id->idReg1(), size, true);
11524                 emitDispReg(id->idReg2(), size, true);
11525                 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11526             }
11527             else // INS_sha1su0, INS_sha256su1
11528             {
11529                 // Vd, Vn, Vm   (vector)
11530                 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11531                 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11532                 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11533             }
11534             break;
11535
11536         case IF_DV_3DI: // DV_3DI  .........XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (scalar by elem)
11537             emitDispReg(id->idReg1(), size, true);
11538             emitDispReg(id->idReg2(), size, true);
11539             elemsize = size;
11540             emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11541             break;
11542
11543         case IF_DV_4A: // DV_4A   .........X.mmmmm .aaaaannnnnddddd      Vd Va Vn Vm (scalar)
11544             emitDispReg(id->idReg1(), size, true);
11545             emitDispReg(id->idReg2(), size, true);
11546             emitDispReg(id->idReg3(), size, true);
11547             emitDispReg(id->idReg4(), size, false);
11548             break;
11549
11550         case IF_SN_0A: // SN_0A   ................ ................
11551             break;
11552
11553         case IF_SI_0A: // SI_0A   ...........iiiii iiiiiiiiiii.....               imm16
11554             emitDispImm(emitGetInsSC(id), false);
11555             break;
11556
11557         case IF_SI_0B: // SI_0B   ................ ....bbbb........               imm4 - barrier
11558             emitDispBarrier((insBarrier)emitGetInsSC(id));
11559             break;
11560
11561         default:
11562             printf("unexpected format %s", emitIfName(id->idInsFmt()));
11563             assert(!"unexpectedFormat");
11564             break;
11565     }
11566
11567     if (id->idDebugOnlyInfo()->idVarRefOffs)
11568     {
11569         printf("\t// ");
11570         emitDispFrameRef(id->idAddr()->iiaLclVar.lvaVarNum(), id->idAddr()->iiaLclVar.lvaOffset(),
11571                          id->idDebugOnlyInfo()->idVarRefOffs, asmfm);
11572     }
11573
11574     printf("\n");
11575 }
11576
11577 /*****************************************************************************
11578  *
11579  *  Display a stack frame reference.
11580  */
11581
11582 void emitter::emitDispFrameRef(int varx, int disp, int offs, bool asmfm)
11583 {
11584     printf("[");
11585
11586     if (varx < 0)
11587         printf("TEMP_%02u", -varx);
11588     else
11589         emitComp->gtDispLclVar(+varx, false);
11590
11591     if (disp < 0)
11592         printf("-0x%02x", -disp);
11593     else if (disp > 0)
11594         printf("+0x%02x", +disp);
11595
11596     printf("]");
11597
11598     if (varx >= 0 && emitComp->opts.varNames)
11599     {
11600         LclVarDsc*  varDsc;
11601         const char* varName;
11602
11603         assert((unsigned)varx < emitComp->lvaCount);
11604         varDsc  = emitComp->lvaTable + varx;
11605         varName = emitComp->compLocalVarName(varx, offs);
11606
11607         if (varName)
11608         {
11609             printf("'%s", varName);
11610
11611             if (disp < 0)
11612                 printf("-%d", -disp);
11613             else if (disp > 0)
11614                 printf("+%d", +disp);
11615
11616             printf("'");
11617         }
11618     }
11619 }
11620
11621 #endif // DEBUG
11622
11623 // Generate code for a load or store operation with a potentially complex addressing mode
11624 // This method handles the case of a GT_IND with contained GT_LEA op1 of the x86 form [base + index*sccale + offset]
11625 // Since Arm64 does not directly support this complex of an addressing mode
11626 // we may generates up to three instructions for this for Arm64
11627 //
11628 void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataReg, GenTreeIndir* indir)
11629 {
11630     emitAttr ldstAttr = isVectorRegister(dataReg) ? attr : emitInsAdjustLoadStoreAttr(ins, attr);
11631
11632     GenTree* addr = indir->Addr();
11633
11634     if (addr->isContained())
11635     {
11636         assert(addr->OperGet() == GT_LCL_VAR_ADDR || addr->OperGet() == GT_LEA);
11637
11638         int   offset = 0;
11639         DWORD lsl    = 0;
11640
11641         if (addr->OperGet() == GT_LEA)
11642         {
11643             offset = addr->AsAddrMode()->Offset();
11644             if (addr->AsAddrMode()->gtScale > 0)
11645             {
11646                 assert(isPow2(addr->AsAddrMode()->gtScale));
11647                 BitScanForward(&lsl, addr->AsAddrMode()->gtScale);
11648             }
11649         }
11650
11651         GenTree* memBase = indir->Base();
11652
11653         if (indir->HasIndex())
11654         {
11655             GenTree* index = indir->Index();
11656
11657             if (offset != 0)
11658             {
11659                 regNumber tmpReg = indir->GetSingleTempReg();
11660
11661                 emitAttr addType = varTypeIsGC(memBase) ? EA_BYREF : EA_PTRSIZE;
11662
11663                 if (emitIns_valid_imm_for_add(offset, EA_8BYTE))
11664                 {
11665                     if (lsl > 0)
11666                     {
11667                         // Generate code to set tmpReg = base + index*scale
11668                         emitIns_R_R_R_I(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum, lsl,
11669                                         INS_OPTS_LSL);
11670                     }
11671                     else // no scale
11672                     {
11673                         // Generate code to set tmpReg = base + index
11674                         emitIns_R_R_R(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum);
11675                     }
11676
11677                     noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11678
11679                     // Then load/store dataReg from/to [tmpReg + offset]
11680                     emitIns_R_R_I(ins, ldstAttr, dataReg, tmpReg, offset);
11681                 }
11682                 else // large offset
11683                 {
11684                     // First load/store tmpReg with the large offset constant
11685                     codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11686                     // Then add the base register
11687                     //      rd = rd + base
11688                     emitIns_R_R_R(INS_add, addType, tmpReg, tmpReg, memBase->gtRegNum);
11689
11690                     noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11691                     noway_assert(tmpReg != index->gtRegNum);
11692
11693                     // Then load/store dataReg from/to [tmpReg + index*scale]
11694                     emitIns_R_R_R_I(ins, ldstAttr, dataReg, tmpReg, index->gtRegNum, lsl, INS_OPTS_LSL);
11695                 }
11696             }
11697             else // (offset == 0)
11698             {
11699                 if (lsl > 0)
11700                 {
11701                     // Then load/store dataReg from/to [memBase + index*scale]
11702                     emitIns_R_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum, lsl, INS_OPTS_LSL);
11703                 }
11704                 else // no scale
11705                 {
11706                     // Then load/store dataReg from/to [memBase + index]
11707                     emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum);
11708                 }
11709             }
11710         }
11711         else // no Index register
11712         {
11713             if (emitIns_valid_imm_for_ldst_offset(offset, EA_SIZE(attr)))
11714             {
11715                 // Then load/store dataReg from/to [memBase + offset]
11716                 emitIns_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, offset);
11717             }
11718             else
11719             {
11720                 // We require a tmpReg to hold the offset
11721                 regNumber tmpReg = indir->GetSingleTempReg();
11722
11723                 // First load/store tmpReg with the large offset constant
11724                 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11725
11726                 // Then load/store dataReg from/to [memBase + tmpReg]
11727                 emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, tmpReg);
11728             }
11729         }
11730     }
11731     else // addr is not contained, so we evaluate it into a register
11732     {
11733         // Then load/store dataReg from/to [addrReg]
11734         emitIns_R_R(ins, ldstAttr, dataReg, addr->gtRegNum);
11735     }
11736 }
11737
11738 // The callee must call genConsumeReg() for any non-contained srcs
11739 // and genProduceReg() for any non-contained dsts.
11740
11741 regNumber emitter::emitInsBinary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src)
11742 {
11743     regNumber result = REG_NA;
11744
11745     // dst can only be a reg
11746     assert(!dst->isContained());
11747
11748     // src can be immed or reg
11749     assert(!src->isContained() || src->isContainedIntOrIImmed());
11750
11751     // find immed (if any) - it cannot be a dst
11752     GenTreeIntConCommon* intConst = nullptr;
11753     if (src->isContainedIntOrIImmed())
11754     {
11755         intConst = src->AsIntConCommon();
11756     }
11757
11758     if (intConst)
11759     {
11760         emitIns_R_I(ins, attr, dst->gtRegNum, intConst->IconValue());
11761         return dst->gtRegNum;
11762     }
11763     else
11764     {
11765         emitIns_R_R(ins, attr, dst->gtRegNum, src->gtRegNum);
11766         return dst->gtRegNum;
11767     }
11768 }
11769
11770 // The callee must call genConsumeReg() for any non-contained srcs
11771 // and genProduceReg() for any non-contained dsts.
11772
11773 regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src1, GenTree* src2)
11774 {
11775     regNumber result = REG_NA;
11776
11777     // dst can only be a reg
11778     assert(!dst->isContained());
11779
11780     // find immed (if any) - it cannot be a dst
11781     // Only one src can be an int.
11782     GenTreeIntConCommon* intConst  = nullptr;
11783     GenTree*             nonIntReg = nullptr;
11784
11785     if (varTypeIsFloating(dst))
11786     {
11787         // src1 can only be a reg
11788         assert(!src1->isContained());
11789         // src2 can only be a reg
11790         assert(!src2->isContained());
11791     }
11792     else // not floating point
11793     {
11794         // src2 can be immed or reg
11795         assert(!src2->isContained() || src2->isContainedIntOrIImmed());
11796
11797         // Check src2 first as we can always allow it to be a contained immediate
11798         if (src2->isContainedIntOrIImmed())
11799         {
11800             intConst  = src2->AsIntConCommon();
11801             nonIntReg = src1;
11802         }
11803         // Only for commutative operations do we check src1 and allow it to be a contained immediate
11804         else if (dst->OperIsCommutative())
11805         {
11806             // src1 can be immed or reg
11807             assert(!src1->isContained() || src1->isContainedIntOrIImmed());
11808
11809             // Check src1 and allow it to be a contained immediate
11810             if (src1->isContainedIntOrIImmed())
11811             {
11812                 assert(!src2->isContainedIntOrIImmed());
11813                 intConst  = src1->AsIntConCommon();
11814                 nonIntReg = src2;
11815             }
11816         }
11817         else
11818         {
11819             // src1 can only be a reg
11820             assert(!src1->isContained());
11821         }
11822     }
11823
11824     bool isMulOverflow = false;
11825     if (dst->gtOverflowEx())
11826     {
11827         if ((ins == INS_add) || (ins == INS_adds))
11828         {
11829             ins = INS_adds;
11830         }
11831         else if ((ins == INS_sub) || (ins == INS_subs))
11832         {
11833             ins = INS_subs;
11834         }
11835         else if (ins == INS_mul)
11836         {
11837             isMulOverflow = true;
11838             assert(intConst == nullptr); // overflow format doesn't support an int constant operand
11839         }
11840         else
11841         {
11842             assert(!"Invalid ins for overflow check");
11843         }
11844     }
11845     if (intConst != nullptr)
11846     {
11847         emitIns_R_R_I(ins, attr, dst->gtRegNum, nonIntReg->gtRegNum, intConst->IconValue());
11848     }
11849     else
11850     {
11851         if (isMulOverflow)
11852         {
11853             regNumber extraReg = dst->GetSingleTempReg();
11854             assert(extraReg != dst->gtRegNum);
11855
11856             if ((dst->gtFlags & GTF_UNSIGNED) != 0)
11857             {
11858                 if (attr == EA_4BYTE)
11859                 {
11860                     // Compute 8 byte results from 4 byte by 4 byte multiplication.
11861                     emitIns_R_R_R(INS_umull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11862
11863                     // Get the high result by shifting dst.
11864                     emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11865                 }
11866                 else
11867                 {
11868                     assert(attr == EA_8BYTE);
11869                     // Compute the high result.
11870                     emitIns_R_R_R(INS_umulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11871
11872                     // Now multiply without skewing the high result.
11873                     emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11874                 }
11875
11876                 // zero-sign bit comparison to detect overflow.
11877                 emitIns_R_I(INS_cmp, attr, extraReg, 0);
11878             }
11879             else
11880             {
11881                 int bitShift = 0;
11882                 if (attr == EA_4BYTE)
11883                 {
11884                     // Compute 8 byte results from 4 byte by 4 byte multiplication.
11885                     emitIns_R_R_R(INS_smull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11886
11887                     // Get the high result by shifting dst.
11888                     emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11889
11890                     bitShift = 31;
11891                 }
11892                 else
11893                 {
11894                     assert(attr == EA_8BYTE);
11895                     // Save the high result in a temporary register.
11896                     emitIns_R_R_R(INS_smulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11897
11898                     // Now multiply without skewing the high result.
11899                     emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11900
11901                     bitShift = 63;
11902                 }
11903
11904                 // Sign bit comparison to detect overflow.
11905                 emitIns_R_R_I(INS_cmp, attr, extraReg, dst->gtRegNum, bitShift, INS_OPTS_ASR);
11906             }
11907         }
11908         else
11909         {
11910             // We can just multiply.
11911             emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11912         }
11913     }
11914
11915     if (dst->gtOverflowEx())
11916     {
11917         assert(!varTypeIsFloating(dst));
11918         codeGen->genCheckOverflow(dst);
11919     }
11920
11921     return dst->gtRegNum;
11922 }
11923
11924 #endif // defined(_TARGET_ARM64_)