[Arm64] Add basic ARMv8.1 Atomics
[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     assert(!emitIsTinyInsDsc(id));
93
94     if (emitIsScnsInsDsc(id))
95         return SMALL_IDSC_SIZE;
96
97     assert((unsigned)id->idInsFmt() < emitFmtCount);
98
99     ID_OPS idOp      = (ID_OPS)emitFmtToOps[id->idInsFmt()];
100     bool   isCallIns = (id->idIns() == INS_bl) || (id->idIns() == INS_blr) || (id->idIns() == INS_b_tail) ||
101                      (id->idIns() == INS_br_tail);
102     bool maybeCallIns = (id->idIns() == INS_b) || (id->idIns() == INS_br);
103
104     switch (idOp)
105     {
106         case ID_OP_NONE:
107             break;
108
109         case ID_OP_JMP:
110             return sizeof(instrDescJmp);
111
112         case ID_OP_CALL:
113             assert(isCallIns || maybeCallIns);
114             if (id->idIsLargeCall())
115             {
116                 /* Must be a "fat" call descriptor */
117                 return sizeof(instrDescCGCA);
118             }
119             else
120             {
121                 assert(!id->idIsLargeDsp());
122                 assert(!id->idIsLargeCns());
123                 return sizeof(instrDesc);
124             }
125             break;
126
127         default:
128             NO_WAY("unexpected instruction descriptor format");
129             break;
130     }
131
132     if (id->idIsLargeCns())
133     {
134         if (id->idIsLargeDsp())
135             return sizeof(instrDescCnsDsp);
136         else
137             return sizeof(instrDescCns);
138     }
139     else
140     {
141         if (id->idIsLargeDsp())
142             return sizeof(instrDescDsp);
143         else
144             return sizeof(instrDesc);
145     }
146 }
147
148 #ifdef DEBUG
149 /*****************************************************************************
150  *
151  *  The following called for each recorded instruction -- use for debugging.
152  */
153 void emitter::emitInsSanityCheck(instrDesc* id)
154 {
155     /* What instruction format have we got? */
156
157     switch (id->idInsFmt())
158     {
159         instruction ins;
160         emitAttr    elemsize;
161         emitAttr    datasize;
162         emitAttr    dstsize;
163         emitAttr    srcsize;
164         ssize_t     imm;
165         unsigned    immShift;
166         ssize_t     index;
167         ssize_t     index2;
168
169         case IF_BI_0A: // BI_0A   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
170             break;
171
172         case IF_BI_0B: // BI_0B   ......iiiiiiiiii iiiiiiiiiiii....               simm19:00
173             break;
174
175         case IF_LARGEJMP:
176         case IF_LARGEADR:
177         case IF_LARGELDC:
178             break;
179
180         case IF_BI_0C: // BI_0C   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
181             break;
182
183         case IF_BI_1A: // BI_1A   ......iiiiiiiiii iiiiiiiiiiittttt      Rt       simm19:00
184             assert(isValidGeneralDatasize(id->idOpSize()));
185             assert(isGeneralRegister(id->idReg1()));
186             break;
187
188         case IF_BI_1B: // BI_1B   B.......bbbbbiii iiiiiiiiiiittttt      Rt imm6, simm14:00
189             assert(isValidGeneralDatasize(id->idOpSize()));
190             assert(isGeneralRegister(id->idReg1()));
191             assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
192             break;
193
194         case IF_BR_1A: // BR_1A   ................ ......nnnnn.....         Rn
195             assert(isGeneralRegister(id->idReg1()));
196             break;
197
198         case IF_BR_1B: // BR_1B   ................ ......nnnnn.....         Rn
199             assert(isGeneralRegister(id->idReg3()));
200             break;
201
202         case IF_LS_1A: // LS_1A   .X......iiiiiiii iiiiiiiiiiittttt      Rt    PC imm(1MB)
203             assert(isGeneralRegister(id->idReg1()) || isVectorRegister(id->idReg1()));
204             assert(insOptsNone(id->idInsOpt()));
205             break;
206
207         case IF_LS_2A:                                // LS_2A   .X.......X...... ......nnnnnttttt      Rt Rn
208             assert(isIntegerRegister(id->idReg1()) || // ZR
209                    isVectorRegister(id->idReg1()));
210             assert(isIntegerRegister(id->idReg2())); // SP
211             assert(emitGetInsSC(id) == 0);
212             assert(insOptsNone(id->idInsOpt()));
213             break;
214
215         case IF_LS_2B: // LS_2B   .X.......Xiiiiii iiiiiinnnnnttttt      Rt Rn    imm(0-4095)
216             assert(isIntegerRegister(id->idReg1()) || // ZR
217                    isVectorRegister(id->idReg1()));
218             assert(isIntegerRegister(id->idReg2())); // SP
219             assert(isValidUimm12(emitGetInsSC(id)));
220             assert(insOptsNone(id->idInsOpt()));
221             break;
222
223         case IF_LS_2C: // LS_2C   .X.......X.iiiii iiiiPPnnnnnttttt      Rt Rn    imm(-256..+255) no/pre/post inc
224             assert(isIntegerRegister(id->idReg1()) || // ZR
225                    isVectorRegister(id->idReg1()));
226             assert(isIntegerRegister(id->idReg2())); // SP
227             assert(emitGetInsSC(id) >= -0x100);
228             assert(emitGetInsSC(id) < 0x100);
229             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
230             break;
231
232         case IF_LS_3A: // LS_3A   .X.......X.mmmmm oooS..nnnnnttttt      Rt Rn Rm ext(Rm) LSL {}
233             assert(isIntegerRegister(id->idReg1()) || // ZR
234                    isVectorRegister(id->idReg1()));
235             assert(isIntegerRegister(id->idReg2())); // SP
236             if (id->idIsLclVar())
237             {
238                 assert(isGeneralRegister(codeGen->rsGetRsvdReg()));
239             }
240             else
241             {
242                 assert(isGeneralRegister(id->idReg3()));
243             }
244             assert(insOptsLSExtend(id->idInsOpt()));
245             break;
246
247         case IF_LS_3B: // LS_3B   X............... .aaaaannnnnttttt      Rt Ra Rn
248             assert((isValidGeneralDatasize(id->idOpSize()) && isIntegerRegister(id->idReg1())) ||
249                    (isValidVectorLSPDatasize(id->idOpSize()) && isVectorRegister(id->idReg1())));
250             assert(isIntegerRegister(id->idReg1()) || // ZR
251                    isVectorRegister(id->idReg1()));
252             assert(isIntegerRegister(id->idReg2()) || // ZR
253                    isVectorRegister(id->idReg2()));
254             assert(isIntegerRegister(id->idReg3())); // SP
255             assert(emitGetInsSC(id) == 0);
256             assert(insOptsNone(id->idInsOpt()));
257             break;
258
259         case IF_LS_3C: // LS_3C   X.........iiiiii iaaaaannnnnttttt      Rt Ra Rn imm(im7,sh)
260             assert((isValidGeneralDatasize(id->idOpSize()) && isIntegerRegister(id->idReg1())) ||
261                    (isValidVectorLSPDatasize(id->idOpSize()) && isVectorRegister(id->idReg1())));
262             assert(isIntegerRegister(id->idReg1()) || // ZR
263                    isVectorRegister(id->idReg1()));
264             assert(isIntegerRegister(id->idReg2()) || // ZR
265                    isVectorRegister(id->idReg2()));
266             assert(isIntegerRegister(id->idReg3())); // SP
267             assert(emitGetInsSC(id) >= -0x40);
268             assert(emitGetInsSC(id) < 0x40);
269             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
270             break;
271
272         case IF_LS_3D: // LS_3D   .X.......X.mmmmm ......nnnnnttttt      Wm Rt Rn
273             assert(isIntegerRegister(id->idReg1()));
274             assert(isIntegerRegister(id->idReg2()));
275             assert(isIntegerRegister(id->idReg3()));
276             assert(emitGetInsSC(id) == 0);
277             assert(!id->idIsLclVar());
278             assert(insOptsNone(id->idInsOpt()));
279             break;
280
281         case IF_LS_3E: // LS_3E   .X.........mmmmm ......nnnnnttttt      Rm Rt Rn ARMv8.1 LSE Atomics
282             assert(isIntegerRegister(id->idReg1()));
283             assert(isIntegerRegister(id->idReg2()));
284             assert(isIntegerRegister(id->idReg3()));
285             assert(emitGetInsSC(id) == 0);
286             assert(!id->idIsLclVar());
287             assert(insOptsNone(id->idInsOpt()));
288             break;
289
290         case IF_DI_1A: // DI_1A   X.......shiiiiii iiiiiinnnnn.....         Rn    imm(i12,sh)
291             assert(isValidGeneralDatasize(id->idOpSize()));
292             assert(isGeneralRegister(id->idReg1()));
293             assert(isValidUimm12(emitGetInsSC(id)));
294             assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
295             break;
296
297         case IF_DI_1B: // DI_1B   X........hwiiiii iiiiiiiiiiiddddd      Rd       imm(i16,hw)
298             assert(isValidGeneralDatasize(id->idOpSize()));
299             assert(isGeneralRegister(id->idReg1()));
300             assert(isValidImmHWVal(emitGetInsSC(id), id->idOpSize()));
301             break;
302
303         case IF_DI_1C: // DI_1C   X........Nrrrrrr ssssssnnnnn.....         Rn    imm(N,r,s)
304             assert(isValidGeneralDatasize(id->idOpSize()));
305             assert(isGeneralRegister(id->idReg1()));
306             assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
307             break;
308
309         case IF_DI_1D: // DI_1D   X........Nrrrrrr ssssss.....ddddd      Rd       imm(N,r,s)
310             assert(isValidGeneralDatasize(id->idOpSize()));
311             assert(isIntegerRegister(id->idReg1())); // SP
312             assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
313             break;
314
315         case IF_DI_1E: // DI_1E   .ii.....iiiiiiii iiiiiiiiiiiddddd      Rd       simm21
316             assert(isGeneralRegister(id->idReg1()));
317             break;
318
319         case IF_DI_1F: // DI_1F   X..........iiiii cccc..nnnnn.nzcv      Rn imm5  nzcv cond
320             assert(isValidGeneralDatasize(id->idOpSize()));
321             assert(isGeneralRegister(id->idReg1()));
322             assert(isValidImmCondFlagsImm5(emitGetInsSC(id)));
323             break;
324
325         case IF_DI_2A: // DI_2A   X.......shiiiiii iiiiiinnnnnddddd      Rd Rn    imm(i12,sh)
326             assert(isValidGeneralDatasize(id->idOpSize()));
327             assert(isIntegerRegister(id->idReg1())); // SP
328             assert(isIntegerRegister(id->idReg2())); // SP
329             assert(isValidUimm12(emitGetInsSC(id)));
330             assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
331             break;
332
333         case IF_DI_2B: // DI_2B   X.........Xnnnnn ssssssnnnnnddddd      Rd Rn    imm(0-63)
334             assert(isValidGeneralDatasize(id->idOpSize()));
335             assert(isGeneralRegister(id->idReg1()));
336             assert(isGeneralRegister(id->idReg2()));
337             assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
338             break;
339
340         case IF_DI_2C: // DI_2C   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imm(N,r,s)
341             assert(isValidGeneralDatasize(id->idOpSize()));
342             assert(isIntegerRegister(id->idReg1())); // SP
343             assert(isGeneralRegister(id->idReg2()));
344             assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
345             break;
346
347         case IF_DI_2D: // DI_2D   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imr, imms   (N,r,s)
348             assert(isValidGeneralDatasize(id->idOpSize()));
349             assert(isGeneralRegister(id->idReg1()));
350             assert(isGeneralRegister(id->idReg2()));
351             assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
352             break;
353
354         case IF_DR_1D: // DR_1D   X............... cccc.......ddddd      Rd       cond
355             assert(isValidGeneralDatasize(id->idOpSize()));
356             assert(isGeneralRegister(id->idReg1()));
357             assert(isValidImmCond(emitGetInsSC(id)));
358             break;
359
360         case IF_DR_2A: // DR_2A   X..........mmmmm ......nnnnn.....         Rn Rm
361             assert(isValidGeneralDatasize(id->idOpSize()));
362             assert(isGeneralRegister(id->idReg1()));
363             assert(isGeneralRegister(id->idReg2()));
364             break;
365
366         case IF_DR_2B: // DR_2B   X.......sh.mmmmm ssssssnnnnn.....         Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
367             assert(isValidGeneralDatasize(id->idOpSize()));
368             assert(isIntegerRegister(id->idReg1())); // ZR
369             assert(isGeneralRegister(id->idReg2()));
370             assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
371             if (!insOptsNone(id->idInsOpt()))
372             {
373                 if (id->idIns() == INS_tst) // tst allows ROR, cmp/cmn don't
374                 {
375                     assert(insOptsAnyShift(id->idInsOpt()));
376                 }
377                 else
378                 {
379                     assert(insOptsAluShift(id->idInsOpt()));
380                 }
381             }
382             assert(insOptsNone(id->idInsOpt()) || (emitGetInsSC(id) > 0));
383             break;
384
385         case IF_DR_2C: // DR_2C   X..........mmmmm ooosssnnnnn.....         Rn Rm ext(Rm) LSL imm(0-4)
386             assert(isValidGeneralDatasize(id->idOpSize()));
387             assert(isIntegerRegister(id->idReg1())); // SP
388             assert(isGeneralRegister(id->idReg2()));
389             assert(insOptsNone(id->idInsOpt()) || insOptsLSL(id->idInsOpt()) || insOptsAnyExtend(id->idInsOpt()));
390             assert(emitGetInsSC(id) >= 0);
391             assert(emitGetInsSC(id) <= 4);
392             if (insOptsLSL(id->idInsOpt()))
393             {
394                 assert(emitGetInsSC(id) > 0);
395             }
396             break;
397
398         case IF_DR_2D: // DR_2D   X..........nnnnn cccc..nnnnnmmmmm      Rd Rn    cond
399             assert(isValidGeneralDatasize(id->idOpSize()));
400             assert(isGeneralRegister(id->idReg1()));
401             assert(isGeneralRegister(id->idReg2()));
402             assert(isValidImmCond(emitGetInsSC(id)));
403             break;
404
405         case IF_DR_2E: // DR_2E   X..........mmmmm ...........ddddd      Rd    Rm
406             assert(isValidGeneralDatasize(id->idOpSize()));
407             assert(isGeneralRegister(id->idReg1()));
408             assert(isIntegerRegister(id->idReg2())); // ZR
409             break;
410
411         case IF_DR_2F: // DR_2F   X.......sh.mmmmm ssssss.....ddddd      Rd    Rm {LSL,LSR,ASR} imm(0-63)
412             assert(isValidGeneralDatasize(id->idOpSize()));
413             assert(isGeneralRegister(id->idReg1()));
414             assert(isGeneralRegister(id->idReg2()));
415             assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
416             assert(insOptsNone(id->idInsOpt()) || insOptsAluShift(id->idInsOpt()));
417             assert(insOptsNone(id->idInsOpt()) || (emitGetInsSC(id) > 0));
418             break;
419
420         case IF_DR_2G: // DR_2G   X............... ......nnnnnddddd      Rd    Rm
421             assert(isValidGeneralDatasize(id->idOpSize()));
422             assert(isIntegerRegister(id->idReg1())); // SP
423             assert(isIntegerRegister(id->idReg2())); // SP
424             break;
425
426         case IF_DR_2H: // DR_2H   X........X...... ......nnnnnddddd      Rd Rn
427             assert(isValidGeneralDatasize(id->idOpSize()));
428             assert(isGeneralRegister(id->idReg1()));
429             assert(isGeneralRegister(id->idReg2()));
430             break;
431
432         case IF_DR_2I: // DR_2I   X..........mmmmm cccc..nnnnn.nzcv      Rn Rm    nzcv cond
433             assert(isValidGeneralDatasize(id->idOpSize()));
434             assert(isGeneralRegister(id->idReg1()));
435             assert(isGeneralRegister(id->idReg2()));
436             assert(isValidImmCondFlags(emitGetInsSC(id)));
437             break;
438
439         case IF_DR_2J: // DR_2J   ................ ......nnnnnddddd      Sd Sn    (sha1h)
440             assert(isValidGeneralDatasize(id->idOpSize()));
441             assert(isVectorRegister(id->idReg1()));
442             assert(isVectorRegister(id->idReg2()));
443             break;
444
445         case IF_DR_3A: // DR_3A   X..........mmmmm ......nnnnnmmmmm      Rd Rn Rm
446             assert(isValidGeneralDatasize(id->idOpSize()));
447             assert(isIntegerRegister(id->idReg1())); // SP
448             assert(isIntegerRegister(id->idReg2())); // SP
449             if (id->idIsLclVar())
450             {
451                 assert(isGeneralRegister(codeGen->rsGetRsvdReg()));
452             }
453             else
454             {
455                 assert(isGeneralRegister(id->idReg3()));
456             }
457             assert(insOptsNone(id->idInsOpt()));
458             break;
459
460         case IF_DR_3B: // DR_3B   X.......sh.mmmmm ssssssnnnnnddddd      Rd Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
461             assert(isValidGeneralDatasize(id->idOpSize()));
462             assert(isGeneralRegister(id->idReg1()));
463             assert(isGeneralRegister(id->idReg2()));
464             assert(isGeneralRegister(id->idReg3()));
465             assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
466             assert(insOptsNone(id->idInsOpt()) || insOptsAnyShift(id->idInsOpt()));
467             assert(insOptsNone(id->idInsOpt()) || (emitGetInsSC(id) > 0));
468             break;
469
470         case IF_DR_3C: // DR_3C   X..........mmmmm ooosssnnnnnddddd      Rd Rn Rm ext(Rm) LSL imm(0-4)
471             assert(isValidGeneralDatasize(id->idOpSize()));
472             assert(isIntegerRegister(id->idReg1())); // SP
473             assert(isIntegerRegister(id->idReg2())); // SP
474             assert(isGeneralRegister(id->idReg3()));
475             assert(insOptsNone(id->idInsOpt()) || insOptsLSL(id->idInsOpt()) || insOptsAnyExtend(id->idInsOpt()));
476             assert(emitGetInsSC(id) >= 0);
477             assert(emitGetInsSC(id) <= 4);
478             if (insOptsLSL(id->idInsOpt()))
479             {
480                 assert((emitGetInsSC(id) > 0) ||
481                        (id->idReg2() == REG_ZR)); // REG_ZR encodes SP and we allow a shift of zero
482             }
483             break;
484
485         case IF_DR_3D: // DR_3D   X..........mmmmm cccc..nnnnnmmmmm      Rd Rn Rm cond
486             assert(isValidGeneralDatasize(id->idOpSize()));
487             assert(isGeneralRegister(id->idReg1()));
488             assert(isGeneralRegister(id->idReg2()));
489             assert(isGeneralRegister(id->idReg3()));
490             assert(isValidImmCond(emitGetInsSC(id)));
491             break;
492
493         case IF_DR_3E: // DR_3E   X........X.mmmmm ssssssnnnnnddddd      Rd Rn Rm imm(0-63)
494             assert(isValidGeneralDatasize(id->idOpSize()));
495             assert(isGeneralRegister(id->idReg1()));
496             assert(isGeneralRegister(id->idReg2()));
497             assert(isGeneralRegister(id->idReg3()));
498             assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
499             assert(insOptsNone(id->idInsOpt()));
500             break;
501
502         case IF_DR_4A: // DR_4A   X..........mmmmm .aaaaannnnnddddd      Rd Rn Rm Ra
503             assert(isValidGeneralDatasize(id->idOpSize()));
504             assert(isGeneralRegister(id->idReg1()));
505             assert(isGeneralRegister(id->idReg2()));
506             assert(isGeneralRegister(id->idReg3()));
507             assert(isGeneralRegister(id->idReg4()));
508             break;
509
510         case IF_DV_1A: // DV_1A   .........X.iiiii iii........ddddd      Vd imm8    (fmov - immediate scalar)
511             assert(insOptsNone(id->idInsOpt()));
512             elemsize = id->idOpSize();
513             assert(isValidVectorElemsizeFloat(elemsize));
514             assert(isVectorRegister(id->idReg1()));
515             assert(isValidUimm8(emitGetInsSC(id)));
516             break;
517
518         case IF_DV_1B: // DV_1B   .QX..........iii cmod..iiiiiddddd      Vd imm8    (immediate vector)
519             ins      = id->idIns();
520             imm      = emitGetInsSC(id) & 0x0ff;
521             immShift = (emitGetInsSC(id) & 0x700) >> 8;
522             assert(immShift >= 0);
523             datasize = id->idOpSize();
524             assert(isValidVectorDatasize(datasize));
525             assert(isValidArrangement(datasize, id->idInsOpt()));
526             elemsize = optGetElemsize(id->idInsOpt());
527             if (ins == INS_fmov)
528             {
529                 assert(isValidVectorElemsizeFloat(elemsize));
530                 assert(id->idInsOpt() != INS_OPTS_1D); // Reserved encoding
531                 assert(immShift == 0);
532             }
533             else
534             {
535                 assert(isValidVectorElemsize(elemsize));
536                 assert((immShift != 4) && (immShift != 7)); // always invalid values
537                 if (ins != INS_movi)                        // INS_mvni, INS_orr, INS_bic
538                 {
539                     assert((elemsize != EA_1BYTE) && (elemsize != EA_8BYTE)); // only H or S
540                     if (elemsize == EA_2BYTE)
541                     {
542                         assert(immShift < 2);
543                     }
544                     else // (elemsize == EA_4BYTE)
545                     {
546                         if (ins != INS_mvni)
547                         {
548                             assert(immShift < 4);
549                         }
550                     }
551                 }
552             }
553             assert(isVectorRegister(id->idReg1()));
554             assert(isValidUimm8(imm));
555             break;
556
557         case IF_DV_1C: // DV_1C   .........X...... ......nnnnn.....      Vn #0.0    (fcmp - with zero)
558             assert(insOptsNone(id->idInsOpt()));
559             elemsize = id->idOpSize();
560             assert(isValidVectorElemsizeFloat(elemsize));
561             assert(isVectorRegister(id->idReg1()));
562             break;
563
564         case IF_DV_2A: // DV_2A   .Q.......X...... ......nnnnnddddd      Vd Vn      (fabs, fcvt - vector)
565         case IF_DV_2M: // DV_2M   .Q......XX...... ......nnnnnddddd      Vd Vn      (abs, neg   - vector)
566         case IF_DV_2P: // DV_2P   ................ ......nnnnnddddd      Vd Vn      (aes*, sha1su1)
567             assert(isValidVectorDatasize(id->idOpSize()));
568             assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
569             assert(isVectorRegister(id->idReg1()));
570             assert(isVectorRegister(id->idReg2()));
571             break;
572
573         case IF_DV_2N: // DV_2N   .........iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - scalar)
574             assert(id->idOpSize() == EA_8BYTE);
575             assert(insOptsNone(id->idInsOpt()));
576             assert(isVectorRegister(id->idReg1()));
577             assert(isVectorRegister(id->idReg2()));
578             assert(isValidImmShift(emitGetInsSC(id), EA_8BYTE));
579             break;
580
581         case IF_DV_2O: // DV_2O   .Q.......iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - vector)
582             assert(isValidVectorDatasize(id->idOpSize()));
583             assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
584             assert(isVectorRegister(id->idReg1()));
585             assert(isVectorRegister(id->idReg2()));
586             elemsize = optGetElemsize(id->idInsOpt());
587             assert(isValidImmShift(emitGetInsSC(id), elemsize));
588             break;
589
590         case IF_DV_2B: // DV_2B   .Q.........iiiii ......nnnnnddddd      Rd Vn[]  (umov/smov    - to general)
591             elemsize = id->idOpSize();
592             index    = emitGetInsSC(id);
593             assert(insOptsNone(id->idInsOpt()));
594             assert(isValidVectorIndex(EA_16BYTE, elemsize, index));
595             assert(isValidVectorElemsize(elemsize));
596             assert(isGeneralRegister(id->idReg1()));
597             assert(isVectorRegister(id->idReg2()));
598             break;
599
600         case IF_DV_2C: // DV_2C   .Q.........iiiii ......nnnnnddddd      Vd Rn    (dup/ins - vector from general)
601             if (id->idIns() == INS_dup)
602             {
603                 datasize = id->idOpSize();
604                 assert(isValidVectorDatasize(datasize));
605                 assert(isValidArrangement(datasize, id->idInsOpt()));
606                 elemsize = optGetElemsize(id->idInsOpt());
607             }
608             else // INS_ins
609             {
610                 datasize = EA_16BYTE;
611                 elemsize = id->idOpSize();
612                 assert(isValidVectorElemsize(elemsize));
613             }
614             assert(isVectorRegister(id->idReg1()));
615             assert(isGeneralRegisterOrZR(id->idReg2()));
616             break;
617
618         case IF_DV_2D: // DV_2D   .Q.........iiiii ......nnnnnddddd      Vd Vn[]  (dup - vector)
619             datasize = id->idOpSize();
620             assert(isValidVectorDatasize(datasize));
621             assert(isValidArrangement(datasize, id->idInsOpt()));
622             elemsize = optGetElemsize(id->idInsOpt());
623             index    = emitGetInsSC(id);
624             assert(isValidVectorIndex(datasize, elemsize, index));
625             assert(isVectorRegister(id->idReg1()));
626             assert(isVectorRegister(id->idReg2()));
627             break;
628
629         case IF_DV_2E: // DV_2E   ...........iiiii ......nnnnnddddd      Vd Vn[]  (dup - scalar)
630             elemsize = id->idOpSize();
631             index    = emitGetInsSC(id);
632             assert(isValidVectorIndex(EA_16BYTE, elemsize, index));
633             assert(isValidVectorElemsize(elemsize));
634             assert(isVectorRegister(id->idReg1()));
635             assert(isVectorRegister(id->idReg2()));
636             break;
637
638         case IF_DV_2F: // DV_2F   ...........iiiii .jjjj.nnnnnddddd      Vd[] Vn[] (ins - element)
639             imm      = emitGetInsSC(id);
640             index    = (imm >> 4) & 0xf;
641             index2   = imm & 0xf;
642             elemsize = id->idOpSize();
643             assert(isValidVectorElemsize(elemsize));
644             assert(isValidVectorIndex(EA_16BYTE, elemsize, index));
645             assert(isValidVectorIndex(EA_16BYTE, elemsize, index2));
646             assert(isVectorRegister(id->idReg1()));
647             assert(isVectorRegister(id->idReg2()));
648             break;
649
650         case IF_DV_2L: // DV_2L   ........XX...... ......nnnnnddddd      Vd Vn      (abs, neg - scalar)
651             assert(id->idOpSize() == EA_8BYTE); // only type D is supported
652             __fallthrough;
653
654         case IF_DV_2G: // DV_2G   .........X...... ......nnnnnddddd      Vd Vn      (fmov, fcvtXX - register)
655         case IF_DV_2K: // DV_2K   .........X.mmmmm ......nnnnn.....      Vn Vm      (fcmp)
656             assert(insOptsNone(id->idInsOpt()));
657             assert(isValidVectorElemsizeFloat(id->idOpSize()));
658             assert(isVectorRegister(id->idReg1()));
659             assert(isVectorRegister(id->idReg2()));
660             break;
661
662         case IF_DV_2H: // DV_2H   X........X...... ......nnnnnddddd      Rd Vn      (fmov/fcvtXX - to general)
663             assert(insOptsConvertFloatToInt(id->idInsOpt()));
664             dstsize = optGetDstsize(id->idInsOpt());
665             srcsize = optGetSrcsize(id->idInsOpt());
666             assert(isValidGeneralDatasize(dstsize));
667             assert(isValidVectorElemsizeFloat(srcsize));
668             assert(dstsize == id->idOpSize());
669             assert(isGeneralRegister(id->idReg1()));
670             assert(isVectorRegister(id->idReg2()));
671             break;
672
673         case IF_DV_2I: // DV_2I   X........X...... ......nnnnnddddd      Vd Rn      (fmov/Xcvtf - from general)
674             assert(insOptsConvertIntToFloat(id->idInsOpt()));
675             dstsize = optGetDstsize(id->idInsOpt());
676             srcsize = optGetSrcsize(id->idInsOpt());
677             assert(isValidGeneralDatasize(srcsize));
678             assert(isValidVectorElemsizeFloat(dstsize));
679             assert(dstsize == id->idOpSize());
680             assert(isVectorRegister(id->idReg1()));
681             assert(isGeneralRegister(id->idReg2()));
682             break;
683
684         case IF_DV_2J: // DV_2J   ........SS.....D D.....nnnnnddddd      Vd Vn      (fcvt)
685             assert(insOptsConvertFloatToFloat(id->idInsOpt()));
686             dstsize = optGetDstsize(id->idInsOpt());
687             srcsize = optGetSrcsize(id->idInsOpt());
688             assert(isValidVectorFcvtsize(srcsize));
689             assert(isValidVectorFcvtsize(dstsize));
690             assert(dstsize == id->idOpSize());
691             assert(isVectorRegister(id->idReg1()));
692             assert(isVectorRegister(id->idReg2()));
693             break;
694
695         case IF_DV_3A: // DV_3A   .Q......XX.mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
696             assert(isValidVectorDatasize(id->idOpSize()));
697             assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
698             assert(isVectorRegister(id->idReg1()));
699             assert(isVectorRegister(id->idReg2()));
700             assert(isVectorRegister(id->idReg3()));
701             elemsize = optGetElemsize(id->idInsOpt());
702             ins      = id->idIns();
703             if (ins == INS_mul)
704             {
705                 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
706             }
707             else if (ins == INS_pmul)
708             {
709                 assert(elemsize == EA_1BYTE); // only supports 8B or 16B
710             }
711             break;
712
713         case IF_DV_3AI: // DV_3AI  .Q......XXLMmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector by elem)
714             assert(isValidVectorDatasize(id->idOpSize()));
715             assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
716             assert(isVectorRegister(id->idReg1()));
717             assert(isVectorRegister(id->idReg2()));
718             assert(isVectorRegister(id->idReg3()));
719             elemsize = optGetElemsize(id->idInsOpt());
720             assert(isValidVectorIndex(EA_16BYTE, elemsize, emitGetInsSC(id)));
721             // Only has encodings for H or S elemsize
722             assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE));
723             break;
724
725         case IF_DV_3B: // DV_3B   .Q.......X.mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
726             assert(isValidVectorDatasize(id->idOpSize()));
727             assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
728             assert(isVectorRegister(id->idReg1()));
729             assert(isVectorRegister(id->idReg2()));
730             assert(isVectorRegister(id->idReg3()));
731             break;
732
733         case IF_DV_3BI: // DV_3BI  .Q.......XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector by elem)
734             assert(isValidVectorDatasize(id->idOpSize()));
735             assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
736             assert(isVectorRegister(id->idReg1()));
737             assert(isVectorRegister(id->idReg2()));
738             assert(isVectorRegister(id->idReg3()));
739             elemsize = optGetElemsize(id->idInsOpt());
740             assert(isValidVectorIndex(id->idOpSize(), elemsize, emitGetInsSC(id)));
741             break;
742
743         case IF_DV_3C: // DV_3C   .Q.........mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
744             assert(isValidVectorDatasize(id->idOpSize()));
745             assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
746             assert(isVectorRegister(id->idReg1()));
747             assert(isVectorRegister(id->idReg2()));
748             assert(isVectorRegister(id->idReg3()));
749             break;
750
751         case IF_DV_3D: // DV_3D   .........X.mmmmm ......nnnnnddddd      Vd Vn Vm   (scalar)
752             assert(isValidScalarDatasize(id->idOpSize()));
753             assert(insOptsNone(id->idInsOpt()));
754             assert(isVectorRegister(id->idReg1()));
755             assert(isVectorRegister(id->idReg2()));
756             assert(isVectorRegister(id->idReg3()));
757             break;
758
759         case IF_DV_3DI: // DV_3DI  .........XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (scalar by elem)
760             assert(isValidScalarDatasize(id->idOpSize()));
761             assert(insOptsNone(id->idInsOpt()));
762             assert(isVectorRegister(id->idReg1()));
763             assert(isVectorRegister(id->idReg2()));
764             assert(isVectorRegister(id->idReg3()));
765             elemsize = id->idOpSize();
766             assert(isValidVectorIndex(EA_16BYTE, elemsize, emitGetInsSC(id)));
767             break;
768
769         case IF_DV_3E: // DV_3E   ...........mmmmm ......nnnnnddddd      Vd Vn Vm  (scalar)
770             assert(insOptsNone(id->idInsOpt()));
771             assert(id->idOpSize() == EA_8BYTE);
772             assert(isVectorRegister(id->idReg1()));
773             assert(isVectorRegister(id->idReg2()));
774             assert(isVectorRegister(id->idReg3()));
775             break;
776
777         case IF_DV_3F: // DV_3F   ...........mmmmm ......nnnnnddddd      Vd Vn Vm
778             assert(isValidVectorDatasize(id->idOpSize()));
779             assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
780             assert(isVectorRegister(id->idReg1()));
781             assert(isVectorRegister(id->idReg2()));
782             assert(isVectorRegister(id->idReg3()));
783             break;
784
785         case IF_DV_4A: // DR_4A   .........X.mmmmm .aaaaannnnnddddd      Rd Rn Rm Ra (scalar)
786             assert(isValidGeneralDatasize(id->idOpSize()));
787             assert(isVectorRegister(id->idReg1()));
788             assert(isVectorRegister(id->idReg2()));
789             assert(isVectorRegister(id->idReg3()));
790             assert(isVectorRegister(id->idReg4()));
791             break;
792
793         case IF_SN_0A: // SN_0A   ................ ................
794         case IF_SI_0A: // SI_0A   ...........iiiii iiiiiiiiiii.....               imm16
795         case IF_SI_0B: // SI_0B   ................ ....bbbb........               imm4 - barrier
796             break;
797
798         default:
799             printf("unexpected format %s\n", emitIfName(id->idInsFmt()));
800             assert(!"Unexpected format");
801             break;
802     }
803 }
804 #endif // DEBUG
805
806 bool emitter::emitInsMayWriteToGCReg(instrDesc* id)
807 {
808     instruction ins = id->idIns();
809     insFormat   fmt = id->idInsFmt();
810
811     switch (fmt)
812     {
813
814         // These are the formats with "destination" registers:
815
816         case IF_DI_1B: // DI_1B   X........hwiiiii iiiiiiiiiiiddddd      Rd       imm(i16,hw)
817         case IF_DI_1D: // DI_1D   X........Nrrrrrr ssssss.....ddddd      Rd       imm(N,r,s)
818         case IF_DI_1E: // DI_1E   .ii.....iiiiiiii iiiiiiiiiiiddddd      Rd       simm21
819
820         case IF_DI_2A: // DI_2A   X.......shiiiiii iiiiiinnnnnddddd      Rd Rn    imm(i12,sh)
821         case IF_DI_2B: // DI_2B   X.........Xnnnnn ssssssnnnnnddddd      Rd Rn    imm(0-63)
822         case IF_DI_2C: // DI_2C   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imm(N,r,s)
823         case IF_DI_2D: // DI_2D   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imr, imms   (N,r,s)
824
825         case IF_DR_1D: // DR_1D   X............... cccc.......ddddd      Rd       cond
826
827         case IF_DR_2D: // DR_2D   X..........nnnnn cccc..nnnnnddddd      Rd Rn    cond
828         case IF_DR_2E: // DR_2E   X..........mmmmm ...........ddddd      Rd    Rm
829         case IF_DR_2F: // DR_2F   X.......sh.mmmmm ssssss.....ddddd      Rd    Rm {LSL,LSR,ASR} imm(0-63)
830         case IF_DR_2G: // DR_2G   X............... ......nnnnnddddd      Rd Rn
831         case IF_DR_2H: // DR_2H   X........X...... ......nnnnnddddd      Rd Rn
832
833         case IF_DR_3A: // DR_3A   X..........mmmmm ......nnnnnddddd      Rd Rn Rm
834         case IF_DR_3B: // DR_3B   X.......sh.mmmmm ssssssnnnnnddddd      Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
835         case IF_DR_3C: // DR_3C   X..........mmmmm xxxsssnnnnnddddd      Rd Rn Rm ext(Rm) LSL imm(0-4)
836         case IF_DR_3D: // DR_3D   X..........mmmmm cccc..nnnnnddddd      Rd Rn Rm cond
837         case IF_DR_3E: // DR_3E   X........X.mmmmm ssssssnnnnnddddd      Rd Rn Rm imm(0-63)
838         case IF_DV_3F: // DV_3F   ...........mmmmm ......nnnnnddddd      Vd Vn Vm (vector) - Vd both source and dest
839
840         case IF_DR_4A: // DR_4A   X..........mmmmm .aaaaannnnnddddd      Rd Rn Rm Ra
841
842         case IF_DV_2B: // DV_2B   .Q.........iiiii ......nnnnnddddd      Rd Vn[]    (umov - to general)
843         case IF_DV_2H: // DV_2H   X........X...... ......nnnnnddddd      Rd Vn      (fmov - to general)
844
845             return true;
846
847         case IF_DV_2C: // DV_2C   .Q.........iiiii ......nnnnnddddd      Vd Rn      (dup/ins - vector from general)
848         case IF_DV_2D: // DV_2D   .Q.........iiiii ......nnnnnddddd      Vd Vn[]    (dup - vector)
849         case IF_DV_2E: // DV_2E   ...........iiiii ......nnnnnddddd      Vd Vn[]    (dup - scalar)
850         case IF_DV_2F: // DV_2F   ...........iiiii .jjjj.nnnnnddddd      Vd[] Vn[]  (ins - element)
851         case IF_DV_2G: // DV_2G   .........X...... ......nnnnnddddd      Vd Vn      (fmov, fcvtXX - register)
852         case IF_DV_2I: // DV_2I   X........X...... ......nnnnnddddd      Vd Rn      (fmov - from general)
853         case IF_DV_2J: // DV_2J   ........SS.....D D.....nnnnnddddd      Vd Vn      (fcvt)
854         case IF_DV_2K: // DV_2K   .........X.mmmmm ......nnnnn.....      Vn Vm      (fcmp)
855         case IF_DV_2L: // DV_2L   ........XX...... ......nnnnnddddd      Vd Vn      (abs, neg - scalar)
856         case IF_DV_2M: // DV_2M   .Q......XX...... ......nnnnnddddd      Vd Vn      (abs, neg - vector)
857         case IF_DV_2P: // DV_2P   ................ ......nnnnnddddd      Vd Vn      (aes*, sha1su1) - Vd both source and
858                        // destination
859
860         case IF_DV_3A:  // DV_3A   .Q......XX.mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
861         case IF_DV_3AI: // DV_3AI  .Q......XXLMmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector)
862         case IF_DV_3B:  // DV_3B   .Q.......X.mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
863         case IF_DV_3BI: // DV_3BI  .Q.......XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector by elem)
864         case IF_DV_3C:  // DV_3C   .Q.........mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
865         case IF_DV_3D:  // DV_3D   .........X.mmmmm ......nnnnnddddd      Vd Vn Vm   (scalar)
866         case IF_DV_3DI: // DV_3DI  .........XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (scalar by elem)
867         case IF_DV_3E:  // DV_3E   ...........mmmmm ......nnnnnddddd      Vd Vn Vm   (scalar)
868         case IF_DV_4A:  // DV_4A   .........X.mmmmm .aaaaannnnnddddd      Vd Va Vn Vm (scalar)
869             // Tracked GC pointers cannot be placed into the SIMD registers.
870             return false;
871
872         // These are the load/store formats with "target" registers:
873
874         case IF_LS_1A: // LS_1A   XX...V..iiiiiiii iiiiiiiiiiittttt      Rt    PC imm(1MB)
875         case IF_LS_2A: // LS_2A   .X.......X...... ......nnnnnttttt      Rt Rn
876         case IF_LS_2B: // LS_2B   .X.......Xiiiiii iiiiiinnnnnttttt      Rt Rn    imm(0-4095)
877         case IF_LS_2C: // LS_2C   .X.......X.iiiii iiiiP.nnnnnttttt      Rt Rn    imm(-256..+255) pre/post inc
878         case IF_LS_3A: // LS_3A   .X.......X.mmmmm xxxS..nnnnnttttt      Rt Rn Rm ext(Rm) LSL {}
879         case IF_LS_3B: // LS_3B   X............... .aaaaannnnnttttt      Rt Ra Rn
880         case IF_LS_3C: // LS_3C   X.........iiiiii iaaaaannnnnttttt      Rt Ra Rn imm(im7,sh)
881         case IF_LS_3D: // LS_3D   .X.......X.mmmmm ......nnnnnttttt      Wm Rt Rn
882
883             // For the Store instructions the "target" register is actually a "source" value
884
885             if (emitInsIsStore(ins))
886             {
887                 return false;
888             }
889             else
890             {
891                 assert(emitInsIsLoad(ins));
892                 return true;
893             }
894
895         case IF_LS_3E: // LS_3E   .X.........mmmmm ......nnnnnttttt      Rm Rt Rn ARMv8.1 LSE Atomics
896             // ARMv8.1 Atomics
897             assert(emitInsIsStore(ins));
898             assert(emitInsIsLoad(ins));
899             return true;
900
901         default:
902             return false;
903     }
904 }
905
906 bool emitter::emitInsWritesToLclVarStackLoc(instrDesc* id)
907 {
908     if (!id->idIsLclVar())
909         return false;
910
911     instruction ins = id->idIns();
912
913     // This list is related to the list of instructions used to store local vars in emitIns_S_R().
914     // We don't accept writing to float local vars.
915
916     switch (ins)
917     {
918         case INS_strb:
919         case INS_strh:
920         case INS_str:
921         case INS_stur:
922         case INS_sturb:
923         case INS_sturh:
924             return true;
925         default:
926             return false;
927     }
928 }
929
930 bool emitter::emitInsWritesToLclVarStackLocPair(instrDesc* id)
931 {
932     if (!id->idIsLclVar())
933         return false;
934
935     instruction ins = id->idIns();
936
937     // This list is related to the list of instructions used to store local vars in emitIns_S_S_R_R().
938     // We don't accept writing to float local vars.
939
940     switch (ins)
941     {
942         case INS_stnp:
943         case INS_stp:
944             return true;
945         default:
946             return false;
947     }
948 }
949
950 bool emitter::emitInsMayWriteMultipleRegs(instrDesc* id)
951 {
952     instruction ins = id->idIns();
953
954     switch (ins)
955     {
956         case INS_ldp:
957         case INS_ldpsw:
958         case INS_ldnp:
959             return true;
960         default:
961             return false;
962     }
963 }
964
965 // For the small loads/store instruction we adjust the size 'attr'
966 // depending upon whether we have a load or a store
967 //
968 emitAttr emitter::emitInsAdjustLoadStoreAttr(instruction ins, emitAttr attr)
969 {
970     if (EA_SIZE(attr) <= EA_4BYTE)
971     {
972         if (emitInsIsLoad(ins))
973         {
974             // The value of 'ins' encodes the size to load
975             // we use EA_8BYTE here because it is the size we will write (into dataReg)
976             // it is also required when ins is INS_ldrsw
977             //
978             attr = EA_8BYTE;
979         }
980         else
981         {
982             assert(emitInsIsStore(ins));
983
984             // The value of 'ins' encodes the size to store
985             // we use EA_4BYTE here because it is the size of the register
986             // that we want to display when storing small values
987             //
988             attr = EA_4BYTE;
989         }
990     }
991     return attr;
992 }
993
994 // Takes an instrDesc 'id' and uses the instruction 'ins' to determine the
995 // size of the target register that is written or read by the instruction.
996 // Note that even if EA_4BYTE is returned a load instruction will still
997 // always zero the upper 4 bytes of the target register.
998 // This method is required so that we can distinguish between loads that are
999 // sign-extending as they can have two different sizes for their target register.
1000 // Additionally for instructions like 'ldr' and 'str' these can load/store
1001 // either 4 byte or 8 bytes to/from the target register.
1002 // By convention the small unsigned load instructions are considered to write
1003 // a 4 byte sized target register, though since these also zero the upper 4 bytes
1004 // they could equally be considered to write the unsigned value to full 8 byte register.
1005 //
1006 emitAttr emitter::emitInsTargetRegSize(instrDesc* id)
1007 {
1008     instruction ins    = id->idIns();
1009     emitAttr    result = EA_UNKNOWN;
1010
1011     // This is used to determine the size of the target registers for a load/store instruction
1012
1013     switch (ins)
1014     {
1015         case INS_ldxrb:
1016         case INS_ldarb:
1017         case INS_ldaxrb:
1018         case INS_stxrb:
1019         case INS_stlrb:
1020         case INS_stlxrb:
1021         case INS_ldrb:
1022         case INS_strb:
1023         case INS_ldurb:
1024         case INS_sturb:
1025             result = EA_4BYTE;
1026             break;
1027
1028         case INS_ldxrh:
1029         case INS_ldarh:
1030         case INS_ldaxrh:
1031         case INS_stxrh:
1032         case INS_stlrh:
1033         case INS_stlxrh:
1034         case INS_ldrh:
1035         case INS_strh:
1036         case INS_ldurh:
1037         case INS_sturh:
1038             result = EA_4BYTE;
1039             break;
1040
1041         case INS_ldrsb:
1042         case INS_ldursb:
1043         case INS_ldrsh:
1044         case INS_ldursh:
1045             if (id->idOpSize() == EA_8BYTE)
1046                 result = EA_8BYTE;
1047             else
1048                 result = EA_4BYTE;
1049             break;
1050
1051         case INS_ldrsw:
1052         case INS_ldursw:
1053         case INS_ldpsw:
1054             result = EA_8BYTE;
1055             break;
1056
1057         case INS_ldp:
1058         case INS_stp:
1059         case INS_ldnp:
1060         case INS_stnp:
1061             result = id->idOpSize();
1062             break;
1063
1064         case INS_ldxr:
1065         case INS_ldar:
1066         case INS_ldaxr:
1067         case INS_stxr:
1068         case INS_stlr:
1069         case INS_stlxr:
1070         case INS_ldr:
1071         case INS_str:
1072         case INS_ldur:
1073         case INS_stur:
1074             result = id->idOpSize();
1075             break;
1076
1077         default:
1078             NO_WAY("unexpected instruction");
1079             break;
1080     }
1081     return result;
1082 }
1083
1084 // Takes an instrDesc and uses the instruction to determine the 'size' of the
1085 // data that is loaded from memory.
1086 //
1087 emitAttr emitter::emitInsLoadStoreSize(instrDesc* id)
1088 {
1089     instruction ins    = id->idIns();
1090     emitAttr    result = EA_UNKNOWN;
1091
1092     // The 'result' returned is the 'size' of the data that is loaded from memory.
1093
1094     switch (ins)
1095     {
1096         case INS_ldarb:
1097         case INS_stlrb:
1098         case INS_ldrb:
1099         case INS_strb:
1100         case INS_ldurb:
1101         case INS_sturb:
1102         case INS_ldrsb:
1103         case INS_ldursb:
1104             result = EA_1BYTE;
1105             break;
1106
1107         case INS_ldarh:
1108         case INS_stlrh:
1109         case INS_ldrh:
1110         case INS_strh:
1111         case INS_ldurh:
1112         case INS_sturh:
1113         case INS_ldrsh:
1114         case INS_ldursh:
1115             result = EA_2BYTE;
1116             break;
1117
1118         case INS_ldrsw:
1119         case INS_ldursw:
1120         case INS_ldpsw:
1121             result = EA_4BYTE;
1122             break;
1123
1124         case INS_ldp:
1125         case INS_stp:
1126         case INS_ldnp:
1127         case INS_stnp:
1128             result = id->idOpSize();
1129             break;
1130
1131         case INS_ldar:
1132         case INS_stlr:
1133         case INS_ldr:
1134         case INS_str:
1135         case INS_ldur:
1136         case INS_stur:
1137             result = id->idOpSize();
1138             break;
1139
1140         default:
1141             NO_WAY("unexpected instruction");
1142             break;
1143     }
1144     return result;
1145 }
1146
1147 /*****************************************************************************/
1148 #ifdef DEBUG
1149
1150 // clang-format off
1151 static const char * const  xRegNames[] =
1152 {
1153     #define REGDEF(name, rnum, mask, xname, wname) xname,
1154     #include "register.h"
1155 };
1156
1157 static const char * const  wRegNames[] =
1158 {
1159     #define REGDEF(name, rnum, mask, xname, wname) wname,
1160     #include "register.h"
1161 };
1162
1163 static const char * const  vRegNames[] =
1164 {
1165     "v0",  "v1",  "v2",  "v3",  "v4", 
1166     "v5",  "v6",  "v7",  "v8",  "v9", 
1167     "v10", "v11", "v12", "v13", "v14", 
1168     "v15", "v16", "v17", "v18", "v19", 
1169     "v20", "v21", "v22", "v23", "v24", 
1170     "v25", "v26", "v27", "v28", "v29",
1171     "v30", "v31"
1172 };
1173
1174 static const char * const  qRegNames[] =
1175 {
1176     "q0",  "q1",  "q2",  "q3",  "q4", 
1177     "q5",  "q6",  "q7",  "q8",  "q9", 
1178     "q10", "q11", "q12", "q13", "q14", 
1179     "q15", "q16", "q17", "q18", "q19", 
1180     "q20", "q21", "q22", "q23", "q24", 
1181     "q25", "q26", "q27", "q28", "q29",
1182     "q30", "q31"
1183 };
1184
1185 static const char * const  hRegNames[] =
1186 {
1187     "h0",  "h1",  "h2",  "h3",  "h4", 
1188     "h5",  "h6",  "h7",  "h8",  "h9", 
1189     "h10", "h11", "h12", "h13", "h14", 
1190     "h15", "h16", "h17", "h18", "h19", 
1191     "h20", "h21", "h22", "h23", "h24", 
1192     "h25", "h26", "h27", "h28", "h29",
1193     "h30", "h31"
1194 };
1195 static const char * const  bRegNames[] =
1196 {
1197     "b0",  "b1",  "b2",  "b3",  "b4", 
1198     "b5",  "b6",  "b7",  "b8",  "b9", 
1199     "b10", "b11", "b12", "b13", "b14", 
1200     "b15", "b16", "b17", "b18", "b19", 
1201     "b20", "b21", "b22", "b23", "b24", 
1202     "b25", "b26", "b27", "b28", "b29",
1203     "b30", "b31"
1204 };
1205 // clang-format on
1206
1207 /*****************************************************************************
1208  *
1209  *  Return a string that represents the given register.
1210  */
1211
1212 const char* emitter::emitRegName(regNumber reg, emitAttr size, bool varName)
1213 {
1214     assert(reg < REG_COUNT);
1215
1216     const char* rn = nullptr;
1217
1218     if (size == EA_8BYTE)
1219     {
1220         rn = xRegNames[reg];
1221     }
1222     else if (size == EA_4BYTE)
1223     {
1224         rn = wRegNames[reg];
1225     }
1226     else if (isVectorRegister(reg))
1227     {
1228         if (size == EA_16BYTE)
1229         {
1230             rn = qRegNames[reg - REG_V0];
1231         }
1232         else if (size == EA_2BYTE)
1233         {
1234             rn = hRegNames[reg - REG_V0];
1235         }
1236         else if (size == EA_1BYTE)
1237         {
1238             rn = bRegNames[reg - REG_V0];
1239         }
1240     }
1241
1242     assert(rn != nullptr);
1243
1244     return rn;
1245 }
1246
1247 /*****************************************************************************
1248  *
1249  *  Return a string that represents the given register.
1250  */
1251
1252 const char* emitter::emitVectorRegName(regNumber reg)
1253 {
1254     assert((reg >= REG_V0) && (reg <= REG_V31));
1255
1256     int index = (int)reg - (int)REG_V0;
1257
1258     return vRegNames[index];
1259 }
1260 #endif // DEBUG
1261
1262 /*****************************************************************************
1263  *
1264  *  Returns the base encoding of the given CPU instruction.
1265  */
1266
1267 emitter::insFormat emitter::emitInsFormat(instruction ins)
1268 {
1269     // clang-format off
1270     const static insFormat insFormats[] =
1271     {
1272         #define INST1(id, nm, fp, ldst, fmt, e1                                ) fmt,
1273         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            ) fmt,
1274         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        ) fmt,
1275         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    ) fmt,
1276         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                ) fmt,
1277         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            ) fmt,
1278         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) fmt,
1279         #include "instrs.h"
1280     };
1281     // clang-format on
1282
1283     assert(ins < ArrLen(insFormats));
1284     assert((insFormats[ins] != IF_NONE));
1285
1286     return insFormats[ins];
1287 }
1288
1289 // INST_FP is 1
1290 #define LD 2
1291 #define ST 4
1292 #define CMP 8
1293
1294 // clang-format off
1295 /*static*/ const BYTE CodeGenInterface::instInfo[] =
1296 {
1297     #define INST1(id, nm, fp, ldst, fmt, e1                                ) ldst | INST_FP*fp,
1298     #define INST2(id, nm, fp, ldst, fmt, e1, e2                            ) ldst | INST_FP*fp,
1299     #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        ) ldst | INST_FP*fp,
1300     #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    ) ldst | INST_FP*fp,
1301     #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                ) ldst | INST_FP*fp,
1302     #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            ) ldst | INST_FP*fp,
1303     #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) ldst | INST_FP*fp,
1304     #include "instrs.h"
1305 };
1306 // clang-format on
1307
1308 /*****************************************************************************
1309  *
1310  *  Returns true if the instruction is some kind of compare or test instruction
1311  */
1312
1313 bool emitter::emitInsIsCompare(instruction ins)
1314 {
1315     // We have pseudo ins like lea which are not included in emitInsLdStTab.
1316     if (ins < ArrLen(CodeGenInterface::instInfo))
1317         return (CodeGenInterface::instInfo[ins] & CMP) ? true : false;
1318     else
1319         return false;
1320 }
1321
1322 /*****************************************************************************
1323  *
1324  *  Returns true if the instruction is some kind of load instruction
1325  */
1326
1327 bool emitter::emitInsIsLoad(instruction ins)
1328 {
1329     // We have pseudo ins like lea which are not included in emitInsLdStTab.
1330     if (ins < ArrLen(CodeGenInterface::instInfo))
1331         return (CodeGenInterface::instInfo[ins] & LD) ? true : false;
1332     else
1333         return false;
1334 }
1335 /*****************************************************************************
1336  *
1337  *  Returns true if the instruction is some kind of store instruction
1338  */
1339
1340 bool emitter::emitInsIsStore(instruction ins)
1341 {
1342     // We have pseudo ins like lea which are not included in emitInsLdStTab.
1343     if (ins < ArrLen(CodeGenInterface::instInfo))
1344         return (CodeGenInterface::instInfo[ins] & ST) ? true : false;
1345     else
1346         return false;
1347 }
1348
1349 /*****************************************************************************
1350  *
1351  *  Returns true if the instruction is some kind of load/store instruction
1352  */
1353
1354 bool emitter::emitInsIsLoadOrStore(instruction ins)
1355 {
1356     // We have pseudo ins like lea which are not included in emitInsLdStTab.
1357     if (ins < ArrLen(CodeGenInterface::instInfo))
1358         return (CodeGenInterface::instInfo[ins] & (LD | ST)) ? true : false;
1359     else
1360         return false;
1361 }
1362
1363 #undef LD
1364 #undef ST
1365 #undef CMP
1366
1367 /*****************************************************************************
1368  *
1369  *  Returns the specific encoding of the given CPU instruction and format
1370  */
1371
1372 emitter::code_t emitter::emitInsCode(instruction ins, insFormat fmt)
1373 {
1374     // clang-format off
1375     const static code_t insCodes1[] =
1376     {
1377         #define INST1(id, nm, fp, ldst, fmt, e1                                ) e1,
1378         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            ) e1,
1379         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        ) e1,
1380         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    ) e1,
1381         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                ) e1,
1382         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            ) e1,
1383         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e1,
1384         #include "instrs.h"
1385     };
1386     const static code_t insCodes2[] =
1387     {
1388         #define INST1(id, nm, fp, ldst, fmt, e1                                )
1389         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            ) e2,
1390         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        ) e2,
1391         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    ) e2,
1392         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                ) e2,
1393         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            ) e2,
1394         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e2,
1395         #include "instrs.h"
1396     };
1397     const static code_t insCodes3[] =
1398     {
1399         #define INST1(id, nm, fp, ldst, fmt, e1                                )
1400         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            )
1401         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        ) e3,
1402         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    ) e3,
1403         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                ) e3,
1404         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            ) e3,
1405         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e3,
1406         #include "instrs.h"
1407     };
1408     const static code_t insCodes4[] =
1409     {
1410         #define INST1(id, nm, fp, ldst, fmt, e1                                )
1411         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            )
1412         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        )
1413         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    ) e4,
1414         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                ) e4,
1415         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            ) e4,
1416         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e4,
1417         #include "instrs.h"
1418     };
1419     const static code_t insCodes5[] =
1420     {
1421         #define INST1(id, nm, fp, ldst, fmt, e1                                )
1422         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            )
1423         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        )
1424         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    )
1425         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                ) e5,
1426         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            ) e5,
1427         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e5,
1428         #include "instrs.h"
1429     };
1430     const static code_t insCodes6[] =
1431     {
1432         #define INST1(id, nm, fp, ldst, fmt, e1                                )
1433         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            )
1434         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        )
1435         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    )
1436         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                )
1437         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            ) e6,
1438         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e6,
1439         #include "instrs.h"
1440     };
1441     const static code_t insCodes7[] =
1442     {
1443         #define INST1(id, nm, fp, ldst, fmt, e1                                )
1444         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            )
1445         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        )
1446         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    )
1447         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                )
1448         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            )
1449         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e7,
1450         #include "instrs.h"
1451     };
1452     const static code_t insCodes8[] =
1453     {
1454         #define INST1(id, nm, fp, ldst, fmt, e1                                )
1455         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            )
1456         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        )
1457         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    )
1458         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                )
1459         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            )
1460         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e8,
1461         #include "instrs.h"
1462     };
1463     const static code_t insCodes9[] =
1464     {
1465         #define INST1(id, nm, fp, ldst, fmt, e1                                )
1466         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            )
1467         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        )
1468         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    )
1469         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                )
1470         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            )
1471         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e9,
1472         #include "instrs.h"
1473     };
1474     // clang-format on
1475
1476     const static insFormat formatEncode9[9] = {IF_DR_2E, IF_DR_2G, IF_DI_1B, IF_DI_1D, IF_DV_3C,
1477                                                IF_DV_2B, IF_DV_2C, IF_DV_2E, IF_DV_2F};
1478     const static insFormat formatEncode6A[6] = {IF_DR_3A, IF_DR_3B, IF_DR_3C, IF_DI_2A, IF_DV_3A, IF_DV_3E};
1479     const static insFormat formatEncode5A[5] = {IF_LS_2A, IF_LS_2B, IF_LS_2C, IF_LS_3A, IF_LS_1A};
1480     const static insFormat formatEncode5B[5] = {IF_DV_2G, IF_DV_2H, IF_DV_2I, IF_DV_1A, IF_DV_1B};
1481     const static insFormat formatEncode5C[5] = {IF_DR_3A, IF_DR_3B, IF_DI_2C, IF_DV_3C, IF_DV_1B};
1482     const static insFormat formatEncode4A[4] = {IF_LS_2A, IF_LS_2B, IF_LS_2C, IF_LS_3A};
1483     const static insFormat formatEncode4B[4] = {IF_DR_3A, IF_DR_3B, IF_DR_3C, IF_DI_2A};
1484     const static insFormat formatEncode4C[4] = {IF_DR_2A, IF_DR_2B, IF_DR_2C, IF_DI_1A};
1485     const static insFormat formatEncode4D[4] = {IF_DV_3B, IF_DV_3D, IF_DV_3BI, IF_DV_3DI};
1486     const static insFormat formatEncode4E[4] = {IF_DR_3A, IF_DR_3B, IF_DI_2C, IF_DV_3C};
1487     const static insFormat formatEncode4F[4] = {IF_DR_3A, IF_DR_3B, IF_DV_3C, IF_DV_1B};
1488     const static insFormat formatEncode4G[4] = {IF_DR_2E, IF_DR_2F, IF_DV_2M, IF_DV_2L};
1489     const static insFormat formatEncode4H[4] = {IF_DV_3E, IF_DV_3A, IF_DV_2L, IF_DV_2M};
1490     const static insFormat formatEncode4I[4] = {IF_DV_3D, IF_DV_3B, IF_DV_2G, IF_DV_2A};
1491     const static insFormat formatEncode3A[3] = {IF_DR_3A, IF_DR_3B, IF_DI_2C};
1492     const static insFormat formatEncode3B[3] = {IF_DR_2A, IF_DR_2B, IF_DI_1C};
1493     const static insFormat formatEncode3C[3] = {IF_DR_3A, IF_DR_3B, IF_DV_3C};
1494     const static insFormat formatEncode3D[3] = {IF_DV_2C, IF_DV_2D, IF_DV_2E};
1495     const static insFormat formatEncode3E[3] = {IF_DV_3B, IF_DV_3BI, IF_DV_3DI};
1496     const static insFormat formatEncode3F[3] = {IF_DV_2A, IF_DV_2G, IF_DV_2H};
1497     const static insFormat formatEncode3G[3] = {IF_DV_2A, IF_DV_2G, IF_DV_2I};
1498     const static insFormat formatEncode3H[3] = {IF_DR_3A, IF_DV_3A, IF_DV_3AI};
1499     const static insFormat formatEncode3I[3] = {IF_DR_2E, IF_DR_2F, IF_DV_2M};
1500     const static insFormat formatEncode2A[2] = {IF_DR_2E, IF_DR_2F};
1501     const static insFormat formatEncode2B[2] = {IF_DR_3A, IF_DR_3B};
1502     const static insFormat formatEncode2C[2] = {IF_DR_3A, IF_DI_2D};
1503     const static insFormat formatEncode2D[2] = {IF_DR_3A, IF_DI_2B};
1504     const static insFormat formatEncode2E[2] = {IF_LS_3B, IF_LS_3C};
1505     const static insFormat formatEncode2F[2] = {IF_DR_2I, IF_DI_1F};
1506     const static insFormat formatEncode2G[2] = {IF_DV_3B, IF_DV_3D};
1507     const static insFormat formatEncode2H[2] = {IF_DV_2C, IF_DV_2F};
1508     const static insFormat formatEncode2I[2] = {IF_DV_2K, IF_DV_1C};
1509     const static insFormat formatEncode2J[2] = {IF_DV_2A, IF_DV_2G};
1510     const static insFormat formatEncode2K[2] = {IF_DV_2M, IF_DV_2L};
1511     const static insFormat formatEncode2L[2] = {IF_DV_2G, IF_DV_2M};
1512     const static insFormat formatEncode2M[2] = {IF_DV_3A, IF_DV_3AI};
1513     const static insFormat formatEncode2N[2] = {IF_DV_2N, IF_DV_2O};
1514     const static insFormat formatEncode2O[2] = {IF_DV_3E, IF_DV_3A};
1515     const static insFormat formatEncode2P[2] = {IF_DV_2G, IF_DV_3B};
1516
1517     code_t    code           = BAD_CODE;
1518     insFormat insFmt         = emitInsFormat(ins);
1519     bool      encoding_found = false;
1520     int       index          = -1;
1521
1522     switch (insFmt)
1523     {
1524         case IF_EN9:
1525             for (index = 0; index < 9; index++)
1526             {
1527                 if (fmt == formatEncode9[index])
1528                 {
1529                     encoding_found = true;
1530                     break;
1531                 }
1532             }
1533             break;
1534
1535         case IF_EN6A:
1536             for (index = 0; index < 6; index++)
1537             {
1538                 if (fmt == formatEncode6A[index])
1539                 {
1540                     encoding_found = true;
1541                     break;
1542                 }
1543             }
1544             break;
1545
1546         case IF_EN5A:
1547             for (index = 0; index < 5; index++)
1548             {
1549                 if (fmt == formatEncode5A[index])
1550                 {
1551                     encoding_found = true;
1552                     break;
1553                 }
1554             }
1555             break;
1556
1557         case IF_EN5B:
1558             for (index = 0; index < 5; index++)
1559             {
1560                 if (fmt == formatEncode5B[index])
1561                 {
1562                     encoding_found = true;
1563                     break;
1564                 }
1565             }
1566             break;
1567
1568         case IF_EN5C:
1569             for (index = 0; index < 5; index++)
1570             {
1571                 if (fmt == formatEncode5C[index])
1572                 {
1573                     encoding_found = true;
1574                     break;
1575                 }
1576             }
1577             break;
1578
1579         case IF_EN4A:
1580             for (index = 0; index < 4; index++)
1581             {
1582                 if (fmt == formatEncode4A[index])
1583                 {
1584                     encoding_found = true;
1585                     break;
1586                 }
1587             }
1588             break;
1589
1590         case IF_EN4B:
1591             for (index = 0; index < 4; index++)
1592             {
1593                 if (fmt == formatEncode4B[index])
1594                 {
1595                     encoding_found = true;
1596                     break;
1597                 }
1598             }
1599             break;
1600
1601         case IF_EN4C:
1602             for (index = 0; index < 4; index++)
1603             {
1604                 if (fmt == formatEncode4C[index])
1605                 {
1606                     encoding_found = true;
1607                     break;
1608                 }
1609             }
1610             break;
1611
1612         case IF_EN4D:
1613             for (index = 0; index < 4; index++)
1614             {
1615                 if (fmt == formatEncode4D[index])
1616                 {
1617                     encoding_found = true;
1618                     break;
1619                 }
1620             }
1621             break;
1622
1623         case IF_EN4E:
1624             for (index = 0; index < 4; index++)
1625             {
1626                 if (fmt == formatEncode4E[index])
1627                 {
1628                     encoding_found = true;
1629                     break;
1630                 }
1631             }
1632             break;
1633
1634         case IF_EN4F:
1635             for (index = 0; index < 4; index++)
1636             {
1637                 if (fmt == formatEncode4F[index])
1638                 {
1639                     encoding_found = true;
1640                     break;
1641                 }
1642             }
1643             break;
1644
1645         case IF_EN4G:
1646             for (index = 0; index < 4; index++)
1647             {
1648                 if (fmt == formatEncode4G[index])
1649                 {
1650                     encoding_found = true;
1651                     break;
1652                 }
1653             }
1654             break;
1655
1656         case IF_EN4H:
1657             for (index = 0; index < 4; index++)
1658             {
1659                 if (fmt == formatEncode4H[index])
1660                 {
1661                     encoding_found = true;
1662                     break;
1663                 }
1664             }
1665             break;
1666
1667         case IF_EN4I:
1668             for (index = 0; index < 4; index++)
1669             {
1670                 if (fmt == formatEncode4I[index])
1671                 {
1672                     encoding_found = true;
1673                     break;
1674                 }
1675             }
1676             break;
1677
1678         case IF_EN3A:
1679             for (index = 0; index < 3; index++)
1680             {
1681                 if (fmt == formatEncode3A[index])
1682                 {
1683                     encoding_found = true;
1684                     break;
1685                 }
1686             }
1687             break;
1688
1689         case IF_EN3B:
1690             for (index = 0; index < 3; index++)
1691             {
1692                 if (fmt == formatEncode3B[index])
1693                 {
1694                     encoding_found = true;
1695                     break;
1696                 }
1697             }
1698             break;
1699
1700         case IF_EN3C:
1701             for (index = 0; index < 3; index++)
1702             {
1703                 if (fmt == formatEncode3C[index])
1704                 {
1705                     encoding_found = true;
1706                     break;
1707                 }
1708             }
1709             break;
1710
1711         case IF_EN3D:
1712             for (index = 0; index < 3; index++)
1713             {
1714                 if (fmt == formatEncode3D[index])
1715                 {
1716                     encoding_found = true;
1717                     break;
1718                 }
1719             }
1720             break;
1721
1722         case IF_EN3E:
1723             for (index = 0; index < 3; index++)
1724             {
1725                 if (fmt == formatEncode3E[index])
1726                 {
1727                     encoding_found = true;
1728                     break;
1729                 }
1730             }
1731             break;
1732
1733         case IF_EN3F:
1734             for (index = 0; index < 3; index++)
1735             {
1736                 if (fmt == formatEncode3F[index])
1737                 {
1738                     encoding_found = true;
1739                     break;
1740                 }
1741             }
1742             break;
1743
1744         case IF_EN3G:
1745             for (index = 0; index < 3; index++)
1746             {
1747                 if (fmt == formatEncode3G[index])
1748                 {
1749                     encoding_found = true;
1750                     break;
1751                 }
1752             }
1753             break;
1754
1755         case IF_EN3H:
1756             for (index = 0; index < 3; index++)
1757             {
1758                 if (fmt == formatEncode3H[index])
1759                 {
1760                     encoding_found = true;
1761                     break;
1762                 }
1763             }
1764             break;
1765
1766         case IF_EN3I:
1767             for (index = 0; index < 3; index++)
1768             {
1769                 if (fmt == formatEncode3I[index])
1770                 {
1771                     encoding_found = true;
1772                     break;
1773                 }
1774             }
1775             break;
1776
1777         case IF_EN2A:
1778             for (index = 0; index < 2; index++)
1779             {
1780                 if (fmt == formatEncode2A[index])
1781                 {
1782                     encoding_found = true;
1783                     break;
1784                 }
1785             }
1786             break;
1787
1788         case IF_EN2B:
1789             for (index = 0; index < 2; index++)
1790             {
1791                 if (fmt == formatEncode2B[index])
1792                 {
1793                     encoding_found = true;
1794                     break;
1795                 }
1796             }
1797             break;
1798
1799         case IF_EN2C:
1800             for (index = 0; index < 2; index++)
1801             {
1802                 if (fmt == formatEncode2C[index])
1803                 {
1804                     encoding_found = true;
1805                     break;
1806                 }
1807             }
1808             break;
1809
1810         case IF_EN2D:
1811             for (index = 0; index < 2; index++)
1812             {
1813                 if (fmt == formatEncode2D[index])
1814                 {
1815                     encoding_found = true;
1816                     break;
1817                 }
1818             }
1819             break;
1820
1821         case IF_EN2E:
1822             for (index = 0; index < 2; index++)
1823             {
1824                 if (fmt == formatEncode2E[index])
1825                 {
1826                     encoding_found = true;
1827                     break;
1828                 }
1829             }
1830             break;
1831
1832         case IF_EN2F:
1833             for (index = 0; index < 2; index++)
1834             {
1835                 if (fmt == formatEncode2F[index])
1836                 {
1837                     encoding_found = true;
1838                     break;
1839                 }
1840             }
1841             break;
1842
1843         case IF_EN2G:
1844             for (index = 0; index < 2; index++)
1845             {
1846                 if (fmt == formatEncode2G[index])
1847                 {
1848                     encoding_found = true;
1849                     break;
1850                 }
1851             }
1852             break;
1853
1854         case IF_EN2H:
1855             for (index = 0; index < 2; index++)
1856             {
1857                 if (fmt == formatEncode2H[index])
1858                 {
1859                     encoding_found = true;
1860                     break;
1861                 }
1862             }
1863             break;
1864
1865         case IF_EN2I:
1866             for (index = 0; index < 2; index++)
1867             {
1868                 if (fmt == formatEncode2I[index])
1869                 {
1870                     encoding_found = true;
1871                     break;
1872                 }
1873             }
1874             break;
1875
1876         case IF_EN2J:
1877             for (index = 0; index < 2; index++)
1878             {
1879                 if (fmt == formatEncode2J[index])
1880                 {
1881                     encoding_found = true;
1882                     break;
1883                 }
1884             }
1885             break;
1886
1887         case IF_EN2K:
1888             for (index = 0; index < 2; index++)
1889             {
1890                 if (fmt == formatEncode2K[index])
1891                 {
1892                     encoding_found = true;
1893                     break;
1894                 }
1895             }
1896             break;
1897
1898         case IF_EN2L:
1899             for (index = 0; index < 2; index++)
1900             {
1901                 if (fmt == formatEncode2L[index])
1902                 {
1903                     encoding_found = true;
1904                     break;
1905                 }
1906             }
1907             break;
1908
1909         case IF_EN2M:
1910             for (index = 0; index < 2; index++)
1911             {
1912                 if (fmt == formatEncode2M[index])
1913                 {
1914                     encoding_found = true;
1915                     break;
1916                 }
1917             }
1918             break;
1919
1920         case IF_EN2N:
1921             for (index = 0; index < 2; index++)
1922             {
1923                 if (fmt == formatEncode2N[index])
1924                 {
1925                     encoding_found = true;
1926                     break;
1927                 }
1928             }
1929             break;
1930
1931         case IF_EN2O:
1932             for (index = 0; index < 2; index++)
1933             {
1934                 if (fmt == formatEncode2O[index])
1935                 {
1936                     encoding_found = true;
1937                     break;
1938                 }
1939             }
1940             break;
1941
1942         case IF_EN2P:
1943             for (index = 0; index < 2; index++)
1944             {
1945                 if (fmt == formatEncode2P[index])
1946                 {
1947                     encoding_found = true;
1948                     break;
1949                 }
1950             }
1951             break;
1952
1953         case IF_BI_0A:
1954         case IF_BI_0B:
1955         case IF_BI_0C:
1956         case IF_BI_1A:
1957         case IF_BI_1B:
1958         case IF_BR_1A:
1959         case IF_BR_1B:
1960         case IF_LS_1A:
1961         case IF_LS_2A:
1962         case IF_LS_2B:
1963         case IF_LS_2C:
1964         case IF_LS_3A:
1965         case IF_LS_3B:
1966         case IF_LS_3C:
1967         case IF_LS_3D:
1968         case IF_LS_3E:
1969         case IF_DI_1A:
1970         case IF_DI_1B:
1971         case IF_DI_1C:
1972         case IF_DI_1D:
1973         case IF_DI_1E:
1974         case IF_DI_1F:
1975         case IF_DI_2A:
1976         case IF_DI_2B:
1977         case IF_DI_2C:
1978         case IF_DI_2D:
1979         case IF_DR_1D:
1980         case IF_DR_2A:
1981         case IF_DR_2B:
1982         case IF_DR_2C:
1983         case IF_DR_2D:
1984         case IF_DR_2E:
1985         case IF_DR_2F:
1986         case IF_DR_2G:
1987         case IF_DR_2H:
1988         case IF_DR_2I:
1989         case IF_DR_2J:
1990         case IF_DR_3A:
1991         case IF_DR_3B:
1992         case IF_DR_3C:
1993         case IF_DR_3D:
1994         case IF_DR_3E:
1995         case IF_DR_4A:
1996         case IF_DV_1A:
1997         case IF_DV_1B:
1998         case IF_DV_1C:
1999         case IF_DV_2A:
2000         case IF_DV_2B:
2001         case IF_DV_2C:
2002         case IF_DV_2D:
2003         case IF_DV_2E:
2004         case IF_DV_2F:
2005         case IF_DV_2G:
2006         case IF_DV_2H:
2007         case IF_DV_2I:
2008         case IF_DV_2J:
2009         case IF_DV_2K:
2010         case IF_DV_2L:
2011         case IF_DV_2M:
2012         case IF_DV_2N:
2013         case IF_DV_2O:
2014         case IF_DV_2P:
2015         case IF_DV_3A:
2016         case IF_DV_3AI:
2017         case IF_DV_3B:
2018         case IF_DV_3BI:
2019         case IF_DV_3C:
2020         case IF_DV_3D:
2021         case IF_DV_3DI:
2022         case IF_DV_3E:
2023         case IF_DV_3F:
2024         case IF_DV_4A:
2025         case IF_SN_0A:
2026         case IF_SI_0A:
2027         case IF_SI_0B:
2028
2029             index          = 0;
2030             encoding_found = true;
2031             break;
2032
2033         default:
2034
2035             encoding_found = false;
2036             break;
2037     }
2038
2039     assert(encoding_found);
2040
2041     switch (index)
2042     {
2043         case 0:
2044             assert(ins < ArrLen(insCodes1));
2045             code = insCodes1[ins];
2046             break;
2047         case 1:
2048             assert(ins < ArrLen(insCodes2));
2049             code = insCodes2[ins];
2050             break;
2051         case 2:
2052             assert(ins < ArrLen(insCodes3));
2053             code = insCodes3[ins];
2054             break;
2055         case 3:
2056             assert(ins < ArrLen(insCodes4));
2057             code = insCodes4[ins];
2058             break;
2059         case 4:
2060             assert(ins < ArrLen(insCodes5));
2061             code = insCodes5[ins];
2062             break;
2063         case 5:
2064             assert(ins < ArrLen(insCodes6));
2065             code = insCodes6[ins];
2066             break;
2067         case 6:
2068             assert(ins < ArrLen(insCodes7));
2069             code = insCodes7[ins];
2070             break;
2071         case 7:
2072             assert(ins < ArrLen(insCodes8));
2073             code = insCodes8[ins];
2074             break;
2075         case 8:
2076             assert(ins < ArrLen(insCodes9));
2077             code = insCodes9[ins];
2078             break;
2079     }
2080
2081     assert((code != BAD_CODE));
2082
2083     return code;
2084 }
2085
2086 // true if this 'imm' can be encoded as a input operand to a mov instruction
2087 /*static*/ bool emitter::emitIns_valid_imm_for_mov(INT64 imm, emitAttr size)
2088 {
2089     // Check for "MOV (wide immediate)".
2090     if (canEncodeHalfwordImm(imm, size))
2091         return true;
2092
2093     // Next try the ones-complement form of 'halfword immediate' imm(i16,hw),
2094     // namely "MOV (inverted wide immediate)".
2095     ssize_t notOfImm = NOT_helper(imm, getBitWidth(size));
2096     if (canEncodeHalfwordImm(notOfImm, size))
2097         return true;
2098
2099     // Finally try "MOV (bitmask immediate)" imm(N,r,s)
2100     if (canEncodeBitMaskImm(imm, size))
2101         return true;
2102
2103     return false;
2104 }
2105
2106 // true if this 'imm' can be encoded as a input operand to a vector movi instruction
2107 /*static*/ bool emitter::emitIns_valid_imm_for_movi(INT64 imm, emitAttr elemsize)
2108 {
2109     if (elemsize == EA_8BYTE)
2110     {
2111         UINT64 uimm = imm;
2112         while (uimm != 0)
2113         {
2114             INT64 loByte = uimm & 0xFF;
2115             if ((loByte == 0) || (loByte == 0xFF))
2116             {
2117                 uimm >>= 8;
2118             }
2119             else
2120             {
2121                 return false;
2122             }
2123         }
2124         assert(uimm == 0);
2125         return true;
2126     }
2127     else
2128     {
2129         // First try the standard 'byteShifted immediate' imm(i8,bySh)
2130         if (canEncodeByteShiftedImm(imm, elemsize, true))
2131             return true;
2132
2133         // Next try the ones-complement form of the 'immediate' imm(i8,bySh)
2134         ssize_t notOfImm = NOT_helper(imm, getBitWidth(elemsize));
2135         if (canEncodeByteShiftedImm(notOfImm, elemsize, true))
2136             return true;
2137     }
2138     return false;
2139 }
2140
2141 // true if this 'imm' can be encoded as a input operand to a fmov instruction
2142 /*static*/ bool emitter::emitIns_valid_imm_for_fmov(double immDbl)
2143 {
2144     if (canEncodeFloatImm8(immDbl))
2145         return true;
2146
2147     return false;
2148 }
2149
2150 // true if this 'imm' can be encoded as a input operand to an add instruction
2151 /*static*/ bool emitter::emitIns_valid_imm_for_add(INT64 imm, emitAttr size)
2152 {
2153     if (unsigned_abs(imm) <= 0x0fff)
2154         return true;
2155     else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
2156         return true;
2157
2158     return false;
2159 }
2160
2161 // true if this 'imm' can be encoded as a input operand to an non-add/sub alu instruction
2162 /*static*/ bool emitter::emitIns_valid_imm_for_cmp(INT64 imm, emitAttr size)
2163 {
2164     return emitIns_valid_imm_for_add(imm, size);
2165 }
2166
2167 // true if this 'imm' can be encoded as a input operand to an non-add/sub alu instruction
2168 /*static*/ bool emitter::emitIns_valid_imm_for_alu(INT64 imm, emitAttr size)
2169 {
2170     if (canEncodeBitMaskImm(imm, size))
2171         return true;
2172
2173     return false;
2174 }
2175
2176 // true if this 'imm' can be encoded as the offset in a ldr/str instruction
2177 /*static*/ bool emitter::emitIns_valid_imm_for_ldst_offset(INT64 imm, emitAttr attr)
2178 {
2179     if (imm == 0)
2180         return true; // Encodable using IF_LS_2A
2181
2182     if ((imm >= -256) && (imm <= 255))
2183         return true; // Encodable using IF_LS_2C (or possibly IF_LS_2B)
2184
2185     if (imm < 0)
2186         return false; // not encodable
2187
2188     emitAttr size  = EA_SIZE(attr);
2189     unsigned scale = NaturalScale_helper(size);
2190     ssize_t  mask  = size - 1; // the mask of low bits that must be zero to encode the immediate
2191
2192     if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
2193         return true; // Encodable using IF_LS_2B
2194
2195     return false; // not encodable
2196 }
2197
2198 /************************************************************************
2199  *
2200  *   A helper method to return the natural scale for an EA 'size'
2201  */
2202
2203 /*static*/ unsigned emitter::NaturalScale_helper(emitAttr size)
2204 {
2205     assert(size == EA_1BYTE || size == EA_2BYTE || size == EA_4BYTE || size == EA_8BYTE || size == EA_16BYTE);
2206
2207     unsigned result = 0;
2208     unsigned utemp  = (unsigned)size;
2209
2210     // Compute log base 2 of utemp (aka 'size')
2211     while (utemp > 1)
2212     {
2213         result++;
2214         utemp >>= 1;
2215     }
2216
2217     return result;
2218 }
2219
2220 /************************************************************************
2221  *
2222  *  A helper method to perform a Rotate-Right shift operation
2223  *  the source is 'value' and it is rotated right by 'sh' bits
2224  *  'value' is considered to be a fixed size 'width' set of bits.
2225  *
2226  *  Example
2227  *      value is '00001111', sh is 2 and width is 8
2228  *     result is '11000011'
2229  */
2230
2231 /*static*/ UINT64 emitter::ROR_helper(UINT64 value, unsigned sh, unsigned width)
2232 {
2233     assert(width <= 64);
2234     // Check that 'value' fits in 'width' bits
2235     assert((width == 64) || (value < (1ULL << width)));
2236     // We don't support shifts >= width
2237     assert(sh < width);
2238
2239     UINT64 result;
2240
2241     unsigned rsh = sh;
2242     unsigned lsh = width - rsh;
2243
2244     result = (value >> rsh);
2245     result |= (value << lsh);
2246
2247     if (width < 64)
2248     {
2249         // mask off any extra bits that we got from the left shift
2250         result &= ((1ULL << width) - 1);
2251     }
2252     return result;
2253 }
2254 /************************************************************************
2255  *
2256  *  A helper method to perform a 'NOT' bitwise complement operation.
2257  *  'value' is considered to be a fixed size 'width' set of bits.
2258  *
2259  *  Example
2260  *      value is '01001011', and width is 8
2261  *     result is '10110100'
2262  */
2263
2264 /*static*/ UINT64 emitter::NOT_helper(UINT64 value, unsigned width)
2265 {
2266     assert(width <= 64);
2267
2268     UINT64 result = ~value;
2269
2270     if (width < 64)
2271     {
2272         // Check that 'value' fits in 'width' bits. Don't consider "sign" bits above width.
2273         UINT64 maxVal       = 1ULL << width;
2274         UINT64 lowBitsMask  = maxVal - 1;
2275         UINT64 signBitsMask = ~lowBitsMask | (1ULL << (width - 1)); // The high bits must be set, and the top bit
2276                                                                     // (sign bit) must be set.
2277         assert((value < maxVal) || ((value & signBitsMask) == signBitsMask));
2278
2279         // mask off any extra bits that we got from the complement operation
2280         result &= lowBitsMask;
2281     }
2282
2283     return result;
2284 }
2285
2286 /************************************************************************
2287  *
2288  *  A helper method to perform a bit Replicate operation
2289  *  the source is 'value' with a fixed size 'width' set of bits.
2290  *  value is replicated to fill out 32 or 64 bits as determined by 'size'.
2291  *
2292  *  Example
2293  *      value is '11000011' (0xE3), width is 8 and size is EA_8BYTE
2294  *     result is '11000011 11000011 11000011 11000011 11000011 11000011 11000011 11000011'
2295  *               0xE3E3E3E3E3E3E3E3
2296  */
2297
2298 /*static*/ UINT64 emitter::Replicate_helper(UINT64 value, unsigned width, emitAttr size)
2299 {
2300     assert(emitter::isValidGeneralDatasize(size));
2301
2302     unsigned immWidth = (size == EA_8BYTE) ? 64 : 32;
2303     assert(width <= immWidth);
2304
2305     UINT64   result     = value;
2306     unsigned filledBits = width;
2307
2308     while (filledBits < immWidth)
2309     {
2310         value <<= width;
2311         result |= value;
2312         filledBits += width;
2313     }
2314     return result;
2315 }
2316
2317 /************************************************************************
2318  *
2319  *  Convert an imm(N,r,s) into a 64-bit immediate
2320  *  inputs 'bmImm' a bitMaskImm struct
2321  *         'size' specifies the size of the result (64 or 32 bits)
2322  */
2323
2324 /*static*/ INT64 emitter::emitDecodeBitMaskImm(const emitter::bitMaskImm bmImm, emitAttr size)
2325 {
2326     assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2327
2328     unsigned N = bmImm.immN; // read the N,R and S values from the 'bitMaskImm' encoding
2329     unsigned R = bmImm.immR;
2330     unsigned S = bmImm.immS;
2331
2332     unsigned elemWidth = 64; // used when immN == 1
2333
2334     if (bmImm.immN == 0) // find the smaller elemWidth when immN == 0
2335     {
2336         // Scan S for the highest bit not set
2337         elemWidth = 32;
2338         for (unsigned bitNum = 5; bitNum > 0; bitNum--)
2339         {
2340             unsigned oneBit = elemWidth;
2341             if ((S & oneBit) == 0)
2342                 break;
2343             elemWidth /= 2;
2344         }
2345     }
2346     else
2347     {
2348         assert(size == EA_8BYTE);
2349     }
2350
2351     unsigned maskSR = elemWidth - 1;
2352
2353     S &= maskSR;
2354     R &= maskSR;
2355
2356     // encoding for S is one less than the number of consecutive one bits
2357     S++; // Number of consecutive ones to generate in 'welem'
2358
2359     // At this point:
2360     //
2361     //    'elemWidth' is the number of bits that we will use for the ROR and Replicate operations
2362     //    'S'         is the number of consecutive 1 bits for the immediate
2363     //    'R'         is the number of bits that we will Rotate Right the immediate
2364     //    'size'      selects the final size of the immedate that we return (64 or 32 bits)
2365
2366     assert(S < elemWidth); // 'elemWidth' consecutive one's is a reserved encoding
2367
2368     UINT64 welem;
2369     UINT64 wmask;
2370
2371     welem = (1ULL << S) - 1;
2372
2373     wmask = ROR_helper(welem, R, elemWidth);
2374     wmask = Replicate_helper(wmask, elemWidth, size);
2375
2376     return wmask;
2377 }
2378
2379 /*****************************************************************************
2380  *
2381  *  Check if an immediate can use the left shifted by 12 bits encoding
2382  */
2383
2384 /*static*/ bool emitter::canEncodeWithShiftImmBy12(INT64 imm)
2385 {
2386     if (imm < 0)
2387     {
2388         imm = -imm; // convert to unsigned
2389     }
2390
2391     if (imm < 0)
2392     {
2393         return false; // Must be MIN_INT64
2394     }
2395
2396     if ((imm & 0xfff) != 0) // Now the low 12 bits all have to be zero
2397     {
2398         return false;
2399     }
2400
2401     imm >>= 12; // shift right by 12 bits
2402
2403     return (imm <= 0x0fff); // Does it fit in 12 bits
2404 }
2405
2406 /*****************************************************************************
2407  *
2408  *  Normalize the 'imm' so that the upper bits, as defined by 'size' are zero
2409  */
2410
2411 /*static*/ INT64 emitter::normalizeImm64(INT64 imm, emitAttr size)
2412 {
2413     unsigned immWidth = getBitWidth(size);
2414     INT64    result   = imm;
2415
2416     if (immWidth < 64)
2417     {
2418         // Check that 'imm' fits in 'immWidth' bits. Don't consider "sign" bits above width.
2419         INT64 maxVal      = 1LL << immWidth;
2420         INT64 lowBitsMask = maxVal - 1;
2421         INT64 hiBitsMask  = ~lowBitsMask;
2422         INT64 signBitsMask =
2423             hiBitsMask | (1LL << (immWidth - 1)); // The high bits must be set, and the top bit (sign bit) must be set.
2424         assert((imm < maxVal) || ((imm & signBitsMask) == signBitsMask));
2425
2426         // mask off the hiBits
2427         result &= lowBitsMask;
2428     }
2429     return result;
2430 }
2431
2432 /*****************************************************************************
2433  *
2434  *  Normalize the 'imm' so that the upper bits, as defined by 'size' are zero
2435  */
2436
2437 /*static*/ INT32 emitter::normalizeImm32(INT32 imm, emitAttr size)
2438 {
2439     unsigned immWidth = getBitWidth(size);
2440     INT32    result   = imm;
2441
2442     if (immWidth < 32)
2443     {
2444         // Check that 'imm' fits in 'immWidth' bits. Don't consider "sign" bits above width.
2445         INT32 maxVal       = 1 << immWidth;
2446         INT32 lowBitsMask  = maxVal - 1;
2447         INT32 hiBitsMask   = ~lowBitsMask;
2448         INT32 signBitsMask = hiBitsMask | (1 << (immWidth - 1)); // The high bits must be set, and the top bit
2449                                                                  // (sign bit) must be set.
2450         assert((imm < maxVal) || ((imm & signBitsMask) == signBitsMask));
2451
2452         // mask off the hiBits
2453         result &= lowBitsMask;
2454     }
2455     return result;
2456 }
2457
2458 /************************************************************************
2459  *
2460  *  returns true if 'imm' of 'size bits (32/64) can be encoded
2461  *  using the ARM64 'bitmask immediate' form.
2462  *  When a non-null value is passed for 'wbBMI' then this method
2463  *  writes back the 'N','S' and 'R' values use to encode this immediate
2464  *
2465  */
2466
2467 /*static*/ bool emitter::canEncodeBitMaskImm(INT64 imm, emitAttr size, emitter::bitMaskImm* wbBMI)
2468 {
2469     assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2470
2471     unsigned immWidth = (size == EA_8BYTE) ? 64 : 32;
2472     unsigned maxLen   = (size == EA_8BYTE) ? 6 : 5;
2473
2474     imm = normalizeImm64(imm, size);
2475
2476     // Starting with len=1, elemWidth is 2 bits
2477     //               len=2, elemWidth is 4 bits
2478     //               len=3, elemWidth is 8 bits
2479     //               len=4, elemWidth is 16 bits
2480     //               len=5, elemWidth is 32 bits
2481     // (optionally)  len=6, elemWidth is 64 bits
2482     //
2483     for (unsigned len = 1; (len <= maxLen); len++)
2484     {
2485         unsigned elemWidth = 1 << len;
2486         UINT64   elemMask  = ((UINT64)-1) >> (64 - elemWidth);
2487         UINT64   tempImm   = (UINT64)imm;        // A working copy of 'imm' that we can mutate
2488         UINT64   elemVal   = tempImm & elemMask; // The low 'elemWidth' bits of 'imm'
2489
2490         // Check for all 1's or 0's as these can't be encoded
2491         if ((elemVal == 0) || (elemVal == elemMask))
2492             continue;
2493
2494         // 'checkedBits' is the count of bits that are known to match 'elemVal' when replicated
2495         unsigned checkedBits = elemWidth; // by definition the first 'elemWidth' bits match
2496
2497         // Now check to see if each of the next bits match...
2498         //
2499         while (checkedBits < immWidth)
2500         {
2501             tempImm >>= elemWidth;
2502
2503             UINT64 nextElem = tempImm & elemMask;
2504             if (nextElem != elemVal)
2505             {
2506                 // Not matching, exit this loop and checkedBits will not be equal to immWidth
2507                 break;
2508             }
2509
2510             // The 'nextElem' is matching, so increment 'checkedBits'
2511             checkedBits += elemWidth;
2512         }
2513
2514         // Did the full immediate contain bits that can be formed by repeating 'elemVal'?
2515         if (checkedBits == immWidth)
2516         {
2517             // We are not quite done, since the only values that we can encode as a
2518             // 'bitmask immediate' are those that can be formed by starting with a
2519             // bit string of 0*1* that is rotated by some number of bits.
2520             //
2521             // We check to see if 'elemVal' can be formed using these restrictions.
2522             //
2523             // Observation:
2524             // Rotating by one bit any value that passes these restrictions
2525             // can be xor-ed with the original value and will result it a string
2526             // of bits that have exactly two 1 bits: 'elemRorXor'
2527             // Further the distance between the two one bits tells us the value
2528             // of S and the location of the 1 bits tells us the value of R
2529             //
2530             // Some examples:   (immWidth is 8)
2531             //
2532             // S=4,R=0   S=5,R=3   S=3,R=6
2533             // elemVal:        00001111  11100011  00011100
2534             // elemRor:        10000111  11110001  00001110
2535             // elemRorXor:     10001000  00010010  00010010
2536             //      compute S  45678---  ---5678-  ---3210-
2537             //      compute R  01234567  ---34567  ------67
2538
2539             UINT64 elemRor    = ROR_helper(elemVal, 1, elemWidth); // Rotate 'elemVal' Right by one bit
2540             UINT64 elemRorXor = elemVal ^ elemRor;                 // Xor elemVal and elemRor
2541
2542             // If we only have a two-bit change in elemROR then we can form a mask for this value
2543             unsigned bitCount = 0;
2544             UINT64   oneBit   = 0x1;
2545             unsigned R        = elemWidth; // R is shift count for ROR (rotate right shift)
2546             unsigned S        = 0;         // S is number of consecutive one bits
2547             int      incr     = -1;
2548
2549             // Loop over the 'elemWidth' bits in 'elemRorXor'
2550             //
2551             for (unsigned bitNum = 0; bitNum < elemWidth; bitNum++)
2552             {
2553                 if (incr == -1)
2554                 {
2555                     R--; // We decrement R by one whenever incr is -1
2556                 }
2557                 if (bitCount == 1)
2558                 {
2559                     S += incr; // We incr/decr S, after we find the first one bit in 'elemRorXor'
2560                 }
2561
2562                 // Is this bit position a 1 bit in 'elemRorXor'?
2563                 //
2564                 if (oneBit & elemRorXor)
2565                 {
2566                     bitCount++;
2567                     // Is this the first 1 bit that we found in 'elemRorXor'?
2568                     if (bitCount == 1)
2569                     {
2570                         // Does this 1 bit represent a transition to zero bits?
2571                         bool toZeros = ((oneBit & elemVal) != 0);
2572                         if (toZeros)
2573                         {
2574                             // S :: Count down from elemWidth
2575                             S    = elemWidth;
2576                             incr = -1;
2577                         }
2578                         else // this 1 bit represent a transition to one bits.
2579                         {
2580                             // S :: Count up from zero
2581                             S    = 0;
2582                             incr = +1;
2583                         }
2584                     }
2585                     else // bitCount > 1
2586                     {
2587                         // We found the second (or third...) 1 bit in 'elemRorXor'
2588                         incr = 0; // stop decrementing 'R'
2589
2590                         if (bitCount > 2)
2591                         {
2592                             // More than 2 transitions from 0/1 in 'elemVal'
2593                             // This means that 'elemVal' can't be encoded
2594                             // using a 'bitmask immediate'.
2595                             //
2596                             // Furthermore, it will continue to fail
2597                             // with any larger 'len' that we try.
2598                             // so just return false.
2599                             //
2600                             return false;
2601                         }
2602                     }
2603                 }
2604
2605                 // shift oneBit left by one bit to test the next position
2606                 oneBit <<= 1;
2607             }
2608
2609             // We expect that bitCount will always be two at this point
2610             // but just in case return false for any bad cases.
2611             //
2612             assert(bitCount == 2);
2613             if (bitCount != 2)
2614                 return false;
2615
2616             // Perform some sanity checks on the values of 'S' and 'R'
2617             assert(S > 0);
2618             assert(S < elemWidth);
2619             assert(R < elemWidth);
2620
2621             // Does the caller want us to return the N,R,S encoding values?
2622             //
2623             if (wbBMI != nullptr)
2624             {
2625
2626                 // The encoding used for S is one less than the
2627                 //  number of consecutive one bits
2628                 S--;
2629
2630                 if (len == 6)
2631                 {
2632                     wbBMI->immN = 1;
2633                 }
2634                 else
2635                 {
2636                     wbBMI->immN = 0;
2637                     // The encoding used for 'S' here is a bit peculiar.
2638                     //
2639                     // The upper bits need to be complemented, followed by a zero bit
2640                     // then the value of 'S-1'
2641                     //
2642                     unsigned upperBitsOfS = 64 - (1 << (len + 1));
2643                     S |= upperBitsOfS;
2644                 }
2645                 wbBMI->immR = R;
2646                 wbBMI->immS = S;
2647
2648                 // Verify that what we are returning is correct.
2649                 assert(imm == emitDecodeBitMaskImm(*wbBMI, size));
2650             }
2651             // Tell the caller that we can successfully encode this immediate
2652             // using a 'bitmask immediate'.
2653             //
2654             return true;
2655         }
2656     }
2657     return false;
2658 }
2659
2660 /************************************************************************
2661  *
2662  *  Convert a 64-bit immediate into its 'bitmask immediate' representation imm(N,r,s)
2663  */
2664
2665 /*static*/ emitter::bitMaskImm emitter::emitEncodeBitMaskImm(INT64 imm, emitAttr size)
2666 {
2667     emitter::bitMaskImm result;
2668     result.immNRS = 0;
2669
2670     bool canEncode = canEncodeBitMaskImm(imm, size, &result);
2671     assert(canEncode);
2672
2673     return result;
2674 }
2675
2676 /************************************************************************
2677  *
2678  *  Convert an imm(i16,hw) into a 32/64-bit immediate
2679  *  inputs 'hwImm' a halfwordImm struct
2680  *         'size' specifies the size of the result (64 or 32 bits)
2681  */
2682
2683 /*static*/ INT64 emitter::emitDecodeHalfwordImm(const emitter::halfwordImm hwImm, emitAttr size)
2684 {
2685     assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2686
2687     unsigned hw  = hwImm.immHW;
2688     INT64    val = (INT64)hwImm.immVal;
2689
2690     assert((hw <= 1) || (size == EA_8BYTE));
2691
2692     INT64 result = val << (16 * hw);
2693     return result;
2694 }
2695
2696 /************************************************************************
2697  *
2698  *  returns true if 'imm' of 'size' bits (32/64) can be encoded
2699  *  using the ARM64 'halfword immediate' form.
2700  *  When a non-null value is passed for 'wbHWI' then this method
2701  *  writes back the 'immHW' and 'immVal' values use to encode this immediate
2702  *
2703  */
2704
2705 /*static*/ bool emitter::canEncodeHalfwordImm(INT64 imm, emitAttr size, emitter::halfwordImm* wbHWI)
2706 {
2707     assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2708
2709     unsigned immWidth = (size == EA_8BYTE) ? 64 : 32;
2710     unsigned maxHW    = (size == EA_8BYTE) ? 4 : 2;
2711
2712     // setup immMask to a (EA_4BYTE) 0x00000000_FFFFFFFF or (EA_8BYTE) 0xFFFFFFFF_FFFFFFFF
2713     const UINT64 immMask = ((UINT64)-1) >> (64 - immWidth);
2714     const INT64  mask16  = (INT64)0xFFFF;
2715
2716     imm = normalizeImm64(imm, size);
2717
2718     // Try each of the valid hw shift sizes
2719     for (unsigned hw = 0; (hw < maxHW); hw++)
2720     {
2721         INT64 curMask   = mask16 << (hw * 16); // Represents the mask of the bits in the current halfword
2722         INT64 checkBits = immMask & ~curMask;
2723
2724         // Excluding the current halfword (using ~curMask)
2725         //  does the immediate have zero bits in every other bit that we care about?
2726         //  note we care about all 64-bits for EA_8BYTE
2727         //  and we care about the lowest 32 bits for EA_4BYTE
2728         //
2729         if ((imm & checkBits) == 0)
2730         {
2731             // Does the caller want us to return the imm(i16,hw) encoding values?
2732             //
2733             if (wbHWI != nullptr)
2734             {
2735                 INT64 val     = ((imm & curMask) >> (hw * 16)) & mask16;
2736                 wbHWI->immHW  = hw;
2737                 wbHWI->immVal = val;
2738
2739                 // Verify that what we are returning is correct.
2740                 assert(imm == emitDecodeHalfwordImm(*wbHWI, size));
2741             }
2742             // Tell the caller that we can successfully encode this immediate
2743             // using a 'halfword immediate'.
2744             //
2745             return true;
2746         }
2747     }
2748     return false;
2749 }
2750
2751 /************************************************************************
2752  *
2753  *  Convert a 64-bit immediate into its 'halfword immediate' representation imm(i16,hw)
2754  */
2755
2756 /*static*/ emitter::halfwordImm emitter::emitEncodeHalfwordImm(INT64 imm, emitAttr size)
2757 {
2758     emitter::halfwordImm result;
2759     result.immHWVal = 0;
2760
2761     bool canEncode = canEncodeHalfwordImm(imm, size, &result);
2762     assert(canEncode);
2763
2764     return result;
2765 }
2766
2767 /************************************************************************
2768  *
2769  *  Convert an imm(i8,sh) into a 16/32-bit immediate
2770  *  inputs 'bsImm' a byteShiftedImm struct
2771  *         'size' specifies the size of the result (16 or 32 bits)
2772  */
2773
2774 /*static*/ INT32 emitter::emitDecodeByteShiftedImm(const emitter::byteShiftedImm bsImm, emitAttr size)
2775 {
2776     bool     onesShift = (bsImm.immOnes == 1);
2777     unsigned bySh      = bsImm.immBY;         // Num Bytes to shift 0,1,2,3
2778     INT32    val       = (INT32)bsImm.immVal; // 8-bit immediate
2779     INT32    result    = val;
2780
2781     if (bySh > 0)
2782     {
2783         assert((size == EA_2BYTE) || (size == EA_4BYTE)); // Only EA_2BYTE or EA_4BYTE forms
2784         if (size == EA_2BYTE)
2785         {
2786             assert(bySh < 2);
2787         }
2788         else
2789         {
2790             assert(bySh < 4);
2791         }
2792
2793         result <<= (8 * bySh);
2794
2795         if (onesShift)
2796         {
2797             result |= ((1 << (8 * bySh)) - 1);
2798         }
2799     }
2800     return result;
2801 }
2802
2803 /************************************************************************
2804  *
2805  *  returns true if 'imm' of 'size' bits (16/32) can be encoded
2806  *  using the ARM64 'byteShifted immediate' form.
2807  *  When a non-null value is passed for 'wbBSI' then this method
2808  *  writes back the 'immBY' and 'immVal' values use to encode this immediate
2809  *
2810  */
2811
2812 /*static*/ bool emitter::canEncodeByteShiftedImm(INT64                    imm,
2813                                                  emitAttr                 size,
2814                                                  bool                     allow_MSL,
2815                                                  emitter::byteShiftedImm* wbBSI)
2816 {
2817     bool     canEncode = false;
2818     bool     onesShift = false; // true if we use the shifting ones variant
2819     unsigned bySh      = 0;     // number of bytes to shift: 0, 1, 2, 3
2820     unsigned imm8      = 0;     // immediate to use in the encoding
2821
2822     imm = normalizeImm64(imm, size);
2823
2824     if (size == EA_1BYTE)
2825     {
2826         imm8 = (unsigned)imm;
2827         assert(imm8 < 0x100);
2828         canEncode = true;
2829     }
2830     else if (size == EA_8BYTE)
2831     {
2832         imm8 = (unsigned)imm;
2833         assert(imm8 < 0x100);
2834         canEncode = true;
2835     }
2836     else
2837     {
2838         assert((size == EA_2BYTE) || (size == EA_4BYTE)); // Only EA_2BYTE or EA_4BYTE forms
2839
2840         unsigned immWidth = (size == EA_4BYTE) ? 32 : 16;
2841         unsigned maxBY    = (size == EA_4BYTE) ? 4 : 2;
2842
2843         // setup immMask to a (EA_2BYTE) 0x0000FFFF or (EA_4BYTE) 0xFFFFFFFF
2844         const UINT32 immMask = ((UINT32)-1) >> (32 - immWidth);
2845         const INT32  mask8   = (INT32)0xFF;
2846
2847         // Try each of the valid by shift sizes
2848         for (bySh = 0; (bySh < maxBY); bySh++)
2849         {
2850             INT32 curMask   = mask8 << (bySh * 8); // Represents the mask of the bits in the current byteShifted
2851             INT32 checkBits = immMask & ~curMask;
2852             INT32 immCheck  = (imm & checkBits);
2853
2854             // Excluding the current byte (using ~curMask)
2855             //  does the immediate have zero bits in every other bit that we care about?
2856             //  or can be use the shifted one variant?
2857             //  note we care about all 32-bits for EA_4BYTE
2858             //  and we care about the lowest 16 bits for EA_2BYTE
2859             //
2860             if (immCheck == 0)
2861             {
2862                 canEncode = true;
2863             }
2864             if (allow_MSL)
2865             {
2866                 if ((bySh == 1) && (immCheck == 0xFF))
2867                 {
2868                     canEncode = true;
2869                     onesShift = true;
2870                 }
2871                 else if ((bySh == 2) && (immCheck == 0xFFFF))
2872                 {
2873                     canEncode = true;
2874                     onesShift = true;
2875                 }
2876             }
2877             if (canEncode)
2878             {
2879                 imm8 = (unsigned)(((imm & curMask) >> (bySh * 8)) & mask8);
2880                 break;
2881             }
2882         }
2883     }
2884
2885     if (canEncode)
2886     {
2887         // Does the caller want us to return the imm(i8,bySh) encoding values?
2888         //
2889         if (wbBSI != nullptr)
2890         {
2891             wbBSI->immOnes = onesShift;
2892             wbBSI->immBY   = bySh;
2893             wbBSI->immVal  = imm8;
2894
2895             // Verify that what we are returning is correct.
2896             assert(imm == emitDecodeByteShiftedImm(*wbBSI, size));
2897         }
2898         // Tell the caller that we can successfully encode this immediate
2899         // using a 'byteShifted immediate'.
2900         //
2901         return true;
2902     }
2903     return false;
2904 }
2905
2906 /************************************************************************
2907  *
2908  *  Convert a 32-bit immediate into its 'byteShifted immediate' representation imm(i8,by)
2909  */
2910
2911 /*static*/ emitter::byteShiftedImm emitter::emitEncodeByteShiftedImm(INT64 imm, emitAttr size, bool allow_MSL)
2912 {
2913     emitter::byteShiftedImm result;
2914     result.immBSVal = 0;
2915
2916     bool canEncode = canEncodeByteShiftedImm(imm, size, allow_MSL, &result);
2917     assert(canEncode);
2918
2919     return result;
2920 }
2921
2922 /************************************************************************
2923  *
2924  *  Convert a 'float 8-bit immediate' into a double.
2925  *  inputs 'fpImm' a floatImm8 struct
2926  */
2927
2928 /*static*/ double emitter::emitDecodeFloatImm8(const emitter::floatImm8 fpImm)
2929 {
2930     unsigned sign  = fpImm.immSign;
2931     unsigned exp   = fpImm.immExp ^ 0x4;
2932     unsigned mant  = fpImm.immMant + 16;
2933     unsigned scale = 16 * 8;
2934
2935     while (exp > 0)
2936     {
2937         scale /= 2;
2938         exp--;
2939     }
2940
2941     double result = ((double)mant) / ((double)scale);
2942     if (sign == 1)
2943     {
2944         result = -result;
2945     }
2946
2947     return result;
2948 }
2949
2950 /************************************************************************
2951  *
2952  *  returns true if the 'immDbl' can be encoded using the 'float 8-bit immediate' form.
2953  *  also returns the encoding if wbFPI is non-null
2954  *
2955  */
2956
2957 /*static*/ bool emitter::canEncodeFloatImm8(double immDbl, emitter::floatImm8* wbFPI)
2958 {
2959     bool   canEncode = false;
2960     double val       = immDbl;
2961
2962     int sign = 0;
2963     if (val < 0.0)
2964     {
2965         val  = -val;
2966         sign = 1;
2967     }
2968
2969     int exp = 0;
2970     while ((val < 1.0) && (exp >= -4))
2971     {
2972         val *= 2.0;
2973         exp--;
2974     }
2975     while ((val >= 2.0) && (exp <= 5))
2976     {
2977         val *= 0.5;
2978         exp++;
2979     }
2980     exp += 3;
2981     val *= 16.0;
2982     int ival = (int)val;
2983
2984     if ((exp >= 0) && (exp <= 7))
2985     {
2986         if (val == (double)ival)
2987         {
2988             canEncode = true;
2989
2990             if (wbFPI != nullptr)
2991             {
2992                 ival -= 16;
2993                 assert((ival >= 0) && (ival <= 15));
2994
2995                 wbFPI->immSign = sign;
2996                 wbFPI->immExp  = exp ^ 0x4;
2997                 wbFPI->immMant = ival;
2998                 unsigned imm8  = wbFPI->immFPIVal;
2999                 assert((imm8 >= 0) && (imm8 <= 0xff));
3000             }
3001         }
3002     }
3003
3004     return canEncode;
3005 }
3006
3007 /************************************************************************
3008  *
3009  *  Convert a double into its 'float 8-bit immediate' representation
3010  */
3011
3012 /*static*/ emitter::floatImm8 emitter::emitEncodeFloatImm8(double immDbl)
3013 {
3014     emitter::floatImm8 result;
3015     result.immFPIVal = 0;
3016
3017     bool canEncode = canEncodeFloatImm8(immDbl, &result);
3018     assert(canEncode);
3019
3020     return result;
3021 }
3022
3023 /*****************************************************************************
3024  *
3025  *  For the given 'ins' returns the reverse instruction
3026  *  if one exists, otherwise returns INS_INVALID
3027  */
3028
3029 /*static*/ instruction emitter::insReverse(instruction ins)
3030 {
3031     switch (ins)
3032     {
3033         case INS_add:
3034             return INS_sub;
3035         case INS_adds:
3036             return INS_subs;
3037
3038         case INS_sub:
3039             return INS_add;
3040         case INS_subs:
3041             return INS_adds;
3042
3043         case INS_cmp:
3044             return INS_cmn;
3045         case INS_cmn:
3046             return INS_cmp;
3047
3048         case INS_ccmp:
3049             return INS_ccmn;
3050         case INS_ccmn:
3051             return INS_ccmp;
3052
3053         default:
3054             return INS_invalid;
3055     }
3056 }
3057
3058 /*****************************************************************************
3059  *
3060  *  For the given 'datasize' and 'elemsize', make the proper arrangement option
3061  *  returns the insOpts that specifies the vector register arrangement
3062  *  if one does not exist returns INS_OPTS_NONE
3063  */
3064
3065 /*static*/ insOpts emitter::optMakeArrangement(emitAttr datasize, emitAttr elemsize)
3066 {
3067     insOpts result = INS_OPTS_NONE;
3068
3069     if (datasize == EA_8BYTE)
3070     {
3071         switch (elemsize)
3072         {
3073             case EA_1BYTE:
3074                 result = INS_OPTS_8B;
3075                 break;
3076             case EA_2BYTE:
3077                 result = INS_OPTS_4H;
3078                 break;
3079             case EA_4BYTE:
3080                 result = INS_OPTS_2S;
3081                 break;
3082             case EA_8BYTE:
3083                 result = INS_OPTS_1D;
3084                 break;
3085             default:
3086                 unreached();
3087                 break;
3088         }
3089     }
3090     else if (datasize == EA_16BYTE)
3091     {
3092         switch (elemsize)
3093         {
3094             case EA_1BYTE:
3095                 result = INS_OPTS_16B;
3096                 break;
3097             case EA_2BYTE:
3098                 result = INS_OPTS_8H;
3099                 break;
3100             case EA_4BYTE:
3101                 result = INS_OPTS_4S;
3102                 break;
3103             case EA_8BYTE:
3104                 result = INS_OPTS_2D;
3105                 break;
3106             default:
3107                 unreached();
3108                 break;
3109         }
3110     }
3111     return result;
3112 }
3113
3114 /*****************************************************************************
3115  *
3116  *  For the given 'datasize' and arrangement 'opts'
3117  *  returns true is the pair spcifies a valid arrangement
3118  */
3119 /*static*/ bool emitter::isValidArrangement(emitAttr datasize, insOpts opt)
3120 {
3121     if (datasize == EA_8BYTE)
3122     {
3123         if ((opt == INS_OPTS_8B) || (opt == INS_OPTS_4H) || (opt == INS_OPTS_2S) || (opt == INS_OPTS_1D))
3124         {
3125             return true;
3126         }
3127     }
3128     else if (datasize == EA_16BYTE)
3129     {
3130         if ((opt == INS_OPTS_16B) || (opt == INS_OPTS_8H) || (opt == INS_OPTS_4S) || (opt == INS_OPTS_2D))
3131         {
3132             return true;
3133         }
3134     }
3135     return false;
3136 }
3137
3138 //  For the given 'arrangement' returns the 'datasize' specified by the vector register arrangement
3139 //  asserts and returns EA_UNKNOWN if an invalid 'arrangement' value is passed
3140 //
3141 /*static*/ emitAttr emitter::optGetDatasize(insOpts arrangement)
3142 {
3143     if ((arrangement == INS_OPTS_8B) || (arrangement == INS_OPTS_4H) || (arrangement == INS_OPTS_2S) ||
3144         (arrangement == INS_OPTS_1D))
3145     {
3146         return EA_8BYTE;
3147     }
3148     else if ((arrangement == INS_OPTS_16B) || (arrangement == INS_OPTS_8H) || (arrangement == INS_OPTS_4S) ||
3149              (arrangement == INS_OPTS_2D))
3150     {
3151         return EA_16BYTE;
3152     }
3153     else
3154     {
3155         assert(!" invalid 'arrangement' value");
3156         return EA_UNKNOWN;
3157     }
3158 }
3159
3160 //  For the given 'arrangement' returns the 'elemsize' specified by the vector register arrangement
3161 //  asserts and returns EA_UNKNOWN if an invalid 'arrangement' value is passed
3162 //
3163 /*static*/ emitAttr emitter::optGetElemsize(insOpts arrangement)
3164 {
3165     if ((arrangement == INS_OPTS_8B) || (arrangement == INS_OPTS_16B))
3166     {
3167         return EA_1BYTE;
3168     }
3169     else if ((arrangement == INS_OPTS_4H) || (arrangement == INS_OPTS_8H))
3170     {
3171         return EA_2BYTE;
3172     }
3173     else if ((arrangement == INS_OPTS_2S) || (arrangement == INS_OPTS_4S))
3174     {
3175         return EA_4BYTE;
3176     }
3177     else if ((arrangement == INS_OPTS_1D) || (arrangement == INS_OPTS_2D))
3178     {
3179         return EA_8BYTE;
3180     }
3181     else
3182     {
3183         assert(!" invalid 'arrangement' value");
3184         return EA_UNKNOWN;
3185     }
3186 }
3187
3188 //  For the given 'arrangement' returns the 'widen-arrangement' specified by the vector register arrangement
3189 //  asserts and returns INS_OPTS_NONE if an invalid 'arrangement' value is passed
3190 //
3191 /*static*/ insOpts emitter::optWidenElemsize(insOpts arrangement)
3192 {
3193     if ((arrangement == INS_OPTS_8B) || (arrangement == INS_OPTS_16B))
3194     {
3195         return INS_OPTS_8H;
3196     }
3197     else if ((arrangement == INS_OPTS_4H) || (arrangement == INS_OPTS_8H))
3198     {
3199         return INS_OPTS_4S;
3200     }
3201     else if ((arrangement == INS_OPTS_2S) || (arrangement == INS_OPTS_4S))
3202     {
3203         return INS_OPTS_2D;
3204     }
3205     else
3206     {
3207         assert(!" invalid 'arrangement' value");
3208         return INS_OPTS_NONE;
3209     }
3210 }
3211
3212 //  For the given 'conversion' returns the 'dstsize' specified by the conversion option
3213 /*static*/ emitAttr emitter::optGetDstsize(insOpts conversion)
3214 {
3215     switch (conversion)
3216     {
3217         case INS_OPTS_S_TO_8BYTE:
3218         case INS_OPTS_D_TO_8BYTE:
3219         case INS_OPTS_4BYTE_TO_D:
3220         case INS_OPTS_8BYTE_TO_D:
3221         case INS_OPTS_S_TO_D:
3222         case INS_OPTS_H_TO_D:
3223
3224             return EA_8BYTE;
3225
3226         case INS_OPTS_S_TO_4BYTE:
3227         case INS_OPTS_D_TO_4BYTE:
3228         case INS_OPTS_4BYTE_TO_S:
3229         case INS_OPTS_8BYTE_TO_S:
3230         case INS_OPTS_D_TO_S:
3231         case INS_OPTS_H_TO_S:
3232
3233             return EA_4BYTE;
3234
3235         case INS_OPTS_S_TO_H:
3236         case INS_OPTS_D_TO_H:
3237
3238             return EA_2BYTE;
3239
3240         default:
3241             assert(!" invalid 'conversion' value");
3242             return EA_UNKNOWN;
3243     }
3244 }
3245
3246 //  For the given 'conversion' returns the 'srcsize' specified by the conversion option
3247 /*static*/ emitAttr emitter::optGetSrcsize(insOpts conversion)
3248 {
3249     switch (conversion)
3250     {
3251         case INS_OPTS_D_TO_8BYTE:
3252         case INS_OPTS_D_TO_4BYTE:
3253         case INS_OPTS_8BYTE_TO_D:
3254         case INS_OPTS_8BYTE_TO_S:
3255         case INS_OPTS_D_TO_S:
3256         case INS_OPTS_D_TO_H:
3257
3258             return EA_8BYTE;
3259
3260         case INS_OPTS_S_TO_8BYTE:
3261         case INS_OPTS_S_TO_4BYTE:
3262         case INS_OPTS_4BYTE_TO_S:
3263         case INS_OPTS_4BYTE_TO_D:
3264         case INS_OPTS_S_TO_D:
3265         case INS_OPTS_S_TO_H:
3266
3267             return EA_4BYTE;
3268
3269         case INS_OPTS_H_TO_S:
3270         case INS_OPTS_H_TO_D:
3271
3272             return EA_2BYTE;
3273
3274         default:
3275             assert(!" invalid 'conversion' value");
3276             return EA_UNKNOWN;
3277     }
3278 }
3279
3280 //    For the given 'size' and 'index' returns true if it specifies a valid index for a vector register of 'size'
3281 /*static*/ bool emitter::isValidVectorIndex(emitAttr datasize, emitAttr elemsize, ssize_t index)
3282 {
3283     assert(isValidVectorDatasize(datasize));
3284     assert(isValidVectorElemsize(elemsize));
3285
3286     bool result = false;
3287     if (index >= 0)
3288     {
3289         if (datasize == EA_8BYTE)
3290         {
3291             switch (elemsize)
3292             {
3293                 case EA_1BYTE:
3294                     result = (index < 8);
3295                     break;
3296                 case EA_2BYTE:
3297                     result = (index < 4);
3298                     break;
3299                 case EA_4BYTE:
3300                     result = (index < 2);
3301                     break;
3302                 case EA_8BYTE:
3303                     result = (index < 1);
3304                     break;
3305                 default:
3306                     unreached();
3307                     break;
3308             }
3309         }
3310         else if (datasize == EA_16BYTE)
3311         {
3312             switch (elemsize)
3313             {
3314                 case EA_1BYTE:
3315                     result = (index < 16);
3316                     break;
3317                 case EA_2BYTE:
3318                     result = (index < 8);
3319                     break;
3320                 case EA_4BYTE:
3321                     result = (index < 4);
3322                     break;
3323                 case EA_8BYTE:
3324                     result = (index < 2);
3325                     break;
3326                 default:
3327                     unreached();
3328                     break;
3329             }
3330         }
3331     }
3332     return result;
3333 }
3334
3335 /*****************************************************************************
3336  *
3337  *  Add an instruction with no operands.
3338  */
3339
3340 void emitter::emitIns(instruction ins)
3341 {
3342     instrDesc* id  = emitNewInstrSmall(EA_8BYTE);
3343     insFormat  fmt = emitInsFormat(ins);
3344
3345     assert(fmt == IF_SN_0A);
3346
3347     id->idIns(ins);
3348     id->idInsFmt(fmt);
3349
3350     dispIns(id);
3351     appendToCurIG(id);
3352 }
3353
3354 /*****************************************************************************
3355  *
3356  *  Add an instruction with a single immediate value.
3357  */
3358
3359 void emitter::emitIns_I(instruction ins, emitAttr attr, ssize_t imm)
3360 {
3361     insFormat fmt = IF_NONE;
3362
3363     /* Figure out the encoding format of the instruction */
3364     switch (ins)
3365     {
3366         case INS_brk:
3367             if ((imm & 0x0000ffff) == imm)
3368             {
3369                 fmt = IF_SI_0A;
3370             }
3371             else
3372             {
3373                 assert(!"Instruction cannot be encoded: IF_SI_0A");
3374             }
3375             break;
3376         default:
3377             unreached();
3378             break;
3379     }
3380     assert(fmt != IF_NONE);
3381
3382     instrDesc* id = emitNewInstrSC(attr, imm);
3383
3384     id->idIns(ins);
3385     id->idInsFmt(fmt);
3386
3387     dispIns(id);
3388     appendToCurIG(id);
3389 }
3390
3391 /*****************************************************************************
3392  *
3393  *  Add an instruction referencing a single register.
3394  */
3395
3396 void emitter::emitIns_R(instruction ins, emitAttr attr, regNumber reg)
3397 {
3398     emitAttr   size = EA_SIZE(attr);
3399     insFormat  fmt  = IF_NONE;
3400     instrDesc* id   = nullptr;
3401
3402     /* Figure out the encoding format of the instruction */
3403     switch (ins)
3404     {
3405         case INS_br:
3406         case INS_ret:
3407             assert(isGeneralRegister(reg));
3408             id = emitNewInstrSmall(attr);
3409             id->idReg1(reg);
3410             fmt = IF_BR_1A;
3411             break;
3412
3413         default:
3414             unreached();
3415     }
3416
3417     assert(fmt != IF_NONE);
3418
3419     id->idIns(ins);
3420     id->idInsFmt(fmt);
3421
3422     dispIns(id);
3423     appendToCurIG(id);
3424 }
3425
3426 /*****************************************************************************
3427  *
3428  *  Add an instruction referencing a register and a constant.
3429  */
3430
3431 void emitter::emitIns_R_I(instruction ins, emitAttr attr, regNumber reg, ssize_t imm, insOpts opt /* = INS_OPTS_NONE */)
3432 {
3433     emitAttr  size      = EA_SIZE(attr);
3434     emitAttr  elemsize  = EA_UNKNOWN;
3435     insFormat fmt       = IF_NONE;
3436     bool      canEncode = false;
3437
3438     /* Figure out the encoding format of the instruction */
3439     switch (ins)
3440     {
3441         bitMaskImm     bmi;
3442         halfwordImm    hwi;
3443         byteShiftedImm bsi;
3444         ssize_t        notOfImm;
3445
3446         case INS_tst:
3447             assert(insOptsNone(opt));
3448             assert(isGeneralRegister(reg));
3449             bmi.immNRS = 0;
3450             canEncode  = canEncodeBitMaskImm(imm, size, &bmi);
3451             if (canEncode)
3452             {
3453                 imm = bmi.immNRS;
3454                 assert(isValidImmNRS(imm, size));
3455                 fmt = IF_DI_1C;
3456             }
3457             break;
3458
3459         case INS_movk:
3460         case INS_movn:
3461         case INS_movz:
3462             assert(isValidGeneralDatasize(size));
3463             assert(insOptsNone(opt)); // No LSL here (you must use emitIns_R_I_I if a shift is needed)
3464             assert(isGeneralRegister(reg));
3465             assert(isValidUimm16(imm));
3466
3467             hwi.immHW  = 0;
3468             hwi.immVal = imm;
3469             assert(imm == emitDecodeHalfwordImm(hwi, size));
3470
3471             imm       = hwi.immHWVal;
3472             canEncode = true;
3473             fmt       = IF_DI_1B;
3474             break;
3475
3476         case INS_mov:
3477             assert(isValidGeneralDatasize(size));
3478             assert(insOptsNone(opt)); // No explicit LSL here
3479             // We will automatically determine the shift based upon the imm
3480
3481             // First try the standard 'halfword immediate' imm(i16,hw)
3482             hwi.immHWVal = 0;
3483             canEncode    = canEncodeHalfwordImm(imm, size, &hwi);
3484             if (canEncode)
3485             {
3486                 // uses a movz encoding
3487                 assert(isGeneralRegister(reg));
3488                 imm = hwi.immHWVal;
3489                 assert(isValidImmHWVal(imm, size));
3490                 fmt = IF_DI_1B;
3491                 break;
3492             }
3493
3494             // Next try the ones-complement form of 'halfword immediate' imm(i16,hw)
3495             notOfImm  = NOT_helper(imm, getBitWidth(size));
3496             canEncode = canEncodeHalfwordImm(notOfImm, size, &hwi);
3497             if (canEncode)
3498             {
3499                 assert(isGeneralRegister(reg));
3500                 imm = hwi.immHWVal;
3501                 ins = INS_movn; // uses a movn encoding
3502                 assert(isValidImmHWVal(imm, size));
3503                 fmt = IF_DI_1B;
3504                 break;
3505             }
3506
3507             // Finally try the 'bitmask immediate' imm(N,r,s)
3508             bmi.immNRS = 0;
3509             canEncode  = canEncodeBitMaskImm(imm, size, &bmi);
3510             if (canEncode)
3511             {
3512                 assert(isGeneralRegisterOrSP(reg));
3513                 reg = encodingSPtoZR(reg);
3514                 imm = bmi.immNRS;
3515                 assert(isValidImmNRS(imm, size));
3516                 fmt = IF_DI_1D;
3517                 break;
3518             }
3519             else
3520             {
3521                 assert(!"Instruction cannot be encoded: mov imm");
3522             }
3523
3524             break;
3525
3526         case INS_movi:
3527             assert(isValidVectorDatasize(size));
3528             assert(isVectorRegister(reg));
3529             if (insOptsNone(opt) && (size == EA_8BYTE))
3530             {
3531                 opt = INS_OPTS_1D;
3532             }
3533             assert(isValidArrangement(size, opt));
3534             elemsize = optGetElemsize(opt);
3535
3536             if (elemsize == EA_8BYTE)
3537             {
3538                 size_t   uimm = imm;
3539                 ssize_t  imm8 = 0;
3540                 unsigned pos  = 0;
3541                 canEncode     = true;
3542                 bool failed   = false;
3543                 while (uimm != 0)
3544                 {
3545                     INT64 loByte = uimm & 0xFF;
3546                     if (((loByte == 0) || (loByte == 0xFF)) && (pos < 8))
3547                     {
3548                         if (loByte == 0xFF)
3549                         {
3550                             imm8 |= (1 << pos);
3551                         }
3552                         uimm >>= 8;
3553                         pos++;
3554                     }
3555                     else
3556                     {
3557                         canEncode = false;
3558                         break;
3559                     }
3560                 }
3561                 imm = imm8;
3562                 assert(isValidUimm8(imm));
3563                 fmt = IF_DV_1B;
3564                 break;
3565             }
3566             else
3567             {
3568                 // Vector operation
3569
3570                 // No explicit LSL/MSL is used for the immediate
3571                 // We will automatically determine the shift based upon the value of imm
3572
3573                 // First try the standard 'byteShifted immediate' imm(i8,bySh)
3574                 bsi.immBSVal = 0;
3575                 canEncode    = canEncodeByteShiftedImm(imm, elemsize, true, &bsi);
3576                 if (canEncode)
3577                 {
3578                     imm = bsi.immBSVal;
3579                     assert(isValidImmBSVal(imm, size));
3580                     fmt = IF_DV_1B;
3581                     break;
3582                 }
3583
3584                 // Next try the ones-complement form of the 'immediate' imm(i8,bySh)
3585                 if ((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE)) // Only EA_2BYTE or EA_4BYTE forms
3586                 {
3587                     notOfImm  = NOT_helper(imm, getBitWidth(elemsize));
3588                     canEncode = canEncodeByteShiftedImm(notOfImm, elemsize, true, &bsi);
3589                     if (canEncode)
3590                     {
3591                         imm = bsi.immBSVal;
3592                         ins = INS_mvni; // uses a mvni encoding
3593                         assert(isValidImmBSVal(imm, size));
3594                         fmt = IF_DV_1B;
3595                         break;
3596                     }
3597                 }
3598             }
3599             break;
3600
3601         case INS_orr:
3602         case INS_bic:
3603         case INS_mvni:
3604             assert(isValidVectorDatasize(size));
3605             assert(isVectorRegister(reg));
3606             assert(isValidArrangement(size, opt));
3607             elemsize = optGetElemsize(opt);
3608             assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE)); // Only EA_2BYTE or EA_4BYTE forms
3609
3610             // Vector operation
3611
3612             // No explicit LSL/MSL is used for the immediate
3613             // We will automatically determine the shift based upon the value of imm
3614
3615             // First try the standard 'byteShifted immediate' imm(i8,bySh)
3616             bsi.immBSVal = 0;
3617             canEncode    = canEncodeByteShiftedImm(imm, elemsize,
3618                                                 (ins == INS_mvni), // mvni supports the ones shifting variant (aka MSL)
3619                                                 &bsi);
3620             if (canEncode)
3621             {
3622                 imm = bsi.immBSVal;
3623                 assert(isValidImmBSVal(imm, size));
3624                 fmt = IF_DV_1B;
3625                 break;
3626             }
3627             break;
3628
3629         case INS_cmp:
3630         case INS_cmn:
3631             assert(insOptsNone(opt));
3632             assert(isGeneralRegister(reg));
3633
3634             if (unsigned_abs(imm) <= 0x0fff)
3635             {
3636                 if (imm < 0)
3637                 {
3638                     ins = insReverse(ins);
3639                     imm = -imm;
3640                 }
3641                 assert(isValidUimm12(imm));
3642                 canEncode = true;
3643                 fmt       = IF_DI_1A;
3644             }
3645             else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
3646             {
3647                 // Encoding will use a 12-bit left shift of the immediate
3648                 opt = INS_OPTS_LSL12;
3649                 if (imm < 0)
3650                 {
3651                     ins = insReverse(ins);
3652                     imm = -imm;
3653                 }
3654                 assert((imm & 0xfff) == 0);
3655                 imm >>= 12;
3656                 assert(isValidUimm12(imm));
3657                 canEncode = true;
3658                 fmt       = IF_DI_1A;
3659             }
3660             else
3661             {
3662                 assert(!"Instruction cannot be encoded: IF_DI_1A");
3663             }
3664             break;
3665
3666         default:
3667             unreached();
3668             break;
3669
3670     } // end switch (ins)
3671
3672     assert(canEncode);
3673     assert(fmt != IF_NONE);
3674
3675     instrDesc* id = emitNewInstrSC(attr, imm);
3676
3677     id->idIns(ins);
3678     id->idInsFmt(fmt);
3679     id->idInsOpt(opt);
3680
3681     id->idReg1(reg);
3682
3683     dispIns(id);
3684     appendToCurIG(id);
3685 }
3686
3687 /*****************************************************************************
3688  *
3689  *  Add an instruction referencing a register and a floating point constant.
3690  */
3691
3692 void emitter::emitIns_R_F(
3693     instruction ins, emitAttr attr, regNumber reg, double immDbl, insOpts opt /* = INS_OPTS_NONE */)
3694
3695 {
3696     emitAttr  size      = EA_SIZE(attr);
3697     emitAttr  elemsize  = EA_UNKNOWN;
3698     insFormat fmt       = IF_NONE;
3699     ssize_t   imm       = 0;
3700     bool      canEncode = false;
3701
3702     /* Figure out the encoding format of the instruction */
3703     switch (ins)
3704     {
3705         floatImm8 fpi;
3706
3707         case INS_fcmp:
3708         case INS_fcmpe:
3709             assert(insOptsNone(opt));
3710             assert(isValidVectorElemsizeFloat(size));
3711             assert(isVectorRegister(reg));
3712             if (immDbl == 0.0)
3713             {
3714                 canEncode = true;
3715                 fmt       = IF_DV_1C;
3716             }
3717             break;
3718
3719         case INS_fmov:
3720             assert(isVectorRegister(reg));
3721             fpi.immFPIVal = 0;
3722             canEncode     = canEncodeFloatImm8(immDbl, &fpi);
3723
3724             if (insOptsAnyArrangement(opt))
3725             {
3726                 // Vector operation
3727                 assert(isValidVectorDatasize(size));
3728                 assert(isValidArrangement(size, opt));
3729                 elemsize = optGetElemsize(opt);
3730                 assert(isValidVectorElemsizeFloat(elemsize));
3731                 assert(opt != INS_OPTS_1D); // Reserved encoding
3732
3733                 if (canEncode)
3734                 {
3735                     imm = fpi.immFPIVal;
3736                     assert((imm >= 0) && (imm <= 0xff));
3737                     fmt = IF_DV_1B;
3738                 }
3739             }
3740             else
3741             {
3742                 // Scalar operation
3743                 assert(insOptsNone(opt));
3744                 assert(isValidVectorElemsizeFloat(size));
3745
3746                 if (canEncode)
3747                 {
3748                     imm = fpi.immFPIVal;
3749                     assert((imm >= 0) && (imm <= 0xff));
3750                     fmt = IF_DV_1A;
3751                 }
3752             }
3753             break;
3754
3755         default:
3756             unreached();
3757             break;
3758
3759     } // end switch (ins)
3760
3761     assert(canEncode);
3762     assert(fmt != IF_NONE);
3763
3764     instrDesc* id = emitNewInstrSC(attr, imm);
3765
3766     id->idIns(ins);
3767     id->idInsFmt(fmt);
3768     id->idInsOpt(opt);
3769
3770     id->idReg1(reg);
3771
3772     dispIns(id);
3773     appendToCurIG(id);
3774 }
3775
3776 /*****************************************************************************
3777  *
3778  *  Add an instruction referencing two registers
3779  */
3780
3781 void emitter::emitIns_R_R(
3782     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insOpts opt /* = INS_OPTS_NONE */)
3783 {
3784     emitAttr  size     = EA_SIZE(attr);
3785     emitAttr  elemsize = EA_UNKNOWN;
3786     insFormat fmt      = IF_NONE;
3787
3788     /* Figure out the encoding format of the instruction */
3789     switch (ins)
3790     {
3791         case INS_mov:
3792             assert(insOptsNone(opt));
3793             // Is the mov even necessary?
3794             if (reg1 == reg2)
3795             {
3796                 // A mov with a EA_4BYTE has the side-effect of clearing the upper bits
3797                 // So only eliminate mov instructions that are not clearing the upper bits
3798                 //
3799                 if (isGeneralRegisterOrSP(reg1) && (size == EA_8BYTE))
3800                 {
3801                     return;
3802                 }
3803                 else if (isVectorRegister(reg1) && (size == EA_16BYTE))
3804                 {
3805                     return;
3806                 }
3807             }
3808
3809             // Check for the 'mov' aliases for the vector registers
3810             if (isVectorRegister(reg1))
3811             {
3812                 if (isVectorRegister(reg2) && isValidVectorDatasize(size))
3813                 {
3814                     return emitIns_R_R_R(INS_mov, size, reg1, reg2, reg2);
3815                 }
3816                 else
3817                 {
3818                     return emitIns_R_R_I(INS_mov, size, reg1, reg2, 0);
3819                 }
3820             }
3821             else
3822             {
3823                 if (isVectorRegister(reg2))
3824                 {
3825                     assert(isGeneralRegister(reg1));
3826                     return emitIns_R_R_I(INS_mov, size, reg1, reg2, 0);
3827                 }
3828             }
3829
3830             // Is this a MOV to/from SP instruction?
3831             if ((reg1 == REG_SP) || (reg2 == REG_SP))
3832             {
3833                 assert(isGeneralRegisterOrSP(reg1));
3834                 assert(isGeneralRegisterOrSP(reg2));
3835                 reg1 = encodingSPtoZR(reg1);
3836                 reg2 = encodingSPtoZR(reg2);
3837                 fmt  = IF_DR_2G;
3838             }
3839             else
3840             {
3841                 assert(insOptsNone(opt));
3842                 assert(isGeneralRegister(reg1));
3843                 assert(isGeneralRegisterOrZR(reg2));
3844                 fmt = IF_DR_2E;
3845             }
3846             break;
3847
3848         case INS_dup:
3849             // Vector operation
3850             assert(insOptsAnyArrangement(opt));
3851             assert(isVectorRegister(reg1));
3852             assert(isGeneralRegisterOrZR(reg2));
3853             assert(isValidVectorDatasize(size));
3854             assert(isValidArrangement(size, opt));
3855             fmt = IF_DV_2C;
3856             break;
3857
3858         case INS_abs:
3859         case INS_not:
3860             assert(isVectorRegister(reg1));
3861             assert(isVectorRegister(reg2));
3862             if (ins == INS_not)
3863             {
3864                 assert(isValidVectorDatasize(size));
3865                 // Bitwise behavior is independent of element size, but is always encoded as 1 Byte
3866                 opt = optMakeArrangement(size, EA_1BYTE);
3867             }
3868             if (insOptsNone(opt))
3869             {
3870                 // Scalar operation
3871                 assert(size == EA_8BYTE); // Only type D is supported
3872                 fmt = IF_DV_2L;
3873             }
3874             else
3875             {
3876                 // Vector operation
3877                 assert(insOptsAnyArrangement(opt));
3878                 assert(isValidVectorDatasize(size));
3879                 assert(isValidArrangement(size, opt));
3880                 elemsize = optGetElemsize(opt);
3881                 fmt      = IF_DV_2M;
3882             }
3883             break;
3884
3885         case INS_mvn:
3886         case INS_neg:
3887             if (isVectorRegister(reg1))
3888             {
3889                 assert(isVectorRegister(reg2));
3890                 if (ins == INS_mvn)
3891                 {
3892                     assert(isValidVectorDatasize(size));
3893                     // Bitwise behavior is independent of element size, but is always encoded as 1 Byte
3894                     opt = optMakeArrangement(size, EA_1BYTE);
3895                 }
3896                 if (insOptsNone(opt))
3897                 {
3898                     // Scalar operation
3899                     assert(size == EA_8BYTE); // Only type D is supported
3900                     fmt = IF_DV_2L;
3901                 }
3902                 else
3903                 {
3904                     // Vector operation
3905                     assert(isValidVectorDatasize(size));
3906                     assert(isValidArrangement(size, opt));
3907                     elemsize = optGetElemsize(opt);
3908                     fmt      = IF_DV_2M;
3909                 }
3910                 break;
3911             }
3912             __fallthrough;
3913
3914         case INS_negs:
3915             assert(insOptsNone(opt));
3916             assert(isGeneralRegister(reg1));
3917             assert(isGeneralRegisterOrZR(reg2));
3918             fmt = IF_DR_2E;
3919             break;
3920
3921         case INS_sxtw:
3922             assert(size == EA_8BYTE);
3923             __fallthrough;
3924
3925         case INS_sxtb:
3926         case INS_sxth:
3927         case INS_uxtb:
3928         case INS_uxth:
3929             assert(insOptsNone(opt));
3930             assert(isValidGeneralDatasize(size));
3931             assert(isGeneralRegister(reg1));
3932             assert(isGeneralRegister(reg2));
3933             fmt = IF_DR_2H;
3934             break;
3935
3936         case INS_sxtl:
3937         case INS_sxtl2:
3938         case INS_uxtl:
3939         case INS_uxtl2:
3940             return emitIns_R_R_I(ins, size, reg1, reg2, 0, opt);
3941
3942         case INS_cls:
3943         case INS_clz:
3944         case INS_rbit:
3945         case INS_rev16:
3946         case INS_rev32:
3947         case INS_cnt:
3948             if (isVectorRegister(reg1))
3949             {
3950                 assert(isVectorRegister(reg2));
3951                 assert(isValidVectorDatasize(size));
3952                 assert(isValidArrangement(size, opt));
3953                 elemsize = optGetElemsize(opt);
3954                 if ((ins == INS_cls) || (ins == INS_clz))
3955                 {
3956                     assert(elemsize != EA_8BYTE); // No encoding for type D
3957                 }
3958                 else if (ins == INS_rev32)
3959                 {
3960                     assert((elemsize == EA_2BYTE) || (elemsize == EA_1BYTE));
3961                 }
3962                 else
3963                 {
3964                     assert(elemsize == EA_1BYTE); // Only supports 8B or 16B
3965                 }
3966                 fmt = IF_DV_2M;
3967                 break;
3968             }
3969             if (ins == INS_cnt)
3970             {
3971                 // Doesn't have general register version(s)
3972                 break;
3973             }
3974
3975             __fallthrough;
3976
3977         case INS_rev:
3978             assert(insOptsNone(opt));
3979             assert(isGeneralRegister(reg1));
3980             assert(isGeneralRegister(reg2));
3981             if (ins == INS_rev32)
3982             {
3983                 assert(size == EA_8BYTE);
3984             }
3985             else
3986             {
3987                 assert(isValidGeneralDatasize(size));
3988             }
3989             fmt = IF_DR_2G;
3990             break;
3991
3992         case INS_addv:
3993         case INS_saddlv:
3994         case INS_smaxv:
3995         case INS_sminv:
3996         case INS_uaddlv:
3997         case INS_umaxv:
3998         case INS_uminv:
3999         case INS_rev64:
4000             assert(isVectorRegister(reg1));
4001             assert(isVectorRegister(reg2));
4002             assert(isValidVectorDatasize(size));
4003             assert(isValidArrangement(size, opt));
4004             elemsize = optGetElemsize(opt);
4005             assert(elemsize != EA_8BYTE); // No encoding for type D
4006             fmt = IF_DV_2M;
4007             break;
4008
4009         case INS_xtn:
4010         case INS_xtn2:
4011             assert(isVectorRegister(reg1));
4012             assert(isVectorRegister(reg2));
4013             assert(isValidVectorDatasize(size));
4014             assert(isValidArrangement(size, opt));
4015             elemsize = optGetElemsize(opt);
4016             // size is determined by instruction
4017             if (ins == INS_xtn)
4018             {
4019                 assert(size == EA_8BYTE);
4020             }
4021             else // ins == INS_xtn2
4022             {
4023                 assert(size == EA_16BYTE);
4024             }
4025             assert(elemsize != EA_8BYTE); // Narrowing must not end with 8 byte data
4026             fmt = IF_DV_2M;
4027             break;
4028
4029         case INS_ldar:
4030         case INS_ldaxr:
4031         case INS_ldxr:
4032         case INS_stlr:
4033             assert(isValidGeneralDatasize(size));
4034
4035             __fallthrough;
4036
4037         case INS_ldarb:
4038         case INS_ldaxrb:
4039         case INS_ldxrb:
4040         case INS_ldarh:
4041         case INS_ldaxrh:
4042         case INS_ldxrh:
4043         case INS_stlrb:
4044         case INS_stlrh:
4045             assert(isValidGeneralLSDatasize(size));
4046             assert(isGeneralRegisterOrZR(reg1));
4047             assert(isGeneralRegisterOrSP(reg2));
4048             assert(insOptsNone(opt));
4049
4050             reg2 = encodingSPtoZR(reg2);
4051
4052             fmt = IF_LS_2A;
4053             break;
4054
4055         case INS_ldr:
4056         case INS_ldrb:
4057         case INS_ldrh:
4058         case INS_ldrsb:
4059         case INS_ldrsh:
4060         case INS_ldrsw:
4061         case INS_str:
4062         case INS_strb:
4063         case INS_strh:
4064
4065         case INS_cmp:
4066         case INS_cmn:
4067         case INS_tst:
4068             assert(insOptsNone(opt));
4069             emitIns_R_R_I(ins, attr, reg1, reg2, 0, INS_OPTS_NONE);
4070             return;
4071
4072         case INS_staddb:
4073             emitIns_R_R_R(INS_ldaddb, attr, reg1, REG_ZR, reg2);
4074             return;
4075         case INS_staddlb:
4076             emitIns_R_R_R(INS_ldaddlb, attr, reg1, REG_ZR, reg2);
4077             return;
4078         case INS_staddh:
4079             emitIns_R_R_R(INS_ldaddh, attr, reg1, REG_ZR, reg2);
4080             return;
4081         case INS_staddlh:
4082             emitIns_R_R_R(INS_ldaddlh, attr, reg1, REG_ZR, reg2);
4083             return;
4084         case INS_stadd:
4085             emitIns_R_R_R(INS_ldadd, attr, reg1, REG_ZR, reg2);
4086             return;
4087         case INS_staddl:
4088             emitIns_R_R_R(INS_ldaddl, attr, reg1, REG_ZR, reg2);
4089             return;
4090
4091         case INS_fmov:
4092             assert(isValidVectorElemsizeFloat(size));
4093
4094             // Is the mov even necessary?
4095             if (reg1 == reg2)
4096             {
4097                 return;
4098             }
4099
4100             if (isVectorRegister(reg1))
4101             {
4102                 if (isVectorRegister(reg2))
4103                 {
4104                     assert(insOptsNone(opt));
4105                     fmt = IF_DV_2G;
4106                 }
4107                 else
4108                 {
4109                     assert(isGeneralRegister(reg2));
4110
4111                     // if the optional conversion specifier is not present we calculate it
4112                     if (opt == INS_OPTS_NONE)
4113                     {
4114                         opt = (size == EA_4BYTE) ? INS_OPTS_4BYTE_TO_S : INS_OPTS_8BYTE_TO_D;
4115                     }
4116                     assert(insOptsConvertIntToFloat(opt));
4117
4118                     fmt = IF_DV_2I;
4119                 }
4120             }
4121             else
4122             {
4123                 assert(isGeneralRegister(reg1));
4124                 assert(isVectorRegister(reg2));
4125
4126                 // if the optional conversion specifier is not present we calculate it
4127                 if (opt == INS_OPTS_NONE)
4128                 {
4129                     opt = (size == EA_4BYTE) ? INS_OPTS_S_TO_4BYTE : INS_OPTS_D_TO_8BYTE;
4130                 }
4131                 assert(insOptsConvertFloatToInt(opt));
4132
4133                 fmt = IF_DV_2H;
4134             }
4135             break;
4136
4137         case INS_fcmp:
4138         case INS_fcmpe:
4139             assert(insOptsNone(opt));
4140             assert(isValidVectorElemsizeFloat(size));
4141             assert(isVectorRegister(reg1));
4142             assert(isVectorRegister(reg2));
4143             fmt = IF_DV_2K;
4144             break;
4145
4146         case INS_fcvtns:
4147         case INS_fcvtnu:
4148         case INS_fcvtas:
4149         case INS_fcvtau:
4150         case INS_fcvtps:
4151         case INS_fcvtpu:
4152         case INS_fcvtms:
4153         case INS_fcvtmu:
4154         case INS_fcvtzs:
4155         case INS_fcvtzu:
4156             if (insOptsAnyArrangement(opt))
4157             {
4158                 // Vector operation
4159                 assert(isVectorRegister(reg1));
4160                 assert(isVectorRegister(reg2));
4161                 assert(isValidVectorDatasize(size));
4162                 assert(isValidArrangement(size, opt));
4163                 elemsize = optGetElemsize(opt);
4164                 assert(isValidVectorElemsizeFloat(elemsize));
4165                 assert(opt != INS_OPTS_1D); // Reserved encoding
4166                 fmt = IF_DV_2A;
4167             }
4168             else
4169             {
4170                 // Scalar operation
4171                 assert(isVectorRegister(reg2));
4172                 if (isVectorRegister(reg1))
4173                 {
4174                     assert(insOptsNone(opt));
4175                     assert(isValidVectorElemsizeFloat(size));
4176                     fmt = IF_DV_2G;
4177                 }
4178                 else
4179                 {
4180                     assert(isGeneralRegister(reg1));
4181                     assert(insOptsConvertFloatToInt(opt));
4182                     assert(isValidVectorElemsizeFloat(size));
4183                     fmt = IF_DV_2H;
4184                 }
4185             }
4186             break;
4187
4188         case INS_fcvtl:
4189         case INS_fcvtl2:
4190         case INS_fcvtn:
4191         case INS_fcvtn2:
4192             assert(isVectorRegister(reg1));
4193             assert(isVectorRegister(reg2));
4194             assert(isValidVectorDatasize(size));
4195             assert(insOptsNone(opt));
4196             assert(size == EA_8BYTE); // Narrowing from Double or Widening to Double (Half not supported)
4197             fmt = IF_DV_2G;
4198             break;
4199
4200         case INS_scvtf:
4201         case INS_ucvtf:
4202             if (insOptsAnyArrangement(opt))
4203             {
4204                 // Vector operation
4205                 assert(isVectorRegister(reg1));
4206                 assert(isVectorRegister(reg2));
4207                 assert(isValidVectorDatasize(size));
4208                 assert(isValidArrangement(size, opt));
4209                 elemsize = optGetElemsize(opt);
4210                 assert(isValidVectorElemsizeFloat(elemsize));
4211                 assert(opt != INS_OPTS_1D); // Reserved encoding
4212                 fmt = IF_DV_2A;
4213             }
4214             else
4215             {
4216                 // Scalar operation
4217                 assert(isVectorRegister(reg1));
4218                 if (isVectorRegister(reg2))
4219                 {
4220                     assert(insOptsNone(opt));
4221                     assert(isValidVectorElemsizeFloat(size));
4222                     fmt = IF_DV_2G;
4223                 }
4224                 else
4225                 {
4226                     assert(isGeneralRegister(reg2));
4227                     assert(insOptsConvertIntToFloat(opt));
4228                     assert(isValidVectorElemsizeFloat(size));
4229                     fmt = IF_DV_2I;
4230                 }
4231             }
4232             break;
4233
4234         case INS_fabs:
4235         case INS_fneg:
4236         case INS_fsqrt:
4237         case INS_frinta:
4238         case INS_frinti:
4239         case INS_frintm:
4240         case INS_frintn:
4241         case INS_frintp:
4242         case INS_frintx:
4243         case INS_frintz:
4244             if (insOptsAnyArrangement(opt))
4245             {
4246                 // Vector operation
4247                 assert(isVectorRegister(reg1));
4248                 assert(isVectorRegister(reg2));
4249                 assert(isValidVectorDatasize(size));
4250                 assert(isValidArrangement(size, opt));
4251                 elemsize = optGetElemsize(opt);
4252                 assert(isValidVectorElemsizeFloat(elemsize));
4253                 assert(opt != INS_OPTS_1D); // Reserved encoding
4254                 fmt = IF_DV_2A;
4255             }
4256             else
4257             {
4258                 // Scalar operation
4259                 assert(insOptsNone(opt));
4260                 assert(isValidVectorElemsizeFloat(size));
4261                 assert(isVectorRegister(reg1));
4262                 assert(isVectorRegister(reg2));
4263                 fmt = IF_DV_2G;
4264             }
4265             break;
4266
4267         case INS_faddp:
4268             // Scalar operation
4269             assert(insOptsNone(opt));
4270             assert(isValidVectorElemsizeFloat(size));
4271             assert(isVectorRegister(reg1));
4272             assert(isVectorRegister(reg2));
4273             fmt = IF_DV_2G;
4274             break;
4275
4276         case INS_fcvt:
4277             assert(insOptsConvertFloatToFloat(opt));
4278             assert(isValidVectorFcvtsize(size));
4279             assert(isVectorRegister(reg1));
4280             assert(isVectorRegister(reg2));
4281             fmt = IF_DV_2J;
4282             break;
4283
4284         case INS_cmeq:
4285         case INS_cmge:
4286         case INS_cmgt:
4287         case INS_cmle:
4288         case INS_cmlt:
4289             assert(isVectorRegister(reg1));
4290             assert(isVectorRegister(reg2));
4291
4292             if (isValidVectorDatasize(size))
4293             {
4294                 // Vector operation
4295                 assert(insOptsAnyArrangement(opt));
4296                 assert(isValidArrangement(size, opt));
4297                 elemsize = optGetElemsize(opt);
4298                 fmt      = IF_DV_2M;
4299             }
4300             else
4301             {
4302                 NYI("Untested");
4303                 // Scalar operation
4304                 assert(size == EA_8BYTE); // Only Double supported
4305                 fmt = IF_DV_2L;
4306             }
4307             break;
4308
4309         case INS_fcmeq:
4310         case INS_fcmge:
4311         case INS_fcmgt:
4312         case INS_fcmle:
4313         case INS_fcmlt:
4314             assert(isVectorRegister(reg1));
4315             assert(isVectorRegister(reg2));
4316
4317             if (isValidVectorDatasize(size))
4318             {
4319                 // Vector operation
4320                 assert(insOptsAnyArrangement(opt));
4321                 assert(isValidArrangement(size, opt));
4322                 elemsize = optGetElemsize(opt);
4323                 assert((elemsize == EA_8BYTE) || (elemsize == EA_4BYTE)); // Only Double/Float supported
4324                 assert(opt != INS_OPTS_1D);                               // Reserved encoding
4325                 fmt = IF_DV_2A;
4326             }
4327             else
4328             {
4329                 NYI("Untested");
4330                 // Scalar operation
4331                 assert((size == EA_8BYTE) || (size == EA_4BYTE)); // Only Double/Float supported
4332                 fmt = IF_DV_2G;
4333             }
4334             break;
4335         case INS_aesd:
4336         case INS_aese:
4337         case INS_aesmc:
4338         case INS_aesimc:
4339             assert(isVectorRegister(reg1));
4340             assert(isVectorRegister(reg2));
4341             assert(isValidVectorDatasize(size));
4342             elemsize = optGetElemsize(opt);
4343             assert(elemsize == EA_1BYTE);
4344             fmt = IF_DV_2P;
4345             break;
4346
4347         case INS_sha1h:
4348             assert(insOptsNone(opt));
4349             assert(isVectorRegister(reg1));
4350             assert(isVectorRegister(reg2));
4351             fmt = IF_DR_2J;
4352             break;
4353
4354         case INS_sha256su0:
4355         case INS_sha1su1:
4356             assert(isVectorRegister(reg1));
4357             assert(isVectorRegister(reg2));
4358             assert(isValidVectorDatasize(size));
4359             elemsize = optGetElemsize(opt);
4360             assert(elemsize == EA_4BYTE);
4361             fmt = IF_DV_2P;
4362             break;
4363
4364         default:
4365             unreached();
4366             break;
4367
4368     } // end switch (ins)
4369
4370     assert(fmt != IF_NONE);
4371
4372     instrDesc* id = emitNewInstrSmall(attr);
4373
4374     id->idIns(ins);
4375     id->idInsFmt(fmt);
4376     id->idInsOpt(opt);
4377
4378     id->idReg1(reg1);
4379     id->idReg2(reg2);
4380
4381     dispIns(id);
4382     appendToCurIG(id);
4383 }
4384
4385 /*****************************************************************************
4386  *
4387  *  Add an instruction referencing a register and two constants.
4388  */
4389
4390 void emitter::emitIns_R_I_I(
4391     instruction ins, emitAttr attr, regNumber reg, ssize_t imm1, ssize_t imm2, insOpts opt /* = INS_OPTS_NONE */)
4392 {
4393     emitAttr  size   = EA_SIZE(attr);
4394     insFormat fmt    = IF_NONE;
4395     size_t    immOut = 0; // composed from imm1 and imm2 and stored in the instrDesc
4396
4397     /* Figure out the encoding format of the instruction */
4398     switch (ins)
4399     {
4400         bool        canEncode;
4401         halfwordImm hwi;
4402
4403         case INS_mov:
4404             ins = INS_movz; // INS_mov with LSL is an alias for INS_movz LSL
4405             __fallthrough;
4406
4407         case INS_movk:
4408         case INS_movn:
4409         case INS_movz:
4410             assert(isValidGeneralDatasize(size));
4411             assert(isGeneralRegister(reg));
4412             assert(isValidUimm16(imm1));
4413             assert(insOptsLSL(opt)); // Must be INS_OPTS_LSL
4414
4415             if (size == EA_8BYTE)
4416             {
4417                 assert((imm2 == 0) || (imm2 == 16) || // shift amount: 0, 16, 32 or 48
4418                        (imm2 == 32) || (imm2 == 48));
4419             }
4420             else // EA_4BYTE
4421             {
4422                 assert((imm2 == 0) || (imm2 == 16)); // shift amount: 0 or 16
4423             }
4424
4425             hwi.immHWVal = 0;
4426
4427             switch (imm2)
4428             {
4429                 case 0:
4430                     hwi.immHW = 0;
4431                     canEncode = true;
4432                     break;
4433
4434                 case 16:
4435                     hwi.immHW = 1;
4436                     canEncode = true;
4437                     break;
4438
4439                 case 32:
4440                     hwi.immHW = 2;
4441                     canEncode = true;
4442                     break;
4443
4444                 case 48:
4445                     hwi.immHW = 3;
4446                     canEncode = true;
4447                     break;
4448
4449                 default:
4450                     canEncode = false;
4451             }
4452
4453             if (canEncode)
4454             {
4455                 hwi.immVal = imm1;
4456
4457                 immOut = hwi.immHWVal;
4458                 assert(isValidImmHWVal(immOut, size));
4459                 fmt = IF_DI_1B;
4460             }
4461             break;
4462
4463         default:
4464             unreached();
4465             break;
4466
4467     } // end switch (ins)
4468
4469     assert(fmt != IF_NONE);
4470
4471     instrDesc* id = emitNewInstrSC(attr, immOut);
4472
4473     id->idIns(ins);
4474     id->idInsFmt(fmt);
4475
4476     id->idReg1(reg);
4477
4478     dispIns(id);
4479     appendToCurIG(id);
4480 }
4481
4482 /*****************************************************************************
4483  *
4484  *  Add an instruction referencing two registers and a constant.
4485  */
4486
4487 void emitter::emitIns_R_R_I(
4488     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm, insOpts opt /* = INS_OPTS_NONE */)
4489 {
4490     emitAttr  size       = EA_SIZE(attr);
4491     emitAttr  elemsize   = EA_UNKNOWN;
4492     insFormat fmt        = IF_NONE;
4493     bool      isLdSt     = false;
4494     bool      isSIMD     = false;
4495     bool      isAddSub   = false;
4496     bool      setFlags   = false;
4497     unsigned  scale      = 0;
4498     bool      unscaledOp = false;
4499
4500     /* Figure out the encoding format of the instruction */
4501     switch (ins)
4502     {
4503         bool       canEncode;
4504         bitMaskImm bmi;
4505
4506         case INS_mov:
4507             // Check for the 'mov' aliases for the vector registers
4508             assert(insOptsNone(opt));
4509             assert(isValidVectorElemsize(size));
4510             elemsize = size;
4511             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4512
4513             if (isVectorRegister(reg1))
4514             {
4515                 if (isGeneralRegisterOrZR(reg2))
4516                 {
4517                     fmt = IF_DV_2C; // Alias for 'ins'
4518                     break;
4519                 }
4520                 else if (isVectorRegister(reg2))
4521                 {
4522                     fmt = IF_DV_2E; // Alias for 'dup'
4523                     break;
4524                 }
4525             }
4526             else // isGeneralRegister(reg1)
4527             {
4528                 assert(isGeneralRegister(reg1));
4529                 if (isVectorRegister(reg2))
4530                 {
4531                     fmt = IF_DV_2B; // Alias for 'umov'
4532                     break;
4533                 }
4534             }
4535             assert(!" invalid INS_mov operands");
4536             break;
4537
4538         case INS_lsl:
4539         case INS_lsr:
4540         case INS_asr:
4541             assert(insOptsNone(opt));
4542             assert(isValidGeneralDatasize(size));
4543             assert(isGeneralRegister(reg1));
4544             assert(isGeneralRegister(reg2));
4545             assert(isValidImmShift(imm, size));
4546             fmt = IF_DI_2D;
4547             break;
4548
4549         case INS_ror:
4550             assert(insOptsNone(opt));
4551             assert(isValidGeneralDatasize(size));
4552             assert(isGeneralRegister(reg1));
4553             assert(isGeneralRegister(reg2));
4554             assert(isValidImmShift(imm, size));
4555             fmt = IF_DI_2B;
4556             break;
4557
4558         case INS_sshr:
4559         case INS_ssra:
4560         case INS_srshr:
4561         case INS_srsra:
4562         case INS_shl:
4563         case INS_ushr:
4564         case INS_usra:
4565         case INS_urshr:
4566         case INS_ursra:
4567         case INS_sri:
4568         case INS_sli:
4569             assert(isVectorRegister(reg1));
4570             assert(isVectorRegister(reg2));
4571             if (insOptsAnyArrangement(opt))
4572             {
4573                 // Vector operation
4574                 assert(isValidVectorDatasize(size));
4575                 assert(isValidArrangement(size, opt));
4576                 elemsize = optGetElemsize(opt);
4577                 assert(isValidVectorElemsize(elemsize));
4578                 assert(isValidImmShift(imm, elemsize));
4579                 assert(opt != INS_OPTS_1D); // Reserved encoding
4580                 fmt = IF_DV_2O;
4581                 break;
4582             }
4583             else
4584             {
4585                 // Scalar operation
4586                 assert(insOptsNone(opt));
4587                 assert(size == EA_8BYTE); // only supported size
4588                 assert(isValidImmShift(imm, size));
4589                 fmt = IF_DV_2N;
4590             }
4591             break;
4592
4593         case INS_sxtl:
4594         case INS_uxtl:
4595             assert(imm == 0);
4596             __fallthrough;
4597
4598         case INS_shrn:
4599         case INS_rshrn:
4600         case INS_sshll:
4601         case INS_ushll:
4602             assert(isVectorRegister(reg1));
4603             assert(isVectorRegister(reg2));
4604             // Vector operation
4605             assert(size == EA_8BYTE);
4606             assert(isValidArrangement(size, opt));
4607             elemsize = optGetElemsize(opt);
4608             assert(elemsize != EA_8BYTE); // Reserved encodings
4609             assert(isValidVectorElemsize(elemsize));
4610             assert(isValidImmShift(imm, elemsize));
4611             fmt = IF_DV_2O;
4612             break;
4613
4614         case INS_sxtl2:
4615         case INS_uxtl2:
4616             assert(imm == 0);
4617             __fallthrough;
4618
4619         case INS_shrn2:
4620         case INS_rshrn2:
4621         case INS_sshll2:
4622         case INS_ushll2:
4623             assert(isVectorRegister(reg1));
4624             assert(isVectorRegister(reg2));
4625             // Vector operation
4626             assert(size == EA_16BYTE);
4627             assert(isValidArrangement(size, opt));
4628             elemsize = optGetElemsize(opt);
4629             assert(elemsize != EA_8BYTE); // Reserved encodings
4630             assert(isValidVectorElemsize(elemsize));
4631             assert(isValidImmShift(imm, elemsize));
4632             fmt = IF_DV_2O;
4633             break;
4634
4635         case INS_mvn:
4636         case INS_neg:
4637         case INS_negs:
4638             assert(isValidGeneralDatasize(size));
4639             assert(isGeneralRegister(reg1));
4640             assert(isGeneralRegisterOrZR(reg2));
4641
4642             if (imm == 0)
4643             {
4644                 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4645
4646                 fmt = IF_DR_2E;
4647             }
4648             else
4649             {
4650                 if (ins == INS_mvn)
4651                 {
4652                     assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
4653                 }
4654                 else // neg or negs
4655                 {
4656                     assert(insOptsAluShift(opt)); // a non-zero imm, must select shift kind, can't use ROR
4657                 }
4658                 assert(isValidImmShift(imm, size));
4659                 fmt = IF_DR_2F;
4660             }
4661             break;
4662
4663         case INS_tst:
4664             assert(isValidGeneralDatasize(size));
4665             assert(isGeneralRegisterOrZR(reg1));
4666             assert(isGeneralRegister(reg2));
4667
4668             if (insOptsAnyShift(opt))
4669             {
4670                 assert(isValidImmShift(imm, size) && (imm != 0));
4671                 fmt = IF_DR_2B;
4672             }
4673             else
4674             {
4675                 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4676                 assert(imm == 0);
4677                 fmt = IF_DR_2A;
4678             }
4679             break;
4680
4681         case INS_cmp:
4682         case INS_cmn:
4683             assert(isValidGeneralDatasize(size));
4684             assert(isGeneralRegisterOrSP(reg1));
4685             assert(isGeneralRegister(reg2));
4686
4687             reg1 = encodingSPtoZR(reg1);
4688             if (insOptsAnyExtend(opt))
4689             {
4690                 assert((imm >= 0) && (imm <= 4));
4691
4692                 fmt = IF_DR_2C;
4693             }
4694             else if (imm == 0)
4695             {
4696                 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4697
4698                 fmt = IF_DR_2A;
4699             }
4700             else
4701             {
4702                 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
4703                 assert(isValidImmShift(imm, size));
4704                 fmt = IF_DR_2B;
4705             }
4706             break;
4707
4708         case INS_ands:
4709         case INS_and:
4710         case INS_eor:
4711         case INS_orr:
4712             assert(insOptsNone(opt));
4713             assert(isGeneralRegister(reg2));
4714             if (ins == INS_ands)
4715             {
4716                 assert(isGeneralRegister(reg1));
4717             }
4718             else
4719             {
4720                 assert(isGeneralRegisterOrSP(reg1));
4721                 reg1 = encodingSPtoZR(reg1);
4722             }
4723
4724             bmi.immNRS = 0;
4725             canEncode  = canEncodeBitMaskImm(imm, size, &bmi);
4726             if (canEncode)
4727             {
4728                 imm = bmi.immNRS;
4729                 assert(isValidImmNRS(imm, size));
4730                 fmt = IF_DI_2C;
4731             }
4732             break;
4733
4734         case INS_dup: // by element, imm selects the element of reg2
4735             assert(isVectorRegister(reg1));
4736             if (isVectorRegister(reg2))
4737             {
4738                 if (insOptsAnyArrangement(opt))
4739                 {
4740                     // Vector operation
4741                     assert(isValidVectorDatasize(size));
4742                     assert(isValidArrangement(size, opt));
4743                     elemsize = optGetElemsize(opt);
4744                     assert(isValidVectorElemsize(elemsize));
4745                     assert(isValidVectorIndex(size, elemsize, imm));
4746                     assert(opt != INS_OPTS_1D); // Reserved encoding
4747                     fmt = IF_DV_2D;
4748                     break;
4749                 }
4750                 else
4751                 {
4752                     // Scalar operation
4753                     assert(insOptsNone(opt));
4754                     elemsize = size;
4755                     assert(isValidVectorElemsize(elemsize));
4756                     assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4757                     fmt = IF_DV_2E;
4758                     break;
4759                 }
4760             }
4761             __fallthrough;
4762
4763         case INS_ins: // (MOV from general)
4764             assert(insOptsNone(opt));
4765             assert(isValidVectorElemsize(size));
4766             assert(isVectorRegister(reg1));
4767             assert(isGeneralRegisterOrZR(reg2));
4768             elemsize = size;
4769             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4770             fmt = IF_DV_2C;
4771             break;
4772
4773         case INS_umov: // (MOV to general)
4774             assert(insOptsNone(opt));
4775             assert(isValidVectorElemsize(size));
4776             assert(isGeneralRegister(reg1));
4777             assert(isVectorRegister(reg2));
4778             elemsize = size;
4779             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4780             fmt = IF_DV_2B;
4781             break;
4782
4783         case INS_smov:
4784             assert(insOptsNone(opt));
4785             assert(isValidVectorElemsize(size));
4786             assert(size != EA_8BYTE); // no encoding, use INS_umov
4787             assert(isGeneralRegister(reg1));
4788             assert(isVectorRegister(reg2));
4789             elemsize = size;
4790             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4791             fmt = IF_DV_2B;
4792             break;
4793
4794         case INS_add:
4795         case INS_sub:
4796             setFlags = false;
4797             isAddSub = true;
4798             break;
4799
4800         case INS_adds:
4801         case INS_subs:
4802             setFlags = true;
4803             isAddSub = true;
4804             break;
4805
4806         case INS_ldrsb:
4807         case INS_ldursb:
4808             // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4809             assert(isValidGeneralDatasize(size));
4810             unscaledOp = (ins == INS_ldursb);
4811             scale      = 0;
4812             isLdSt     = true;
4813             break;
4814
4815         case INS_ldrsh:
4816         case INS_ldursh:
4817             // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4818             assert(isValidGeneralDatasize(size));
4819             unscaledOp = (ins == INS_ldursh);
4820             scale      = 1;
4821             isLdSt     = true;
4822             break;
4823
4824         case INS_ldrsw:
4825         case INS_ldursw:
4826             // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4827             assert(size == EA_8BYTE);
4828             unscaledOp = (ins == INS_ldursw);
4829             scale      = 2;
4830             isLdSt     = true;
4831             break;
4832
4833         case INS_ldrb:
4834         case INS_strb:
4835             // size is ignored
4836             unscaledOp = false;
4837             scale      = 0;
4838             isLdSt     = true;
4839             break;
4840
4841         case INS_ldurb:
4842         case INS_sturb:
4843             // size is ignored
4844             unscaledOp = true;
4845             scale      = 0;
4846             isLdSt     = true;
4847             break;
4848
4849         case INS_ldrh:
4850         case INS_strh:
4851             // size is ignored
4852             unscaledOp = false;
4853             scale      = 1;
4854             isLdSt     = true;
4855             break;
4856
4857         case INS_ldurh:
4858         case INS_sturh:
4859             // size is ignored
4860             unscaledOp = true;
4861             scale      = 0;
4862             isLdSt     = true;
4863             break;
4864
4865         case INS_ldr:
4866         case INS_str:
4867             // Is the target a vector register?
4868             if (isVectorRegister(reg1))
4869             {
4870                 assert(isValidVectorLSDatasize(size));
4871                 assert(isGeneralRegisterOrSP(reg2));
4872                 isSIMD = true;
4873             }
4874             else
4875             {
4876                 assert(isValidGeneralDatasize(size));
4877             }
4878             unscaledOp = false;
4879             scale      = NaturalScale_helper(size);
4880             isLdSt     = true;
4881             break;
4882
4883         case INS_ldur:
4884         case INS_stur:
4885             // Is the target a vector register?
4886             if (isVectorRegister(reg1))
4887             {
4888                 assert(isValidVectorLSDatasize(size));
4889                 assert(isGeneralRegisterOrSP(reg2));
4890                 isSIMD = true;
4891             }
4892             else
4893             {
4894                 assert(isValidGeneralDatasize(size));
4895             }
4896             unscaledOp = true;
4897             scale      = 0;
4898             isLdSt     = true;
4899             break;
4900
4901         default:
4902             unreached();
4903             break;
4904
4905     } // end switch (ins)
4906
4907     if (isLdSt)
4908     {
4909         assert(!isAddSub);
4910
4911         if (isSIMD)
4912         {
4913             assert(isValidVectorLSDatasize(size));
4914             assert(isVectorRegister(reg1));
4915             assert((scale >= 0) && (scale <= 4));
4916         }
4917         else
4918         {
4919             assert(isValidGeneralLSDatasize(size));
4920             assert(isGeneralRegisterOrZR(reg1));
4921             assert((scale >= 0) && (scale <= 3));
4922         }
4923
4924         assert(isGeneralRegisterOrSP(reg2));
4925
4926         // Load/Store reserved encodings:
4927         if (insOptsIndexed(opt))
4928         {
4929             assert(reg1 != reg2);
4930         }
4931
4932         reg2 = encodingSPtoZR(reg2);
4933
4934         ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
4935         if (imm == 0)
4936         {
4937             assert(insOptsNone(opt)); // PRE/POST Index doesn't make sense with an immediate of zero
4938
4939             fmt = IF_LS_2A;
4940         }
4941         else if (insOptsIndexed(opt) || unscaledOp || (imm < 0) || ((imm & mask) != 0))
4942         {
4943             if ((imm >= -256) && (imm <= 255))
4944             {
4945                 fmt = IF_LS_2C;
4946             }
4947             else
4948             {
4949                 assert(!"Instruction cannot be encoded: IF_LS_2C");
4950             }
4951         }
4952         else if (imm > 0)
4953         {
4954             assert(insOptsNone(opt));
4955             assert(!unscaledOp);
4956
4957             if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
4958             {
4959                 imm >>= scale; // The immediate is scaled by the size of the ld/st
4960
4961                 fmt = IF_LS_2B;
4962             }
4963             else
4964             {
4965                 assert(!"Instruction cannot be encoded: IF_LS_2B");
4966             }
4967         }
4968     }
4969     else if (isAddSub)
4970     {
4971         assert(!isLdSt);
4972         assert(insOptsNone(opt));
4973
4974         if (setFlags) // Can't encode SP with setFlags
4975         {
4976             assert(isGeneralRegister(reg1));
4977             assert(isGeneralRegister(reg2));
4978         }
4979         else
4980         {
4981             assert(isGeneralRegisterOrSP(reg1));
4982             assert(isGeneralRegisterOrSP(reg2));
4983
4984             // Is it just a mov?
4985             if (imm == 0)
4986             {
4987                 // Is the mov even necessary?
4988                 if (reg1 != reg2)
4989                 {
4990                     emitIns_R_R(INS_mov, attr, reg1, reg2);
4991                 }
4992                 return;
4993             }
4994
4995             reg1 = encodingSPtoZR(reg1);
4996             reg2 = encodingSPtoZR(reg2);
4997         }
4998
4999         if (unsigned_abs(imm) <= 0x0fff)
5000         {
5001             if (imm < 0)
5002             {
5003                 ins = insReverse(ins);
5004                 imm = -imm;
5005             }
5006             assert(isValidUimm12(imm));
5007             fmt = IF_DI_2A;
5008         }
5009         else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
5010         {
5011             // Encoding will use a 12-bit left shift of the immediate
5012             opt = INS_OPTS_LSL12;
5013             if (imm < 0)
5014             {
5015                 ins = insReverse(ins);
5016                 imm = -imm;
5017             }
5018             assert((imm & 0xfff) == 0);
5019             imm >>= 12;
5020             assert(isValidUimm12(imm));
5021             fmt = IF_DI_2A;
5022         }
5023         else
5024         {
5025             assert(!"Instruction cannot be encoded: IF_DI_2A");
5026         }
5027     }
5028
5029     assert(fmt != IF_NONE);
5030
5031     instrDesc* id = emitNewInstrSC(attr, imm);
5032
5033     id->idIns(ins);
5034     id->idInsFmt(fmt);
5035     id->idInsOpt(opt);
5036
5037     id->idReg1(reg1);
5038     id->idReg2(reg2);
5039
5040     dispIns(id);
5041     appendToCurIG(id);
5042 }
5043
5044 /*****************************************************************************
5045 *
5046 *  Add an instruction referencing two registers and a constant.
5047 *  Also checks for a large immediate that needs a second instruction
5048 *  and will load it in reg1
5049 *
5050 *  - Supports instructions: add, adds, sub, subs, and, ands, eor and orr
5051 *  - Requires that reg1 is a general register and not SP or ZR
5052 *  - Requires that reg1 != reg2
5053 */
5054 void emitter::emitIns_R_R_Imm(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm)
5055 {
5056     assert(isGeneralRegister(reg1));
5057     assert(reg1 != reg2);
5058
5059     bool immFits = true;
5060
5061     switch (ins)
5062     {
5063         case INS_add:
5064         case INS_adds:
5065         case INS_sub:
5066         case INS_subs:
5067             immFits = emitter::emitIns_valid_imm_for_add(imm, attr);
5068             break;
5069
5070         case INS_ands:
5071         case INS_and:
5072         case INS_eor:
5073         case INS_orr:
5074             immFits = emitter::emitIns_valid_imm_for_alu(imm, attr);
5075             break;
5076
5077         default:
5078             assert(!"Unsupported instruction in emitIns_R_R_Imm");
5079     }
5080
5081     if (immFits)
5082     {
5083         emitIns_R_R_I(ins, attr, reg1, reg2, imm);
5084     }
5085     else
5086     {
5087         // Load 'imm' into the reg1 register
5088         // then issue:   'ins'  reg1, reg2, reg1
5089         //
5090         codeGen->instGen_Set_Reg_To_Imm(attr, reg1, imm);
5091         emitIns_R_R_R(ins, attr, reg1, reg2, reg1);
5092     }
5093 }
5094
5095 /*****************************************************************************
5096  *
5097  *  Add an instruction referencing three registers.
5098  */
5099
5100 void emitter::emitIns_R_R_R(
5101     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insOpts opt) /* = INS_OPTS_NONE */
5102 {
5103     emitAttr  size     = EA_SIZE(attr);
5104     emitAttr  elemsize = EA_UNKNOWN;
5105     insFormat fmt      = IF_NONE;
5106
5107     /* Figure out the encoding format of the instruction */
5108     switch (ins)
5109     {
5110         case INS_lsl:
5111         case INS_lsr:
5112         case INS_asr:
5113         case INS_ror:
5114         case INS_adc:
5115         case INS_adcs:
5116         case INS_sbc:
5117         case INS_sbcs:
5118         case INS_udiv:
5119         case INS_sdiv:
5120         case INS_mneg:
5121         case INS_smull:
5122         case INS_smnegl:
5123         case INS_smulh:
5124         case INS_umull:
5125         case INS_umnegl:
5126         case INS_umulh:
5127         case INS_lslv:
5128         case INS_lsrv:
5129         case INS_asrv:
5130         case INS_rorv:
5131             assert(insOptsNone(opt));
5132             assert(isValidGeneralDatasize(size));
5133             assert(isGeneralRegister(reg1));
5134             assert(isGeneralRegister(reg2));
5135             assert(isGeneralRegister(reg3));
5136             fmt = IF_DR_3A;
5137             break;
5138
5139         case INS_mul:
5140             if (insOptsNone(opt))
5141             {
5142                 // general register
5143                 assert(isValidGeneralDatasize(size));
5144                 assert(isGeneralRegister(reg1));
5145                 assert(isGeneralRegister(reg2));
5146                 assert(isGeneralRegister(reg3));
5147                 fmt = IF_DR_3A;
5148                 break;
5149             }
5150             __fallthrough;
5151
5152         case INS_mla:
5153         case INS_mls:
5154         case INS_pmul:
5155             assert(insOptsAnyArrangement(opt));
5156             assert(isVectorRegister(reg1));
5157             assert(isVectorRegister(reg2));
5158             assert(isVectorRegister(reg3));
5159             assert(isValidVectorDatasize(size));
5160             assert(isValidArrangement(size, opt));
5161             elemsize = optGetElemsize(opt);
5162             if (ins == INS_pmul)
5163             {
5164                 assert(elemsize == EA_1BYTE); // only supports 8B or 16B
5165             }
5166             else // INS_mul, INS_mla, INS_mls
5167             {
5168                 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
5169             }
5170             fmt = IF_DV_3A;
5171             break;
5172
5173         case INS_add:
5174         case INS_sub:
5175             if (isVectorRegister(reg1))
5176             {
5177                 assert(isVectorRegister(reg2));
5178                 assert(isVectorRegister(reg3));
5179
5180                 if (insOptsAnyArrangement(opt))
5181                 {
5182                     // Vector operation
5183                     assert(opt != INS_OPTS_1D); // Reserved encoding
5184                     assert(isValidVectorDatasize(size));
5185                     assert(isValidArrangement(size, opt));
5186                     fmt = IF_DV_3A;
5187                 }
5188                 else
5189                 {
5190                     // Scalar operation
5191                     assert(insOptsNone(opt));
5192                     assert(size == EA_8BYTE);
5193                     fmt = IF_DV_3E;
5194                 }
5195                 break;
5196             }
5197             __fallthrough;
5198
5199         case INS_adds:
5200         case INS_subs:
5201             emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, INS_OPTS_NONE);
5202             return;
5203
5204         case INS_cmeq:
5205         case INS_cmge:
5206         case INS_cmgt:
5207         case INS_cmhi:
5208         case INS_cmhs:
5209         case INS_ctst:
5210             assert(isVectorRegister(reg1));
5211             assert(isVectorRegister(reg2));
5212             assert(isVectorRegister(reg3));
5213
5214             if (isValidVectorDatasize(size))
5215             {
5216                 // Vector operation
5217                 assert(insOptsAnyArrangement(opt));
5218                 assert(isValidArrangement(size, opt));
5219                 elemsize = optGetElemsize(opt);
5220                 fmt      = IF_DV_3A;
5221             }
5222             else
5223             {
5224                 NYI("Untested");
5225                 // Scalar operation
5226                 assert(size == EA_8BYTE); // Only Double supported
5227                 fmt = IF_DV_3E;
5228             }
5229             break;
5230
5231         case INS_fcmeq:
5232         case INS_fcmge:
5233         case INS_fcmgt:
5234             assert(isVectorRegister(reg1));
5235             assert(isVectorRegister(reg2));
5236             assert(isVectorRegister(reg3));
5237
5238             if (isValidVectorDatasize(size))
5239             {
5240                 // Vector operation
5241                 assert(insOptsAnyArrangement(opt));
5242                 assert(isValidArrangement(size, opt));
5243                 elemsize = optGetElemsize(opt);
5244                 assert((elemsize == EA_8BYTE) || (elemsize == EA_4BYTE)); // Only Double/Float supported
5245                 assert(opt != INS_OPTS_1D);                               // Reserved encoding
5246                 fmt = IF_DV_3B;
5247             }
5248             else
5249             {
5250                 NYI("Untested");
5251                 // Scalar operation
5252                 assert((size == EA_8BYTE) || (size == EA_4BYTE)); // Only Double/Float supported
5253                 fmt = IF_DV_3D;
5254             }
5255             break;
5256
5257         case INS_saba:
5258         case INS_sabd:
5259         case INS_smax:
5260         case INS_smin:
5261         case INS_uaba:
5262         case INS_uabd:
5263         case INS_umax:
5264         case INS_umin:
5265             assert(isVectorRegister(reg1));
5266             assert(isVectorRegister(reg2));
5267             assert(isVectorRegister(reg3));
5268             assert(insOptsAnyArrangement(opt));
5269
5270             // Vector operation
5271             assert(isValidVectorDatasize(size));
5272             assert(isValidArrangement(size, opt));
5273             elemsize = optGetElemsize(opt);
5274             assert(elemsize != EA_8BYTE); // can't use 2D or 1D
5275
5276             fmt = IF_DV_3A;
5277             break;
5278
5279         case INS_mov:
5280             assert(isVectorRegister(reg1));
5281             assert(isVectorRegister(reg2));
5282             assert(reg2 == reg3);
5283             assert(isValidVectorDatasize(size));
5284             // INS_mov is an alias for INS_orr (vector register)
5285             if (opt == INS_OPTS_NONE)
5286             {
5287                 elemsize = EA_1BYTE;
5288                 opt      = optMakeArrangement(size, elemsize);
5289             }
5290             assert(isValidArrangement(size, opt));
5291             fmt = IF_DV_3C;
5292             break;
5293
5294         case INS_and:
5295         case INS_bic:
5296         case INS_eor:
5297         case INS_orr:
5298         case INS_orn:
5299             if (isVectorRegister(reg1))
5300             {
5301                 assert(isValidVectorDatasize(size));
5302                 assert(isVectorRegister(reg2));
5303                 assert(isVectorRegister(reg3));
5304                 if (opt == INS_OPTS_NONE)
5305                 {
5306                     elemsize = EA_1BYTE;
5307                     opt      = optMakeArrangement(size, elemsize);
5308                 }
5309                 assert(isValidArrangement(size, opt));
5310                 fmt = IF_DV_3C;
5311                 break;
5312             }
5313             __fallthrough;
5314
5315         case INS_ands:
5316         case INS_bics:
5317         case INS_eon:
5318             emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, INS_OPTS_NONE);
5319             return;
5320
5321         case INS_bsl:
5322         case INS_bit:
5323         case INS_bif:
5324             assert(isValidVectorDatasize(size));
5325             assert(isVectorRegister(reg1));
5326             assert(isVectorRegister(reg2));
5327             assert(isVectorRegister(reg3));
5328             if (opt == INS_OPTS_NONE)
5329             {
5330                 elemsize = EA_1BYTE;
5331                 opt      = optMakeArrangement(size, elemsize);
5332             }
5333             assert(isValidArrangement(size, opt));
5334             fmt = IF_DV_3C;
5335             break;
5336
5337         case INS_fadd:
5338         case INS_fsub:
5339         case INS_fdiv:
5340         case INS_fmax:
5341         case INS_fmin:
5342         case INS_fabd:
5343         case INS_fmul:
5344         case INS_fmulx:
5345             assert(isVectorRegister(reg1));
5346             assert(isVectorRegister(reg2));
5347             assert(isVectorRegister(reg3));
5348             if (insOptsAnyArrangement(opt))
5349             {
5350                 // Vector operation
5351                 assert(isValidVectorDatasize(size));
5352                 assert(isValidArrangement(size, opt));
5353                 elemsize = optGetElemsize(opt);
5354                 assert(isValidVectorElemsizeFloat(elemsize));
5355                 assert(opt != INS_OPTS_1D); // Reserved encoding
5356                 fmt = IF_DV_3B;
5357             }
5358             else
5359             {
5360                 // Scalar operation
5361                 assert(insOptsNone(opt));
5362                 assert(isValidScalarDatasize(size));
5363                 fmt = IF_DV_3D;
5364             }
5365             break;
5366
5367         case INS_fnmul:
5368             // Scalar operation
5369             assert(insOptsNone(opt));
5370             assert(isVectorRegister(reg1));
5371             assert(isVectorRegister(reg2));
5372             assert(isVectorRegister(reg3));
5373             assert(isValidScalarDatasize(size));
5374             fmt = IF_DV_3D;
5375             break;
5376
5377         case INS_faddp:
5378         case INS_fmla:
5379         case INS_fmls:
5380             assert(isVectorRegister(reg1));
5381             assert(isVectorRegister(reg2));
5382             assert(isVectorRegister(reg3));
5383             assert(insOptsAnyArrangement(opt)); // no scalar encoding, use 4-operand 'fmadd' or 'fmsub'
5384
5385             // Vector operation
5386             assert(isValidVectorDatasize(size));
5387             assert(isValidArrangement(size, opt));
5388             elemsize = optGetElemsize(opt);
5389             assert(isValidVectorElemsizeFloat(elemsize));
5390             assert(opt != INS_OPTS_1D); // Reserved encoding
5391             fmt = IF_DV_3B;
5392             break;
5393
5394         case INS_ldr:
5395         case INS_ldrb:
5396         case INS_ldrh:
5397         case INS_ldrsb:
5398         case INS_ldrsh:
5399         case INS_ldrsw:
5400         case INS_str:
5401         case INS_strb:
5402         case INS_strh:
5403             emitIns_R_R_R_Ext(ins, attr, reg1, reg2, reg3, opt);
5404             return;
5405
5406         case INS_ldp:
5407         case INS_ldpsw:
5408         case INS_ldnp:
5409         case INS_stp:
5410         case INS_stnp:
5411             emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0);
5412             return;
5413
5414         case INS_stxr:
5415         case INS_stxrb:
5416         case INS_stxrh:
5417         case INS_stlxr:
5418         case INS_stlxrb:
5419         case INS_stlxrh:
5420             assert(isGeneralRegisterOrZR(reg1));
5421             assert(isGeneralRegisterOrZR(reg2));
5422             assert(isGeneralRegisterOrSP(reg3));
5423             fmt = IF_LS_3D;
5424             break;
5425
5426         case INS_casb:
5427         case INS_casab:
5428         case INS_casalb:
5429         case INS_caslb:
5430         case INS_cash:
5431         case INS_casah:
5432         case INS_casalh:
5433         case INS_caslh:
5434         case INS_cas:
5435         case INS_casa:
5436         case INS_casal:
5437         case INS_casl:
5438         case INS_ldaddb:
5439         case INS_ldaddab:
5440         case INS_ldaddalb:
5441         case INS_ldaddlb:
5442         case INS_ldaddh:
5443         case INS_ldaddah:
5444         case INS_ldaddalh:
5445         case INS_ldaddlh:
5446         case INS_ldadd:
5447         case INS_ldadda:
5448         case INS_ldaddal:
5449         case INS_ldaddl:
5450         case INS_swpb:
5451         case INS_swpab:
5452         case INS_swpalb:
5453         case INS_swplb:
5454         case INS_swph:
5455         case INS_swpah:
5456         case INS_swpalh:
5457         case INS_swplh:
5458         case INS_swp:
5459         case INS_swpa:
5460         case INS_swpal:
5461         case INS_swpl:
5462             assert(isGeneralRegisterOrZR(reg1));
5463             assert(isGeneralRegisterOrZR(reg2));
5464             assert(isGeneralRegisterOrSP(reg3));
5465             fmt = IF_LS_3E;
5466             break;
5467
5468         case INS_sha256h:
5469         case INS_sha256h2:
5470         case INS_sha256su1:
5471         case INS_sha1su0:
5472         case INS_sha1c:
5473         case INS_sha1p:
5474         case INS_sha1m:
5475             assert(isValidVectorDatasize(size));
5476             assert(isVectorRegister(reg1));
5477             assert(isVectorRegister(reg2));
5478             assert(isVectorRegister(reg3));
5479             if (opt == INS_OPTS_NONE)
5480             {
5481                 elemsize = EA_4BYTE;
5482                 opt      = optMakeArrangement(size, elemsize);
5483             }
5484             assert(isValidArrangement(size, opt));
5485             fmt = IF_DV_3F;
5486             break;
5487
5488         default:
5489             unreached();
5490             break;
5491
5492     } // end switch (ins)
5493
5494     assert(fmt != IF_NONE);
5495
5496     instrDesc* id = emitNewInstr(attr);
5497
5498     id->idIns(ins);
5499     id->idInsFmt(fmt);
5500     id->idInsOpt(opt);
5501
5502     id->idReg1(reg1);
5503     id->idReg2(reg2);
5504     id->idReg3(reg3);
5505
5506     dispIns(id);
5507     appendToCurIG(id);
5508 }
5509
5510 /*****************************************************************************
5511  *
5512  *  Add an instruction referencing three registers and a constant.
5513  */
5514
5515 void emitter::emitIns_R_R_R_I(instruction ins,
5516                               emitAttr    attr,
5517                               regNumber   reg1,
5518                               regNumber   reg2,
5519                               regNumber   reg3,
5520                               ssize_t     imm,
5521                               insOpts     opt /* = INS_OPTS_NONE */,
5522                               emitAttr    attrReg2 /* = EA_UNKNOWN */)
5523 {
5524     emitAttr  size     = EA_SIZE(attr);
5525     emitAttr  elemsize = EA_UNKNOWN;
5526     insFormat fmt      = IF_NONE;
5527     bool      isLdSt   = false;
5528     bool      isSIMD   = false;
5529     bool      isAddSub = false;
5530     bool      setFlags = false;
5531     unsigned  scale    = 0;
5532
5533     /* Figure out the encoding format of the instruction */
5534     switch (ins)
5535     {
5536         case INS_extr:
5537             assert(insOptsNone(opt));
5538             assert(isValidGeneralDatasize(size));
5539             assert(isGeneralRegister(reg1));
5540             assert(isGeneralRegister(reg2));
5541             assert(isGeneralRegister(reg3));
5542             assert(isValidImmShift(imm, size));
5543             fmt = IF_DR_3E;
5544             break;
5545
5546         case INS_and:
5547         case INS_ands:
5548         case INS_eor:
5549         case INS_orr:
5550         case INS_bic:
5551         case INS_bics:
5552         case INS_eon:
5553         case INS_orn:
5554             assert(isValidGeneralDatasize(size));
5555             assert(isGeneralRegister(reg1));
5556             assert(isGeneralRegister(reg2));
5557             assert(isGeneralRegister(reg3));
5558             assert(isValidImmShift(imm, size));
5559             if (imm == 0)
5560             {
5561                 assert(insOptsNone(opt)); // a zero imm, means no shift kind
5562                 fmt = IF_DR_3A;
5563             }
5564             else
5565             {
5566                 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
5567                 fmt = IF_DR_3B;
5568             }
5569             break;
5570
5571         case INS_fmul: // by element, imm[0..3] selects the element of reg3
5572         case INS_fmla:
5573         case INS_fmls:
5574         case INS_fmulx:
5575             assert(isVectorRegister(reg1));
5576             assert(isVectorRegister(reg2));
5577             assert(isVectorRegister(reg3));
5578             if (insOptsAnyArrangement(opt))
5579             {
5580                 // Vector operation
5581                 assert(isValidVectorDatasize(size));
5582                 assert(isValidArrangement(size, opt));
5583                 elemsize = optGetElemsize(opt);
5584                 assert(isValidVectorElemsizeFloat(elemsize));
5585                 assert(isValidVectorIndex(size, elemsize, imm));
5586                 assert(opt != INS_OPTS_1D); // Reserved encoding
5587                 fmt = IF_DV_3BI;
5588             }
5589             else
5590             {
5591                 // Scalar operation
5592                 assert(insOptsNone(opt));
5593                 assert(isValidScalarDatasize(size));
5594                 elemsize = size;
5595                 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
5596                 fmt = IF_DV_3DI;
5597             }
5598             break;
5599
5600         case INS_mul: // by element, imm[0..7] selects the element of reg3
5601         case INS_mla:
5602         case INS_mls:
5603             assert(isVectorRegister(reg1));
5604             assert(isVectorRegister(reg2));
5605             assert(isVectorRegister(reg3));
5606             // Vector operation
5607             assert(insOptsAnyArrangement(opt));
5608             assert(isValidVectorDatasize(size));
5609             assert(isValidArrangement(size, opt));
5610             elemsize = optGetElemsize(opt);
5611             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
5612             // Only has encodings for H or S elemsize
5613             assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE));
5614             // Only has encodings for V0..V15
5615             if ((elemsize == EA_2BYTE) && (reg3 >= REG_V16))
5616             {
5617                 noway_assert(!"Invalid reg3");
5618             }
5619             fmt = IF_DV_3AI;
5620             break;
5621
5622         case INS_add:
5623         case INS_sub:
5624             setFlags = false;
5625             isAddSub = true;
5626             break;
5627
5628         case INS_adds:
5629         case INS_subs:
5630             setFlags = true;
5631             isAddSub = true;
5632             break;
5633
5634         case INS_ldpsw:
5635             scale  = 2;
5636             isLdSt = true;
5637             break;
5638
5639         case INS_ldnp:
5640         case INS_stnp:
5641             assert(insOptsNone(opt)); // Can't use Pre/Post index on these two instructions
5642             __fallthrough;
5643
5644         case INS_ldp:
5645         case INS_stp:
5646             // Is the target a vector register?
5647             if (isVectorRegister(reg1))
5648             {
5649                 scale  = NaturalScale_helper(size);
5650                 isSIMD = true;
5651             }
5652             else
5653             {
5654                 scale = (size == EA_8BYTE) ? 3 : 2;
5655             }
5656             isLdSt = true;
5657             break;
5658
5659         default:
5660             unreached();
5661             break;
5662
5663     } // end switch (ins)
5664
5665     if (isLdSt)
5666     {
5667         assert(!isAddSub);
5668         assert(isGeneralRegisterOrSP(reg3));
5669         assert(insOptsNone(opt) || insOptsIndexed(opt));
5670
5671         if (isSIMD)
5672         {
5673             assert(isValidVectorLSPDatasize(size));
5674             assert(isVectorRegister(reg1));
5675             assert(isVectorRegister(reg2));
5676             assert((scale >= 2) && (scale <= 4));
5677         }
5678         else
5679         {
5680             assert(isValidGeneralDatasize(size));
5681             assert(isGeneralRegisterOrZR(reg1));
5682             assert(isGeneralRegisterOrZR(reg2));
5683             assert((scale == 2) || (scale == 3));
5684         }
5685
5686         // Load/Store Pair reserved encodings:
5687         if (emitInsIsLoad(ins))
5688         {
5689             assert(reg1 != reg2);
5690         }
5691         if (insOptsIndexed(opt))
5692         {
5693             assert(reg1 != reg3);
5694             assert(reg2 != reg3);
5695         }
5696
5697         reg3 = encodingSPtoZR(reg3);
5698
5699         ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
5700         if (imm == 0)
5701         {
5702             assert(insOptsNone(opt)); // PRE/POST Index doesn't make sense with an immediate of zero
5703
5704             fmt = IF_LS_3B;
5705         }
5706         else
5707         {
5708             if ((imm & mask) == 0)
5709             {
5710                 imm >>= scale; // The immediate is scaled by the size of the ld/st
5711
5712                 if ((imm >= -64) && (imm <= 63))
5713                 {
5714                     fmt = IF_LS_3C;
5715                 }
5716             }
5717 #ifdef DEBUG
5718             if (fmt != IF_LS_3C)
5719             {
5720                 assert(!"Instruction cannot be encoded: IF_LS_3C");
5721             }
5722 #endif
5723         }
5724     }
5725     else if (isAddSub)
5726     {
5727         bool reg2IsSP = (reg2 == REG_SP);
5728         assert(!isLdSt);
5729         assert(isValidGeneralDatasize(size));
5730         assert(isGeneralRegister(reg3));
5731
5732         if (setFlags || insOptsAluShift(opt)) // Can't encode SP in reg1 with setFlags or AluShift option
5733         {
5734             assert(isGeneralRegisterOrZR(reg1));
5735         }
5736         else
5737         {
5738             assert(isGeneralRegisterOrSP(reg1));
5739             reg1 = encodingSPtoZR(reg1);
5740         }
5741
5742         if (insOptsAluShift(opt)) // Can't encode SP in reg2 with AluShift option
5743         {
5744             assert(isGeneralRegister(reg2));
5745         }
5746         else
5747         {
5748             assert(isGeneralRegisterOrSP(reg2));
5749             reg2 = encodingSPtoZR(reg2);
5750         }
5751
5752         if (insOptsAnyExtend(opt))
5753         {
5754             assert((imm >= 0) && (imm <= 4));
5755
5756             fmt = IF_DR_3C;
5757         }
5758         else if (insOptsAluShift(opt))
5759         {
5760             // imm should be non-zero and in [1..63]
5761             assert(isValidImmShift(imm, size) && (imm != 0));
5762             fmt = IF_DR_3B;
5763         }
5764         else if (imm == 0)
5765         {
5766             assert(insOptsNone(opt));
5767
5768             if (reg2IsSP)
5769             {
5770                 // To encode the SP register as reg2 we must use the IF_DR_3C encoding
5771                 // and also specify a LSL of zero (imm == 0)
5772                 opt = INS_OPTS_LSL;
5773                 fmt = IF_DR_3C;
5774             }
5775             else
5776             {
5777                 fmt = IF_DR_3A;
5778             }
5779         }
5780         else
5781         {
5782             assert(!"Instruction cannot be encoded: Add/Sub IF_DR_3A");
5783         }
5784     }
5785     assert(fmt != IF_NONE);
5786
5787     instrDesc* id = emitNewInstrCns(attr, imm);
5788
5789     id->idIns(ins);
5790     id->idInsFmt(fmt);
5791     id->idInsOpt(opt);
5792
5793     id->idReg1(reg1);
5794     id->idReg2(reg2);
5795     id->idReg3(reg3);
5796
5797     // Record the attribute for the second register in the pair
5798     id->idGCrefReg2(GCT_NONE);
5799     if (attrReg2 != EA_UNKNOWN)
5800     {
5801         // Record the attribute for the second register in the pair
5802         assert((fmt == IF_LS_3B) || (fmt == IF_LS_3C));
5803         if (EA_IS_GCREF(attrReg2))
5804         {
5805             id->idGCrefReg2(GCT_GCREF);
5806         }
5807         else if (EA_IS_BYREF(attrReg2))
5808         {
5809             id->idGCrefReg2(GCT_BYREF);
5810         }
5811     }
5812
5813     dispIns(id);
5814     appendToCurIG(id);
5815 }
5816
5817 /*****************************************************************************
5818  *
5819  *  Add an instruction referencing three registers, with an extend option
5820  */
5821
5822 void emitter::emitIns_R_R_R_Ext(instruction ins,
5823                                 emitAttr    attr,
5824                                 regNumber   reg1,
5825                                 regNumber   reg2,
5826                                 regNumber   reg3,
5827                                 insOpts     opt,         /* = INS_OPTS_NONE */
5828                                 int         shiftAmount) /* = -1 -- unset   */
5829 {
5830     emitAttr  size   = EA_SIZE(attr);
5831     insFormat fmt    = IF_NONE;
5832     bool      isSIMD = false;
5833     int       scale  = -1;
5834
5835     /* Figure out the encoding format of the instruction */
5836     switch (ins)
5837     {
5838         case INS_ldrb:
5839         case INS_ldrsb:
5840         case INS_strb:
5841             scale = 0;
5842             break;
5843
5844         case INS_ldrh:
5845         case INS_ldrsh:
5846         case INS_strh:
5847             scale = 1;
5848             break;
5849
5850         case INS_ldrsw:
5851             scale = 2;
5852             break;
5853
5854         case INS_ldr:
5855         case INS_str:
5856             // Is the target a vector register?
5857             if (isVectorRegister(reg1))
5858             {
5859                 assert(isValidVectorLSDatasize(size));
5860                 scale  = NaturalScale_helper(size);
5861                 isSIMD = true;
5862             }
5863             else
5864             {
5865                 assert(isValidGeneralDatasize(size));
5866                 scale = (size == EA_8BYTE) ? 3 : 2;
5867             }
5868
5869             break;
5870
5871         default:
5872             unreached();
5873             break;
5874
5875     } // end switch (ins)
5876
5877     assert(scale != -1);
5878     assert(insOptsLSExtend(opt));
5879
5880     if (isSIMD)
5881     {
5882         assert(isValidVectorLSDatasize(size));
5883         assert(isVectorRegister(reg1));
5884     }
5885     else
5886     {
5887         assert(isValidGeneralLSDatasize(size));
5888         assert(isGeneralRegisterOrZR(reg1));
5889     }
5890
5891     assert(isGeneralRegisterOrSP(reg2));
5892     assert(isGeneralRegister(reg3));
5893
5894     // Load/Store reserved encodings:
5895     if (insOptsIndexed(opt))
5896     {
5897         assert(reg1 != reg2);
5898     }
5899
5900     if (shiftAmount == -1)
5901     {
5902         shiftAmount = insOptsLSL(opt) ? scale : 0;
5903     }
5904     assert((shiftAmount == scale) || (shiftAmount == 0));
5905
5906     reg2 = encodingSPtoZR(reg2);
5907     fmt  = IF_LS_3A;
5908
5909     instrDesc* id = emitNewInstr(attr);
5910
5911     id->idIns(ins);
5912     id->idInsFmt(fmt);
5913     id->idInsOpt(opt);
5914
5915     id->idReg1(reg1);
5916     id->idReg2(reg2);
5917     id->idReg3(reg3);
5918     id->idReg3Scaled(shiftAmount == scale);
5919
5920     dispIns(id);
5921     appendToCurIG(id);
5922 }
5923
5924 /*****************************************************************************
5925  *
5926  *  Add an instruction referencing two registers and two constants.
5927  */
5928
5929 void emitter::emitIns_R_R_I_I(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, int imm1, int imm2)
5930 {
5931     emitAttr  size     = EA_SIZE(attr);
5932     emitAttr  elemsize = EA_UNKNOWN;
5933     insFormat fmt      = IF_NONE;
5934     size_t    immOut   = 0; // composed from imm1 and imm2 and stored in the instrDesc
5935
5936     /* Figure out the encoding format of the instruction */
5937     switch (ins)
5938     {
5939         int        lsb;
5940         int        width;
5941         bitMaskImm bmi;
5942
5943         case INS_bfm:
5944         case INS_sbfm:
5945         case INS_ubfm:
5946             assert(isGeneralRegister(reg1));
5947             assert(isGeneralRegister(reg2));
5948             assert(isValidImmShift(imm1, size));
5949             assert(isValidImmShift(imm2, size));
5950             bmi.immNRS = 0;
5951             bmi.immN   = (size == EA_8BYTE);
5952             bmi.immR   = imm1;
5953             bmi.immS   = imm2;
5954             immOut     = bmi.immNRS;
5955             fmt        = IF_DI_2D;
5956             break;
5957
5958         case INS_bfi:
5959         case INS_sbfiz:
5960         case INS_ubfiz:
5961             assert(isGeneralRegister(reg1));
5962             assert(isGeneralRegister(reg2));
5963             lsb   = getBitWidth(size) - imm1;
5964             width = imm2 - 1;
5965             assert(isValidImmShift(lsb, size));
5966             assert(isValidImmShift(width, size));
5967             bmi.immNRS = 0;
5968             bmi.immN   = (size == EA_8BYTE);
5969             bmi.immR   = lsb;
5970             bmi.immS   = width;
5971             immOut     = bmi.immNRS;
5972             fmt        = IF_DI_2D;
5973             break;
5974
5975         case INS_bfxil:
5976         case INS_sbfx:
5977         case INS_ubfx:
5978             assert(isGeneralRegister(reg1));
5979             assert(isGeneralRegister(reg2));
5980             lsb   = imm1;
5981             width = imm2 + imm1 - 1;
5982             assert(isValidImmShift(lsb, size));
5983             assert(isValidImmShift(width, size));
5984             bmi.immNRS = 0;
5985             bmi.immN   = (size == EA_8BYTE);
5986             bmi.immR   = imm1;
5987             bmi.immS   = imm2 + imm1 - 1;
5988             immOut     = bmi.immNRS;
5989             fmt        = IF_DI_2D;
5990             break;
5991
5992         case INS_mov:
5993         case INS_ins:
5994             assert(isVectorRegister(reg1));
5995             assert(isVectorRegister(reg2));
5996             elemsize = size;
5997             assert(isValidVectorElemsize(elemsize));
5998             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm1));
5999             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm2));
6000             immOut = (imm1 << 4) + imm2;
6001             fmt    = IF_DV_2F;
6002             break;
6003
6004         default:
6005             unreached();
6006             break;
6007     }
6008     assert(fmt != IF_NONE);
6009
6010     instrDesc* id = emitNewInstrSC(attr, immOut);
6011
6012     id->idIns(ins);
6013     id->idInsFmt(fmt);
6014
6015     id->idReg1(reg1);
6016     id->idReg2(reg2);
6017
6018     dispIns(id);
6019     appendToCurIG(id);
6020 }
6021
6022 /*****************************************************************************
6023  *
6024  *  Add an instruction referencing four registers.
6025  */
6026
6027 void emitter::emitIns_R_R_R_R(
6028     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, regNumber reg4)
6029 {
6030     emitAttr  size = EA_SIZE(attr);
6031     insFormat fmt  = IF_NONE;
6032
6033     /* Figure out the encoding format of the instruction */
6034     switch (ins)
6035     {
6036         case INS_madd:
6037         case INS_msub:
6038         case INS_smaddl:
6039         case INS_smsubl:
6040         case INS_umaddl:
6041         case INS_umsubl:
6042             assert(isValidGeneralDatasize(size));
6043             assert(isGeneralRegister(reg1));
6044             assert(isGeneralRegister(reg2));
6045             assert(isGeneralRegister(reg3));
6046             assert(isGeneralRegister(reg4));
6047             fmt = IF_DR_4A;
6048             break;
6049
6050         case INS_fmadd:
6051         case INS_fmsub:
6052         case INS_fnmadd:
6053         case INS_fnmsub:
6054             // Scalar operation
6055             assert(isValidScalarDatasize(size));
6056             assert(isVectorRegister(reg1));
6057             assert(isVectorRegister(reg2));
6058             assert(isVectorRegister(reg3));
6059             assert(isVectorRegister(reg4));
6060             fmt = IF_DV_4A;
6061             break;
6062
6063         case INS_invalid:
6064             fmt = IF_NONE;
6065             break;
6066
6067         default:
6068             unreached();
6069             break;
6070     }
6071     assert(fmt != IF_NONE);
6072
6073     instrDesc* id = emitNewInstr(attr);
6074
6075     id->idIns(ins);
6076     id->idInsFmt(fmt);
6077
6078     id->idReg1(reg1);
6079     id->idReg2(reg2);
6080     id->idReg3(reg3);
6081     id->idReg4(reg4);
6082
6083     dispIns(id);
6084     appendToCurIG(id);
6085 }
6086
6087 /*****************************************************************************
6088  *
6089  *  Add an instruction referencing a register and a condition code
6090  */
6091
6092 void emitter::emitIns_R_COND(instruction ins, emitAttr attr, regNumber reg, insCond cond)
6093 {
6094     emitAttr     size = EA_SIZE(attr);
6095     insFormat    fmt  = IF_NONE;
6096     condFlagsImm cfi;
6097     cfi.immCFVal = 0;
6098
6099     /* Figure out the encoding format of the instruction */
6100     switch (ins)
6101     {
6102         case INS_cset:
6103         case INS_csetm:
6104             assert(isGeneralRegister(reg));
6105             cfi.cond = cond;
6106             fmt      = IF_DR_1D;
6107             break;
6108
6109         default:
6110             unreached();
6111             break;
6112
6113     } // end switch (ins)
6114
6115     assert(fmt != IF_NONE);
6116     assert(isValidImmCond(cfi.immCFVal));
6117
6118     instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6119
6120     id->idIns(ins);
6121     id->idInsFmt(fmt);
6122     id->idInsOpt(INS_OPTS_NONE);
6123
6124     id->idReg1(reg);
6125
6126     dispIns(id);
6127     appendToCurIG(id);
6128 }
6129
6130 /*****************************************************************************
6131  *
6132  *  Add an instruction referencing two registers and a condition code
6133  */
6134
6135 void emitter::emitIns_R_R_COND(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insCond cond)
6136 {
6137     emitAttr     size = EA_SIZE(attr);
6138     insFormat    fmt  = IF_NONE;
6139     condFlagsImm cfi;
6140     cfi.immCFVal = 0;
6141
6142     /* Figure out the encoding format of the instruction */
6143     switch (ins)
6144     {
6145         case INS_cinc:
6146         case INS_cinv:
6147         case INS_cneg:
6148             assert(isGeneralRegister(reg1));
6149             assert(isGeneralRegister(reg2));
6150             cfi.cond = cond;
6151             fmt      = IF_DR_2D;
6152             break;
6153         default:
6154             unreached();
6155             break;
6156
6157     } // end switch (ins)
6158
6159     assert(fmt != IF_NONE);
6160     assert(isValidImmCond(cfi.immCFVal));
6161
6162     instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6163
6164     id->idIns(ins);
6165     id->idInsFmt(fmt);
6166     id->idInsOpt(INS_OPTS_NONE);
6167
6168     id->idReg1(reg1);
6169     id->idReg2(reg2);
6170
6171     dispIns(id);
6172     appendToCurIG(id);
6173 }
6174
6175 /*****************************************************************************
6176  *
6177  *  Add an instruction referencing two registers and a condition code
6178  */
6179
6180 void emitter::emitIns_R_R_R_COND(
6181     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insCond cond)
6182 {
6183     emitAttr     size = EA_SIZE(attr);
6184     insFormat    fmt  = IF_NONE;
6185     condFlagsImm cfi;
6186     cfi.immCFVal = 0;
6187
6188     /* Figure out the encoding format of the instruction */
6189     switch (ins)
6190     {
6191         case INS_csel:
6192         case INS_csinc:
6193         case INS_csinv:
6194         case INS_csneg:
6195             assert(isGeneralRegister(reg1));
6196             assert(isGeneralRegister(reg2));
6197             assert(isGeneralRegister(reg3));
6198             cfi.cond = cond;
6199             fmt      = IF_DR_3D;
6200             break;
6201
6202         default:
6203             unreached();
6204             break;
6205
6206     } // end switch (ins)
6207
6208     assert(fmt != IF_NONE);
6209     assert(isValidImmCond(cfi.immCFVal));
6210
6211     instrDesc* id = emitNewInstr(attr);
6212
6213     id->idIns(ins);
6214     id->idInsFmt(fmt);
6215     id->idInsOpt(INS_OPTS_NONE);
6216
6217     id->idReg1(reg1);
6218     id->idReg2(reg2);
6219     id->idReg3(reg3);
6220     id->idSmallCns(cfi.immCFVal);
6221
6222     dispIns(id);
6223     appendToCurIG(id);
6224 }
6225
6226 /*****************************************************************************
6227  *
6228  *  Add an instruction referencing two registers the flags and a condition code
6229  */
6230
6231 void emitter::emitIns_R_R_FLAGS_COND(
6232     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insCflags flags, insCond cond)
6233 {
6234     emitAttr     size = EA_SIZE(attr);
6235     insFormat    fmt  = IF_NONE;
6236     condFlagsImm cfi;
6237     cfi.immCFVal = 0;
6238
6239     /* Figure out the encoding format of the instruction */
6240     switch (ins)
6241     {
6242         case INS_ccmp:
6243         case INS_ccmn:
6244             assert(isGeneralRegister(reg1));
6245             assert(isGeneralRegister(reg2));
6246             cfi.flags = flags;
6247             cfi.cond  = cond;
6248             fmt       = IF_DR_2I;
6249             break;
6250         default:
6251             unreached();
6252             break;
6253     } // end switch (ins)
6254
6255     assert(fmt != IF_NONE);
6256     assert(isValidImmCondFlags(cfi.immCFVal));
6257
6258     instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6259
6260     id->idIns(ins);
6261     id->idInsFmt(fmt);
6262     id->idInsOpt(INS_OPTS_NONE);
6263
6264     id->idReg1(reg1);
6265     id->idReg2(reg2);
6266
6267     dispIns(id);
6268     appendToCurIG(id);
6269 }
6270
6271 /*****************************************************************************
6272  *
6273  *  Add an instruction referencing a register, an immediate, the flags and a condition code
6274  */
6275
6276 void emitter::emitIns_R_I_FLAGS_COND(
6277     instruction ins, emitAttr attr, regNumber reg, int imm, insCflags flags, insCond cond)
6278 {
6279     emitAttr     size = EA_SIZE(attr);
6280     insFormat    fmt  = IF_NONE;
6281     condFlagsImm cfi;
6282     cfi.immCFVal = 0;
6283
6284     /* Figure out the encoding format of the instruction */
6285     switch (ins)
6286     {
6287         case INS_ccmp:
6288         case INS_ccmn:
6289             assert(isGeneralRegister(reg));
6290             if (imm < 0)
6291             {
6292                 ins = insReverse(ins);
6293                 imm = -imm;
6294             }
6295             if ((imm >= 0) && (imm <= 31))
6296             {
6297                 cfi.imm5  = imm;
6298                 cfi.flags = flags;
6299                 cfi.cond  = cond;
6300                 fmt       = IF_DI_1F;
6301             }
6302             else
6303             {
6304                 assert(!"Instruction cannot be encoded: ccmp/ccmn imm5");
6305             }
6306             break;
6307         default:
6308             unreached();
6309             break;
6310     } // end switch (ins)
6311
6312     assert(fmt != IF_NONE);
6313     assert(isValidImmCondFlagsImm5(cfi.immCFVal));
6314
6315     instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6316
6317     id->idIns(ins);
6318     id->idInsFmt(fmt);
6319     id->idInsOpt(INS_OPTS_NONE);
6320
6321     id->idReg1(reg);
6322
6323     dispIns(id);
6324     appendToCurIG(id);
6325 }
6326
6327 /*****************************************************************************
6328  *
6329  *  Add a memory barrier instruction with a 'barrier' immediate
6330  */
6331
6332 void emitter::emitIns_BARR(instruction ins, insBarrier barrier)
6333 {
6334     insFormat fmt = IF_NONE;
6335     ssize_t   imm = 0;
6336
6337     /* Figure out the encoding format of the instruction */
6338     switch (ins)
6339     {
6340         case INS_dsb:
6341         case INS_dmb:
6342         case INS_isb:
6343
6344             fmt = IF_SI_0B;
6345             imm = (ssize_t)barrier;
6346             break;
6347         default:
6348             unreached();
6349             break;
6350     } // end switch (ins)
6351
6352     assert(fmt != IF_NONE);
6353
6354     instrDesc* id = emitNewInstrSC(EA_8BYTE, imm);
6355
6356     id->idIns(ins);
6357     id->idInsFmt(fmt);
6358     id->idInsOpt(INS_OPTS_NONE);
6359
6360     dispIns(id);
6361     appendToCurIG(id);
6362 }
6363
6364 /*****************************************************************************
6365  *
6366  *  Add an instruction with a static data member operand. If 'size' is 0, the
6367  *  instruction operates on the address of the static member instead of its
6368  *  value (e.g. "push offset clsvar", rather than "push dword ptr [clsvar]").
6369  */
6370
6371 void emitter::emitIns_C(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, int offs)
6372 {
6373     NYI("emitIns_C");
6374 }
6375
6376 /*****************************************************************************
6377  *
6378  *  Add an instruction referencing stack-based local variable.
6379  */
6380
6381 void emitter::emitIns_S(instruction ins, emitAttr attr, int varx, int offs)
6382 {
6383     NYI("emitIns_S");
6384 }
6385
6386 /*****************************************************************************
6387  *
6388  *  Add an instruction referencing a register and a stack-based local variable.
6389  */
6390 void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
6391 {
6392     emitAttr  size  = EA_SIZE(attr);
6393     insFormat fmt   = IF_NONE;
6394     int       disp  = 0;
6395     unsigned  scale = 0;
6396
6397     assert(offs >= 0);
6398
6399     // TODO-ARM64-CQ: use unscaled loads?
6400     /* Figure out the encoding format of the instruction */
6401     switch (ins)
6402     {
6403         case INS_strb:
6404         case INS_ldrb:
6405         case INS_ldrsb:
6406             scale = 0;
6407             break;
6408
6409         case INS_strh:
6410         case INS_ldrh:
6411         case INS_ldrsh:
6412             scale = 1;
6413             break;
6414
6415         case INS_ldrsw:
6416             scale = 2;
6417             break;
6418
6419         case INS_str:
6420         case INS_ldr:
6421             assert(isValidGeneralDatasize(size) || isValidVectorDatasize(size));
6422             scale = genLog2(EA_SIZE_IN_BYTES(size));
6423             break;
6424
6425         case INS_lea:
6426             assert(size == EA_8BYTE);
6427             scale = 0;
6428             break;
6429
6430         default:
6431             NYI("emitIns_R_S"); // FP locals?
6432             return;
6433
6434     } // end switch (ins)
6435
6436     /* Figure out the variable's frame position */
6437     ssize_t imm;
6438     int     base;
6439     bool    FPbased;
6440
6441     base = emitComp->lvaFrameAddress(varx, &FPbased);
6442     disp = base + offs;
6443     assert((scale >= 0) && (scale <= 4));
6444
6445     regNumber reg2 = FPbased ? REG_FPBASE : REG_SPBASE;
6446     reg2           = encodingSPtoZR(reg2);
6447
6448     if (ins == INS_lea)
6449     {
6450         if (disp >= 0)
6451         {
6452             ins = INS_add;
6453             imm = disp;
6454         }
6455         else
6456         {
6457             ins = INS_sub;
6458             imm = -disp;
6459         }
6460
6461         if (imm <= 0x0fff)
6462         {
6463             fmt = IF_DI_2A; // add reg1,reg2,#disp
6464         }
6465         else
6466         {
6467             regNumber rsvdReg = codeGen->rsGetRsvdReg();
6468             codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6469             fmt = IF_DR_3A; // add reg1,reg2,rsvdReg
6470         }
6471     }
6472     else
6473     {
6474         bool    useRegForImm = false;
6475         ssize_t mask         = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6476
6477         imm = disp;
6478         if (imm == 0)
6479         {
6480             fmt = IF_LS_2A;
6481         }
6482         else if ((imm < 0) || ((imm & mask) != 0))
6483         {
6484             if ((imm >= -256) && (imm <= 255))
6485             {
6486                 fmt = IF_LS_2C;
6487             }
6488             else
6489             {
6490                 useRegForImm = true;
6491             }
6492         }
6493         else if (imm > 0)
6494         {
6495             if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
6496             {
6497                 imm >>= scale; // The immediate is scaled by the size of the ld/st
6498
6499                 fmt = IF_LS_2B;
6500             }
6501             else
6502             {
6503                 useRegForImm = true;
6504             }
6505         }
6506
6507         if (useRegForImm)
6508         {
6509             regNumber rsvdReg = codeGen->rsGetRsvdReg();
6510             codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6511             fmt = IF_LS_3A;
6512         }
6513     }
6514
6515     assert(fmt != IF_NONE);
6516
6517     instrDesc* id = emitNewInstrCns(attr, imm);
6518
6519     id->idIns(ins);
6520     id->idInsFmt(fmt);
6521     id->idInsOpt(INS_OPTS_NONE);
6522
6523     id->idReg1(reg1);
6524     id->idReg2(reg2);
6525     id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6526     id->idSetIsLclVar();
6527
6528 #ifdef DEBUG
6529     id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6530 #endif
6531
6532     dispIns(id);
6533     appendToCurIG(id);
6534 }
6535
6536 /*****************************************************************************
6537  *
6538  *  Add an instruction referencing two register and consectutive stack-based local variable slots.
6539  */
6540 void emitter::emitIns_R_R_S_S(
6541     instruction ins, emitAttr attr1, emitAttr attr2, regNumber reg1, regNumber reg2, int varx, int offs)
6542 {
6543     assert((ins == INS_ldp) || (ins == INS_ldnp));
6544     assert(EA_8BYTE == EA_SIZE(attr1));
6545     assert(EA_8BYTE == EA_SIZE(attr2));
6546     assert(isGeneralRegisterOrZR(reg1));
6547     assert(isGeneralRegisterOrZR(reg2));
6548     assert(offs >= 0);
6549
6550     insFormat      fmt   = IF_LS_3B;
6551     int            disp  = 0;
6552     const unsigned scale = 3;
6553
6554     /* Figure out the variable's frame position */
6555     int  base;
6556     bool FPbased;
6557
6558     base = emitComp->lvaFrameAddress(varx, &FPbased);
6559     disp = base + offs;
6560
6561     // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6562     regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE;
6563     reg3           = encodingSPtoZR(reg3);
6564
6565     bool    useRegForAdr = true;
6566     ssize_t imm          = disp;
6567     ssize_t mask         = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6568     if (imm == 0)
6569     {
6570         useRegForAdr = false;
6571     }
6572     else
6573     {
6574         if ((imm & mask) == 0)
6575         {
6576             ssize_t immShift = imm >> scale; // The immediate is scaled by the size of the ld/st
6577
6578             if ((immShift >= -64) && (immShift <= 63))
6579             {
6580                 fmt          = IF_LS_3C;
6581                 useRegForAdr = false;
6582                 imm          = immShift;
6583             }
6584         }
6585     }
6586
6587     if (useRegForAdr)
6588     {
6589         regNumber rsvd = codeGen->rsGetRsvdReg();
6590         emitIns_R_R_Imm(INS_add, EA_PTRSIZE, rsvd, reg3, imm);
6591         reg3 = rsvd;
6592         imm  = 0;
6593     }
6594
6595     assert(fmt != IF_NONE);
6596
6597     instrDesc* id = emitNewInstrCns(attr1, imm);
6598
6599     id->idIns(ins);
6600     id->idInsFmt(fmt);
6601     id->idInsOpt(INS_OPTS_NONE);
6602
6603     // Record the attribute for the second register in the pair
6604     if (EA_IS_GCREF(attr2))
6605     {
6606         id->idGCrefReg2(GCT_GCREF);
6607     }
6608     else if (EA_IS_BYREF(attr2))
6609     {
6610         id->idGCrefReg2(GCT_BYREF);
6611     }
6612     else
6613     {
6614         id->idGCrefReg2(GCT_NONE);
6615     }
6616
6617     id->idReg1(reg1);
6618     id->idReg2(reg2);
6619     id->idReg3(reg3);
6620     id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6621     id->idSetIsLclVar();
6622
6623 #ifdef DEBUG
6624     id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6625 #endif
6626
6627     dispIns(id);
6628     appendToCurIG(id);
6629 }
6630
6631 /*****************************************************************************
6632  *
6633  *  Add an instruction referencing a stack-based local variable and a register
6634  */
6635 void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
6636 {
6637     assert(offs >= 0);
6638     emitAttr  size          = EA_SIZE(attr);
6639     insFormat fmt           = IF_NONE;
6640     int       disp          = 0;
6641     unsigned  scale         = 0;
6642     bool      isVectorStore = false;
6643
6644     // TODO-ARM64-CQ: use unscaled loads?
6645     /* Figure out the encoding format of the instruction */
6646     switch (ins)
6647     {
6648         case INS_strb:
6649             scale = 0;
6650             assert(isGeneralRegisterOrZR(reg1));
6651             break;
6652
6653         case INS_strh:
6654             scale = 1;
6655             assert(isGeneralRegisterOrZR(reg1));
6656             break;
6657
6658         case INS_str:
6659             if (isGeneralRegisterOrZR(reg1))
6660             {
6661                 assert(isValidGeneralDatasize(size));
6662                 scale = (size == EA_8BYTE) ? 3 : 2;
6663             }
6664             else
6665             {
6666                 assert(isVectorRegister(reg1));
6667                 assert(isValidVectorLSDatasize(size));
6668                 scale         = NaturalScale_helper(size);
6669                 isVectorStore = true;
6670             }
6671             break;
6672
6673         default:
6674             NYI("emitIns_S_R"); // FP locals?
6675             return;
6676
6677     } // end switch (ins)
6678
6679     /* Figure out the variable's frame position */
6680     int  base;
6681     bool FPbased;
6682
6683     base = emitComp->lvaFrameAddress(varx, &FPbased);
6684     disp = base + offs;
6685     assert(scale >= 0);
6686     if (isVectorStore)
6687     {
6688         assert(scale <= 4);
6689     }
6690     else
6691     {
6692         assert(scale <= 3);
6693     }
6694
6695     // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6696     regNumber reg2 = FPbased ? REG_FPBASE : REG_SPBASE;
6697     reg2           = encodingSPtoZR(reg2);
6698
6699     bool    useRegForImm = false;
6700     ssize_t imm          = disp;
6701     ssize_t mask         = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6702     if (imm == 0)
6703     {
6704         fmt = IF_LS_2A;
6705     }
6706     else if ((imm < 0) || ((imm & mask) != 0))
6707     {
6708         if ((imm >= -256) && (imm <= 255))
6709         {
6710             fmt = IF_LS_2C;
6711         }
6712         else
6713         {
6714             useRegForImm = true;
6715         }
6716     }
6717     else if (imm > 0)
6718     {
6719         if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
6720         {
6721             imm >>= scale; // The immediate is scaled by the size of the ld/st
6722
6723             fmt = IF_LS_2B;
6724         }
6725         else
6726         {
6727             useRegForImm = true;
6728         }
6729     }
6730
6731     if (useRegForImm)
6732     {
6733         // The reserved register is not stored in idReg3() since that field overlaps with iiaLclVar.
6734         // It is instead implicit when idSetIsLclVar() is set, with this encoding format.
6735         regNumber rsvdReg = codeGen->rsGetRsvdReg();
6736         codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6737         fmt = IF_LS_3A;
6738     }
6739
6740     assert(fmt != IF_NONE);
6741
6742     instrDesc* id = emitNewInstrCns(attr, imm);
6743
6744     id->idIns(ins);
6745     id->idInsFmt(fmt);
6746     id->idInsOpt(INS_OPTS_NONE);
6747
6748     id->idReg1(reg1);
6749     id->idReg2(reg2);
6750     id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6751     id->idSetIsLclVar();
6752
6753 #ifdef DEBUG
6754     id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6755 #endif
6756
6757     dispIns(id);
6758     appendToCurIG(id);
6759 }
6760
6761 /*****************************************************************************
6762  *
6763  *  Add an instruction referencing consecutive stack-based local variable slots and two registers
6764  */
6765 void emitter::emitIns_S_S_R_R(
6766     instruction ins, emitAttr attr1, emitAttr attr2, regNumber reg1, regNumber reg2, int varx, int offs)
6767 {
6768     assert((ins == INS_stp) || (ins == INS_stnp));
6769     assert(EA_8BYTE == EA_SIZE(attr1));
6770     assert(EA_8BYTE == EA_SIZE(attr2));
6771     assert(isGeneralRegisterOrZR(reg1));
6772     assert(isGeneralRegisterOrZR(reg2));
6773     assert(offs >= 0);
6774
6775     insFormat      fmt   = IF_LS_3B;
6776     int            disp  = 0;
6777     const unsigned scale = 3;
6778
6779     /* Figure out the variable's frame position */
6780     int  base;
6781     bool FPbased;
6782
6783     base = emitComp->lvaFrameAddress(varx, &FPbased);
6784     disp = base + offs;
6785
6786     // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6787     regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE;
6788     reg3           = encodingSPtoZR(reg3);
6789
6790     bool    useRegForAdr = true;
6791     ssize_t imm          = disp;
6792     ssize_t mask         = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6793     if (imm == 0)
6794     {
6795         useRegForAdr = false;
6796     }
6797     else
6798     {
6799         if ((imm & mask) == 0)
6800         {
6801             ssize_t immShift = imm >> scale; // The immediate is scaled by the size of the ld/st
6802
6803             if ((immShift >= -64) && (immShift <= 63))
6804             {
6805                 fmt          = IF_LS_3C;
6806                 useRegForAdr = false;
6807                 imm          = immShift;
6808             }
6809         }
6810     }
6811
6812     if (useRegForAdr)
6813     {
6814         regNumber rsvd = codeGen->rsGetRsvdReg();
6815         emitIns_R_R_Imm(INS_add, EA_PTRSIZE, rsvd, reg3, imm);
6816         reg3 = rsvd;
6817         imm  = 0;
6818     }
6819
6820     assert(fmt != IF_NONE);
6821
6822     instrDesc* id = emitNewInstrCns(attr1, imm);
6823
6824     id->idIns(ins);
6825     id->idInsFmt(fmt);
6826     id->idInsOpt(INS_OPTS_NONE);
6827
6828     // Record the attribute for the second register in the pair
6829     if (EA_IS_GCREF(attr2))
6830     {
6831         id->idGCrefReg2(GCT_GCREF);
6832     }
6833     else if (EA_IS_BYREF(attr2))
6834     {
6835         id->idGCrefReg2(GCT_BYREF);
6836     }
6837     else
6838     {
6839         id->idGCrefReg2(GCT_NONE);
6840     }
6841
6842     id->idReg1(reg1);
6843     id->idReg2(reg2);
6844     id->idReg3(reg3);
6845     id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6846     id->idSetIsLclVar();
6847
6848 #ifdef DEBUG
6849     id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6850 #endif
6851
6852     dispIns(id);
6853     appendToCurIG(id);
6854 }
6855
6856 /*****************************************************************************
6857  *
6858  *  Add an instruction referencing stack-based local variable and an immediate
6859  */
6860 void emitter::emitIns_S_I(instruction ins, emitAttr attr, int varx, int offs, int val)
6861 {
6862     NYI("emitIns_S_I");
6863 }
6864
6865 /*****************************************************************************
6866  *
6867  *  Add an instruction with a register + static member operands.
6868  *  Constant is stored into JIT data which is adjacent to code.
6869  *  No relocation is needed. PC-relative offset will be encoded directly into instruction.
6870  *
6871  */
6872 void emitter::emitIns_R_C(
6873     instruction ins, emitAttr attr, regNumber reg, regNumber addrReg, CORINFO_FIELD_HANDLE fldHnd, int offs)
6874 {
6875     assert(offs >= 0);
6876     assert(instrDesc::fitsInSmallCns(offs));
6877
6878     emitAttr      size = EA_SIZE(attr);
6879     insFormat     fmt  = IF_NONE;
6880     int           disp = 0;
6881     instrDescJmp* id   = emitNewInstrJmp();
6882
6883     switch (ins)
6884     {
6885         case INS_adr:
6886             // This is case to get address to the constant data.
6887             fmt = IF_LARGEADR;
6888             assert(isGeneralRegister(reg));
6889             assert(isValidGeneralDatasize(size));
6890             break;
6891
6892         case INS_ldr:
6893             fmt = IF_LARGELDC;
6894             if (isVectorRegister(reg))
6895             {
6896                 assert(isValidScalarDatasize(size));
6897                 // For vector (float/double) register, we should have an integer address reg to
6898                 // compute long address which consists of page address and page offset.
6899                 // For integer constant, this is not needed since the dest reg can be used to
6900                 // compute address as well as contain the final contents.
6901                 assert(isGeneralRegister(reg) || (addrReg != REG_NA));
6902             }
6903             else
6904             {
6905                 assert(isGeneralRegister(reg));
6906                 assert(isValidGeneralDatasize(size));
6907             }
6908             break;
6909         default:
6910             unreached();
6911     }
6912
6913     assert(fmt != IF_NONE);
6914
6915     id->idIns(ins);
6916     id->idInsFmt(fmt);
6917     id->idInsOpt(INS_OPTS_NONE);
6918     id->idSmallCns(offs);
6919     id->idOpSize(size);
6920     id->idAddr()->iiaFieldHnd = fldHnd;
6921     id->idSetIsBound(); // We won't patch address since we will know the exact distance once JIT code and data are
6922                         // allocated together.
6923
6924     id->idReg1(reg); // destination register that will get the constant value.
6925     if (addrReg != REG_NA)
6926     {
6927         id->idReg2(addrReg); // integer register to compute long address (used for vector dest when we end up with long
6928                              // address)
6929     }
6930     id->idjShort = false; // Assume loading constant from long address
6931
6932     // Keep it long if it's in cold code.
6933     id->idjKeepLong = emitComp->fgIsBlockCold(emitComp->compCurBB);
6934
6935 #ifdef DEBUG
6936     if (emitComp->opts.compLongAddress)
6937         id->idjKeepLong = 1;
6938 #endif // DEBUG
6939
6940     // If it's possible to be shortened, then put it in jump list
6941     // to be revisited by emitJumpDistBind.
6942     if (!id->idjKeepLong)
6943     {
6944         /* Record the jump's IG and offset within it */
6945         id->idjIG   = emitCurIG;
6946         id->idjOffs = emitCurIGsize;
6947
6948         /* Append this jump to this IG's jump list */
6949         id->idjNext      = emitCurIGjmpList;
6950         emitCurIGjmpList = id;
6951
6952 #if EMITTER_STATS
6953         emitTotalIGjmps++;
6954 #endif
6955     }
6956
6957     dispIns(id);
6958     appendToCurIG(id);
6959 }
6960
6961 /*****************************************************************************
6962  *
6963  *  Add an instruction with a static member + constant.
6964  */
6965
6966 void emitter::emitIns_C_I(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, ssize_t offs, ssize_t val)
6967 {
6968     NYI("emitIns_C_I");
6969 }
6970
6971 /*****************************************************************************
6972  *
6973  *  Add an instruction with a static member + register operands.
6974  */
6975
6976 void emitter::emitIns_C_R(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, regNumber reg, int offs)
6977 {
6978     assert(!"emitIns_C_R not supported for RyuJIT backend");
6979 }
6980
6981 void emitter::emitIns_R_AR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
6982 {
6983     NYI("emitIns_R_AR");
6984 }
6985
6986 // This computes address from the immediate which is relocatable.
6987 void emitter::emitIns_R_AI(instruction ins, emitAttr attr, regNumber ireg, ssize_t addr)
6988 {
6989     assert(EA_IS_RELOC(attr));
6990     emitAttr      size    = EA_SIZE(attr);
6991     insFormat     fmt     = IF_DI_1E;
6992     bool          needAdd = false;
6993     instrDescJmp* id      = emitNewInstrJmp();
6994
6995     switch (ins)
6996     {
6997         case INS_adrp:
6998             // This computes page address.
6999             // page offset is needed using add.
7000             needAdd = true;
7001             break;
7002         case INS_adr:
7003             break;
7004         default:
7005             unreached();
7006     }
7007
7008     id->idIns(ins);
7009     id->idInsFmt(fmt);
7010     id->idInsOpt(INS_OPTS_NONE);
7011     id->idOpSize(size);
7012     id->idAddr()->iiaAddr = (BYTE*)addr;
7013     id->idReg1(ireg);
7014     id->idSetIsDspReloc();
7015
7016     dispIns(id);
7017     appendToCurIG(id);
7018
7019     if (needAdd)
7020     {
7021         // add reg, reg, imm
7022         ins           = INS_add;
7023         fmt           = IF_DI_2A;
7024         instrDesc* id = emitAllocInstr(attr);
7025         assert(id->idIsReloc());
7026
7027         id->idIns(ins);
7028         id->idInsFmt(fmt);
7029         id->idInsOpt(INS_OPTS_NONE);
7030         id->idOpSize(size);
7031         id->idAddr()->iiaAddr = (BYTE*)addr;
7032         id->idReg1(ireg);
7033         id->idReg2(ireg);
7034
7035         dispIns(id);
7036         appendToCurIG(id);
7037     }
7038 }
7039
7040 void emitter::emitIns_AR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
7041 {
7042     NYI("emitIns_AR_R");
7043 }
7044
7045 void emitter::emitIns_R_ARR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
7046 {
7047     NYI("emitIns_R_ARR");
7048 }
7049
7050 void emitter::emitIns_ARR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
7051 {
7052     NYI("emitIns_R_ARR");
7053 }
7054
7055 void emitter::emitIns_R_ARX(
7056     instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, unsigned mul, int disp)
7057 {
7058     NYI("emitIns_R_ARR");
7059 }
7060
7061 /*****************************************************************************
7062  *
7063  *  Record that a jump instruction uses the short encoding
7064  *
7065  */
7066 void emitter::emitSetShortJump(instrDescJmp* id)
7067 {
7068     if (id->idjKeepLong)
7069         return;
7070
7071     insFormat fmt = IF_NONE;
7072     if (emitIsCondJump(id))
7073     {
7074         switch (id->idIns())
7075         {
7076             case INS_cbz:
7077             case INS_cbnz:
7078                 fmt = IF_BI_1A;
7079                 break;
7080             case INS_tbz:
7081             case INS_tbnz:
7082                 fmt = IF_BI_1B;
7083                 break;
7084             default:
7085                 fmt = IF_BI_0B;
7086                 break;
7087         }
7088     }
7089     else if (emitIsLoadLabel(id))
7090     {
7091         fmt = IF_DI_1E;
7092     }
7093     else if (emitIsLoadConstant(id))
7094     {
7095         fmt = IF_LS_1A;
7096     }
7097     else
7098     {
7099         unreached();
7100     }
7101
7102     id->idInsFmt(fmt);
7103     id->idjShort = true;
7104 }
7105
7106 /*****************************************************************************
7107  *
7108  *  Add a label instruction.
7109  */
7110
7111 void emitter::emitIns_R_L(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
7112 {
7113     assert(dst->bbFlags & BBF_JMP_TARGET);
7114
7115     insFormat fmt = IF_NONE;
7116
7117     switch (ins)
7118     {
7119         case INS_adr:
7120             fmt = IF_LARGEADR;
7121             break;
7122         default:
7123             unreached();
7124     }
7125
7126     instrDescJmp* id = emitNewInstrJmp();
7127
7128     id->idIns(ins);
7129     id->idInsFmt(fmt);
7130     id->idjShort             = false;
7131     id->idAddr()->iiaBBlabel = dst;
7132     id->idReg1(reg);
7133     id->idOpSize(EA_PTRSIZE);
7134
7135 #ifdef DEBUG
7136     // Mark the catch return
7137     if (emitComp->compCurBB->bbJumpKind == BBJ_EHCATCHRET)
7138     {
7139         id->idDebugOnlyInfo()->idCatchRet = true;
7140     }
7141 #endif // DEBUG
7142
7143     id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7144
7145 #ifdef DEBUG
7146     if (emitComp->opts.compLongAddress)
7147         id->idjKeepLong = 1;
7148 #endif // DEBUG
7149
7150     /* Record the jump's IG and offset within it */
7151
7152     id->idjIG   = emitCurIG;
7153     id->idjOffs = emitCurIGsize;
7154
7155     /* Append this jump to this IG's jump list */
7156
7157     id->idjNext      = emitCurIGjmpList;
7158     emitCurIGjmpList = id;
7159
7160 #if EMITTER_STATS
7161     emitTotalIGjmps++;
7162 #endif
7163
7164     dispIns(id);
7165     appendToCurIG(id);
7166 }
7167
7168 /*****************************************************************************
7169  *
7170  *  Add a data label instruction.
7171  */
7172
7173 void emitter::emitIns_R_D(instruction ins, emitAttr attr, unsigned offs, regNumber reg)
7174 {
7175     NYI("emitIns_R_D");
7176 }
7177
7178 void emitter::emitIns_J_R(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
7179 {
7180     assert((ins == INS_cbz) || (ins == INS_cbnz));
7181
7182     assert(dst != nullptr);
7183     assert((dst->bbFlags & BBF_JMP_TARGET) != 0);
7184
7185     insFormat fmt = IF_LARGEJMP;
7186
7187     instrDescJmp* id = emitNewInstrJmp();
7188
7189     id->idIns(ins);
7190     id->idInsFmt(fmt);
7191     id->idReg1(reg);
7192     id->idjShort = false;
7193     id->idOpSize(EA_SIZE(attr));
7194
7195     id->idAddr()->iiaBBlabel = dst;
7196     id->idjKeepLong          = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7197
7198     /* Record the jump's IG and offset within it */
7199
7200     id->idjIG   = emitCurIG;
7201     id->idjOffs = emitCurIGsize;
7202
7203     /* Append this jump to this IG's jump list */
7204
7205     id->idjNext      = emitCurIGjmpList;
7206     emitCurIGjmpList = id;
7207
7208 #if EMITTER_STATS
7209     emitTotalIGjmps++;
7210 #endif
7211
7212     dispIns(id);
7213     appendToCurIG(id);
7214 }
7215
7216 void emitter::emitIns_J_R_I(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg, int imm)
7217 {
7218     assert((ins == INS_tbz) || (ins == INS_tbnz));
7219
7220     assert(dst != nullptr);
7221     assert((dst->bbFlags & BBF_JMP_TARGET) != 0);
7222     assert((EA_SIZE(attr) == EA_4BYTE) || (EA_SIZE(attr) == EA_8BYTE));
7223     assert(imm < ((EA_SIZE(attr) == EA_4BYTE) ? 32 : 64));
7224
7225     insFormat fmt = IF_LARGEJMP;
7226
7227     instrDescJmp* id = emitNewInstrJmp();
7228
7229     id->idIns(ins);
7230     id->idInsFmt(fmt);
7231     id->idReg1(reg);
7232     id->idjShort = false;
7233     id->idSmallCns(imm);
7234     id->idOpSize(EA_SIZE(attr));
7235
7236     id->idAddr()->iiaBBlabel = dst;
7237     id->idjKeepLong          = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7238
7239     /* Record the jump's IG and offset within it */
7240
7241     id->idjIG   = emitCurIG;
7242     id->idjOffs = emitCurIGsize;
7243
7244     /* Append this jump to this IG's jump list */
7245
7246     id->idjNext      = emitCurIGjmpList;
7247     emitCurIGjmpList = id;
7248
7249 #if EMITTER_STATS
7250     emitTotalIGjmps++;
7251 #endif
7252
7253     dispIns(id);
7254     appendToCurIG(id);
7255 }
7256
7257 void emitter::emitIns_J(instruction ins, BasicBlock* dst, int instrCount)
7258 {
7259     insFormat fmt = IF_NONE;
7260
7261     if (dst != nullptr)
7262     {
7263         assert(dst->bbFlags & BBF_JMP_TARGET);
7264     }
7265     else
7266     {
7267         assert(instrCount != 0);
7268     }
7269
7270     /* Figure out the encoding format of the instruction */
7271
7272     bool idjShort = false;
7273     switch (ins)
7274     {
7275         case INS_bl_local:
7276         case INS_b:
7277             // Unconditional jump is a single form.
7278             idjShort = true;
7279             fmt      = IF_BI_0A;
7280             break;
7281
7282         case INS_beq:
7283         case INS_bne:
7284         case INS_bhs:
7285         case INS_blo:
7286         case INS_bmi:
7287         case INS_bpl:
7288         case INS_bvs:
7289         case INS_bvc:
7290         case INS_bhi:
7291         case INS_bls:
7292         case INS_bge:
7293         case INS_blt:
7294         case INS_bgt:
7295         case INS_ble:
7296             // Assume conditional jump is long.
7297             fmt = IF_LARGEJMP;
7298             break;
7299
7300         default:
7301             unreached();
7302             break;
7303     }
7304
7305     instrDescJmp* id = emitNewInstrJmp();
7306
7307     id->idIns(ins);
7308     id->idInsFmt(fmt);
7309     id->idjShort = idjShort;
7310
7311 #ifdef DEBUG
7312     // Mark the finally call
7313     if (ins == INS_bl_local && emitComp->compCurBB->bbJumpKind == BBJ_CALLFINALLY)
7314     {
7315         id->idDebugOnlyInfo()->idFinallyCall = true;
7316     }
7317 #endif // DEBUG
7318
7319     if (dst != nullptr)
7320     {
7321         id->idAddr()->iiaBBlabel = dst;
7322
7323         // Skip unconditional jump that has a single form.
7324         // TODO-ARM64-NYI: enable hot/cold splittingNYI.
7325         // The target needs to be relocated.
7326         if (!idjShort)
7327         {
7328             id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7329
7330 #ifdef DEBUG
7331             if (emitComp->opts.compLongAddress) // Force long branches
7332                 id->idjKeepLong = 1;
7333 #endif // DEBUG
7334         }
7335     }
7336     else
7337     {
7338         id->idAddr()->iiaSetInstrCount(instrCount);
7339         id->idjKeepLong = false;
7340         /* This jump must be short */
7341         emitSetShortJump(id);
7342         id->idSetIsBound();
7343     }
7344
7345     /* Record the jump's IG and offset within it */
7346
7347     id->idjIG   = emitCurIG;
7348     id->idjOffs = emitCurIGsize;
7349
7350     /* Append this jump to this IG's jump list */
7351
7352     id->idjNext      = emitCurIGjmpList;
7353     emitCurIGjmpList = id;
7354
7355 #if EMITTER_STATS
7356     emitTotalIGjmps++;
7357 #endif
7358
7359     dispIns(id);
7360     appendToCurIG(id);
7361 }
7362
7363 /*****************************************************************************
7364  *
7365  *  Add a call instruction (direct or indirect).
7366  *      argSize<0 means that the caller will pop the arguments
7367  *
7368  * The other arguments are interpreted depending on callType as shown:
7369  * Unless otherwise specified, ireg,xreg,xmul,disp should have default values.
7370  *
7371  * EC_FUNC_TOKEN       : addr is the method address
7372  * EC_FUNC_ADDR        : addr is the absolute address of the function
7373  *
7374  * If callType is one of these emitCallTypes, addr has to be NULL.
7375  * EC_INDIR_R          : "call ireg".
7376  *
7377  * For ARM xreg, xmul and disp are never used and should always be 0/REG_NA.
7378  *
7379  *  Please consult the "debugger team notification" comment in genFnProlog().
7380  */
7381
7382 void emitter::emitIns_Call(EmitCallType          callType,
7383                            CORINFO_METHOD_HANDLE methHnd,
7384                            INDEBUG_LDISASM_COMMA(CORINFO_SIG_INFO* sigInfo) // used to report call sites to the EE
7385                            void*            addr,
7386                            ssize_t          argSize,
7387                            emitAttr         retSize,
7388                            emitAttr         secondRetSize,
7389                            VARSET_VALARG_TP ptrVars,
7390                            regMaskTP        gcrefRegs,
7391                            regMaskTP        byrefRegs,
7392                            IL_OFFSETX       ilOffset /* = BAD_IL_OFFSET */,
7393                            regNumber        ireg /* = REG_NA */,
7394                            regNumber        xreg /* = REG_NA */,
7395                            unsigned         xmul /* = 0     */,
7396                            ssize_t          disp /* = 0     */,
7397                            bool             isJump /* = false */,
7398                            bool             isNoGC /* = false */,
7399                            bool             isProfLeaveCB /* = false */)
7400 {
7401     /* Sanity check the arguments depending on callType */
7402
7403     assert(callType < EC_COUNT);
7404     assert((callType != EC_FUNC_TOKEN && callType != EC_FUNC_ADDR) ||
7405            (ireg == REG_NA && xreg == REG_NA && xmul == 0 && disp == 0));
7406     assert(callType < EC_INDIR_R || addr == NULL);
7407     assert(callType != EC_INDIR_R || (ireg < REG_COUNT && xreg == REG_NA && xmul == 0 && disp == 0));
7408
7409     // ARM never uses these
7410     assert(xreg == REG_NA && xmul == 0 && disp == 0);
7411
7412     // Our stack level should be always greater than the bytes of arguments we push. Just
7413     // a sanity test.
7414     assert((unsigned)abs(argSize) <= codeGen->genStackLevel);
7415
7416     int        argCnt;
7417     instrDesc* id;
7418
7419     /* This is the saved set of registers after a normal call */
7420     regMaskTP savedSet = RBM_CALLEE_SAVED;
7421
7422     /* some special helper calls have a different saved set registers */
7423
7424     if (isNoGC)
7425     {
7426         assert(emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
7427
7428         // Get the set of registers that this call kills and remove it from the saved set.
7429         savedSet = RBM_ALLINT & ~emitComp->compNoGCHelperCallKillSet(Compiler::eeGetHelperNum(methHnd));
7430
7431         // In case of Leave profiler callback, we need to preserve liveness of REG_PROFILER_RET_SCRATCH
7432         if (isProfLeaveCB)
7433         {
7434             savedSet |= RBM_PROFILER_RET_SCRATCH;
7435         }
7436
7437 #ifdef DEBUG
7438         if (emitComp->verbose)
7439         {
7440             printf("NOGC Call: savedSet=");
7441             printRegMaskInt(savedSet);
7442             emitDispRegSet(savedSet);
7443             printf("\n");
7444         }
7445 #endif
7446     }
7447     else
7448     {
7449         assert(!emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
7450     }
7451
7452     /* Trim out any callee-trashed registers from the live set */
7453
7454     gcrefRegs &= savedSet;
7455     byrefRegs &= savedSet;
7456
7457 #ifdef DEBUG
7458     if (EMIT_GC_VERBOSE)
7459     {
7460         printf("Call: GCvars=%s ", VarSetOps::ToString(emitComp, ptrVars));
7461         dumpConvertedVarSet(emitComp, ptrVars);
7462         printf(", gcrefRegs=");
7463         printRegMaskInt(gcrefRegs);
7464         emitDispRegSet(gcrefRegs);
7465         printf(", byrefRegs=");
7466         printRegMaskInt(byrefRegs);
7467         emitDispRegSet(byrefRegs);
7468         printf("\n");
7469     }
7470 #endif
7471
7472     assert(argSize % REGSIZE_BYTES == 0);
7473     argCnt = (int)(argSize / (int)REGSIZE_BYTES);
7474
7475     /* Managed RetVal: emit sequence point for the call */
7476     if (emitComp->opts.compDbgInfo && ilOffset != BAD_IL_OFFSET)
7477     {
7478         codeGen->genIPmappingAdd(ilOffset, false);
7479     }
7480
7481     /*
7482         We need to allocate the appropriate instruction descriptor based
7483         on whether this is a direct/indirect call, and whether we need to
7484         record an updated set of live GC variables.
7485      */
7486
7487     if (callType >= EC_INDIR_R)
7488     {
7489         /* Indirect call, virtual calls */
7490
7491         assert(callType == EC_INDIR_R);
7492
7493         id = emitNewInstrCallInd(argCnt, disp, ptrVars, gcrefRegs, byrefRegs, retSize, secondRetSize);
7494     }
7495     else
7496     {
7497         /* Helper/static/nonvirtual/function calls (direct or through handle),
7498            and calls to an absolute addr. */
7499
7500         assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
7501
7502         id = emitNewInstrCallDir(argCnt, ptrVars, gcrefRegs, byrefRegs, retSize, secondRetSize);
7503     }
7504
7505     /* Update the emitter's live GC ref sets */
7506
7507     VarSetOps::Assign(emitComp, emitThisGCrefVars, ptrVars);
7508     emitThisGCrefRegs = gcrefRegs;
7509     emitThisByrefRegs = byrefRegs;
7510
7511     /* Set the instruction - special case jumping a function */
7512     instruction ins;
7513     insFormat   fmt = IF_NONE;
7514
7515     id->idSetIsNoGC(isNoGC);
7516
7517     /* Record the address: method, indirection, or funcptr */
7518
7519     if (callType > EC_FUNC_ADDR)
7520     {
7521         /* This is an indirect call (either a virtual call or func ptr call) */
7522
7523         switch (callType)
7524         {
7525             case EC_INDIR_R: // the address is in a register
7526
7527                 id->idSetIsCallRegPtr();
7528
7529                 if (isJump)
7530                 {
7531                     ins = INS_br_tail; // INS_br_tail  Reg
7532                 }
7533                 else
7534                 {
7535                     ins = INS_blr; // INS_blr Reg
7536                 }
7537                 fmt = IF_BR_1B;
7538
7539                 id->idIns(ins);
7540                 id->idInsFmt(fmt);
7541
7542                 id->idReg3(ireg);
7543                 assert(xreg == REG_NA);
7544                 break;
7545
7546             default:
7547                 NO_WAY("unexpected instruction");
7548                 break;
7549         }
7550     }
7551     else
7552     {
7553         /* This is a simple direct call: "call helper/method/addr" */
7554
7555         assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
7556
7557         assert(addr != NULL);
7558
7559         if (isJump)
7560         {
7561             ins = INS_b_tail; // INS_b_tail imm28
7562         }
7563         else
7564         {
7565             ins = INS_bl; // INS_bl imm28
7566         }
7567         fmt = IF_BI_0C;
7568
7569         id->idIns(ins);
7570         id->idInsFmt(fmt);
7571
7572         id->idAddr()->iiaAddr = (BYTE*)addr;
7573
7574         if (callType == EC_FUNC_ADDR)
7575         {
7576             id->idSetIsCallAddr();
7577         }
7578
7579         if (emitComp->opts.compReloc)
7580         {
7581             id->idSetIsDspReloc();
7582         }
7583     }
7584
7585 #ifdef DEBUG
7586     if (EMIT_GC_VERBOSE)
7587     {
7588         if (id->idIsLargeCall())
7589         {
7590             printf("[%02u] Rec call GC vars = %s\n", id->idDebugOnlyInfo()->idNum,
7591                    VarSetOps::ToString(emitComp, ((instrDescCGCA*)id)->idcGCvars));
7592         }
7593     }
7594
7595     id->idDebugOnlyInfo()->idMemCookie = (size_t)methHnd; // method token
7596     id->idDebugOnlyInfo()->idCallSig   = sigInfo;
7597 #endif // DEBUG
7598
7599 #ifdef LATE_DISASM
7600     if (addr != nullptr)
7601     {
7602         codeGen->getDisAssembler().disSetMethod((size_t)addr, methHnd);
7603     }
7604 #endif // LATE_DISASM
7605
7606     dispIns(id);
7607     appendToCurIG(id);
7608 }
7609
7610 /*****************************************************************************
7611  *
7612  *  Returns true if 'imm' is valid Cond encoding
7613  */
7614
7615 /*static*/ bool emitter::isValidImmCond(ssize_t imm)
7616 {
7617     // range check the ssize_t value, to make sure it is a small unsigned value
7618     // and that only the bits in the cfi.cond are set
7619     if ((imm < 0) || (imm > 0xF))
7620         return false;
7621
7622     condFlagsImm cfi;
7623     cfi.immCFVal = (unsigned)imm;
7624
7625     return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7626 }
7627
7628 /*****************************************************************************
7629  *
7630  *  Returns true if 'imm' is valid Cond/Flags encoding
7631  */
7632
7633 /*static*/ bool emitter::isValidImmCondFlags(ssize_t imm)
7634 {
7635     // range check the ssize_t value, to make sure it is a small unsigned value
7636     // and that only the bits in the cfi.cond or cfi.flags are set
7637     if ((imm < 0) || (imm > 0xFF))
7638         return false;
7639
7640     condFlagsImm cfi;
7641     cfi.immCFVal = (unsigned)imm;
7642
7643     return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7644 }
7645
7646 /*****************************************************************************
7647  *
7648  *  Returns true if 'imm' is valid Cond/Flags/Imm5 encoding
7649  */
7650
7651 /*static*/ bool emitter::isValidImmCondFlagsImm5(ssize_t imm)
7652 {
7653     // range check the ssize_t value, to make sure it is a small unsigned value
7654     // and that only the bits in the cfi.cond, cfi.flags or cfi.imm5 are set
7655     if ((imm < 0) || (imm > 0x1FFF))
7656         return false;
7657
7658     condFlagsImm cfi;
7659     cfi.immCFVal = (unsigned)imm;
7660
7661     return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7662 }
7663
7664 /*****************************************************************************
7665  *
7666  *  Returns an encoding for the specified register used in the 'Rd' position
7667  */
7668
7669 /*static*/ emitter::code_t emitter::insEncodeReg_Rd(regNumber reg)
7670 {
7671     assert(isIntegerRegister(reg));
7672     emitter::code_t ureg = (emitter::code_t)reg;
7673     assert((ureg >= 0) && (ureg <= 31));
7674     return ureg;
7675 }
7676
7677 /*****************************************************************************
7678  *
7679  *  Returns an encoding for the specified register used in the 'Rt' position
7680  */
7681
7682 /*static*/ emitter::code_t emitter::insEncodeReg_Rt(regNumber reg)
7683 {
7684     assert(isIntegerRegister(reg));
7685     emitter::code_t ureg = (emitter::code_t)reg;
7686     assert((ureg >= 0) && (ureg <= 31));
7687     return ureg;
7688 }
7689
7690 /*****************************************************************************
7691  *
7692  *  Returns an encoding for the specified register used in the 'Rn' position
7693  */
7694
7695 /*static*/ emitter::code_t emitter::insEncodeReg_Rn(regNumber reg)
7696 {
7697     assert(isIntegerRegister(reg));
7698     emitter::code_t ureg = (emitter::code_t)reg;
7699     assert((ureg >= 0) && (ureg <= 31));
7700     return ureg << 5;
7701 }
7702
7703 /*****************************************************************************
7704  *
7705  *  Returns an encoding for the specified register used in the 'Rm' position
7706  */
7707
7708 /*static*/ emitter::code_t emitter::insEncodeReg_Rm(regNumber reg)
7709 {
7710     assert(isIntegerRegister(reg));
7711     emitter::code_t ureg = (emitter::code_t)reg;
7712     assert((ureg >= 0) && (ureg <= 31));
7713     return ureg << 16;
7714 }
7715
7716 /*****************************************************************************
7717  *
7718  *  Returns an encoding for the specified register used in the 'Ra' position
7719  */
7720
7721 /*static*/ emitter::code_t emitter::insEncodeReg_Ra(regNumber reg)
7722 {
7723     assert(isIntegerRegister(reg));
7724     emitter::code_t ureg = (emitter::code_t)reg;
7725     assert((ureg >= 0) && (ureg <= 31));
7726     return ureg << 10;
7727 }
7728
7729 /*****************************************************************************
7730  *
7731  *  Returns an encoding for the specified register used in the 'Vd' position
7732  */
7733
7734 /*static*/ emitter::code_t emitter::insEncodeReg_Vd(regNumber reg)
7735 {
7736     assert(emitter::isVectorRegister(reg));
7737     emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7738     assert((ureg >= 0) && (ureg <= 31));
7739     return ureg;
7740 }
7741
7742 /*****************************************************************************
7743  *
7744  *  Returns an encoding for the specified register used in the 'Vt' position
7745  */
7746
7747 /*static*/ emitter::code_t emitter::insEncodeReg_Vt(regNumber reg)
7748 {
7749     assert(emitter::isVectorRegister(reg));
7750     emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7751     assert((ureg >= 0) && (ureg <= 31));
7752     return ureg;
7753 }
7754
7755 /*****************************************************************************
7756  *
7757  *  Returns an encoding for the specified register used in the 'Vn' position
7758  */
7759
7760 /*static*/ emitter::code_t emitter::insEncodeReg_Vn(regNumber reg)
7761 {
7762     assert(emitter::isVectorRegister(reg));
7763     emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7764     assert((ureg >= 0) && (ureg <= 31));
7765     return ureg << 5;
7766 }
7767
7768 /*****************************************************************************
7769  *
7770  *  Returns an encoding for the specified register used in the 'Vm' position
7771  */
7772
7773 /*static*/ emitter::code_t emitter::insEncodeReg_Vm(regNumber reg)
7774 {
7775     assert(emitter::isVectorRegister(reg));
7776     emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7777     assert((ureg >= 0) && (ureg <= 31));
7778     return ureg << 16;
7779 }
7780
7781 /*****************************************************************************
7782  *
7783  *  Returns an encoding for the specified register used in the 'Va' position
7784  */
7785
7786 /*static*/ emitter::code_t emitter::insEncodeReg_Va(regNumber reg)
7787 {
7788     assert(emitter::isVectorRegister(reg));
7789     emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7790     assert((ureg >= 0) && (ureg <= 31));
7791     return ureg << 10;
7792 }
7793
7794 /*****************************************************************************
7795  *
7796  *  Returns an encoding for the specified condition code.
7797  */
7798
7799 /*static*/ emitter::code_t emitter::insEncodeCond(insCond cond)
7800 {
7801     emitter::code_t uimm = (emitter::code_t)cond;
7802     return uimm << 12;
7803 }
7804
7805 /*****************************************************************************
7806  *
7807  *  Returns an encoding for the condition code with the lowest bit inverted (marked by invert(<cond>) in the
7808  *  architecture manual).
7809  */
7810
7811 /*static*/ emitter::code_t emitter::insEncodeInvertedCond(insCond cond)
7812 {
7813     emitter::code_t uimm = (emitter::code_t)cond;
7814     uimm ^= 1; // invert the lowest bit
7815     return uimm << 12;
7816 }
7817
7818 /*****************************************************************************
7819  *
7820  *  Returns an encoding for the specified flags.
7821  */
7822
7823 /*static*/ emitter::code_t emitter::insEncodeFlags(insCflags flags)
7824 {
7825     emitter::code_t uimm = (emitter::code_t)flags;
7826     return uimm;
7827 }
7828
7829 /*****************************************************************************
7830  *
7831  *  Returns the encoding for the Shift Count bits to be used for Arm64 encodings
7832  */
7833
7834 /*static*/ emitter::code_t emitter::insEncodeShiftCount(ssize_t imm, emitAttr size)
7835 {
7836     assert((imm & 0x003F) == imm);
7837     assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
7838
7839     return (emitter::code_t)imm << 10;
7840 }
7841
7842 /*****************************************************************************
7843  *
7844  *  Returns the encoding to select a 64-bit datasize for an Arm64 instruction
7845  */
7846
7847 /*static*/ emitter::code_t emitter::insEncodeDatasize(emitAttr size)
7848 {
7849     if (size == EA_8BYTE)
7850     {
7851         return 0x80000000; // set the bit at location 31
7852     }
7853     else
7854     {
7855         assert(size == EA_4BYTE);
7856         return 0;
7857     }
7858 }
7859
7860 /*****************************************************************************
7861  *
7862  *  Returns the encoding to select the datasize for the general load/store Arm64 instructions
7863  *
7864  */
7865
7866 /*static*/ emitter::code_t emitter::insEncodeDatasizeLS(emitter::code_t code, emitAttr size)
7867 {
7868     bool exclusive = ((code & 0x35000000) == 0);
7869     bool atomic    = ((code & 0x31200C00) == 0x30200000);
7870
7871     if ((code & 0x00800000) && !exclusive && !atomic) // Is this a sign-extending opcode? (i.e. ldrsw, ldrsh, ldrsb)
7872     {
7873         if ((code & 0x80000000) == 0) // Is it a ldrsh or ldrsb and not ldrsw ?
7874         {
7875             if (EA_SIZE(size) != EA_8BYTE) // Do we need to encode the 32-bit Rt size bit?
7876             {
7877                 return 0x00400000; // set the bit at location 22
7878             }
7879         }
7880     }
7881     else if (code & 0x80000000) // Is this a ldr/str/ldur/stur opcode?
7882     {
7883         if (EA_SIZE(size) == EA_8BYTE) // Do we need to encode the 64-bit size bit?
7884         {
7885             return 0x40000000; // set the bit at location 30
7886         }
7887     }
7888     return 0;
7889 }
7890
7891 /*****************************************************************************
7892  *
7893  *  Returns the encoding to select the datasize for the vector load/store Arm64 instructions
7894  *
7895  */
7896
7897 /*static*/ emitter::code_t emitter::insEncodeDatasizeVLS(emitter::code_t code, emitAttr size)
7898 {
7899     code_t result = 0;
7900
7901     // Check bit 29
7902     if ((code & 0x20000000) == 0)
7903     {
7904         // LDR literal
7905
7906         if (size == EA_16BYTE)
7907         {
7908             // set the operation size in bit 31
7909             result = 0x80000000;
7910         }
7911         else if (size == EA_8BYTE)
7912         {
7913             // set the operation size in bit 30
7914             result = 0x40000000;
7915         }
7916         else
7917         {
7918             assert(size == EA_4BYTE);
7919             // no bits are set
7920             result = 0x00000000;
7921         }
7922     }
7923     else
7924     {
7925         // LDR non-literal
7926
7927         if (size == EA_16BYTE)
7928         {
7929             // The operation size in bits 31 and 30 are zero
7930             // Bit 23 specifies a 128-bit Load/Store
7931             result = 0x00800000;
7932         }
7933         else if (size == EA_8BYTE)
7934         {
7935             // set the operation size in bits 31 and 30
7936             result = 0xC0000000;
7937         }
7938         else if (size == EA_4BYTE)
7939         {
7940             // set the operation size in bit 31
7941             result = 0x80000000;
7942         }
7943         else if (size == EA_2BYTE)
7944         {
7945             // set the operation size in bit 30
7946             result = 0x40000000;
7947         }
7948         else
7949         {
7950             assert(size == EA_1BYTE);
7951             // The operation size in bits 31 and 30 are zero
7952             result = 0x00000000;
7953         }
7954     }
7955
7956     // Or in bit 26 to indicate a Vector register is used as 'target'
7957     result |= 0x04000000;
7958
7959     return result;
7960 }
7961
7962 /*****************************************************************************
7963  *
7964  *  Returns the encoding to select the datasize for the vector load/store Arm64 instructions
7965  *
7966  */
7967
7968 /*static*/ emitter::code_t emitter::insEncodeDatasizeVPLS(emitter::code_t code, emitAttr size)
7969 {
7970     code_t result = 0;
7971
7972     if (size == EA_16BYTE)
7973     {
7974         // The operation size in bits 31 and 30 are zero
7975         // Bit 23 specifies a 128-bit Load/Store
7976         result = 0x80000000;
7977     }
7978     else if (size == EA_8BYTE)
7979     {
7980         // set the operation size in bits 31 and 30
7981         result = 0x40000000;
7982     }
7983     else if (size == EA_4BYTE)
7984     {
7985         // set the operation size in bit 31
7986         result = 0x00000000;
7987     }
7988
7989     // Or in bit 26 to indicate a Vector register is used as 'target'
7990     result |= 0x04000000;
7991
7992     return result;
7993 }
7994
7995 /*****************************************************************************
7996  *
7997  *  Returns the encoding to set the size bit and the N bits for a 'bitfield' instruction
7998  *
7999  */
8000
8001 /*static*/ emitter::code_t emitter::insEncodeDatasizeBF(emitter::code_t code, emitAttr size)
8002 {
8003     // is bit 30 equal to 0?
8004     if ((code & 0x40000000) == 0) // is the opcode one of extr, sxtb, sxth or sxtw
8005     {
8006         if (size == EA_8BYTE) // Do we need to set the sf and N bits?
8007         {
8008             return 0x80400000; // set the sf-bit at location 31 and the N-bit at location 22
8009         }
8010     }
8011     return 0; // don't set any bits
8012 }
8013
8014 /*****************************************************************************
8015  *
8016  *  Returns the encoding to select the 64/128-bit datasize for an Arm64 vector instruction
8017  */
8018
8019 /*static*/ emitter::code_t emitter::insEncodeVectorsize(emitAttr size)
8020 {
8021     if (size == EA_16BYTE)
8022     {
8023         return 0x40000000; // set the bit at location 30
8024     }
8025     else
8026     {
8027         assert(size == EA_8BYTE);
8028         return 0;
8029     }
8030 }
8031
8032 /*****************************************************************************
8033  *
8034  *  Returns the encoding to select 'index' for an Arm64 vector elem instruction
8035  */
8036 /*static*/ emitter::code_t emitter::insEncodeVectorIndex(emitAttr elemsize, ssize_t index)
8037 {
8038     code_t bits = (code_t)index;
8039     if (elemsize == EA_1BYTE)
8040     {
8041         bits <<= 1;
8042         bits |= 1;
8043     }
8044     else if (elemsize == EA_2BYTE)
8045     {
8046         bits <<= 2;
8047         bits |= 2;
8048     }
8049     else if (elemsize == EA_4BYTE)
8050     {
8051         bits <<= 3;
8052         bits |= 4;
8053     }
8054     else
8055     {
8056         assert(elemsize == EA_8BYTE);
8057         bits <<= 4;
8058         bits |= 8;
8059     }
8060     assert((bits >= 1) && (bits <= 0x1f));
8061
8062     return (bits << 16); // bits at locations [20,19,18,17,16]
8063 }
8064
8065 /*****************************************************************************
8066  *
8067  *  Returns the encoding to select 'index2' for an Arm64 'ins' elem instruction
8068  */
8069 /*static*/ emitter::code_t emitter::insEncodeVectorIndex2(emitAttr elemsize, ssize_t index2)
8070 {
8071     code_t bits = (code_t)index2;
8072     if (elemsize == EA_1BYTE)
8073     {
8074         // bits are correct
8075     }
8076     else if (elemsize == EA_2BYTE)
8077     {
8078         bits <<= 1;
8079     }
8080     else if (elemsize == EA_4BYTE)
8081     {
8082         bits <<= 2;
8083     }
8084     else
8085     {
8086         assert(elemsize == EA_8BYTE);
8087         bits <<= 3;
8088     }
8089     assert((bits >= 0) && (bits <= 0xf));
8090
8091     return (bits << 11); // bits at locations [14,13,12,11]
8092 }
8093
8094 /*****************************************************************************
8095  *
8096  *  Returns the encoding to select the 'index' for an Arm64 'mul' by elem instruction
8097  */
8098 /*static*/ emitter::code_t emitter::insEncodeVectorIndexLMH(emitAttr elemsize, ssize_t index)
8099 {
8100     code_t bits = 0;
8101
8102     if (elemsize == EA_2BYTE)
8103     {
8104         assert((index >= 0) && (index <= 7));
8105         if (index & 0x4)
8106         {
8107             bits |= (1 << 11); // set bit 11 'H'
8108         }
8109         if (index & 0x2)
8110         {
8111             bits |= (1 << 21); // set bit 21 'L'
8112         }
8113         if (index & 0x1)
8114         {
8115             bits |= (1 << 20); // set bit 20 'M'
8116         }
8117     }
8118     else if (elemsize == EA_4BYTE)
8119     {
8120         assert((index >= 0) && (index <= 3));
8121         if (index & 0x2)
8122         {
8123             bits |= (1 << 11); // set bit 11 'H'
8124         }
8125         if (index & 0x1)
8126         {
8127             bits |= (1 << 21); // set bit 21 'L'
8128         }
8129     }
8130     else
8131     {
8132         assert(!"Invalid 'elemsize' value");
8133     }
8134
8135     return bits;
8136 }
8137
8138 /*****************************************************************************
8139  *
8140  *   Returns the encoding to shift by 'shift' for an Arm64 vector or scalar instruction
8141  */
8142
8143 /*static*/ emitter::code_t emitter::insEncodeVectorShift(emitAttr size, ssize_t shift)
8144 {
8145     assert(shift < getBitWidth(size));
8146
8147     code_t imm = (code_t)(getBitWidth(size) + shift);
8148
8149     return imm << 16;
8150 }
8151
8152 /*****************************************************************************
8153  *
8154  *  Returns the encoding to select the 1/2/4/8 byte elemsize for an Arm64 vector instruction
8155  */
8156
8157 /*static*/ emitter::code_t emitter::insEncodeElemsize(emitAttr size)
8158 {
8159     if (size == EA_8BYTE)
8160     {
8161         return 0x00C00000; // set the bit at location 23 and 22
8162     }
8163     else if (size == EA_4BYTE)
8164     {
8165         return 0x00800000; // set the bit at location 23
8166     }
8167     else if (size == EA_2BYTE)
8168     {
8169         return 0x00400000; // set the bit at location 22
8170     }
8171     assert(size == EA_1BYTE);
8172     return 0x00000000;
8173 }
8174
8175 /*****************************************************************************
8176  *
8177  *  Returns the encoding to select the 4/8 byte elemsize for an Arm64 float vector instruction
8178  */
8179
8180 /*static*/ emitter::code_t emitter::insEncodeFloatElemsize(emitAttr size)
8181 {
8182     if (size == EA_8BYTE)
8183     {
8184         return 0x00400000; // set the bit at location 22
8185     }
8186     assert(size == EA_4BYTE);
8187     return 0x00000000;
8188 }
8189
8190 // Returns the encoding to select the index for an Arm64 float vector by elem instruction
8191 /*static*/ emitter::code_t emitter::insEncodeFloatIndex(emitAttr elemsize, ssize_t index)
8192 {
8193     code_t result = 0x00000000;
8194     if (elemsize == EA_8BYTE)
8195     {
8196         assert((index >= 0) && (index <= 1));
8197         if (index == 1)
8198         {
8199             result |= 0x00000800; // 'H' - set the bit at location 11
8200         }
8201     }
8202     else
8203     {
8204         assert(elemsize == EA_4BYTE);
8205         assert((index >= 0) && (index <= 3));
8206         if (index & 2)
8207         {
8208             result |= 0x00000800; // 'H' - set the bit at location 11
8209         }
8210         if (index & 1)
8211         {
8212             result |= 0x00200000; // 'L' - set the bit at location 21
8213         }
8214     }
8215     return result;
8216 }
8217
8218 /*****************************************************************************
8219  *
8220  *  Returns the encoding to select the fcvt operation for Arm64 instructions
8221  */
8222 /*static*/ emitter::code_t emitter::insEncodeConvertOpt(insFormat fmt, insOpts conversion)
8223 {
8224     code_t result = 0;
8225     switch (conversion)
8226     {
8227         case INS_OPTS_S_TO_D: // Single to Double
8228             assert(fmt == IF_DV_2J);
8229             result = 0x00008000; // type=00, opc=01
8230             break;
8231
8232         case INS_OPTS_D_TO_S: // Double to Single
8233             assert(fmt == IF_DV_2J);
8234             result = 0x00400000; // type=01, opc=00
8235             break;
8236
8237         case INS_OPTS_H_TO_S: // Half to Single
8238             assert(fmt == IF_DV_2J);
8239             result = 0x00C00000; // type=11, opc=00
8240             break;
8241
8242         case INS_OPTS_H_TO_D: // Half to Double
8243             assert(fmt == IF_DV_2J);
8244             result = 0x00C08000; // type=11, opc=01
8245             break;
8246
8247         case INS_OPTS_S_TO_H: // Single to Half
8248             assert(fmt == IF_DV_2J);
8249             result = 0x00018000; // type=00, opc=11
8250             break;
8251
8252         case INS_OPTS_D_TO_H: // Double to Half
8253             assert(fmt == IF_DV_2J);
8254             result = 0x00418000; // type=01, opc=11
8255             break;
8256
8257         case INS_OPTS_S_TO_4BYTE: // Single to INT32
8258             assert(fmt == IF_DV_2H);
8259             result = 0x00000000; // sf=0, type=00
8260             break;
8261
8262         case INS_OPTS_D_TO_4BYTE: // Double to INT32
8263             assert(fmt == IF_DV_2H);
8264             result = 0x00400000; // sf=0, type=01
8265             break;
8266
8267         case INS_OPTS_S_TO_8BYTE: // Single to INT64
8268             assert(fmt == IF_DV_2H);
8269             result = 0x80000000; // sf=1, type=00
8270             break;
8271
8272         case INS_OPTS_D_TO_8BYTE: // Double to INT64
8273             assert(fmt == IF_DV_2H);
8274             result = 0x80400000; // sf=1, type=01
8275             break;
8276
8277         case INS_OPTS_4BYTE_TO_S: // INT32 to Single
8278             assert(fmt == IF_DV_2I);
8279             result = 0x00000000; // sf=0, type=00
8280             break;
8281
8282         case INS_OPTS_4BYTE_TO_D: // INT32 to Double
8283             assert(fmt == IF_DV_2I);
8284             result = 0x00400000; // sf=0, type=01
8285             break;
8286
8287         case INS_OPTS_8BYTE_TO_S: // INT64 to Single
8288             assert(fmt == IF_DV_2I);
8289             result = 0x80000000; // sf=1, type=00
8290             break;
8291
8292         case INS_OPTS_8BYTE_TO_D: // INT64 to Double
8293             assert(fmt == IF_DV_2I);
8294             result = 0x80400000; // sf=1, type=01
8295             break;
8296
8297         default:
8298             assert(!"Invalid 'conversion' value");
8299             break;
8300     }
8301     return result;
8302 }
8303
8304 /*****************************************************************************
8305  *
8306  *  Returns the encoding to have the Rn register be updated Pre/Post indexed
8307  *  or not updated
8308  */
8309
8310 /*static*/ emitter::code_t emitter::insEncodeIndexedOpt(insOpts opt)
8311 {
8312     assert(emitter::insOptsNone(opt) || emitter::insOptsIndexed(opt));
8313
8314     if (emitter::insOptsIndexed(opt))
8315     {
8316         if (emitter::insOptsPostIndex(opt))
8317         {
8318             return 0x00000400; // set the bit at location 10
8319         }
8320         else
8321         {
8322             assert(emitter::insOptsPreIndex(opt));
8323             return 0x00000C00; // set the bit at location 10 and 11
8324         }
8325     }
8326     else
8327     {
8328         assert(emitter::insOptsNone(opt));
8329         return 0; // bits 10 and 11 are zero
8330     }
8331 }
8332
8333 /*****************************************************************************
8334  *
8335  *  Returns the encoding for a ldp/stp instruction to have the Rn register
8336  *  be updated Pre/Post indexed or not updated
8337  */
8338
8339 /*static*/ emitter::code_t emitter::insEncodePairIndexedOpt(instruction ins, insOpts opt)
8340 {
8341     assert(emitter::insOptsNone(opt) || emitter::insOptsIndexed(opt));
8342
8343     if ((ins == INS_ldnp) || (ins == INS_stnp))
8344     {
8345         assert(emitter::insOptsNone(opt));
8346         return 0; // bits 23 and 24 are zero
8347     }
8348     else
8349     {
8350         if (emitter::insOptsIndexed(opt))
8351         {
8352             if (emitter::insOptsPostIndex(opt))
8353             {
8354                 return 0x00800000; // set the bit at location 23
8355             }
8356             else
8357             {
8358                 assert(emitter::insOptsPreIndex(opt));
8359                 return 0x01800000; // set the bit at location 24 and 23
8360             }
8361         }
8362         else
8363         {
8364             assert(emitter::insOptsNone(opt));
8365             return 0x01000000; // set the bit at location 24
8366         }
8367     }
8368 }
8369
8370 /*****************************************************************************
8371  *
8372  *  Returns the encoding to apply a Shift Type on the Rm register
8373  */
8374
8375 /*static*/ emitter::code_t emitter::insEncodeShiftType(insOpts opt)
8376 {
8377     if (emitter::insOptsNone(opt))
8378     {
8379         // None implies the we encode LSL (with a zero immediate)
8380         opt = INS_OPTS_LSL;
8381     }
8382     assert(emitter::insOptsAnyShift(opt));
8383
8384     emitter::code_t option = (emitter::code_t)opt - (emitter::code_t)INS_OPTS_LSL;
8385     assert(option <= 3);
8386
8387     return option << 22; // bits 23, 22
8388 }
8389
8390 /*****************************************************************************
8391  *
8392  *  Returns the encoding to apply a 12 bit left shift to the immediate
8393  */
8394
8395 /*static*/ emitter::code_t emitter::insEncodeShiftImm12(insOpts opt)
8396 {
8397     if (emitter::insOptsLSL12(opt))
8398     {
8399         return 0x00400000; // set the bit at location 22
8400     }
8401     return 0;
8402 }
8403
8404 /*****************************************************************************
8405  *
8406  *  Returns the encoding to have the Rm register use an extend operation
8407  */
8408
8409 /*static*/ emitter::code_t emitter::insEncodeExtend(insOpts opt)
8410 {
8411     if (emitter::insOptsNone(opt) || (opt == INS_OPTS_LSL))
8412     {
8413         // None or LSL implies the we encode UXTX
8414         opt = INS_OPTS_UXTX;
8415     }
8416     assert(emitter::insOptsAnyExtend(opt));
8417
8418     emitter::code_t option = (emitter::code_t)opt - (emitter::code_t)INS_OPTS_UXTB;
8419     assert(option <= 7);
8420
8421     return option << 13; // bits 15,14,13
8422 }
8423
8424 /*****************************************************************************
8425  *
8426  *  Returns the encoding to scale the Rm register by {0,1,2,3,4}
8427  *  when using an extend operation
8428  */
8429
8430 /*static*/ emitter::code_t emitter::insEncodeExtendScale(ssize_t imm)
8431 {
8432     assert((imm >= 0) && (imm <= 4));
8433
8434     return (emitter::code_t)imm << 10; // bits 12,11,10
8435 }
8436
8437 /*****************************************************************************
8438  *
8439  *  Returns the encoding to have the Rm register be auto scaled by the ld/st size
8440  */
8441
8442 /*static*/ emitter::code_t emitter::insEncodeReg3Scale(bool isScaled)
8443 {
8444     if (isScaled)
8445     {
8446         return 0x00001000; // set the bit at location 12
8447     }
8448     else
8449     {
8450         return 0;
8451     }
8452 }
8453
8454 BYTE* emitter::emitOutputLoadLabel(BYTE* dst, BYTE* srcAddr, BYTE* dstAddr, instrDescJmp* id)
8455 {
8456     instruction ins    = id->idIns();
8457     insFormat   fmt    = id->idInsFmt();
8458     regNumber   dstReg = id->idReg1();
8459     if (id->idjShort)
8460     {
8461         // adr x, [rel addr] --  compute address: current addr(ip) + rel addr.
8462         assert(ins == INS_adr);
8463         assert(fmt == IF_DI_1E);
8464         ssize_t distVal = (ssize_t)(dstAddr - srcAddr);
8465         dst             = emitOutputShortAddress(dst, ins, fmt, distVal, dstReg);
8466     }
8467     else
8468     {
8469         // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8470         assert(fmt == IF_LARGEADR);
8471         ssize_t relPageAddr =
8472             (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8473         dst = emitOutputShortAddress(dst, INS_adrp, IF_DI_1E, relPageAddr, dstReg);
8474
8475         // add x, x, page offs -- compute address = page addr + page offs
8476         ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8477         assert(isValidUimm12(imm12));
8478         code_t code =
8479             emitInsCode(INS_add, IF_DI_2A);  // DI_2A  X0010001shiiiiii iiiiiinnnnnddddd   1100 0000   imm(i12, sh)
8480         code |= insEncodeDatasize(EA_8BYTE); // X
8481         code |= ((code_t)imm12 << 10);       // iiiiiiiiiiii
8482         code |= insEncodeReg_Rd(dstReg);     // ddddd
8483         code |= insEncodeReg_Rn(dstReg);     // nnnnn
8484         dst += emitOutput_Instr(dst, code);
8485     }
8486     return dst;
8487 }
8488
8489 /*****************************************************************************
8490  *
8491  *  Output a local jump or other instruction with a pc-relative immediate.
8492  *  Note that this may be invoked to overwrite an existing jump instruction at 'dst'
8493  *  to handle forward branch patching.
8494  */
8495
8496 BYTE* emitter::emitOutputLJ(insGroup* ig, BYTE* dst, instrDesc* i)
8497 {
8498     instrDescJmp* id = (instrDescJmp*)i;
8499
8500     unsigned srcOffs;
8501     unsigned dstOffs;
8502     BYTE*    srcAddr;
8503     BYTE*    dstAddr;
8504     ssize_t  distVal;
8505     ssize_t  loBits;
8506
8507     // Set default ins/fmt from id.
8508     instruction ins = id->idIns();
8509     insFormat   fmt = id->idInsFmt();
8510
8511     bool loadLabel    = false;
8512     bool isJump       = false;
8513     bool loadConstant = false;
8514
8515     switch (ins)
8516     {
8517         default:
8518             isJump = true;
8519             break;
8520
8521         case INS_tbz:
8522         case INS_tbnz:
8523         case INS_cbz:
8524         case INS_cbnz:
8525             isJump = true;
8526             break;
8527
8528         case INS_ldr:
8529         case INS_ldrsw:
8530             loadConstant = true;
8531             break;
8532
8533         case INS_adr:
8534         case INS_adrp:
8535             loadLabel = true;
8536             break;
8537     }
8538
8539     /* Figure out the distance to the target */
8540
8541     srcOffs = emitCurCodeOffs(dst);
8542     srcAddr = emitOffsetToPtr(srcOffs);
8543
8544     if (id->idAddr()->iiaIsJitDataOffset())
8545     {
8546         assert(loadConstant || loadLabel);
8547         int doff = id->idAddr()->iiaGetJitDataOffset();
8548         assert(doff >= 0);
8549         ssize_t imm = emitGetInsSC(id);
8550         assert((imm >= 0) && (imm < 0x1000)); // 0x1000 is arbitrary, currently 'imm' is always 0
8551
8552         unsigned dataOffs = (unsigned)(doff + imm);
8553         assert(dataOffs < emitDataSize());
8554         dstAddr = emitDataOffsetToPtr(dataOffs);
8555
8556         regNumber dstReg  = id->idReg1();
8557         regNumber addrReg = dstReg; // an integer register to compute long address.
8558         emitAttr  opSize  = id->idOpSize();
8559
8560         if (loadConstant)
8561         {
8562             if (id->idjShort)
8563             {
8564                 // ldr x/v, [rel addr] -- load constant from current addr(ip) + rel addr.
8565                 assert(ins == INS_ldr);
8566                 assert(fmt == IF_LS_1A);
8567                 distVal = (ssize_t)(dstAddr - srcAddr);
8568                 dst     = emitOutputShortConstant(dst, ins, fmt, distVal, dstReg, opSize);
8569             }
8570             else
8571             {
8572                 // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8573                 assert(fmt == IF_LARGELDC);
8574                 ssize_t relPageAddr =
8575                     (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8576                 if (isVectorRegister(dstReg))
8577                 {
8578                     // Update addrReg with the reserved integer register
8579                     // since we cannot use dstReg (vector) to load constant directly from memory.
8580                     addrReg = id->idReg2();
8581                     assert(isGeneralRegister(addrReg));
8582                 }
8583                 ins = INS_adrp;
8584                 fmt = IF_DI_1E;
8585                 dst = emitOutputShortAddress(dst, ins, fmt, relPageAddr, addrReg);
8586
8587                 // ldr x, [x, page offs] -- load constant from page address + page offset into integer register.
8588                 ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8589                 assert(isValidUimm12(imm12));
8590                 ins = INS_ldr;
8591                 fmt = IF_LS_2B;
8592                 dst = emitOutputShortConstant(dst, ins, fmt, imm12, addrReg, opSize);
8593
8594                 // fmov v, d -- copy constant in integer register to vector register.
8595                 // This is needed only for vector constant.
8596                 if (addrReg != dstReg)
8597                 {
8598                     //  fmov    Vd,Rn                DV_2I  X00111100X100111 000000nnnnnddddd   1E27 0000   Vd,Rn
8599                     //  (scalar, from general)
8600                     assert(isVectorRegister(dstReg) && isGeneralRegister(addrReg));
8601                     ins         = INS_fmov;
8602                     fmt         = IF_DV_2I;
8603                     code_t code = emitInsCode(ins, fmt);
8604
8605                     code |= insEncodeReg_Vd(dstReg);  // ddddd
8606                     code |= insEncodeReg_Rn(addrReg); // nnnnn
8607                     if (id->idOpSize() == EA_8BYTE)
8608                     {
8609                         code |= 0x80400000; // X ... X
8610                     }
8611                     dst += emitOutput_Instr(dst, code);
8612                 }
8613             }
8614         }
8615         else
8616         {
8617             assert(loadLabel);
8618             dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8619         }
8620
8621         return dst;
8622     }
8623
8624     assert(loadLabel || isJump);
8625
8626     if (id->idAddr()->iiaHasInstrCount())
8627     {
8628         assert(ig != NULL);
8629         int      instrCount = id->idAddr()->iiaGetInstrCount();
8630         unsigned insNum     = emitFindInsNum(ig, id);
8631         if (instrCount < 0)
8632         {
8633             // Backward branches using instruction count must be within the same instruction group.
8634             assert(insNum + 1 >= (unsigned)(-instrCount));
8635         }
8636         dstOffs = ig->igOffs + emitFindOffset(ig, (insNum + 1 + instrCount));
8637         dstAddr = emitOffsetToPtr(dstOffs);
8638     }
8639     else
8640     {
8641         dstOffs = id->idAddr()->iiaIGlabel->igOffs;
8642         dstAddr = emitOffsetToPtr(dstOffs);
8643     }
8644
8645     distVal = (ssize_t)(dstAddr - srcAddr);
8646
8647     if (dstOffs <= srcOffs)
8648     {
8649 #if DEBUG_EMIT
8650         /* This is a backward jump - distance is known at this point */
8651
8652         if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8653         {
8654             size_t blkOffs = id->idjIG->igOffs;
8655
8656             if (INTERESTING_JUMP_NUM == 0)
8657                 printf("[3] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8658             printf("[3] Jump  block is at %08X - %02X = %08X\n", blkOffs, emitOffsAdj, blkOffs - emitOffsAdj);
8659             printf("[3] Jump        is at %08X - %02X = %08X\n", srcOffs, emitOffsAdj, srcOffs - emitOffsAdj);
8660             printf("[3] Label block is at %08X - %02X = %08X\n", dstOffs, emitOffsAdj, dstOffs - emitOffsAdj);
8661         }
8662 #endif
8663     }
8664     else
8665     {
8666         /* This is a  forward jump - distance will be an upper limit */
8667
8668         emitFwdJumps = true;
8669
8670         /* The target offset will be closer by at least 'emitOffsAdj', but only if this
8671            jump doesn't cross the hot-cold boundary. */
8672
8673         if (!emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8674         {
8675             dstOffs -= emitOffsAdj;
8676             distVal -= emitOffsAdj;
8677         }
8678
8679         /* Record the location of the jump for later patching */
8680
8681         id->idjOffs = dstOffs;
8682
8683         /* Are we overflowing the id->idjOffs bitfield? */
8684         if (id->idjOffs != dstOffs)
8685             IMPL_LIMITATION("Method is too large");
8686
8687 #if DEBUG_EMIT
8688         if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8689         {
8690             size_t blkOffs = id->idjIG->igOffs;
8691
8692             if (INTERESTING_JUMP_NUM == 0)
8693                 printf("[4] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8694             printf("[4] Jump  block is at %08X\n", blkOffs);
8695             printf("[4] Jump        is at %08X\n", srcOffs);
8696             printf("[4] Label block is at %08X - %02X = %08X\n", dstOffs + emitOffsAdj, emitOffsAdj, dstOffs);
8697         }
8698 #endif
8699     }
8700
8701 #ifdef DEBUG
8702     if (0 && emitComp->verbose)
8703     {
8704         size_t sz          = 4;
8705         int    distValSize = id->idjShort ? 4 : 8;
8706         printf("; %s jump [%08X/%03u] from %0*X to %0*X: dist = %08XH\n", (dstOffs <= srcOffs) ? "Fwd" : "Bwd",
8707                dspPtr(id), id->idDebugOnlyInfo()->idNum, distValSize, srcOffs + sz, distValSize, dstOffs, distVal);
8708     }
8709 #endif
8710
8711     /* For forward jumps, record the address of the distance value */
8712     id->idjTemp.idjAddr = (distVal > 0) ? dst : NULL;
8713
8714     if (emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8715     {
8716         assert(!id->idjShort);
8717         NYI_ARM64("Relocation Support for long address");
8718     }
8719
8720     assert(insOptsNone(id->idInsOpt()));
8721
8722     if (isJump)
8723     {
8724         if (id->idjShort)
8725         {
8726             // Short conditional/unconditional jump
8727             assert(!id->idjKeepLong);
8728             assert(emitJumpCrossHotColdBoundary(srcOffs, dstOffs) == false);
8729             assert((fmt == IF_BI_0A) || (fmt == IF_BI_0B) || (fmt == IF_BI_1A) || (fmt == IF_BI_1B));
8730         }
8731         else
8732         {
8733             // Long conditional jump
8734             assert(fmt == IF_LARGEJMP);
8735             // This is a pseudo-instruction format representing a large conditional branch, to allow
8736             // us to get a greater branch target range than we can get by using a straightforward conditional
8737             // branch. It is encoded as a short conditional branch that branches around a long unconditional
8738             // branch.
8739             //
8740             // Conceptually, we have:
8741             //
8742             //      b<cond> L_target
8743             //
8744             // The code we emit is:
8745             //
8746             //      b<!cond> L_not  // 4 bytes. Note that we reverse the condition.
8747             //      b L_target      // 4 bytes
8748             //   L_not:
8749             //
8750             // Note that we don't actually insert any blocks: we simply encode "b <!cond> L_not" as a branch with
8751             // the correct offset. Note also that this works for both integer and floating-point conditions, because
8752             // the condition inversion takes ordered/unordered into account, preserving NaN behavior. For example,
8753             // "GT" (greater than) is inverted to "LE" (less than, equal, or unordered).
8754
8755             instruction reverseIns;
8756             insFormat   reverseFmt;
8757
8758             switch (ins)
8759             {
8760                 case INS_cbz:
8761                     reverseIns = INS_cbnz;
8762                     reverseFmt = IF_BI_1A;
8763                     break;
8764                 case INS_cbnz:
8765                     reverseIns = INS_cbz;
8766                     reverseFmt = IF_BI_1A;
8767                     break;
8768                 case INS_tbz:
8769                     reverseIns = INS_tbnz;
8770                     reverseFmt = IF_BI_1B;
8771                     break;
8772                 case INS_tbnz:
8773                     reverseIns = INS_tbz;
8774                     reverseFmt = IF_BI_1B;
8775                     break;
8776                 default:
8777                     reverseIns = emitJumpKindToIns(emitReverseJumpKind(emitInsToJumpKind(ins)));
8778                     reverseFmt = IF_BI_0B;
8779             }
8780
8781             dst =
8782                 emitOutputShortBranch(dst,
8783                                       reverseIns, // reverse the conditional instruction
8784                                       reverseFmt,
8785                                       8, /* 8 bytes from start of this large conditional pseudo-instruction to L_not. */
8786                                       id);
8787
8788             // Now, pretend we've got a normal unconditional branch, and fall through to the code to emit that.
8789             ins = INS_b;
8790             fmt = IF_BI_0A;
8791
8792             // The distVal was computed based on the beginning of the pseudo-instruction,
8793             // So subtract the size of the conditional branch so that it is relative to the
8794             // unconditional branch.
8795             distVal -= 4;
8796         }
8797
8798         dst = emitOutputShortBranch(dst, ins, fmt, distVal, id);
8799     }
8800     else if (loadLabel)
8801     {
8802         dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8803     }
8804
8805     return dst;
8806 }
8807
8808 /*****************************************************************************
8809 *
8810 *  Output a short branch instruction.
8811 */
8812 BYTE* emitter::emitOutputShortBranch(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, instrDescJmp* id)
8813 {
8814     code_t code = emitInsCode(ins, fmt);
8815
8816     ssize_t loBits = (distVal & 3);
8817     noway_assert(loBits == 0);
8818     distVal >>= 2; // branch offset encodings are scaled by 4.
8819
8820     if (fmt == IF_BI_0A)
8821     {
8822         // INS_b or INS_bl_local
8823         noway_assert(isValidSimm26(distVal));
8824         distVal &= 0x3FFFFFFLL;
8825         code |= distVal;
8826     }
8827     else if (fmt == IF_BI_0B) // BI_0B   01010100iiiiiiii iiiiiiiiiiiXXXXX      simm19:00
8828     {
8829         // INS_beq, INS_bne, etc...
8830         noway_assert(isValidSimm19(distVal));
8831         distVal &= 0x7FFFFLL;
8832         code |= distVal << 5;
8833     }
8834     else if (fmt == IF_BI_1A) // BI_1A   X.......iiiiiiii iiiiiiiiiiittttt      Rt simm19:00
8835     {
8836         // INS_cbz or INS_cbnz
8837         assert(id != nullptr);
8838         code |= insEncodeDatasize(id->idOpSize()); // X
8839         code |= insEncodeReg_Rt(id->idReg1());     // ttttt
8840
8841         noway_assert(isValidSimm19(distVal));
8842         distVal &= 0x7FFFFLL; // 19 bits
8843         code |= distVal << 5;
8844     }
8845     else if (fmt == IF_BI_1B) // BI_1B   B.......bbbbbiii iiiiiiiiiiittttt      Rt imm6, simm14:00
8846     {
8847         // INS_tbz or INS_tbnz
8848         assert(id != nullptr);
8849         ssize_t imm = emitGetInsSC(id);
8850         assert(isValidImmShift(imm, id->idOpSize()));
8851
8852         if (imm & 0x20) // test bit 32-63 ?
8853         {
8854             code |= 0x80000000; // B
8855         }
8856         code |= ((imm & 0x1F) << 19);          // bbbbb
8857         code |= insEncodeReg_Rt(id->idReg1()); // ttttt
8858
8859         noway_assert(isValidSimm14(distVal));
8860         distVal &= 0x3FFFLL; // 14 bits
8861         code |= distVal << 5;
8862     }
8863     else
8864     {
8865         assert(!"Unknown fmt for emitOutputShortBranch");
8866     }
8867
8868     dst += emitOutput_Instr(dst, code);
8869
8870     return dst;
8871 }
8872
8873 /*****************************************************************************
8874 *
8875 *  Output a short address instruction.
8876 */
8877 BYTE* emitter::emitOutputShortAddress(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, regNumber reg)
8878 {
8879     ssize_t loBits = (distVal & 3);
8880     distVal >>= 2;
8881
8882     code_t code = emitInsCode(ins, fmt);
8883     if (fmt == IF_DI_1E) // DI_1E   .ii.....iiiiiiii iiiiiiiiiiiddddd      Rd simm21
8884     {
8885         // INS_adr or INS_adrp
8886         code |= insEncodeReg_Rd(reg); // ddddd
8887
8888         noway_assert(isValidSimm19(distVal));
8889         distVal &= 0x7FFFFLL; // 19 bits
8890         code |= distVal << 5;
8891         code |= loBits << 29; //  2 bits
8892     }
8893     else
8894     {
8895         assert(!"Unknown fmt for emitOutputShortAddress");
8896     }
8897
8898     dst += emitOutput_Instr(dst, code);
8899
8900     return dst;
8901 }
8902
8903 /*****************************************************************************
8904 *
8905 *  Output a short constant instruction.
8906 */
8907 BYTE* emitter::emitOutputShortConstant(
8908     BYTE* dst, instruction ins, insFormat fmt, ssize_t imm, regNumber reg, emitAttr opSize)
8909 {
8910     code_t code = emitInsCode(ins, fmt);
8911
8912     if (fmt == IF_LS_1A)
8913     {
8914         // LS_1A   XX...V..iiiiiiii iiiiiiiiiiittttt      Rt simm21
8915         // INS_ldr or INS_ldrsw (PC-Relative)
8916
8917         ssize_t loBits = (imm & 3);
8918         noway_assert(loBits == 0);
8919         ssize_t distVal = imm >>= 2; // load offset encodings are scaled by 4.
8920
8921         noway_assert(isValidSimm19(distVal));
8922
8923         // Is the target a vector register?
8924         if (isVectorRegister(reg))
8925         {
8926             code |= insEncodeDatasizeVLS(code, opSize); // XX V
8927             code |= insEncodeReg_Vt(reg);               // ttttt
8928         }
8929         else
8930         {
8931             assert(isGeneralRegister(reg));
8932             // insEncodeDatasizeLS is not quite right for this case.
8933             // So just specialize it.
8934             if ((ins == INS_ldr) && (opSize == EA_8BYTE))
8935             {
8936                 // set the operation size in bit 30
8937                 code |= 0x40000000;
8938             }
8939
8940             code |= insEncodeReg_Rt(reg); // ttttt
8941         }
8942
8943         distVal &= 0x7FFFFLL; // 19 bits
8944         code |= distVal << 5;
8945     }
8946     else if (fmt == IF_LS_2B)
8947     {
8948         //  ldr     Rt,[Xn+pimm12]       LS_2B  1X11100101iiiiii iiiiiinnnnnttttt   B940 0000   imm(0-4095<<{2,3})
8949         // INS_ldr or INS_ldrsw (PC-Relative)
8950         noway_assert(isValidUimm12(imm));
8951         assert(isGeneralRegister(reg));
8952
8953         if (opSize == EA_8BYTE)
8954         {
8955             // insEncodeDatasizeLS is not quite right for this case.
8956             // So just specialize it.
8957             if (ins == INS_ldr)
8958             {
8959                 // set the operation size in bit 30
8960                 code |= 0x40000000;
8961             }
8962             // Low 3 bits should be 0 -- 8 byte JIT data should be aligned on 8 byte.
8963             assert((imm & 7) == 0);
8964             imm >>= 3;
8965         }
8966         else
8967         {
8968             assert(opSize == EA_4BYTE);
8969             // Low 2 bits should be 0 -- 4 byte aligned data.
8970             assert((imm & 3) == 0);
8971             imm >>= 2;
8972         }
8973
8974         code |= insEncodeReg_Rt(reg); // ttttt
8975         code |= insEncodeReg_Rn(reg); // nnnnn
8976         code |= imm << 10;
8977     }
8978     else
8979     {
8980         assert(!"Unknown fmt for emitOutputShortConstant");
8981     }
8982
8983     dst += emitOutput_Instr(dst, code);
8984
8985     return dst;
8986 }
8987 /*****************************************************************************
8988  *
8989  *  Output a call instruction.
8990  */
8991
8992 unsigned emitter::emitOutputCall(insGroup* ig, BYTE* dst, instrDesc* id, code_t code)
8993 {
8994     const unsigned char callInstrSize = sizeof(code_t); // 4 bytes
8995     regMaskTP           gcrefRegs;
8996     regMaskTP           byrefRegs;
8997
8998     VARSET_TP GCvars(VarSetOps::UninitVal());
8999
9000     // Is this a "fat" call descriptor?
9001     if (id->idIsLargeCall())
9002     {
9003         instrDescCGCA* idCall = (instrDescCGCA*)id;
9004         gcrefRegs             = idCall->idcGcrefRegs;
9005         byrefRegs             = idCall->idcByrefRegs;
9006         VarSetOps::Assign(emitComp, GCvars, idCall->idcGCvars);
9007     }
9008     else
9009     {
9010         assert(!id->idIsLargeDsp());
9011         assert(!id->idIsLargeCns());
9012
9013         gcrefRegs = emitDecodeCallGCregs(id);
9014         byrefRegs = 0;
9015         VarSetOps::AssignNoCopy(emitComp, GCvars, VarSetOps::MakeEmpty(emitComp));
9016     }
9017
9018     /* We update the GC info before the call as the variables cannot be
9019         used by the call. Killing variables before the call helps with
9020         boundary conditions if the call is CORINFO_HELP_THROW - see bug 50029.
9021         If we ever track aliased variables (which could be used by the
9022         call), we would have to keep them alive past the call. */
9023
9024     emitUpdateLiveGCvars(GCvars, dst);
9025
9026     // Now output the call instruction and update the 'dst' pointer
9027     //
9028     unsigned outputInstrSize = emitOutput_Instr(dst, code);
9029     dst += outputInstrSize;
9030
9031     // All call instructions are 4-byte in size on ARM64
9032     //
9033     assert(outputInstrSize == callInstrSize);
9034
9035     // If the method returns a GC ref, mark INTRET (R0) appropriately.
9036     if (id->idGCref() == GCT_GCREF)
9037     {
9038         gcrefRegs |= RBM_INTRET;
9039     }
9040     else if (id->idGCref() == GCT_BYREF)
9041     {
9042         byrefRegs |= RBM_INTRET;
9043     }
9044
9045     // If is a multi-register return method is called, mark INTRET_1 (X1) appropriately
9046     if (id->idIsLargeCall())
9047     {
9048         instrDescCGCA* idCall = (instrDescCGCA*)id;
9049         if (idCall->idSecondGCref() == GCT_GCREF)
9050         {
9051             gcrefRegs |= RBM_INTRET_1;
9052         }
9053         else if (idCall->idSecondGCref() == GCT_BYREF)
9054         {
9055             byrefRegs |= RBM_INTRET_1;
9056         }
9057     }
9058
9059     // If the GC register set has changed, report the new set.
9060     if (gcrefRegs != emitThisGCrefRegs)
9061     {
9062         emitUpdateLiveGCregs(GCT_GCREF, gcrefRegs, dst);
9063     }
9064     // If the Byref register set has changed, report the new set.
9065     if (byrefRegs != emitThisByrefRegs)
9066     {
9067         emitUpdateLiveGCregs(GCT_BYREF, byrefRegs, dst);
9068     }
9069
9070     // Some helper calls may be marked as not requiring GC info to be recorded.
9071     if ((!id->idIsNoGC()))
9072     {
9073         // On ARM64, as on AMD64, we don't change the stack pointer to push/pop args.
9074         // So we're not really doing a "stack pop" here (note that "args" is 0), but we use this mechanism
9075         // to record the call for GC info purposes.  (It might be best to use an alternate call,
9076         // and protect "emitStackPop" under the EMIT_TRACK_STACK_DEPTH preprocessor variable.)
9077         emitStackPop(dst, /*isCall*/ true, callInstrSize, /*args*/ 0);
9078
9079         // Do we need to record a call location for GC purposes?
9080         //
9081         if (!emitFullGCinfo)
9082         {
9083             emitRecordGCcall(dst, callInstrSize);
9084         }
9085     }
9086     return callInstrSize;
9087 }
9088
9089 /*****************************************************************************
9090  *
9091  *  Emit a 32-bit Arm64 instruction
9092  */
9093
9094 /*static*/ unsigned emitter::emitOutput_Instr(BYTE* dst, code_t code)
9095 {
9096     assert(sizeof(code_t) == 4);
9097     *((code_t*)dst) = code;
9098
9099     return sizeof(code_t);
9100 }
9101
9102 /*****************************************************************************
9103 *
9104  *  Append the machine code corresponding to the given instruction descriptor
9105  *  to the code block at '*dp'; the base of the code block is 'bp', and 'ig'
9106  *  is the instruction group that contains the instruction. Updates '*dp' to
9107  *  point past the generated code, and returns the size of the instruction
9108  *  descriptor in bytes.
9109  */
9110
9111 size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
9112 {
9113     BYTE*         dst  = *dp;
9114     BYTE*         odst = dst;
9115     code_t        code = 0;
9116     size_t        sz   = emitGetInstrDescSize(id); // TODO-ARM64-Cleanup: on ARM, this is set in each case. why?
9117     instruction   ins  = id->idIns();
9118     insFormat     fmt  = id->idInsFmt();
9119     emitAttr      size = id->idOpSize();
9120     unsigned char callInstrSize = 0;
9121     unsigned      condcode;
9122
9123 #ifdef DEBUG
9124 #if DUMP_GC_TABLES
9125     bool dspOffs = emitComp->opts.dspGCtbls;
9126 #else
9127     bool dspOffs = !emitComp->opts.disDiffable;
9128 #endif
9129 #endif // DEBUG
9130
9131     assert(REG_NA == (int)REG_NA);
9132
9133     VARSET_TP GCvars(VarSetOps::UninitVal());
9134
9135     /* What instruction format have we got? */
9136
9137     switch (fmt)
9138     {
9139         ssize_t  imm;
9140         ssize_t  index;
9141         ssize_t  index2;
9142         unsigned scale;
9143         unsigned cmode;
9144         unsigned immShift;
9145         bool     hasShift;
9146         emitAttr extSize;
9147         emitAttr elemsize;
9148         emitAttr datasize;
9149
9150         case IF_BI_0A: // BI_0A   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
9151         case IF_BI_0B: // BI_0B   ......iiiiiiiiii iiiiiiiiiii.....               simm19:00
9152         case IF_LARGEJMP:
9153             assert(id->idGCref() == GCT_NONE);
9154             assert(id->idIsBound());
9155             dst = emitOutputLJ(ig, dst, id);
9156             sz  = sizeof(instrDescJmp);
9157             break;
9158
9159         case IF_BI_0C: // BI_0C   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
9160             code = emitInsCode(ins, fmt);
9161             sz   = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
9162             dst += emitOutputCall(ig, dst, id, code);
9163             // Always call RecordRelocation so that we wire in a JumpStub when we don't reach
9164             emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_BRANCH26);
9165             break;
9166
9167         case IF_BI_1A: // BI_1A   ......iiiiiiiiii iiiiiiiiiiittttt      Rt       simm19:00
9168             assert(insOptsNone(id->idInsOpt()));
9169             assert(id->idIsBound());
9170
9171             dst = emitOutputLJ(ig, dst, id);
9172             sz  = sizeof(instrDescJmp);
9173             break;
9174
9175         case IF_BI_1B: // BI_1B   B.......bbbbbiii iiiiiiiiiiittttt      Rt imm6, simm14:00
9176             assert(insOptsNone(id->idInsOpt()));
9177             assert(id->idIsBound());
9178
9179             dst = emitOutputLJ(ig, dst, id);
9180             sz  = sizeof(instrDescJmp);
9181             break;
9182
9183         case IF_BR_1A: // BR_1A   ................ ......nnnnn.....         Rn
9184             assert(insOptsNone(id->idInsOpt()));
9185             assert((ins == INS_ret) || (ins == INS_br));
9186             code = emitInsCode(ins, fmt);
9187             code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9188
9189             dst += emitOutput_Instr(dst, code);
9190             break;
9191
9192         case IF_BR_1B: // BR_1B   ................ ......nnnnn.....         Rn
9193             assert(insOptsNone(id->idInsOpt()));
9194             assert((ins == INS_br_tail) || (ins == INS_blr));
9195             code = emitInsCode(ins, fmt);
9196             code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9197
9198             sz = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
9199             dst += emitOutputCall(ig, dst, id, code);
9200             break;
9201
9202         case IF_LS_1A: // LS_1A   XX...V..iiiiiiii iiiiiiiiiiittttt      Rt    PC imm(1MB)
9203         case IF_LARGELDC:
9204             assert(insOptsNone(id->idInsOpt()));
9205             assert(id->idIsBound());
9206
9207             dst = emitOutputLJ(ig, dst, id);
9208             sz  = sizeof(instrDescJmp);
9209             break;
9210
9211         case IF_LS_2A: // LS_2A   .X.......X...... ......nnnnnttttt      Rt Rn
9212             assert(insOptsNone(id->idInsOpt()));
9213             code = emitInsCode(ins, fmt);
9214             // Is the target a vector register?
9215             if (isVectorRegister(id->idReg1()))
9216             {
9217                 code &= 0x3FFFFFFF;                                 // clear the size bits
9218                 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9219                 code |= insEncodeReg_Vt(id->idReg1());              // ttttt
9220             }
9221             else
9222             {
9223                 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9224                 code |= insEncodeReg_Rt(id->idReg1());             // ttttt
9225             }
9226             code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9227             dst += emitOutput_Instr(dst, code);
9228             break;
9229
9230         case IF_LS_2B: // LS_2B   .X.......Xiiiiii iiiiiinnnnnttttt      Rt Rn    imm(0-4095)
9231             assert(insOptsNone(id->idInsOpt()));
9232             imm = emitGetInsSC(id);
9233             assert(isValidUimm12(imm));
9234             code = emitInsCode(ins, fmt);
9235             // Is the target a vector register?
9236             if (isVectorRegister(id->idReg1()))
9237             {
9238                 code &= 0x3FFFFFFF;                                 // clear the size bits
9239                 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9240                 code |= insEncodeReg_Vt(id->idReg1());              // ttttt
9241             }
9242             else
9243             {
9244                 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9245                 code |= insEncodeReg_Rt(id->idReg1());             // ttttt
9246             }
9247             code |= ((code_t)imm << 10);           // iiiiiiiiiiii
9248             code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9249             dst += emitOutput_Instr(dst, code);
9250             break;
9251
9252         case IF_LS_2C: // LS_2C   .X.......X.iiiii iiiiPPnnnnnttttt      Rt Rn    imm(-256..+255) no/pre/post inc
9253             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9254             imm = emitGetInsSC(id);
9255             assert((imm >= -256) && (imm <= 255)); // signed 9 bits
9256             imm &= 0x1ff;                          // force into unsigned 9 bit representation
9257             code = emitInsCode(ins, fmt);
9258             // Is the target a vector register?
9259             if (isVectorRegister(id->idReg1()))
9260             {
9261                 code &= 0x3FFFFFFF;                                 // clear the size bits
9262                 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9263                 code |= insEncodeReg_Vt(id->idReg1());              // ttttt
9264             }
9265             else
9266             {
9267                 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9268                 code |= insEncodeReg_Rt(id->idReg1());             // ttttt
9269             }
9270             code |= insEncodeIndexedOpt(id->idInsOpt()); // PP
9271             code |= ((code_t)imm << 12);                 // iiiiiiiii
9272             code |= insEncodeReg_Rn(id->idReg2());       // nnnnn
9273             dst += emitOutput_Instr(dst, code);
9274             break;
9275
9276         case IF_LS_3A: // LS_3A   .X.......X.mmmmm oooS..nnnnnttttt      Rt Rn Rm ext(Rm) LSL {}
9277             assert(insOptsLSExtend(id->idInsOpt()));
9278             code = emitInsCode(ins, fmt);
9279             // Is the target a vector register?
9280             if (isVectorRegister(id->idReg1()))
9281             {
9282                 code &= 0x3FFFFFFF;                                 // clear the size bits
9283                 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9284                 code |= insEncodeReg_Vt(id->idReg1());              // ttttt
9285             }
9286             else
9287             {
9288                 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9289                 code |= insEncodeReg_Rt(id->idReg1());             // ttttt
9290             }
9291             code |= insEncodeExtend(id->idInsOpt()); // ooo
9292             code |= insEncodeReg_Rn(id->idReg2());   // nnnnn
9293             if (id->idIsLclVar())
9294             {
9295                 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9296             }
9297             else
9298             {
9299                 code |= insEncodeReg3Scale(id->idReg3Scaled()); // S
9300                 code |= insEncodeReg_Rm(id->idReg3());          // mmmmm
9301             }
9302             dst += emitOutput_Instr(dst, code);
9303             break;
9304
9305         case IF_LS_3B: // LS_3B   X............... .aaaaannnnnddddd      Rd Ra Rn
9306             assert(insOptsNone(id->idInsOpt()));
9307             code = emitInsCode(ins, fmt);
9308             // Is the target a vector register?
9309             if (isVectorRegister(id->idReg1()))
9310             {
9311                 code &= 0x3FFFFFFF;                                  // clear the size bits
9312                 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9313                 code |= insEncodeReg_Vt(id->idReg1());               // ttttt
9314                 code |= insEncodeReg_Va(id->idReg2());               // aaaaa
9315             }
9316             else
9317             {
9318                 code |= insEncodeDatasize(id->idOpSize()); // X
9319                 code |= insEncodeReg_Rt(id->idReg1());     // ttttt
9320                 code |= insEncodeReg_Ra(id->idReg2());     // aaaaa
9321             }
9322             code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9323             dst += emitOutput_Instr(dst, code);
9324             break;
9325
9326         case IF_LS_3C: // LS_3C   X......PP.iiiiii iaaaaannnnnddddd      Rd Ra Rn imm(im7,sh)
9327             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9328             imm = emitGetInsSC(id);
9329             assert((imm >= -64) && (imm <= 63)); // signed 7 bits
9330             imm &= 0x7f;                         // force into unsigned 7 bit representation
9331             code = emitInsCode(ins, fmt);
9332             // Is the target a vector register?
9333             if (isVectorRegister(id->idReg1()))
9334             {
9335                 code &= 0x3FFFFFFF;                                  // clear the size bits
9336                 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9337                 code |= insEncodeReg_Vt(id->idReg1());               // ttttt
9338                 code |= insEncodeReg_Va(id->idReg2());               // aaaaa
9339             }
9340             else
9341             {
9342                 code |= insEncodeDatasize(id->idOpSize()); // X
9343                 code |= insEncodeReg_Rt(id->idReg1());     // ttttt
9344                 code |= insEncodeReg_Ra(id->idReg2());     // aaaaa
9345             }
9346             code |= insEncodePairIndexedOpt(ins, id->idInsOpt()); // PP
9347             code |= ((code_t)imm << 15);                          // iiiiiiiii
9348             code |= insEncodeReg_Rn(id->idReg3());                // nnnnn
9349             dst += emitOutput_Instr(dst, code);
9350             break;
9351
9352         case IF_LS_3D: // LS_3D   .X.......X.mmmmm ......nnnnnttttt      Wm Rt Rn
9353             code = emitInsCode(ins, fmt);
9354             // Arm64 store exclusive unpredictable cases
9355             assert(id->idReg1() != id->idReg2());
9356             assert(id->idReg1() != id->idReg3());
9357             code |= insEncodeDatasizeLS(code, id->idOpSize()); // X
9358             code |= insEncodeReg_Rm(id->idReg1());             // mmmmm
9359             code |= insEncodeReg_Rt(id->idReg2());             // ttttt
9360             code |= insEncodeReg_Rn(id->idReg3());             // nnnnn
9361             dst += emitOutput_Instr(dst, code);
9362             break;
9363
9364         case IF_LS_3E: // LS_3E   .X.........mmmmm ......nnnnnttttt      Rm Rt Rn ARMv8.1 LSE Atomics
9365             code = emitInsCode(ins, fmt);
9366             code |= insEncodeDatasizeLS(code, id->idOpSize()); // X
9367             code |= insEncodeReg_Rm(id->idReg1());             // mmmmm
9368             code |= insEncodeReg_Rt(id->idReg2());             // ttttt
9369             code |= insEncodeReg_Rn(id->idReg3());             // nnnnn
9370             dst += emitOutput_Instr(dst, code);
9371             break;
9372
9373         case IF_DI_1A: // DI_1A   X.......shiiiiii iiiiiinnnnn.....         Rn    imm(i12,sh)
9374             assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9375             imm = emitGetInsSC(id);
9376             assert(isValidUimm12(imm));
9377             code = emitInsCode(ins, fmt);
9378             code |= insEncodeDatasize(id->idOpSize());   // X
9379             code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9380             code |= ((code_t)imm << 10);                 // iiiiiiiiiiii
9381             code |= insEncodeReg_Rn(id->idReg1());       // nnnnn
9382             dst += emitOutput_Instr(dst, code);
9383             break;
9384
9385         case IF_DI_1B: // DI_1B   X........hwiiiii iiiiiiiiiiiddddd      Rd       imm(i16,hw)
9386             imm = emitGetInsSC(id);
9387             assert(isValidImmHWVal(imm, id->idOpSize()));
9388             code = emitInsCode(ins, fmt);
9389             code |= insEncodeDatasize(id->idOpSize()); // X
9390             code |= ((code_t)imm << 5);                // hwiiiii iiiiiiiiiii
9391             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9392             dst += emitOutput_Instr(dst, code);
9393             break;
9394
9395         case IF_DI_1C: // DI_1C   X........Nrrrrrr ssssssnnnnn.....         Rn    imm(N,r,s)
9396             imm = emitGetInsSC(id);
9397             assert(isValidImmNRS(imm, id->idOpSize()));
9398             code = emitInsCode(ins, fmt);
9399             code |= ((code_t)imm << 10);               // Nrrrrrrssssss
9400             code |= insEncodeDatasize(id->idOpSize()); // X
9401             code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9402             dst += emitOutput_Instr(dst, code);
9403             break;
9404
9405         case IF_DI_1D: // DI_1D   X........Nrrrrrr ssssss.....ddddd      Rd       imm(N,r,s)
9406             imm = emitGetInsSC(id);
9407             assert(isValidImmNRS(imm, id->idOpSize()));
9408             code = emitInsCode(ins, fmt);
9409             code |= ((code_t)imm << 10);               // Nrrrrrrssssss
9410             code |= insEncodeDatasize(id->idOpSize()); // X
9411             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9412             dst += emitOutput_Instr(dst, code);
9413             break;
9414
9415         case IF_DI_1E: // DI_1E   .ii.....iiiiiiii iiiiiiiiiiiddddd      Rd       simm21
9416         case IF_LARGEADR:
9417             assert(insOptsNone(id->idInsOpt()));
9418             if (id->idIsReloc())
9419             {
9420                 code = emitInsCode(ins, fmt);
9421                 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9422                 dst += emitOutput_Instr(dst, code);
9423                 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEBASE_REL21);
9424             }
9425             else
9426             {
9427                 // Local jmp/load case which does not need a relocation.
9428                 assert(id->idIsBound());
9429                 dst = emitOutputLJ(ig, dst, id);
9430             }
9431             sz = sizeof(instrDescJmp);
9432             break;
9433
9434         case IF_DI_1F: // DI_1F   X..........iiiii cccc..nnnnn.nzcv      Rn imm5  nzcv cond
9435             imm = emitGetInsSC(id);
9436             assert(isValidImmCondFlagsImm5(imm));
9437             {
9438                 condFlagsImm cfi;
9439                 cfi.immCFVal = (unsigned)imm;
9440                 code         = emitInsCode(ins, fmt);
9441                 code |= insEncodeDatasize(id->idOpSize()); // X
9442                 code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9443                 code |= ((code_t)cfi.imm5 << 16);          // iiiii
9444                 code |= insEncodeFlags(cfi.flags);         // nzcv
9445                 code |= insEncodeCond(cfi.cond);           // cccc
9446                 dst += emitOutput_Instr(dst, code);
9447             }
9448             break;
9449
9450         case IF_DI_2A: // DI_2A   X.......shiiiiii iiiiiinnnnnddddd      Rd Rn    imm(i12,sh)
9451             assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9452             imm = emitGetInsSC(id);
9453             assert(isValidUimm12(imm));
9454             code = emitInsCode(ins, fmt);
9455             code |= insEncodeDatasize(id->idOpSize());   // X
9456             code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9457             code |= ((code_t)imm << 10);                 // iiiiiiiiiiii
9458             code |= insEncodeReg_Rd(id->idReg1());       // ddddd
9459             code |= insEncodeReg_Rn(id->idReg2());       // nnnnn
9460             dst += emitOutput_Instr(dst, code);
9461
9462             if (id->idIsReloc())
9463             {
9464                 assert(sz == sizeof(instrDesc));
9465                 assert(id->idAddr()->iiaAddr != nullptr);
9466                 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEOFFSET_12A);
9467             }
9468             break;
9469
9470         case IF_DI_2B: // DI_2B   X.........Xnnnnn ssssssnnnnnddddd      Rd Rn    imm(0-63)
9471             code = emitInsCode(ins, fmt);
9472             imm  = emitGetInsSC(id);
9473             assert(isValidImmShift(imm, id->idOpSize()));
9474             code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9475             code |= insEncodeReg_Rd(id->idReg1());             // ddddd
9476             code |= insEncodeReg_Rn(id->idReg2());             // nnnnn
9477             code |= insEncodeReg_Rm(id->idReg2());             // Reg2 also in mmmmm
9478             code |= insEncodeShiftCount(imm, id->idOpSize());  // ssssss
9479             dst += emitOutput_Instr(dst, code);
9480             break;
9481
9482         case IF_DI_2C: // DI_2C   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imm(N,r,s)
9483             imm = emitGetInsSC(id);
9484             assert(isValidImmNRS(imm, id->idOpSize()));
9485             code = emitInsCode(ins, fmt);
9486             code |= ((code_t)imm << 10);               // Nrrrrrrssssss
9487             code |= insEncodeDatasize(id->idOpSize()); // X
9488             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9489             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9490             dst += emitOutput_Instr(dst, code);
9491             break;
9492
9493         case IF_DI_2D: // DI_2D   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imr, imms   (N,r,s)
9494             if (ins == INS_asr || ins == INS_lsl || ins == INS_lsr)
9495             {
9496                 imm = emitGetInsSC(id);
9497                 assert(isValidImmShift(imm, id->idOpSize()));
9498
9499                 // Shift immediates are aliases of the SBFM/UBFM instructions
9500                 // that actually take 2 registers and 2 constants,
9501                 // Since we stored the shift immediate value
9502                 // we need to calculate the N,R and S values here.
9503
9504                 bitMaskImm bmi;
9505                 bmi.immNRS = 0;
9506
9507                 bmi.immN = (size == EA_8BYTE) ? 1 : 0;
9508                 bmi.immR = imm;
9509                 bmi.immS = (size == EA_8BYTE) ? 0x3f : 0x1f;
9510
9511                 // immR and immS are now set correctly for INS_asr and INS_lsr
9512                 // but for INS_lsl we have to adjust the values for immR and immS
9513                 //
9514                 if (ins == INS_lsl)
9515                 {
9516                     bmi.immR = -imm & bmi.immS;
9517                     bmi.immS = bmi.immS - imm;
9518                 }
9519
9520                 // setup imm with the proper 13 bit value N:R:S
9521                 //
9522                 imm = bmi.immNRS;
9523             }
9524             else
9525             {
9526                 // The other instructions have already have encoded N,R and S values
9527                 imm = emitGetInsSC(id);
9528             }
9529             assert(isValidImmNRS(imm, id->idOpSize()));
9530
9531             code = emitInsCode(ins, fmt);
9532             code |= ((code_t)imm << 10);               // Nrrrrrrssssss
9533             code |= insEncodeDatasize(id->idOpSize()); // X
9534             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9535             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9536             dst += emitOutput_Instr(dst, code);
9537             break;
9538
9539         case IF_DR_1D: // DR_1D   X............... cccc.......ddddd      Rd       cond
9540             imm = emitGetInsSC(id);
9541             assert(isValidImmCond(imm));
9542             {
9543                 condFlagsImm cfi;
9544                 cfi.immCFVal = (unsigned)imm;
9545                 code         = emitInsCode(ins, fmt);
9546                 code |= insEncodeDatasize(id->idOpSize()); // X
9547                 code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9548                 code |= insEncodeInvertedCond(cfi.cond);   // cccc
9549                 dst += emitOutput_Instr(dst, code);
9550             }
9551             break;
9552
9553         case IF_DR_2A: // DR_2A   X..........mmmmm ......nnnnn.....         Rn Rm
9554             assert(insOptsNone(id->idInsOpt()));
9555             code = emitInsCode(ins, fmt);
9556             code |= insEncodeDatasize(id->idOpSize()); // X
9557             code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9558             code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9559             dst += emitOutput_Instr(dst, code);
9560             break;
9561
9562         case IF_DR_2B: // DR_2B   X.......sh.mmmmm ssssssnnnnn.....         Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
9563             code = emitInsCode(ins, fmt);
9564             imm  = emitGetInsSC(id);
9565             assert(isValidImmShift(imm, id->idOpSize()));
9566             code |= insEncodeDatasize(id->idOpSize());        // X
9567             code |= insEncodeShiftType(id->idInsOpt());       // sh
9568             code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9569             code |= insEncodeReg_Rn(id->idReg1());            // nnnnn
9570             code |= insEncodeReg_Rm(id->idReg2());            // mmmmm
9571             dst += emitOutput_Instr(dst, code);
9572             break;
9573
9574         case IF_DR_2C: // DR_2C   X..........mmmmm ooosssnnnnn.....         Rn Rm ext(Rm) LSL imm(0-4)
9575             code = emitInsCode(ins, fmt);
9576             imm  = emitGetInsSC(id);
9577             assert((imm >= 0) && (imm <= 4));          // imm [0..4]
9578             code |= insEncodeDatasize(id->idOpSize()); // X
9579             code |= insEncodeExtend(id->idInsOpt());   // ooo
9580             code |= insEncodeExtendScale(imm);         // sss
9581             code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9582             code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9583             dst += emitOutput_Instr(dst, code);
9584             break;
9585
9586         case IF_DR_2D: // DR_2D   X..........nnnnn cccc..nnnnnddddd      Rd Rn    cond
9587             imm = emitGetInsSC(id);
9588             assert(isValidImmCond(imm));
9589             {
9590                 condFlagsImm cfi;
9591                 cfi.immCFVal = (unsigned)imm;
9592                 code         = emitInsCode(ins, fmt);
9593                 code |= insEncodeDatasize(id->idOpSize()); // X
9594                 code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9595                 code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9596                 code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9597                 code |= insEncodeInvertedCond(cfi.cond);   // cccc
9598                 dst += emitOutput_Instr(dst, code);
9599             }
9600             break;
9601
9602         case IF_DR_2E: // DR_2E   X..........mmmmm ...........ddddd      Rd    Rm
9603             code = emitInsCode(ins, fmt);
9604             code |= insEncodeDatasize(id->idOpSize()); // X
9605             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9606             code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9607             dst += emitOutput_Instr(dst, code);
9608             break;
9609
9610         case IF_DR_2F: // DR_2F   X.......sh.mmmmm ssssss.....ddddd      Rd    Rm {LSL,LSR,ASR} imm(0-63)
9611             code = emitInsCode(ins, fmt);
9612             imm  = emitGetInsSC(id);
9613             assert(isValidImmShift(imm, id->idOpSize()));
9614             code |= insEncodeDatasize(id->idOpSize());        // X
9615             code |= insEncodeShiftType(id->idInsOpt());       // sh
9616             code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9617             code |= insEncodeReg_Rd(id->idReg1());            // ddddd
9618             code |= insEncodeReg_Rm(id->idReg2());            // mmmmm
9619             dst += emitOutput_Instr(dst, code);
9620             break;
9621
9622         case IF_DR_2G: // DR_2G   X............... .....xnnnnnddddd      Rd Rn
9623             code = emitInsCode(ins, fmt);
9624             code |= insEncodeDatasize(id->idOpSize()); // X
9625             if (ins == INS_rev)
9626             {
9627                 if (size == EA_8BYTE)
9628                 {
9629                     code |= 0x00000400; // x - bit at location 10
9630                 }
9631             }
9632             code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9633             code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9634             dst += emitOutput_Instr(dst, code);
9635             break;
9636
9637         case IF_DR_2H: // DR_2H   X........X...... ......nnnnnddddd      Rd Rn
9638             code = emitInsCode(ins, fmt);
9639             code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9640             code |= insEncodeReg_Rd(id->idReg1());             // ddddd
9641             code |= insEncodeReg_Rn(id->idReg2());             // nnnnn
9642             dst += emitOutput_Instr(dst, code);
9643             break;
9644
9645         case IF_DR_2I: // DR_2I   X..........mmmmm cccc..nnnnn.nzcv      Rn Rm    nzcv cond
9646             imm = emitGetInsSC(id);
9647             assert(isValidImmCondFlags(imm));
9648             {
9649                 condFlagsImm cfi;
9650                 cfi.immCFVal = (unsigned)imm;
9651                 code         = emitInsCode(ins, fmt);
9652                 code |= insEncodeDatasize(id->idOpSize()); // X
9653                 code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9654                 code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9655                 code |= insEncodeFlags(cfi.flags);         // nzcv
9656                 code |= insEncodeCond(cfi.cond);           // cccc
9657                 dst += emitOutput_Instr(dst, code);
9658             }
9659             break;
9660
9661         case IF_DR_2J: // DR_2J   ................ ......nnnnnddddd      Sd Sn   (sha1h)
9662             code = emitInsCode(ins, fmt);
9663             code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9664             code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9665             dst += emitOutput_Instr(dst, code);
9666             break;
9667
9668         case IF_DR_3A: // DR_3A   X..........mmmmm ......nnnnnmmmmm      Rd Rn Rm
9669             code = emitInsCode(ins, fmt);
9670             code |= insEncodeDatasize(id->idOpSize()); // X
9671             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9672             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9673             if (id->idIsLclVar())
9674             {
9675                 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9676             }
9677             else
9678             {
9679                 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9680             }
9681             dst += emitOutput_Instr(dst, code);
9682             break;
9683
9684         case IF_DR_3B: // DR_3B   X.......sh.mmmmm ssssssnnnnnddddd      Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
9685             code = emitInsCode(ins, fmt);
9686             imm  = emitGetInsSC(id);
9687             assert(isValidImmShift(imm, id->idOpSize()));
9688             code |= insEncodeDatasize(id->idOpSize());        // X
9689             code |= insEncodeReg_Rd(id->idReg1());            // ddddd
9690             code |= insEncodeReg_Rn(id->idReg2());            // nnnnn
9691             code |= insEncodeReg_Rm(id->idReg3());            // mmmmm
9692             code |= insEncodeShiftType(id->idInsOpt());       // sh
9693             code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9694             dst += emitOutput_Instr(dst, code);
9695             break;
9696
9697         case IF_DR_3C: // DR_3C   X..........mmmmm ooosssnnnnnddddd      Rd Rn Rm ext(Rm) LSL imm(0-4)
9698             code = emitInsCode(ins, fmt);
9699             imm  = emitGetInsSC(id);
9700             assert((imm >= 0) && (imm <= 4));          // imm [0..4]
9701             code |= insEncodeDatasize(id->idOpSize()); // X
9702             code |= insEncodeExtend(id->idInsOpt());   // ooo
9703             code |= insEncodeExtendScale(imm);         // sss
9704             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9705             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9706             code |= insEncodeReg_Rm(id->idReg3());     // mmmmm
9707             dst += emitOutput_Instr(dst, code);
9708             break;
9709
9710         case IF_DR_3D: // DR_3D   X..........mmmmm cccc..nnnnnddddd      Rd Rn Rm cond
9711             imm = emitGetInsSC(id);
9712             assert(isValidImmCond(imm));
9713             {
9714                 condFlagsImm cfi;
9715                 cfi.immCFVal = (unsigned)imm;
9716                 code         = emitInsCode(ins, fmt);
9717                 code |= insEncodeDatasize(id->idOpSize()); // X
9718                 code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9719                 code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9720                 code |= insEncodeReg_Rm(id->idReg3());     // mmmmm
9721                 code |= insEncodeCond(cfi.cond);           // cccc
9722                 dst += emitOutput_Instr(dst, code);
9723             }
9724             break;
9725
9726         case IF_DR_3E: // DR_3E   X........X.mmmmm ssssssnnnnnddddd      Rd Rn Rm imm(0-63)
9727             code = emitInsCode(ins, fmt);
9728             imm  = emitGetInsSC(id);
9729             assert(isValidImmShift(imm, id->idOpSize()));
9730             code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9731             code |= insEncodeReg_Rd(id->idReg1());             // ddddd
9732             code |= insEncodeReg_Rn(id->idReg2());             // nnnnn
9733             code |= insEncodeReg_Rm(id->idReg3());             // mmmmm
9734             code |= insEncodeShiftCount(imm, id->idOpSize());  // ssssss
9735             dst += emitOutput_Instr(dst, code);
9736             break;
9737
9738         case IF_DR_4A: // DR_4A   X..........mmmmm .aaaaannnnnmmmmm      Rd Rn Rm Ra
9739             code = emitInsCode(ins, fmt);
9740             code |= insEncodeDatasize(id->idOpSize()); // X
9741             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9742             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9743             code |= insEncodeReg_Rm(id->idReg3());     // mmmmm
9744             code |= insEncodeReg_Ra(id->idReg4());     // aaaaa
9745             dst += emitOutput_Instr(dst, code);
9746             break;
9747
9748         case IF_DV_1A: // DV_1A   .........X.iiiii iii........ddddd      Vd imm8    (fmov - immediate scalar)
9749             imm      = emitGetInsSC(id);
9750             elemsize = id->idOpSize();
9751             code     = emitInsCode(ins, fmt);
9752             code |= insEncodeFloatElemsize(elemsize); // X
9753             code |= ((code_t)imm << 13);              // iiiii iii
9754             code |= insEncodeReg_Vd(id->idReg1());    // ddddd
9755             dst += emitOutput_Instr(dst, code);
9756             break;
9757
9758         case IF_DV_1B: // DV_1B   .QX..........iii cmod..iiiiiddddd      Vd imm8    (immediate vector)
9759             imm      = emitGetInsSC(id) & 0x0ff;
9760             immShift = (emitGetInsSC(id) & 0x700) >> 8;
9761             elemsize = optGetElemsize(id->idInsOpt());
9762             cmode    = 0;
9763             switch (elemsize)
9764             { // cmode
9765                 case EA_1BYTE:
9766                     cmode = 0xE; // 1110
9767                     break;
9768                 case EA_2BYTE:
9769                     cmode = 0x8;
9770                     cmode |= (immShift << 1); // 10x0
9771                     break;
9772                 case EA_4BYTE:
9773                     if (immShift < 4)
9774                     {
9775                         cmode = 0x0;
9776                         cmode |= (immShift << 1); // 0xx0
9777                     }
9778                     else // MSL
9779                     {
9780                         cmode = 0xC;
9781                         if (immShift & 2)
9782                             cmode |= 1; // 110x
9783                     }
9784                     break;
9785                 case EA_8BYTE:
9786                     cmode = 0xE; // 1110
9787                     break;
9788                 default:
9789                     unreached();
9790                     break;
9791             }
9792
9793             code = emitInsCode(ins, fmt);
9794             code |= insEncodeVectorsize(id->idOpSize()); // Q
9795             if ((ins == INS_fmov) || (ins == INS_movi))
9796             {
9797                 if (elemsize == EA_8BYTE)
9798                 {
9799                     code |= 0x20000000; // X
9800                 }
9801             }
9802             if (ins != INS_fmov)
9803             {
9804                 assert((cmode >= 0) && (cmode <= 0xF));
9805                 code |= (cmode << 12); // cmod
9806             }
9807             code |= (((code_t)imm >> 5) << 16);    // iii
9808             code |= (((code_t)imm & 0x1f) << 5);   // iiiii
9809             code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9810             dst += emitOutput_Instr(dst, code);
9811             break;
9812
9813         case IF_DV_1C: // DV_1C   .........X...... ......nnnnn.....      Vn #0.0    (fcmp - with zero)
9814             elemsize = id->idOpSize();
9815             code     = emitInsCode(ins, fmt);
9816             code |= insEncodeFloatElemsize(elemsize); // X
9817             code |= insEncodeReg_Vn(id->idReg1());    // nnnnn
9818             dst += emitOutput_Instr(dst, code);
9819             break;
9820
9821         case IF_DV_2A: // DV_2A   .Q.......X...... ......nnnnnddddd      Vd Vn      (fabs, fcvt - vector)
9822             elemsize = optGetElemsize(id->idInsOpt());
9823             code     = emitInsCode(ins, fmt);
9824             code |= insEncodeVectorsize(id->idOpSize()); // Q
9825             code |= insEncodeFloatElemsize(elemsize);    // X
9826             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9827             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9828             dst += emitOutput_Instr(dst, code);
9829             break;
9830
9831         case IF_DV_2B: // DV_2B   .Q.........iiiii ......nnnnnddddd      Rd Vn[] (umov/smov    - to general)
9832             elemsize = id->idOpSize();
9833             index    = emitGetInsSC(id);
9834             datasize = (elemsize == EA_8BYTE) ? EA_16BYTE : EA_8BYTE;
9835             if (ins == INS_smov)
9836             {
9837                 datasize = EA_16BYTE;
9838             }
9839             code = emitInsCode(ins, fmt);
9840             code |= insEncodeVectorsize(datasize);         // Q
9841             code |= insEncodeVectorIndex(elemsize, index); // iiiii
9842             code |= insEncodeReg_Rd(id->idReg1());         // ddddd
9843             code |= insEncodeReg_Vn(id->idReg2());         // nnnnn
9844             dst += emitOutput_Instr(dst, code);
9845             break;
9846
9847         case IF_DV_2C: // DV_2C   .Q.........iiiii ......nnnnnddddd      Vd Rn   (dup/ins - vector from general)
9848             if (ins == INS_dup)
9849             {
9850                 datasize = id->idOpSize();
9851                 elemsize = optGetElemsize(id->idInsOpt());
9852                 index    = 0;
9853             }
9854             else // INS_ins
9855             {
9856                 datasize = EA_16BYTE;
9857                 elemsize = id->idOpSize();
9858                 index    = emitGetInsSC(id);
9859             }
9860             code = emitInsCode(ins, fmt);
9861             code |= insEncodeVectorsize(datasize);         // Q
9862             code |= insEncodeVectorIndex(elemsize, index); // iiiii
9863             code |= insEncodeReg_Vd(id->idReg1());         // ddddd
9864             code |= insEncodeReg_Rn(id->idReg2());         // nnnnn
9865             dst += emitOutput_Instr(dst, code);
9866             break;
9867
9868         case IF_DV_2D: // DV_2D   .Q.........iiiii ......nnnnnddddd      Vd Vn[]   (dup - vector)
9869             index    = emitGetInsSC(id);
9870             elemsize = optGetElemsize(id->idInsOpt());
9871             code     = emitInsCode(ins, fmt);
9872             code |= insEncodeVectorsize(id->idOpSize());   // Q
9873             code |= insEncodeVectorIndex(elemsize, index); // iiiii
9874             code |= insEncodeReg_Vd(id->idReg1());         // ddddd
9875             code |= insEncodeReg_Vn(id->idReg2());         // nnnnn
9876             dst += emitOutput_Instr(dst, code);
9877             break;
9878
9879         case IF_DV_2E: // DV_2E   ...........iiiii ......nnnnnddddd      Vd Vn[]   (dup - scalar)
9880             index    = emitGetInsSC(id);
9881             elemsize = id->idOpSize();
9882             code     = emitInsCode(ins, fmt);
9883             code |= insEncodeVectorIndex(elemsize, index); // iiiii
9884             code |= insEncodeReg_Vd(id->idReg1());         // ddddd
9885             code |= insEncodeReg_Vn(id->idReg2());         // nnnnn
9886             dst += emitOutput_Instr(dst, code);
9887             break;
9888
9889         case IF_DV_2F: // DV_2F   ...........iiiii .jjjj.nnnnnddddd      Vd[] Vn[] (ins - element)
9890             elemsize = id->idOpSize();
9891             imm      = emitGetInsSC(id);
9892             index    = (imm >> 4) & 0xf;
9893             index2   = imm & 0xf;
9894             code     = emitInsCode(ins, fmt);
9895             code |= insEncodeVectorIndex(elemsize, index);   // iiiii
9896             code |= insEncodeVectorIndex2(elemsize, index2); // jjjj
9897             code |= insEncodeReg_Vd(id->idReg1());           // ddddd
9898             code |= insEncodeReg_Vn(id->idReg2());           // nnnnn
9899             dst += emitOutput_Instr(dst, code);
9900             break;
9901
9902         case IF_DV_2G: // DV_2G   .........X...... ......nnnnnddddd      Vd Vn      (fmov,fcvtXX - register)
9903             elemsize = id->idOpSize();
9904             code     = emitInsCode(ins, fmt);
9905             code |= insEncodeFloatElemsize(elemsize); // X
9906             code |= insEncodeReg_Vd(id->idReg1());    // ddddd
9907             code |= insEncodeReg_Vn(id->idReg2());    // nnnnn
9908             dst += emitOutput_Instr(dst, code);
9909             break;
9910
9911         case IF_DV_2H: // DV_2H   X........X...... ......nnnnnddddd      Rd Vn      (fmov - to general)
9912             elemsize = id->idOpSize();
9913             code     = emitInsCode(ins, fmt);
9914             code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X   X
9915             code |= insEncodeReg_Rd(id->idReg1());            // ddddd
9916             code |= insEncodeReg_Vn(id->idReg2());            // nnnnn
9917             dst += emitOutput_Instr(dst, code);
9918             break;
9919
9920         case IF_DV_2I: // DV_2I   X........X...... ......nnnnnddddd      Vd Rn      (fmov - from general)
9921             elemsize = id->idOpSize();
9922             code     = emitInsCode(ins, fmt);
9923             code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X   X
9924             code |= insEncodeReg_Vd(id->idReg1());            // ddddd
9925             code |= insEncodeReg_Rn(id->idReg2());            // nnnnn
9926             dst += emitOutput_Instr(dst, code);
9927             break;
9928
9929         case IF_DV_2J: // DV_2J   ........SS.....D D.....nnnnnddddd      Vd Vn      (fcvt)
9930             code = emitInsCode(ins, fmt);
9931             code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // SS DD
9932             code |= insEncodeReg_Vd(id->idReg1());            // ddddd
9933             code |= insEncodeReg_Vn(id->idReg2());            // nnnnn
9934             dst += emitOutput_Instr(dst, code);
9935             break;
9936
9937         case IF_DV_2K: // DV_2K   .........X.mmmmm ......nnnnn.....      Vn Vm      (fcmp)
9938             elemsize = id->idOpSize();
9939             code     = emitInsCode(ins, fmt);
9940             code |= insEncodeFloatElemsize(elemsize); // X
9941             code |= insEncodeReg_Vn(id->idReg1());    // nnnnn
9942             code |= insEncodeReg_Vm(id->idReg2());    // mmmmm
9943             dst += emitOutput_Instr(dst, code);
9944             break;
9945
9946         case IF_DV_2L: // DV_2L   ........XX...... ......nnnnnddddd      Vd Vn      (abs, neg - scalar)
9947             elemsize = id->idOpSize();
9948             code     = emitInsCode(ins, fmt);
9949             code |= insEncodeElemsize(elemsize);   // XX
9950             code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9951             code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9952             dst += emitOutput_Instr(dst, code);
9953             break;
9954
9955         case IF_DV_2M: // DV_2M   .Q......XX...... ......nnnnnddddd      Vd Vn      (abs, neg   - vector)
9956             elemsize = optGetElemsize(id->idInsOpt());
9957             code     = emitInsCode(ins, fmt);
9958             code |= insEncodeVectorsize(id->idOpSize()); // Q
9959             code |= insEncodeElemsize(elemsize);         // XX
9960             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9961             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9962             dst += emitOutput_Instr(dst, code);
9963             break;
9964
9965         case IF_DV_2N: // DV_2N   .........iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - scalar)
9966             imm  = emitGetInsSC(id);
9967             code = emitInsCode(ins, fmt);
9968             code |= insEncodeVectorShift(EA_8BYTE, imm); // iiiiiii
9969             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9970             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9971             dst += emitOutput_Instr(dst, code);
9972             break;
9973
9974         case IF_DV_2O: // DV_2O   .Q.......iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - vector)
9975             imm      = emitGetInsSC(id);
9976             elemsize = optGetElemsize(id->idInsOpt());
9977             code     = emitInsCode(ins, fmt);
9978             code |= insEncodeVectorsize(id->idOpSize()); // Q
9979             code |= insEncodeVectorShift(elemsize, imm); // iiiiiii
9980             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9981             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9982             dst += emitOutput_Instr(dst, code);
9983             break;
9984
9985         case IF_DV_2P: // DV_2P   ............... ......nnnnnddddd      Vd Vn      (aes*, sha1su1)
9986             elemsize = optGetElemsize(id->idInsOpt());
9987             code     = emitInsCode(ins, fmt);
9988             code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9989             code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9990             dst += emitOutput_Instr(dst, code);
9991             break;
9992
9993         case IF_DV_3A: // DV_3A   .Q......XX.mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
9994             code     = emitInsCode(ins, fmt);
9995             elemsize = optGetElemsize(id->idInsOpt());
9996             code |= insEncodeVectorsize(id->idOpSize()); // Q
9997             code |= insEncodeElemsize(elemsize);         // XX
9998             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9999             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
10000             code |= insEncodeReg_Vm(id->idReg3());       // mmmmm
10001             dst += emitOutput_Instr(dst, code);
10002             break;
10003
10004         case IF_DV_3AI: // DV_3AI  .Q......XXLMmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector)
10005             code     = emitInsCode(ins, fmt);
10006             imm      = emitGetInsSC(id);
10007             elemsize = optGetElemsize(id->idInsOpt());
10008             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
10009             code |= insEncodeVectorsize(id->idOpSize());    // Q
10010             code |= insEncodeElemsize(elemsize);            // XX
10011             code |= insEncodeVectorIndexLMH(elemsize, imm); // LM H
10012             code |= insEncodeReg_Vd(id->idReg1());          // ddddd
10013             code |= insEncodeReg_Vn(id->idReg2());          // nnnnn
10014             code |= insEncodeReg_Vm(id->idReg3());          // mmmmm
10015             dst += emitOutput_Instr(dst, code);
10016             break;
10017
10018         case IF_DV_3B: // DV_3B   .Q.......X.mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
10019             code     = emitInsCode(ins, fmt);
10020             elemsize = optGetElemsize(id->idInsOpt());
10021             code |= insEncodeVectorsize(id->idOpSize()); // Q
10022             code |= insEncodeFloatElemsize(elemsize);    // X
10023             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
10024             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
10025             code |= insEncodeReg_Vm(id->idReg3());       // mmmmm
10026             dst += emitOutput_Instr(dst, code);
10027             break;
10028
10029         case IF_DV_3BI: // DV_3BI  .Q.......XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector by elem)
10030             code     = emitInsCode(ins, fmt);
10031             imm      = emitGetInsSC(id);
10032             elemsize = optGetElemsize(id->idInsOpt());
10033             assert(isValidVectorIndex(id->idOpSize(), elemsize, imm));
10034             code |= insEncodeVectorsize(id->idOpSize()); // Q
10035             code |= insEncodeFloatElemsize(elemsize);    // X
10036             code |= insEncodeFloatIndex(elemsize, imm);  // L H
10037             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
10038             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
10039             code |= insEncodeReg_Vm(id->idReg3());       // mmmmm
10040             dst += emitOutput_Instr(dst, code);
10041             break;
10042
10043         case IF_DV_3C: // DV_3C   .Q.........mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
10044             code = emitInsCode(ins, fmt);
10045             code |= insEncodeVectorsize(id->idOpSize()); // Q
10046             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
10047             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
10048             code |= insEncodeReg_Vm(id->idReg3());       // mmmmm
10049             dst += emitOutput_Instr(dst, code);
10050             break;
10051
10052         case IF_DV_3D: // DV_3D   .........X.mmmmm ......nnnnnddddd      Vd Vn Vm   (scalar)
10053             code = emitInsCode(ins, fmt);
10054             code |= insEncodeFloatElemsize(id->idOpSize()); // X
10055             code |= insEncodeReg_Vd(id->idReg1());          // ddddd
10056             code |= insEncodeReg_Vn(id->idReg2());          // nnnnn
10057             code |= insEncodeReg_Vm(id->idReg3());          // mmmmm
10058             dst += emitOutput_Instr(dst, code);
10059             break;
10060
10061         case IF_DV_3DI: // DV_3DI  .........XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (scalar by elem)
10062             code     = emitInsCode(ins, fmt);
10063             imm      = emitGetInsSC(id);
10064             elemsize = id->idOpSize();
10065             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
10066             code |= insEncodeFloatElemsize(elemsize);   // X
10067             code |= insEncodeFloatIndex(elemsize, imm); // L H
10068             code |= insEncodeReg_Vd(id->idReg1());      // ddddd
10069             code |= insEncodeReg_Vn(id->idReg2());      // nnnnn
10070             code |= insEncodeReg_Vm(id->idReg3());      // mmmmm
10071             dst += emitOutput_Instr(dst, code);
10072             break;
10073
10074         case IF_DV_3E: // DV_3E   ...........mmmmm ......nnnnnddddd      Vd Vn Vm   (scalar)
10075         case IF_DV_3F: // DV_3F   ...........mmmmm ......nnnnnddddd      Vd Vn Vm   (vector) - source dest regs overlap
10076             code = emitInsCode(ins, fmt);
10077             code |= insEncodeReg_Vd(id->idReg1()); // ddddd
10078             code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
10079             code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
10080             dst += emitOutput_Instr(dst, code);
10081             break;
10082
10083         case IF_DV_4A: // DV_4A   .........X.mmmmm .aaaaannnnnddddd      Vd Va Vn Vm (scalar)
10084             code     = emitInsCode(ins, fmt);
10085             elemsize = id->idOpSize();
10086             code |= insEncodeFloatElemsize(elemsize); // X
10087             code |= insEncodeReg_Vd(id->idReg1());    // ddddd
10088             code |= insEncodeReg_Vn(id->idReg2());    // nnnnn
10089             code |= insEncodeReg_Vm(id->idReg3());    // mmmmm
10090             code |= insEncodeReg_Va(id->idReg4());    // aaaaa
10091             dst += emitOutput_Instr(dst, code);
10092             break;
10093
10094         case IF_SN_0A: // SN_0A   ................ ................
10095             code = emitInsCode(ins, fmt);
10096             dst += emitOutput_Instr(dst, code);
10097             break;
10098
10099         case IF_SI_0A: // SI_0A   ...........iiiii iiiiiiiiiii.....               imm16
10100             imm = emitGetInsSC(id);
10101             assert(isValidUimm16(imm));
10102             code = emitInsCode(ins, fmt);
10103             code |= ((code_t)imm << 5); // iiiii iiiiiiiiiii
10104             dst += emitOutput_Instr(dst, code);
10105             break;
10106
10107         case IF_SI_0B: // SI_0B   ................ ....bbbb........               imm4 - barrier
10108             imm = emitGetInsSC(id);
10109             assert((imm >= 0) && (imm <= 15));
10110             code = emitInsCode(ins, fmt);
10111             code |= ((code_t)imm << 8); // bbbb
10112             dst += emitOutput_Instr(dst, code);
10113             break;
10114
10115         default:
10116             assert(!"Unexpected format");
10117             break;
10118     }
10119
10120     // Determine if any registers now hold GC refs, or whether a register that was overwritten held a GC ref.
10121     // We assume here that "id->idGCref()" is not GC_NONE only if the instruction described by "id" writes a
10122     // GC ref to register "id->idReg1()".  (It may, apparently, also not be GC_NONE in other cases, such as
10123     // for stores, but we ignore those cases here.)
10124     if (emitInsMayWriteToGCReg(id)) // True if "id->idIns()" writes to a register than can hold GC ref.
10125     {
10126         // We assume that "idReg1" is the primary destination register for all instructions
10127         if (id->idGCref() != GCT_NONE)
10128         {
10129             emitGCregLiveUpd(id->idGCref(), id->idReg1(), dst);
10130         }
10131         else
10132         {
10133             emitGCregDeadUpd(id->idReg1(), dst);
10134         }
10135
10136         if (emitInsMayWriteMultipleRegs(id))
10137         {
10138             // INS_ldp etc...
10139             // "idReg2" is the secondary destination register
10140             if (id->idGCrefReg2() != GCT_NONE)
10141             {
10142                 emitGCregLiveUpd(id->idGCrefReg2(), id->idReg2(), dst);
10143             }
10144             else
10145             {
10146                 emitGCregDeadUpd(id->idReg2(), dst);
10147             }
10148         }
10149     }
10150
10151     // Now we determine if the instruction has written to a (local variable) stack location, and either written a GC
10152     // ref or overwritten one.
10153     if (emitInsWritesToLclVarStackLoc(id) || emitInsWritesToLclVarStackLocPair(id))
10154     {
10155         int      varNum = id->idAddr()->iiaLclVar.lvaVarNum();
10156         unsigned ofs    = AlignDown(id->idAddr()->iiaLclVar.lvaOffset(), TARGET_POINTER_SIZE);
10157         bool     FPbased;
10158         int      adr = emitComp->lvaFrameAddress(varNum, &FPbased);
10159         if (id->idGCref() != GCT_NONE)
10160         {
10161             emitGCvarLiveUpd(adr + ofs, varNum, id->idGCref(), dst);
10162         }
10163         else
10164         {
10165             // If the type of the local is a gc ref type, update the liveness.
10166             var_types vt;
10167             if (varNum >= 0)
10168             {
10169                 // "Regular" (non-spill-temp) local.
10170                 vt = var_types(emitComp->lvaTable[varNum].lvType);
10171             }
10172             else
10173             {
10174                 TempDsc* tmpDsc = emitComp->tmpFindNum(varNum);
10175                 vt              = tmpDsc->tdTempType();
10176             }
10177             if (vt == TYP_REF || vt == TYP_BYREF)
10178                 emitGCvarDeadUpd(adr + ofs, dst);
10179         }
10180         if (emitInsWritesToLclVarStackLocPair(id))
10181         {
10182             unsigned ofs2 = ofs + TARGET_POINTER_SIZE;
10183             if (id->idGCrefReg2() != GCT_NONE)
10184             {
10185                 emitGCvarLiveUpd(adr + ofs2, varNum, id->idGCrefReg2(), dst);
10186             }
10187             else
10188             {
10189                 // If the type of the local is a gc ref type, update the liveness.
10190                 var_types vt;
10191                 if (varNum >= 0)
10192                 {
10193                     // "Regular" (non-spill-temp) local.
10194                     vt = var_types(emitComp->lvaTable[varNum].lvType);
10195                 }
10196                 else
10197                 {
10198                     TempDsc* tmpDsc = emitComp->tmpFindNum(varNum);
10199                     vt              = tmpDsc->tdTempType();
10200                 }
10201                 if (vt == TYP_REF || vt == TYP_BYREF)
10202                     emitGCvarDeadUpd(adr + ofs2, dst);
10203             }
10204         }
10205     }
10206
10207 #ifdef DEBUG
10208     /* Make sure we set the instruction descriptor size correctly */
10209
10210     size_t expected = emitSizeOfInsDsc(id);
10211     assert(sz == expected);
10212
10213     if (emitComp->opts.disAsm || emitComp->opts.dspEmit || emitComp->verbose)
10214     {
10215         emitDispIns(id, false, dspOffs, true, emitCurCodeOffs(odst), *dp, (dst - *dp), ig);
10216     }
10217
10218     if (emitComp->compDebugBreak)
10219     {
10220         // For example, set JitBreakEmitOutputInstr=a6 will break when this method is called for
10221         // emitting instruction a6, (i.e. IN00a6 in jitdump).
10222         if ((unsigned)JitConfig.JitBreakEmitOutputInstr() == id->idDebugOnlyInfo()->idNum)
10223         {
10224             assert(!"JitBreakEmitOutputInstr reached");
10225         }
10226     }
10227 #endif
10228
10229     /* All instructions are expected to generate code */
10230
10231     assert(*dp != dst);
10232
10233     *dp = dst;
10234
10235     return sz;
10236 }
10237
10238 /*****************************************************************************/
10239 /*****************************************************************************/
10240
10241 #ifdef DEBUG
10242
10243 /*****************************************************************************
10244  *
10245  *  Display the instruction name
10246  */
10247 void emitter::emitDispInst(instruction ins)
10248 {
10249     const char* insstr = codeGen->genInsName(ins);
10250     size_t      len    = strlen(insstr);
10251
10252     /* Display the instruction name */
10253
10254     printf("%s", insstr);
10255
10256     //
10257     // Add at least one space after the instruction name
10258     // and add spaces until we have reach the normal size of 8
10259     do
10260     {
10261         printf(" ");
10262         len++;
10263     } while (len < 8);
10264 }
10265
10266 /*****************************************************************************
10267  *
10268  *  Display an reloc value
10269  *  If we are formatting for an assembly listing don't print the hex value
10270  *  since it will prevent us from doing assembly diffs
10271  */
10272 void emitter::emitDispReloc(int value, bool addComma)
10273 {
10274     if (emitComp->opts.disAsm)
10275     {
10276         printf("(reloc)");
10277     }
10278     else
10279     {
10280         printf("(reloc 0x%x)", dspPtr(value));
10281     }
10282
10283     if (addComma)
10284         printf(", ");
10285 }
10286
10287 /*****************************************************************************
10288  *
10289  *  Display an immediate value
10290  */
10291 void emitter::emitDispImm(ssize_t imm, bool addComma, bool alwaysHex /* =false */)
10292 {
10293     if (strictArmAsm)
10294     {
10295         printf("#");
10296     }
10297
10298     // Munge any pointers if we want diff-able disassembly.
10299     // Since some may be emitted as partial words, print as diffable anything that has
10300     // significant bits beyond the lowest 8-bits.
10301     if (emitComp->opts.disDiffable)
10302     {
10303         ssize_t top56bits = (imm >> 8);
10304         if ((top56bits != 0) && (top56bits != -1))
10305             imm = 0xD1FFAB1E;
10306     }
10307
10308     if (!alwaysHex && (imm > -1000) && (imm < 1000))
10309     {
10310         printf("%d", imm);
10311     }
10312     else
10313     {
10314         if ((imm < 0) && ((imm & 0xFFFFFFFF00000000LL) == 0xFFFFFFFF00000000LL))
10315         {
10316             printf("-");
10317             imm = -imm;
10318         }
10319
10320         if ((imm & 0xFFFFFFFF00000000LL) != 0)
10321         {
10322             printf("0x%llx", imm);
10323         }
10324         else
10325         {
10326             printf("0x%02x", imm);
10327         }
10328     }
10329
10330     if (addComma)
10331         printf(", ");
10332 }
10333
10334 /*****************************************************************************
10335  *
10336  *  Display a float zero constant
10337  */
10338 void emitter::emitDispFloatZero()
10339 {
10340     if (strictArmAsm)
10341     {
10342         printf("#");
10343     }
10344     printf("0.0");
10345 }
10346
10347 /*****************************************************************************
10348  *
10349  *  Display an encoded float constant value
10350  */
10351 void emitter::emitDispFloatImm(ssize_t imm8)
10352 {
10353     assert((0 <= imm8) && (imm8 <= 0x0ff));
10354     if (strictArmAsm)
10355     {
10356         printf("#");
10357     }
10358
10359     floatImm8 fpImm;
10360     fpImm.immFPIVal = (unsigned)imm8;
10361     double result   = emitDecodeFloatImm8(fpImm);
10362
10363     printf("%.4f", result);
10364 }
10365
10366 /*****************************************************************************
10367  *
10368  *  Display an immediate that is optionally LSL12.
10369  */
10370 void emitter::emitDispImmOptsLSL12(ssize_t imm, insOpts opt)
10371 {
10372     if (!strictArmAsm && insOptsLSL12(opt))
10373     {
10374         imm <<= 12;
10375     }
10376     emitDispImm(imm, false);
10377     if (strictArmAsm && insOptsLSL12(opt))
10378     {
10379         printf(", LSL #12");
10380     }
10381 }
10382
10383 /*****************************************************************************
10384  *
10385  *  Display an ARM64 condition code for the conditional instructions
10386  */
10387 void emitter::emitDispCond(insCond cond)
10388 {
10389     const static char* armCond[16] = {"eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc",
10390                                       "hi", "ls", "ge", "lt", "gt", "le", "AL", "NV"}; // The last two are invalid
10391     unsigned imm = (unsigned)cond;
10392     assert((0 <= imm) && (imm < ArrLen(armCond)));
10393     printf(armCond[imm]);
10394 }
10395
10396 /*****************************************************************************
10397  *
10398  *  Display an ARM64 flags for the conditional instructions
10399  */
10400 void emitter::emitDispFlags(insCflags flags)
10401 {
10402     const static char* armFlags[16] = {"0", "v",  "c",  "cv",  "z",  "zv",  "zc",  "zcv",
10403                                        "n", "nv", "nc", "ncv", "nz", "nzv", "nzc", "nzcv"};
10404     unsigned imm = (unsigned)flags;
10405     assert((0 <= imm) && (imm < ArrLen(armFlags)));
10406     printf(armFlags[imm]);
10407 }
10408
10409 /*****************************************************************************
10410  *
10411  *  Display an ARM64 'barrier' for the memory barrier instructions
10412  */
10413 void emitter::emitDispBarrier(insBarrier barrier)
10414 {
10415     const static char* armBarriers[16] = {"#0", "oshld", "oshst", "osh", "#4",  "nshld", "nshst", "nsh",
10416                                           "#8", "ishld", "ishst", "ish", "#12", "ld",    "st",    "sy"};
10417     unsigned imm = (unsigned)barrier;
10418     assert((0 <= imm) && (imm < ArrLen(armBarriers)));
10419     printf(armBarriers[imm]);
10420 }
10421
10422 /*****************************************************************************
10423  *
10424  *  Prints the encoding for the Shift Type encoding
10425  */
10426
10427 void emitter::emitDispShiftOpts(insOpts opt)
10428 {
10429     if (opt == INS_OPTS_LSL)
10430         printf(" LSL ");
10431     else if (opt == INS_OPTS_LSR)
10432         printf(" LSR ");
10433     else if (opt == INS_OPTS_ASR)
10434         printf(" ASR ");
10435     else if (opt == INS_OPTS_ROR)
10436         printf(" ROR ");
10437     else if (opt == INS_OPTS_MSL)
10438         printf(" MSL ");
10439     else
10440         assert(!"Bad value");
10441 }
10442
10443 /*****************************************************************************
10444  *
10445  *  Prints the encoding for the Extend Type encoding
10446  */
10447
10448 void emitter::emitDispExtendOpts(insOpts opt)
10449 {
10450     if (opt == INS_OPTS_UXTB)
10451         printf("UXTB");
10452     else if (opt == INS_OPTS_UXTH)
10453         printf("UXTH");
10454     else if (opt == INS_OPTS_UXTW)
10455         printf("UXTW");
10456     else if (opt == INS_OPTS_UXTX)
10457         printf("UXTX");
10458     else if (opt == INS_OPTS_SXTB)
10459         printf("SXTB");
10460     else if (opt == INS_OPTS_SXTH)
10461         printf("SXTH");
10462     else if (opt == INS_OPTS_SXTW)
10463         printf("SXTW");
10464     else if (opt == INS_OPTS_SXTX)
10465         printf("SXTX");
10466     else
10467         assert(!"Bad value");
10468 }
10469
10470 /*****************************************************************************
10471  *
10472  *  Prints the encoding for the Extend Type encoding in loads/stores
10473  */
10474
10475 void emitter::emitDispLSExtendOpts(insOpts opt)
10476 {
10477     if (opt == INS_OPTS_LSL)
10478         printf("LSL");
10479     else if (opt == INS_OPTS_UXTW)
10480         printf("UXTW");
10481     else if (opt == INS_OPTS_UXTX)
10482         printf("UXTX");
10483     else if (opt == INS_OPTS_SXTW)
10484         printf("SXTW");
10485     else if (opt == INS_OPTS_SXTX)
10486         printf("SXTX");
10487     else
10488         assert(!"Bad value");
10489 }
10490
10491 /*****************************************************************************
10492  *
10493  *  Display a register
10494  */
10495 void emitter::emitDispReg(regNumber reg, emitAttr attr, bool addComma)
10496 {
10497     emitAttr size = EA_SIZE(attr);
10498     printf(emitRegName(reg, size));
10499
10500     if (addComma)
10501         printf(", ");
10502 }
10503
10504 /*****************************************************************************
10505  *
10506  *  Display a vector register with an arrangement suffix
10507  */
10508 void emitter::emitDispVectorReg(regNumber reg, insOpts opt, bool addComma)
10509 {
10510     assert(isVectorRegister(reg));
10511     printf(emitVectorRegName(reg));
10512     emitDispArrangement(opt);
10513
10514     if (addComma)
10515         printf(", ");
10516 }
10517
10518 /*****************************************************************************
10519  *
10520  *  Display an vector register index suffix
10521  */
10522 void emitter::emitDispVectorRegIndex(regNumber reg, emitAttr elemsize, ssize_t index, bool addComma)
10523 {
10524     assert(isVectorRegister(reg));
10525     printf(emitVectorRegName(reg));
10526
10527     switch (elemsize)
10528     {
10529         case EA_1BYTE:
10530             printf(".b");
10531             break;
10532         case EA_2BYTE:
10533             printf(".h");
10534             break;
10535         case EA_4BYTE:
10536             printf(".s");
10537             break;
10538         case EA_8BYTE:
10539             printf(".d");
10540             break;
10541         default:
10542             assert(!"invalid elemsize");
10543             break;
10544     }
10545
10546     printf("[%d]", index);
10547
10548     if (addComma)
10549         printf(", ");
10550 }
10551
10552 /*****************************************************************************
10553  *
10554  *  Display an arrangement suffix
10555  */
10556 void emitter::emitDispArrangement(insOpts opt)
10557 {
10558     const char* str = "???";
10559
10560     switch (opt)
10561     {
10562         case INS_OPTS_8B:
10563             str = "8b";
10564             break;
10565         case INS_OPTS_16B:
10566             str = "16b";
10567             break;
10568         case INS_OPTS_4H:
10569             str = "4h";
10570             break;
10571         case INS_OPTS_8H:
10572             str = "8h";
10573             break;
10574         case INS_OPTS_2S:
10575             str = "2s";
10576             break;
10577         case INS_OPTS_4S:
10578             str = "4s";
10579             break;
10580         case INS_OPTS_1D:
10581             str = "1d";
10582             break;
10583         case INS_OPTS_2D:
10584             str = "2d";
10585             break;
10586
10587         default:
10588             assert(!"Invalid insOpt for vector register");
10589     }
10590     printf(".");
10591     printf(str);
10592 }
10593
10594 /*****************************************************************************
10595  *
10596  *  Display a register with an optional shift operation
10597  */
10598 void emitter::emitDispShiftedReg(regNumber reg, insOpts opt, ssize_t imm, emitAttr attr)
10599 {
10600     emitAttr size = EA_SIZE(attr);
10601     assert((imm & 0x003F) == imm);
10602     assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
10603
10604     printf(emitRegName(reg, size));
10605
10606     if (imm > 0)
10607     {
10608         if (strictArmAsm)
10609         {
10610             printf(",");
10611         }
10612         emitDispShiftOpts(opt);
10613         emitDispImm(imm, false);
10614     }
10615 }
10616
10617 /*****************************************************************************
10618  *
10619  *  Display a register with an optional extend and scale operations
10620  */
10621 void emitter::emitDispExtendReg(regNumber reg, insOpts opt, ssize_t imm)
10622 {
10623     assert((imm >= 0) && (imm <= 4));
10624     assert(insOptsNone(opt) || insOptsAnyExtend(opt) || (opt == INS_OPTS_LSL));
10625
10626     // size is based on the extend option, not the instr size.
10627     emitAttr size = insOpts32BitExtend(opt) ? EA_4BYTE : EA_8BYTE;
10628
10629     if (strictArmAsm)
10630     {
10631         if (insOptsNone(opt))
10632         {
10633             emitDispReg(reg, size, false);
10634         }
10635         else
10636         {
10637             emitDispReg(reg, size, true);
10638             if (opt == INS_OPTS_LSL)
10639                 printf("LSL");
10640             else
10641                 emitDispExtendOpts(opt);
10642             if ((imm > 0) || (opt == INS_OPTS_LSL))
10643             {
10644                 printf(" ");
10645                 emitDispImm(imm, false);
10646             }
10647         }
10648     }
10649     else // !strictArmAsm
10650     {
10651         if (insOptsNone(opt))
10652         {
10653             emitDispReg(reg, size, false);
10654         }
10655         else
10656         {
10657             if (opt != INS_OPTS_LSL)
10658             {
10659                 emitDispExtendOpts(opt);
10660                 printf("(");
10661                 emitDispReg(reg, size, false);
10662                 printf(")");
10663             }
10664         }
10665         if (imm > 0)
10666         {
10667             printf("*");
10668             emitDispImm(1 << imm, false);
10669         }
10670     }
10671 }
10672
10673 /*****************************************************************************
10674  *
10675  *  Display an addressing operand [reg + imm]
10676  */
10677 void emitter::emitDispAddrRI(regNumber reg, insOpts opt, ssize_t imm)
10678 {
10679     reg = encodingZRtoSP(reg); // ZR (R31) encodes the SP register
10680
10681     if (strictArmAsm)
10682     {
10683         printf("[");
10684
10685         emitDispReg(reg, EA_8BYTE, false);
10686
10687         if (!insOptsPostIndex(opt) && (imm != 0))
10688         {
10689             printf(",");
10690             emitDispImm(imm, false);
10691         }
10692         printf("]");
10693
10694         if (insOptsPreIndex(opt))
10695         {
10696             printf("!");
10697         }
10698         else if (insOptsPostIndex(opt))
10699         {
10700             printf(",");
10701             emitDispImm(imm, false);
10702         }
10703     }
10704     else // !strictArmAsm
10705     {
10706         printf("[");
10707
10708         const char* operStr = "++";
10709         if (imm < 0)
10710         {
10711             operStr = "--";
10712             imm     = -imm;
10713         }
10714
10715         if (insOptsPreIndex(opt))
10716         {
10717             printf(operStr);
10718         }
10719
10720         emitDispReg(reg, EA_8BYTE, false);
10721
10722         if (insOptsPostIndex(opt))
10723         {
10724             printf(operStr);
10725         }
10726
10727         if (insOptsIndexed(opt))
10728         {
10729             printf(", ");
10730         }
10731         else
10732         {
10733             printf("%c", operStr[1]);
10734         }
10735         emitDispImm(imm, false);
10736         printf("]");
10737     }
10738 }
10739
10740 /*****************************************************************************
10741  *
10742  *  Display an addressing operand [reg + extended reg]
10743  */
10744 void emitter::emitDispAddrRRExt(regNumber reg1, regNumber reg2, insOpts opt, bool isScaled, emitAttr size)
10745 {
10746     reg1 = encodingZRtoSP(reg1); // ZR (R31) encodes the SP register
10747
10748     unsigned scale = 0;
10749     if (isScaled)
10750     {
10751         scale = NaturalScale_helper(size);
10752     }
10753
10754     printf("[");
10755
10756     if (strictArmAsm)
10757     {
10758         emitDispReg(reg1, EA_8BYTE, true);
10759         emitDispExtendReg(reg2, opt, scale);
10760     }
10761     else // !strictArmAsm
10762     {
10763         emitDispReg(reg1, EA_8BYTE, false);
10764         printf("+");
10765         emitDispExtendReg(reg2, opt, scale);
10766     }
10767
10768     printf("]");
10769 }
10770
10771 /*****************************************************************************
10772  *
10773  *  Display (optionally) the instruction encoding in hex
10774  */
10775
10776 void emitter::emitDispInsHex(BYTE* code, size_t sz)
10777 {
10778     // We do not display the instruction hex if we want diff-able disassembly
10779     if (!emitComp->opts.disDiffable)
10780     {
10781         if (sz == 4)
10782         {
10783             printf("  %08X    ", (*((code_t*)code)));
10784         }
10785         else
10786         {
10787             printf("              ");
10788         }
10789     }
10790 }
10791
10792 /****************************************************************************
10793  *
10794  *  Display the given instruction.
10795  */
10796
10797 void emitter::emitDispIns(
10798     instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* pCode, size_t sz, insGroup* ig)
10799 {
10800     if (EMITVERBOSE)
10801     {
10802         unsigned idNum =
10803             id->idDebugOnlyInfo()->idNum; // Do not remove this!  It is needed for VisualStudio conditional breakpoints
10804
10805         printf("IN%04x: ", idNum);
10806     }
10807
10808     if (pCode == NULL)
10809         sz = 0;
10810
10811     if (!emitComp->opts.dspEmit && !isNew && !asmfm && sz)
10812         doffs = true;
10813
10814     /* Display the instruction offset */
10815
10816     emitDispInsOffs(offset, doffs);
10817
10818     /* Display the instruction hex code */
10819
10820     emitDispInsHex(pCode, sz);
10821
10822     printf("      ");
10823
10824     /* Get the instruction and format */
10825
10826     instruction ins = id->idIns();
10827     insFormat   fmt = id->idInsFmt();
10828
10829     emitDispInst(ins);
10830
10831     /* If this instruction has just been added, check its size */
10832
10833     assert(isNew == false || (int)emitSizeOfInsDsc(id) == emitCurIGfreeNext - (BYTE*)id);
10834
10835     /* Figure out the operand size */
10836     emitAttr size = id->idOpSize();
10837     emitAttr attr = size;
10838     if (id->idGCref() == GCT_GCREF)
10839         attr = EA_GCREF;
10840     else if (id->idGCref() == GCT_BYREF)
10841         attr = EA_BYREF;
10842
10843     switch (fmt)
10844     {
10845         code_t       code;
10846         ssize_t      imm;
10847         int          doffs;
10848         bool         isExtendAlias;
10849         bool         canEncode;
10850         bitMaskImm   bmi;
10851         halfwordImm  hwi;
10852         condFlagsImm cfi;
10853         unsigned     scale;
10854         unsigned     immShift;
10855         bool         hasShift;
10856         ssize_t      offs;
10857         const char*  methodName;
10858         emitAttr     elemsize;
10859         emitAttr     datasize;
10860         emitAttr     srcsize;
10861         emitAttr     dstsize;
10862         ssize_t      index;
10863         ssize_t      index2;
10864
10865         case IF_BI_0A: // BI_0A   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
10866         case IF_BI_0B: // BI_0B   ......iiiiiiiiii iiiiiiiiiii.....               simm19:00
10867         case IF_LARGEJMP:
10868         {
10869             if (fmt == IF_LARGEJMP)
10870             {
10871                 printf("(LARGEJMP)");
10872             }
10873             if (id->idAddr()->iiaHasInstrCount())
10874             {
10875                 int instrCount = id->idAddr()->iiaGetInstrCount();
10876
10877                 if (ig == nullptr)
10878                 {
10879                     printf("pc%s%d instructions", (instrCount >= 0) ? "+" : "", instrCount);
10880                 }
10881                 else
10882                 {
10883                     unsigned       insNum  = emitFindInsNum(ig, id);
10884                     UNATIVE_OFFSET srcOffs = ig->igOffs + emitFindOffset(ig, insNum + 1);
10885                     UNATIVE_OFFSET dstOffs = ig->igOffs + emitFindOffset(ig, insNum + 1 + instrCount);
10886                     ssize_t        relOffs = (ssize_t)(emitOffsetToPtr(dstOffs) - emitOffsetToPtr(srcOffs));
10887                     printf("pc%s%d (%d instructions)", (relOffs >= 0) ? "+" : "", relOffs, instrCount);
10888                 }
10889             }
10890             else if (id->idIsBound())
10891             {
10892                 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10893             }
10894             else
10895             {
10896                 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10897             }
10898         }
10899         break;
10900
10901         case IF_BI_0C: // BI_0C   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
10902             if (id->idIsCallAddr())
10903             {
10904                 offs       = (ssize_t)id->idAddr()->iiaAddr;
10905                 methodName = "";
10906             }
10907             else
10908             {
10909                 offs       = 0;
10910                 methodName = emitComp->eeGetMethodFullName((CORINFO_METHOD_HANDLE)id->idDebugOnlyInfo()->idMemCookie);
10911             }
10912
10913             if (offs)
10914             {
10915                 if (id->idIsDspReloc())
10916                     printf("reloc ");
10917                 printf("%08X", offs);
10918             }
10919             else
10920             {
10921                 printf("%s", methodName);
10922             }
10923             break;
10924
10925         case IF_BI_1A: // BI_1A   ......iiiiiiiiii iiiiiiiiiiittttt      Rt       simm19:00
10926             assert(insOptsNone(id->idInsOpt()));
10927             emitDispReg(id->idReg1(), size, true);
10928             if (id->idIsBound())
10929             {
10930                 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10931             }
10932             else
10933             {
10934                 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10935             }
10936             break;
10937
10938         case IF_BI_1B: // BI_1B   B.......bbbbbiii iiiiiiiiiiittttt      Rt imm6, simm14:00
10939             assert(insOptsNone(id->idInsOpt()));
10940             emitDispReg(id->idReg1(), size, true);
10941             emitDispImm(emitGetInsSC(id), true);
10942             if (id->idIsBound())
10943             {
10944                 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10945             }
10946             else
10947             {
10948                 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10949             }
10950             break;
10951
10952         case IF_BR_1A: // BR_1A   ................ ......nnnnn.....         Rn
10953             assert(insOptsNone(id->idInsOpt()));
10954             emitDispReg(id->idReg1(), size, false);
10955             break;
10956
10957         case IF_BR_1B: // BR_1B   ................ ......nnnnn.....         Rn
10958             assert(insOptsNone(id->idInsOpt()));
10959             emitDispReg(id->idReg3(), size, false);
10960             break;
10961
10962         case IF_LS_1A: // LS_1A   XX...V..iiiiiiii iiiiiiiiiiittttt      Rt    PC imm(1MB)
10963         case IF_DI_1E: // DI_1E   .ii.....iiiiiiii iiiiiiiiiiiddddd      Rd       simm21
10964         case IF_LARGELDC:
10965         case IF_LARGEADR:
10966             assert(insOptsNone(id->idInsOpt()));
10967             emitDispReg(id->idReg1(), size, true);
10968             imm = emitGetInsSC(id);
10969
10970             /* Is this actually a reference to a data section? */
10971             if (fmt == IF_LARGEADR)
10972             {
10973                 printf("(LARGEADR)");
10974             }
10975             else if (fmt == IF_LARGELDC)
10976             {
10977                 printf("(LARGELDC)");
10978             }
10979
10980             printf("[");
10981             if (id->idAddr()->iiaIsJitDataOffset())
10982             {
10983                 doffs = Compiler::eeGetJitDataOffs(id->idAddr()->iiaFieldHnd);
10984                 /* Display a data section reference */
10985
10986                 if (doffs & 1)
10987                     printf("@CNS%02u", doffs - 1);
10988                 else
10989                     printf("@RWD%02u", doffs);
10990
10991                 if (imm != 0)
10992                     printf("%+Id", imm);
10993             }
10994             else
10995             {
10996                 assert(imm == 0);
10997                 if (id->idIsReloc())
10998                 {
10999                     printf("RELOC ");
11000                     emitDispImm((ssize_t)id->idAddr()->iiaAddr, false);
11001                 }
11002                 else if (id->idIsBound())
11003                 {
11004                     printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
11005                 }
11006                 else
11007                 {
11008                     printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
11009                 }
11010             }
11011             printf("]");
11012             break;
11013
11014         case IF_LS_2A: // LS_2A   .X.......X...... ......nnnnnttttt      Rt Rn
11015             assert(insOptsNone(id->idInsOpt()));
11016             assert(emitGetInsSC(id) == 0);
11017             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
11018             emitDispAddrRI(id->idReg2(), id->idInsOpt(), 0);
11019             break;
11020
11021         case IF_LS_2B: // LS_2B   .X.......Xiiiiii iiiiiinnnnnttttt      Rt Rn    imm(0-4095)
11022             assert(insOptsNone(id->idInsOpt()));
11023             imm   = emitGetInsSC(id);
11024             scale = NaturalScale_helper(emitInsLoadStoreSize(id));
11025             imm <<= scale; // The immediate is scaled by the size of the ld/st
11026             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
11027             emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
11028             break;
11029
11030         case IF_LS_2C: // LS_2C   .X.......X.iiiii iiiiPPnnnnnttttt      Rt Rn    imm(-256..+255) no/pre/post inc
11031             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
11032             imm = emitGetInsSC(id);
11033             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
11034             emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
11035             break;
11036
11037         case IF_LS_3A: // LS_3A   .X.......X.mmmmm oooS..nnnnnttttt      Rt Rn Rm ext(Rm) LSL {}
11038             assert(insOptsLSExtend(id->idInsOpt()));
11039             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
11040             if (id->idIsLclVar())
11041             {
11042                 emitDispAddrRRExt(id->idReg2(), codeGen->rsGetRsvdReg(), id->idInsOpt(), false, size);
11043             }
11044             else
11045             {
11046                 emitDispAddrRRExt(id->idReg2(), id->idReg3(), id->idInsOpt(), id->idReg3Scaled(), size);
11047             }
11048             break;
11049
11050         case IF_LS_3B: // LS_3B   X............... .aaaaannnnnddddd      Rt Ra Rn
11051             assert(insOptsNone(id->idInsOpt()));
11052             assert(emitGetInsSC(id) == 0);
11053             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
11054             emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
11055             emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
11056             break;
11057
11058         case IF_LS_3C: // LS_3C   X.........iiiiii iaaaaannnnnddddd      Rt Ra Rn imm(im7,sh)
11059             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
11060             imm   = emitGetInsSC(id);
11061             scale = NaturalScale_helper(emitInsLoadStoreSize(id));
11062             imm <<= scale;
11063             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
11064             emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
11065             emitDispAddrRI(id->idReg3(), id->idInsOpt(), imm);
11066             break;
11067
11068         case IF_LS_3D: // LS_3D   .X.......X.mmmmm ......nnnnnttttt      Wm Rt Rn
11069             assert(insOptsNone(id->idInsOpt()));
11070             emitDispReg(id->idReg1(), EA_4BYTE, true);
11071             emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
11072             emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
11073             break;
11074
11075         case IF_LS_3E: // LS_3E   .X.........mmmmm ......nnnnnttttt      Rm Rt Rn ARMv8.1 LSE Atomics
11076             assert(insOptsNone(id->idInsOpt()));
11077             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
11078             emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
11079             emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
11080             break;
11081
11082         case IF_DI_1A: // DI_1A   X.......shiiiiii iiiiiinnnnn.....      Rn       imm(i12,sh)
11083             emitDispReg(id->idReg1(), size, true);
11084             emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
11085             break;
11086
11087         case IF_DI_1B: // DI_1B   X........hwiiiii iiiiiiiiiiiddddd      Rd       imm(i16,hw)
11088             emitDispReg(id->idReg1(), size, true);
11089             hwi.immHWVal = (unsigned)emitGetInsSC(id);
11090             if (ins == INS_mov)
11091             {
11092                 emitDispImm(emitDecodeHalfwordImm(hwi, size), false);
11093             }
11094             else // movz, movn, movk
11095             {
11096                 emitDispImm(hwi.immVal, false);
11097                 if (hwi.immHW != 0)
11098                 {
11099                     emitDispShiftOpts(INS_OPTS_LSL);
11100                     emitDispImm(hwi.immHW * 16, false);
11101                 }
11102             }
11103             break;
11104
11105         case IF_DI_1C: // DI_1C   X........Nrrrrrr ssssssnnnnn.....         Rn    imm(N,r,s)
11106             emitDispReg(id->idReg1(), size, true);
11107             bmi.immNRS = (unsigned)emitGetInsSC(id);
11108             emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
11109             break;
11110
11111         case IF_DI_1D: // DI_1D   X........Nrrrrrr ssssss.....ddddd      Rd       imm(N,r,s)
11112             emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11113             bmi.immNRS = (unsigned)emitGetInsSC(id);
11114             emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
11115             break;
11116
11117         case IF_DI_2A: // DI_2A   X.......shiiiiii iiiiiinnnnnddddd      Rd Rn    imm(i12,sh)
11118             if ((ins == INS_add) || (ins == INS_sub))
11119             {
11120                 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11121                 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11122             }
11123             else
11124             {
11125                 emitDispReg(id->idReg1(), size, true);
11126                 emitDispReg(id->idReg2(), size, true);
11127             }
11128             emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
11129             break;
11130
11131         case IF_DI_2B: // DI_2B   X........X.nnnnn ssssssnnnnnddddd      Rd Rn    imm(0-63)
11132             emitDispReg(id->idReg1(), size, true);
11133             emitDispReg(id->idReg2(), size, true);
11134             emitDispImm(emitGetInsSC(id), false);
11135             break;
11136
11137         case IF_DI_2C: // DI_2C   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imm(N,r,s)
11138             if (ins == INS_ands)
11139             {
11140                 emitDispReg(id->idReg1(), size, true);
11141             }
11142             else
11143             {
11144                 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11145             }
11146             emitDispReg(id->idReg2(), size, true);
11147             bmi.immNRS = (unsigned)emitGetInsSC(id);
11148             emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
11149             break;
11150
11151         case IF_DI_2D: // DI_2D   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imr, ims   (N,r,s)
11152             emitDispReg(id->idReg1(), size, true);
11153             emitDispReg(id->idReg2(), size, true);
11154
11155             imm        = emitGetInsSC(id);
11156             bmi.immNRS = (unsigned)imm;
11157
11158             switch (ins)
11159             {
11160                 case INS_bfm:
11161                 case INS_sbfm:
11162                 case INS_ubfm:
11163                     emitDispImm(bmi.immR, true);
11164                     emitDispImm(bmi.immS, false);
11165                     break;
11166
11167                 case INS_bfi:
11168                 case INS_sbfiz:
11169                 case INS_ubfiz:
11170                     emitDispImm(getBitWidth(size) - bmi.immR, true);
11171                     emitDispImm(bmi.immS + 1, false);
11172                     break;
11173
11174                 case INS_bfxil:
11175                 case INS_sbfx:
11176                 case INS_ubfx:
11177                     emitDispImm(bmi.immR, true);
11178                     emitDispImm(bmi.immS - bmi.immR + 1, false);
11179                     break;
11180
11181                 case INS_asr:
11182                 case INS_lsr:
11183                 case INS_lsl:
11184                     emitDispImm(imm, false);
11185                     break;
11186
11187                 default:
11188                     assert(!"Unexpected instruction in IF_DI_2D");
11189             }
11190
11191             break;
11192
11193         case IF_DI_1F: // DI_1F   X..........iiiii cccc..nnnnn.nzcv      Rn imm5  nzcv cond
11194             emitDispReg(id->idReg1(), size, true);
11195             cfi.immCFVal = (unsigned)emitGetInsSC(id);
11196             emitDispImm(cfi.imm5, true);
11197             emitDispFlags(cfi.flags);
11198             printf(",");
11199             emitDispCond(cfi.cond);
11200             break;
11201
11202         case IF_DR_1D: // DR_1D   X............... cccc.......mmmmm      Rd       cond
11203             emitDispReg(id->idReg1(), size, true);
11204             cfi.immCFVal = (unsigned)emitGetInsSC(id);
11205             emitDispCond(cfi.cond);
11206             break;
11207
11208         case IF_DR_2A: // DR_2A   X..........mmmmm ......nnnnn.....         Rn Rm
11209             emitDispReg(id->idReg1(), size, true);
11210             emitDispReg(id->idReg2(), size, false);
11211             break;
11212
11213         case IF_DR_2B: // DR_2B   X.......sh.mmmmm ssssssnnnnn.....         Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
11214             emitDispReg(id->idReg1(), size, true);
11215             emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
11216             break;
11217
11218         case IF_DR_2C: // DR_2C   X..........mmmmm ooosssnnnnn.....         Rn Rm ext(Rm) LSL imm(0-4)
11219             emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11220             imm = emitGetInsSC(id);
11221             emitDispExtendReg(id->idReg2(), id->idInsOpt(), imm);
11222             break;
11223
11224         case IF_DR_2D: // DR_2D   X..........nnnnn cccc..nnnnnddddd      Rd Rn    cond
11225             emitDispReg(id->idReg1(), size, true);
11226             emitDispReg(id->idReg2(), size, true);
11227             cfi.immCFVal = (unsigned)emitGetInsSC(id);
11228             emitDispCond(cfi.cond);
11229             break;
11230
11231         case IF_DR_2E: // DR_2E   X..........mmmmm ...........ddddd      Rd    Rm
11232         case IF_DR_2J: // DR_2J   ................ ......nnnnnddddd      Sd    Sn
11233             emitDispReg(id->idReg1(), size, true);
11234             emitDispReg(id->idReg2(), size, false);
11235             break;
11236
11237         case IF_DR_2F: // DR_2F   X.......sh.mmmmm ssssss.....ddddd      Rd    Rm {LSL,LSR,ASR} imm(0-63)
11238             emitDispReg(id->idReg1(), size, true);
11239             emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
11240             break;
11241
11242         case IF_DR_2G: // DR_2G   X............... ......nnnnnddddd      Rd Rn
11243             emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11244             emitDispReg(encodingZRtoSP(id->idReg2()), size, false);
11245             break;
11246
11247         case IF_DR_2H: // DR_2H   X........X...... ......nnnnnddddd      Rd Rn
11248             emitDispReg(id->idReg1(), size, true);
11249             emitDispReg(id->idReg2(), size, false);
11250             break;
11251
11252         case IF_DR_2I: // DR_2I   X..........mmmmm cccc..nnnnn.nzcv      Rn Rm    nzcv cond
11253             emitDispReg(id->idReg1(), size, true);
11254             emitDispReg(id->idReg2(), size, true);
11255             cfi.immCFVal = (unsigned)emitGetInsSC(id);
11256             emitDispFlags(cfi.flags);
11257             printf(",");
11258             emitDispCond(cfi.cond);
11259             break;
11260
11261         case IF_DR_3A: // DR_3A   X..........mmmmm ......nnnnnmmmmm      Rd Rn Rm
11262             if ((ins == INS_add) || (ins == INS_sub))
11263             {
11264                 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11265                 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11266             }
11267             else if ((ins == INS_smull) || (ins == INS_smulh))
11268             {
11269                 // Rd is always 8 bytes
11270                 emitDispReg(id->idReg1(), EA_8BYTE, true);
11271
11272                 // Rn, Rm effective size depends on instruction type
11273                 size = (ins == INS_smulh) ? EA_8BYTE : EA_4BYTE;
11274                 emitDispReg(id->idReg2(), size, true);
11275             }
11276             else
11277             {
11278                 emitDispReg(id->idReg1(), size, true);
11279                 emitDispReg(id->idReg2(), size, true);
11280             }
11281             if (id->idIsLclVar())
11282             {
11283                 emitDispReg(codeGen->rsGetRsvdReg(), size, false);
11284             }
11285             else
11286             {
11287                 emitDispReg(id->idReg3(), size, false);
11288             }
11289
11290             break;
11291
11292         case IF_DR_3B: // DR_3B   X.......sh.mmmmm ssssssnnnnnddddd      Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
11293             emitDispReg(id->idReg1(), size, true);
11294             emitDispReg(id->idReg2(), size, true);
11295             emitDispShiftedReg(id->idReg3(), id->idInsOpt(), emitGetInsSC(id), size);
11296             break;
11297
11298         case IF_DR_3C: // DR_3C   X..........mmmmm ooosssnnnnnddddd      Rd Rn Rm ext(Rm) LSL imm(0-4)
11299             emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11300             emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11301             imm = emitGetInsSC(id);
11302             emitDispExtendReg(id->idReg3(), id->idInsOpt(), imm);
11303             break;
11304
11305         case IF_DR_3D: // DR_3D   X..........mmmmm cccc..nnnnnmmmmm      Rd Rn Rm cond
11306             emitDispReg(id->idReg1(), size, true);
11307             emitDispReg(id->idReg2(), size, true);
11308             emitDispReg(id->idReg3(), size, true);
11309             cfi.immCFVal = (unsigned)emitGetInsSC(id);
11310             emitDispCond(cfi.cond);
11311             break;
11312
11313         case IF_DR_3E: // DR_3E   X........X.mmmmm ssssssnnnnnddddd      Rd Rn Rm imm(0-63)
11314             emitDispReg(id->idReg1(), size, true);
11315             emitDispReg(id->idReg2(), size, true);
11316             emitDispReg(id->idReg3(), size, true);
11317             emitDispImm(emitGetInsSC(id), false);
11318             break;
11319
11320         case IF_DR_4A: // DR_4A   X..........mmmmm .aaaaannnnnmmmmm      Rd Rn Rm Ra
11321             emitDispReg(id->idReg1(), size, true);
11322             emitDispReg(id->idReg2(), size, true);
11323             emitDispReg(id->idReg3(), size, true);
11324             emitDispReg(id->idReg4(), size, false);
11325             break;
11326
11327         case IF_DV_1A: // DV_1A   .........X.iiiii iii........ddddd      Vd imm8 (fmov - immediate scalar)
11328             elemsize = id->idOpSize();
11329             emitDispReg(id->idReg1(), elemsize, true);
11330             emitDispFloatImm(emitGetInsSC(id));
11331             break;
11332
11333         case IF_DV_1B: // DV_1B   .QX..........iii cmod..iiiiiddddd      Vd imm8 (immediate vector)
11334             imm      = emitGetInsSC(id) & 0x0ff;
11335             immShift = (emitGetInsSC(id) & 0x700) >> 8;
11336             hasShift = (immShift != 0);
11337             elemsize = optGetElemsize(id->idInsOpt());
11338             if (id->idInsOpt() == INS_OPTS_1D)
11339             {
11340                 assert(elemsize == size);
11341                 emitDispReg(id->idReg1(), size, true);
11342             }
11343             else
11344             {
11345                 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11346             }
11347             if (ins == INS_fmov)
11348             {
11349                 emitDispFloatImm(imm);
11350                 assert(hasShift == false);
11351             }
11352             else
11353             {
11354                 if (elemsize == EA_8BYTE)
11355                 {
11356                     assert(ins == INS_movi);
11357                     ssize_t       imm64 = 0;
11358                     const ssize_t mask8 = 0xFF;
11359                     for (unsigned b = 0; b < 8; b++)
11360                     {
11361                         if (imm & (1 << b))
11362                         {
11363                             imm64 |= (mask8 << (b * 8));
11364                         }
11365                     }
11366                     emitDispImm(imm64, hasShift, true);
11367                 }
11368                 else
11369                 {
11370                     emitDispImm(imm, hasShift, true);
11371                 }
11372                 if (hasShift)
11373                 {
11374                     insOpts  opt   = (immShift & 0x4) ? INS_OPTS_MSL : INS_OPTS_LSL;
11375                     unsigned shift = (immShift & 0x3) * 8;
11376                     emitDispShiftOpts(opt);
11377                     emitDispImm(shift, false);
11378                 }
11379             }
11380             break;
11381
11382         case IF_DV_1C: // DV_1C   .........X...... ......nnnnn.....      Vn #0.0 (fcmp - with zero)
11383             elemsize = id->idOpSize();
11384             emitDispReg(id->idReg1(), elemsize, true);
11385             emitDispFloatZero();
11386             break;
11387
11388         case IF_DV_2A: // DV_2A   .Q.......X...... ......nnnnnddddd      Vd Vn   (fabs, fcvt - vector)
11389         case IF_DV_2M: // DV_2M   .Q......XX...... ......nnnnnddddd      Vd Vn   (abs, neg   - vector)
11390         case IF_DV_2P: // DV_2P   ................ ......nnnnnddddd      Vd Vn   (aes*, sha1su1)
11391             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11392             emitDispVectorReg(id->idReg2(), id->idInsOpt(), false);
11393             break;
11394
11395         case IF_DV_2N: // DV_2N   .........iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - scalar)
11396             elemsize = id->idOpSize();
11397             emitDispReg(id->idReg1(), elemsize, true);
11398             emitDispReg(id->idReg2(), elemsize, true);
11399             emitDispImm(emitGetInsSC(id), false);
11400             break;
11401
11402         case IF_DV_2O: // DV_2O   .Q.......iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - vector)
11403             imm = emitGetInsSC(id);
11404             // Do we have a sxtl or uxtl instruction?
11405             isExtendAlias = ((ins == INS_sxtl) || (ins == INS_sxtl2) || (ins == INS_uxtl) || (ins == INS_uxtl2));
11406             code          = emitInsCode(ins, fmt);
11407             if (code & 0x00008000) // widen/narrow opcodes
11408             {
11409                 if (code & 0x00002000) // SHL opcodes
11410                 {
11411                     emitDispVectorReg(id->idReg1(), optWidenElemsize(id->idInsOpt()), true);
11412                     emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11413                 }
11414                 else // SHR opcodes
11415                 {
11416                     emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11417                     emitDispVectorReg(id->idReg2(), optWidenElemsize(id->idInsOpt()), !isExtendAlias);
11418                 }
11419             }
11420             else
11421             {
11422                 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11423                 emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11424             }
11425             // Print the immediate unless we have a sxtl or uxtl instruction
11426             if (!isExtendAlias)
11427             {
11428                 emitDispImm(imm, false);
11429             }
11430             break;
11431
11432         case IF_DV_2B: // DV_2B   .Q.........iiiii ......nnnnnddddd      Rd Vn[] (umov/smov    - to general)
11433             srcsize = id->idOpSize();
11434             index   = emitGetInsSC(id);
11435             if (ins == INS_smov)
11436             {
11437                 dstsize = EA_8BYTE;
11438             }
11439             else // INS_umov or INS_mov
11440             {
11441                 dstsize = (srcsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE;
11442             }
11443             emitDispReg(id->idReg1(), dstsize, true);
11444             emitDispVectorRegIndex(id->idReg2(), srcsize, index, false);
11445             break;
11446
11447         case IF_DV_2C: // DV_2C   .Q.........iiiii ......nnnnnddddd      Vd Rn   (dup/ins - vector from general)
11448             if (ins == INS_dup)
11449             {
11450                 datasize = id->idOpSize();
11451                 assert(isValidVectorDatasize(datasize));
11452                 assert(isValidArrangement(datasize, id->idInsOpt()));
11453                 elemsize = optGetElemsize(id->idInsOpt());
11454                 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11455             }
11456             else // INS_ins
11457             {
11458                 elemsize = id->idOpSize();
11459                 index    = emitGetInsSC(id);
11460                 assert(isValidVectorElemsize(elemsize));
11461                 emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11462             }
11463             emitDispReg(id->idReg2(), (elemsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE, false);
11464             break;
11465
11466         case IF_DV_2D: // DV_2D   .Q.........iiiii ......nnnnnddddd      Vd Vn[]   (dup - vector)
11467             datasize = id->idOpSize();
11468             assert(isValidVectorDatasize(datasize));
11469             assert(isValidArrangement(datasize, id->idInsOpt()));
11470             elemsize = optGetElemsize(id->idInsOpt());
11471             index    = emitGetInsSC(id);
11472             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11473             emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11474             break;
11475
11476         case IF_DV_2E: // DV_2E   ...........iiiii ......nnnnnddddd      Vd Vn[]   (dup - scalar)
11477             elemsize = id->idOpSize();
11478             index    = emitGetInsSC(id);
11479             emitDispReg(id->idReg1(), elemsize, true);
11480             emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11481             break;
11482
11483         case IF_DV_2F: // DV_2F   ...........iiiii .jjjj.nnnnnddddd      Vd[] Vn[] (ins - element)
11484             imm      = emitGetInsSC(id);
11485             index    = (imm >> 4) & 0xf;
11486             index2   = imm & 0xf;
11487             elemsize = id->idOpSize();
11488             emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11489             emitDispVectorRegIndex(id->idReg2(), elemsize, index2, false);
11490             break;
11491
11492         case IF_DV_2G: // DV_2G   .........X...... ......nnnnnddddd      Vd Vn      (fmov, fcvtXX - register)
11493         case IF_DV_2K: // DV_2K   .........X.mmmmm ......nnnnn.....      Vn Vm      (fcmp)
11494         case IF_DV_2L: // DV_2L   ........XX...... ......nnnnnddddd      Vd Vn      (abs, neg - scalar)
11495             elemsize = id->idOpSize();
11496             emitDispReg(id->idReg1(), elemsize, true);
11497             emitDispReg(id->idReg2(), elemsize, false);
11498             break;
11499
11500         case IF_DV_2H: // DV_2H   X........X...... ......nnnnnddddd      Rd Vn      (fmov, fcvtXX - to general)
11501         case IF_DV_2I: // DV_2I   X........X...... ......nnnnnddddd      Vd Rn      (fmov, Xcvtf - from general)
11502         case IF_DV_2J: // DV_2J   ........SS.....D D.....nnnnnddddd      Vd Vn      (fcvt)
11503             dstsize = optGetDstsize(id->idInsOpt());
11504             srcsize = optGetSrcsize(id->idInsOpt());
11505
11506             emitDispReg(id->idReg1(), dstsize, true);
11507             emitDispReg(id->idReg2(), srcsize, false);
11508             break;
11509
11510         case IF_DV_3A: // DV_3A   .Q......XX.mmmmm ......nnnnnddddd      Vd Vn Vm  (vector)
11511         case IF_DV_3B: // DV_3B   .Q.........mmmmm ......nnnnnddddd      Vd Vn Vm  (vector)
11512             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11513             emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11514             emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11515             break;
11516
11517         case IF_DV_3C: // DV_3C   .Q.........mmmmm ......nnnnnddddd      Vd Vn Vm  (vector)
11518             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11519             if (ins != INS_mov)
11520             {
11521                 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11522             }
11523             emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11524             break;
11525
11526         case IF_DV_3AI: // DV_3AI  .Q......XXLMmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector by elem)
11527         case IF_DV_3BI: // DV_3BI  .Q........Lmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector by elem)
11528             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11529             emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11530             elemsize = optGetElemsize(id->idInsOpt());
11531             emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11532             break;
11533
11534         case IF_DV_3D: // DV_3D   .........X.mmmmm ......nnnnnddddd      Vd Vn Vm  (scalar)
11535         case IF_DV_3E: // DV_3E   ...........mmmmm ......nnnnnddddd      Vd Vn Vm  (scalar)
11536             emitDispReg(id->idReg1(), size, true);
11537             emitDispReg(id->idReg2(), size, true);
11538             emitDispReg(id->idReg3(), size, false);
11539             break;
11540
11541         case IF_DV_3F: // DV_3F   ..........mmmmm ......nnnnnddddd       Vd Vn Vm (vector)
11542             if ((ins == INS_sha1c) || (ins == INS_sha1m) || (ins == INS_sha1p))
11543             {
11544                 // Qd, Sn, Vm (vector)
11545                 emitDispReg(id->idReg1(), size, true);
11546                 emitDispReg(id->idReg2(), EA_4BYTE, true);
11547                 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11548             }
11549             else if ((ins == INS_sha256h) || (ins == INS_sha256h2))
11550             {
11551                 // Qd Qn Vm (vector)
11552                 emitDispReg(id->idReg1(), size, true);
11553                 emitDispReg(id->idReg2(), size, true);
11554                 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11555             }
11556             else // INS_sha1su0, INS_sha256su1
11557             {
11558                 // Vd, Vn, Vm   (vector)
11559                 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11560                 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11561                 emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11562             }
11563             break;
11564
11565         case IF_DV_3DI: // DV_3DI  .........XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (scalar by elem)
11566             emitDispReg(id->idReg1(), size, true);
11567             emitDispReg(id->idReg2(), size, true);
11568             elemsize = size;
11569             emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11570             break;
11571
11572         case IF_DV_4A: // DV_4A   .........X.mmmmm .aaaaannnnnddddd      Vd Va Vn Vm (scalar)
11573             emitDispReg(id->idReg1(), size, true);
11574             emitDispReg(id->idReg2(), size, true);
11575             emitDispReg(id->idReg3(), size, true);
11576             emitDispReg(id->idReg4(), size, false);
11577             break;
11578
11579         case IF_SN_0A: // SN_0A   ................ ................
11580             break;
11581
11582         case IF_SI_0A: // SI_0A   ...........iiiii iiiiiiiiiii.....               imm16
11583             emitDispImm(emitGetInsSC(id), false);
11584             break;
11585
11586         case IF_SI_0B: // SI_0B   ................ ....bbbb........               imm4 - barrier
11587             emitDispBarrier((insBarrier)emitGetInsSC(id));
11588             break;
11589
11590         default:
11591             printf("unexpected format %s", emitIfName(id->idInsFmt()));
11592             assert(!"unexpectedFormat");
11593             break;
11594     }
11595
11596     if (id->idDebugOnlyInfo()->idVarRefOffs)
11597     {
11598         printf("\t// ");
11599         emitDispFrameRef(id->idAddr()->iiaLclVar.lvaVarNum(), id->idAddr()->iiaLclVar.lvaOffset(),
11600                          id->idDebugOnlyInfo()->idVarRefOffs, asmfm);
11601     }
11602
11603     printf("\n");
11604 }
11605
11606 /*****************************************************************************
11607  *
11608  *  Display a stack frame reference.
11609  */
11610
11611 void emitter::emitDispFrameRef(int varx, int disp, int offs, bool asmfm)
11612 {
11613     printf("[");
11614
11615     if (varx < 0)
11616         printf("TEMP_%02u", -varx);
11617     else
11618         emitComp->gtDispLclVar(+varx, false);
11619
11620     if (disp < 0)
11621         printf("-0x%02x", -disp);
11622     else if (disp > 0)
11623         printf("+0x%02x", +disp);
11624
11625     printf("]");
11626
11627     if (varx >= 0 && emitComp->opts.varNames)
11628     {
11629         LclVarDsc*  varDsc;
11630         const char* varName;
11631
11632         assert((unsigned)varx < emitComp->lvaCount);
11633         varDsc  = emitComp->lvaTable + varx;
11634         varName = emitComp->compLocalVarName(varx, offs);
11635
11636         if (varName)
11637         {
11638             printf("'%s", varName);
11639
11640             if (disp < 0)
11641                 printf("-%d", -disp);
11642             else if (disp > 0)
11643                 printf("+%d", +disp);
11644
11645             printf("'");
11646         }
11647     }
11648 }
11649
11650 #endif // DEBUG
11651
11652 // Generate code for a load or store operation with a potentially complex addressing mode
11653 // This method handles the case of a GT_IND with contained GT_LEA op1 of the x86 form [base + index*sccale + offset]
11654 // Since Arm64 does not directly support this complex of an addressing mode
11655 // we may generates up to three instructions for this for Arm64
11656 //
11657 void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataReg, GenTreeIndir* indir)
11658 {
11659     emitAttr ldstAttr = isVectorRegister(dataReg) ? attr : emitInsAdjustLoadStoreAttr(ins, attr);
11660
11661     GenTree* addr = indir->Addr();
11662
11663     if (addr->isContained())
11664     {
11665         assert(addr->OperGet() == GT_LCL_VAR_ADDR || addr->OperGet() == GT_LEA);
11666
11667         int   offset = 0;
11668         DWORD lsl    = 0;
11669
11670         if (addr->OperGet() == GT_LEA)
11671         {
11672             offset = addr->AsAddrMode()->Offset();
11673             if (addr->AsAddrMode()->gtScale > 0)
11674             {
11675                 assert(isPow2(addr->AsAddrMode()->gtScale));
11676                 BitScanForward(&lsl, addr->AsAddrMode()->gtScale);
11677             }
11678         }
11679
11680         GenTree* memBase = indir->Base();
11681
11682         if (indir->HasIndex())
11683         {
11684             GenTree* index = indir->Index();
11685
11686             if (offset != 0)
11687             {
11688                 regNumber tmpReg = indir->GetSingleTempReg();
11689
11690                 emitAttr addType = varTypeIsGC(memBase) ? EA_BYREF : EA_PTRSIZE;
11691
11692                 if (emitIns_valid_imm_for_add(offset, EA_8BYTE))
11693                 {
11694                     if (lsl > 0)
11695                     {
11696                         // Generate code to set tmpReg = base + index*scale
11697                         emitIns_R_R_R_I(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum, lsl,
11698                                         INS_OPTS_LSL);
11699                     }
11700                     else // no scale
11701                     {
11702                         // Generate code to set tmpReg = base + index
11703                         emitIns_R_R_R(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum);
11704                     }
11705
11706                     noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11707
11708                     // Then load/store dataReg from/to [tmpReg + offset]
11709                     emitIns_R_R_I(ins, ldstAttr, dataReg, tmpReg, offset);
11710                 }
11711                 else // large offset
11712                 {
11713                     // First load/store tmpReg with the large offset constant
11714                     codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11715                     // Then add the base register
11716                     //      rd = rd + base
11717                     emitIns_R_R_R(INS_add, addType, tmpReg, tmpReg, memBase->gtRegNum);
11718
11719                     noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11720                     noway_assert(tmpReg != index->gtRegNum);
11721
11722                     // Then load/store dataReg from/to [tmpReg + index*scale]
11723                     emitIns_R_R_R_I(ins, ldstAttr, dataReg, tmpReg, index->gtRegNum, lsl, INS_OPTS_LSL);
11724                 }
11725             }
11726             else // (offset == 0)
11727             {
11728                 if (lsl > 0)
11729                 {
11730                     // Then load/store dataReg from/to [memBase + index*scale]
11731                     emitIns_R_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum, lsl, INS_OPTS_LSL);
11732                 }
11733                 else // no scale
11734                 {
11735                     // Then load/store dataReg from/to [memBase + index]
11736                     emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum);
11737                 }
11738             }
11739         }
11740         else // no Index register
11741         {
11742             if (emitIns_valid_imm_for_ldst_offset(offset, EA_SIZE(attr)))
11743             {
11744                 // Then load/store dataReg from/to [memBase + offset]
11745                 emitIns_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, offset);
11746             }
11747             else
11748             {
11749                 // We require a tmpReg to hold the offset
11750                 regNumber tmpReg = indir->GetSingleTempReg();
11751
11752                 // First load/store tmpReg with the large offset constant
11753                 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11754
11755                 // Then load/store dataReg from/to [memBase + tmpReg]
11756                 emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, tmpReg);
11757             }
11758         }
11759     }
11760     else // addr is not contained, so we evaluate it into a register
11761     {
11762         // Then load/store dataReg from/to [addrReg]
11763         emitIns_R_R(ins, ldstAttr, dataReg, addr->gtRegNum);
11764     }
11765 }
11766
11767 // The callee must call genConsumeReg() for any non-contained srcs
11768 // and genProduceReg() for any non-contained dsts.
11769
11770 regNumber emitter::emitInsBinary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src)
11771 {
11772     regNumber result = REG_NA;
11773
11774     // dst can only be a reg
11775     assert(!dst->isContained());
11776
11777     // src can be immed or reg
11778     assert(!src->isContained() || src->isContainedIntOrIImmed());
11779
11780     // find immed (if any) - it cannot be a dst
11781     GenTreeIntConCommon* intConst = nullptr;
11782     if (src->isContainedIntOrIImmed())
11783     {
11784         intConst = src->AsIntConCommon();
11785     }
11786
11787     if (intConst)
11788     {
11789         emitIns_R_I(ins, attr, dst->gtRegNum, intConst->IconValue());
11790         return dst->gtRegNum;
11791     }
11792     else
11793     {
11794         emitIns_R_R(ins, attr, dst->gtRegNum, src->gtRegNum);
11795         return dst->gtRegNum;
11796     }
11797 }
11798
11799 // The callee must call genConsumeReg() for any non-contained srcs
11800 // and genProduceReg() for any non-contained dsts.
11801
11802 regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src1, GenTree* src2)
11803 {
11804     regNumber result = REG_NA;
11805
11806     // dst can only be a reg
11807     assert(!dst->isContained());
11808
11809     // find immed (if any) - it cannot be a dst
11810     // Only one src can be an int.
11811     GenTreeIntConCommon* intConst  = nullptr;
11812     GenTree*             nonIntReg = nullptr;
11813
11814     if (varTypeIsFloating(dst))
11815     {
11816         // src1 can only be a reg
11817         assert(!src1->isContained());
11818         // src2 can only be a reg
11819         assert(!src2->isContained());
11820     }
11821     else // not floating point
11822     {
11823         // src2 can be immed or reg
11824         assert(!src2->isContained() || src2->isContainedIntOrIImmed());
11825
11826         // Check src2 first as we can always allow it to be a contained immediate
11827         if (src2->isContainedIntOrIImmed())
11828         {
11829             intConst  = src2->AsIntConCommon();
11830             nonIntReg = src1;
11831         }
11832         // Only for commutative operations do we check src1 and allow it to be a contained immediate
11833         else if (dst->OperIsCommutative())
11834         {
11835             // src1 can be immed or reg
11836             assert(!src1->isContained() || src1->isContainedIntOrIImmed());
11837
11838             // Check src1 and allow it to be a contained immediate
11839             if (src1->isContainedIntOrIImmed())
11840             {
11841                 assert(!src2->isContainedIntOrIImmed());
11842                 intConst  = src1->AsIntConCommon();
11843                 nonIntReg = src2;
11844             }
11845         }
11846         else
11847         {
11848             // src1 can only be a reg
11849             assert(!src1->isContained());
11850         }
11851     }
11852
11853     bool isMulOverflow = false;
11854     if (dst->gtOverflowEx())
11855     {
11856         if ((ins == INS_add) || (ins == INS_adds))
11857         {
11858             ins = INS_adds;
11859         }
11860         else if ((ins == INS_sub) || (ins == INS_subs))
11861         {
11862             ins = INS_subs;
11863         }
11864         else if (ins == INS_mul)
11865         {
11866             isMulOverflow = true;
11867             assert(intConst == nullptr); // overflow format doesn't support an int constant operand
11868         }
11869         else
11870         {
11871             assert(!"Invalid ins for overflow check");
11872         }
11873     }
11874     if (intConst != nullptr)
11875     {
11876         emitIns_R_R_I(ins, attr, dst->gtRegNum, nonIntReg->gtRegNum, intConst->IconValue());
11877     }
11878     else
11879     {
11880         if (isMulOverflow)
11881         {
11882             regNumber extraReg = dst->GetSingleTempReg();
11883             assert(extraReg != dst->gtRegNum);
11884
11885             if ((dst->gtFlags & GTF_UNSIGNED) != 0)
11886             {
11887                 if (attr == EA_4BYTE)
11888                 {
11889                     // Compute 8 byte results from 4 byte by 4 byte multiplication.
11890                     emitIns_R_R_R(INS_umull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11891
11892                     // Get the high result by shifting dst.
11893                     emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11894                 }
11895                 else
11896                 {
11897                     assert(attr == EA_8BYTE);
11898                     // Compute the high result.
11899                     emitIns_R_R_R(INS_umulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11900
11901                     // Now multiply without skewing the high result.
11902                     emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11903                 }
11904
11905                 // zero-sign bit comparison to detect overflow.
11906                 emitIns_R_I(INS_cmp, attr, extraReg, 0);
11907             }
11908             else
11909             {
11910                 int bitShift = 0;
11911                 if (attr == EA_4BYTE)
11912                 {
11913                     // Compute 8 byte results from 4 byte by 4 byte multiplication.
11914                     emitIns_R_R_R(INS_smull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11915
11916                     // Get the high result by shifting dst.
11917                     emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11918
11919                     bitShift = 31;
11920                 }
11921                 else
11922                 {
11923                     assert(attr == EA_8BYTE);
11924                     // Save the high result in a temporary register.
11925                     emitIns_R_R_R(INS_smulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11926
11927                     // Now multiply without skewing the high result.
11928                     emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11929
11930                     bitShift = 63;
11931                 }
11932
11933                 // Sign bit comparison to detect overflow.
11934                 emitIns_R_R_I(INS_cmp, attr, extraReg, dst->gtRegNum, bitShift, INS_OPTS_ASR);
11935             }
11936         }
11937         else
11938         {
11939             // We can just multiply.
11940             emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11941         }
11942     }
11943
11944     if (dst->gtOverflowEx())
11945     {
11946         assert(!varTypeIsFloating(dst));
11947         codeGen->genCheckOverflow(dst);
11948     }
11949
11950     return dst->gtRegNum;
11951 }
11952
11953 #endif // defined(_TARGET_ARM64_)