[Arm64] genSIMDIntrinsicNarrow/Widen
[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_DI_1A: // DI_1A   X.......shiiiiii iiiiiinnnnn.....         Rn    imm(i12,sh)
282             assert(isValidGeneralDatasize(id->idOpSize()));
283             assert(isGeneralRegister(id->idReg1()));
284             assert(isValidUimm12(emitGetInsSC(id)));
285             assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
286             break;
287
288         case IF_DI_1B: // DI_1B   X........hwiiiii iiiiiiiiiiiddddd      Rd       imm(i16,hw)
289             assert(isValidGeneralDatasize(id->idOpSize()));
290             assert(isGeneralRegister(id->idReg1()));
291             assert(isValidImmHWVal(emitGetInsSC(id), id->idOpSize()));
292             break;
293
294         case IF_DI_1C: // DI_1C   X........Nrrrrrr ssssssnnnnn.....         Rn    imm(N,r,s)
295             assert(isValidGeneralDatasize(id->idOpSize()));
296             assert(isGeneralRegister(id->idReg1()));
297             assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
298             break;
299
300         case IF_DI_1D: // DI_1D   X........Nrrrrrr ssssss.....ddddd      Rd       imm(N,r,s)
301             assert(isValidGeneralDatasize(id->idOpSize()));
302             assert(isIntegerRegister(id->idReg1())); // SP
303             assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
304             break;
305
306         case IF_DI_1E: // DI_1E   .ii.....iiiiiiii iiiiiiiiiiiddddd      Rd       simm21
307             assert(isGeneralRegister(id->idReg1()));
308             break;
309
310         case IF_DI_1F: // DI_1F   X..........iiiii cccc..nnnnn.nzcv      Rn imm5  nzcv cond
311             assert(isValidGeneralDatasize(id->idOpSize()));
312             assert(isGeneralRegister(id->idReg1()));
313             assert(isValidImmCondFlagsImm5(emitGetInsSC(id)));
314             break;
315
316         case IF_DI_2A: // DI_2A   X.......shiiiiii iiiiiinnnnnddddd      Rd Rn    imm(i12,sh)
317             assert(isValidGeneralDatasize(id->idOpSize()));
318             assert(isIntegerRegister(id->idReg1())); // SP
319             assert(isIntegerRegister(id->idReg2())); // SP
320             assert(isValidUimm12(emitGetInsSC(id)));
321             assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
322             break;
323
324         case IF_DI_2B: // DI_2B   X.........Xnnnnn ssssssnnnnnddddd      Rd Rn    imm(0-63)
325             assert(isValidGeneralDatasize(id->idOpSize()));
326             assert(isGeneralRegister(id->idReg1()));
327             assert(isGeneralRegister(id->idReg2()));
328             assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
329             break;
330
331         case IF_DI_2C: // DI_2C   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imm(N,r,s)
332             assert(isValidGeneralDatasize(id->idOpSize()));
333             assert(isIntegerRegister(id->idReg1())); // SP
334             assert(isGeneralRegister(id->idReg2()));
335             assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
336             break;
337
338         case IF_DI_2D: // DI_2D   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imr, imms   (N,r,s)
339             assert(isValidGeneralDatasize(id->idOpSize()));
340             assert(isGeneralRegister(id->idReg1()));
341             assert(isGeneralRegister(id->idReg2()));
342             assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
343             break;
344
345         case IF_DR_1D: // DR_1D   X............... cccc.......ddddd      Rd       cond
346             assert(isValidGeneralDatasize(id->idOpSize()));
347             assert(isGeneralRegister(id->idReg1()));
348             assert(isValidImmCond(emitGetInsSC(id)));
349             break;
350
351         case IF_DR_2A: // DR_2A   X..........mmmmm ......nnnnn.....         Rn Rm
352             assert(isValidGeneralDatasize(id->idOpSize()));
353             assert(isGeneralRegister(id->idReg1()));
354             assert(isGeneralRegister(id->idReg2()));
355             break;
356
357         case IF_DR_2B: // DR_2B   X.......sh.mmmmm ssssssnnnnn.....         Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
358             assert(isValidGeneralDatasize(id->idOpSize()));
359             assert(isIntegerRegister(id->idReg1())); // ZR
360             assert(isGeneralRegister(id->idReg2()));
361             assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
362             if (!insOptsNone(id->idInsOpt()))
363             {
364                 if (id->idIns() == INS_tst) // tst allows ROR, cmp/cmn don't
365                 {
366                     assert(insOptsAnyShift(id->idInsOpt()));
367                 }
368                 else
369                 {
370                     assert(insOptsAluShift(id->idInsOpt()));
371                 }
372             }
373             assert(insOptsNone(id->idInsOpt()) || (emitGetInsSC(id) > 0));
374             break;
375
376         case IF_DR_2C: // DR_2C   X..........mmmmm ooosssnnnnn.....         Rn Rm ext(Rm) LSL imm(0-4)
377             assert(isValidGeneralDatasize(id->idOpSize()));
378             assert(isIntegerRegister(id->idReg1())); // SP
379             assert(isGeneralRegister(id->idReg2()));
380             assert(insOptsNone(id->idInsOpt()) || insOptsLSL(id->idInsOpt()) || insOptsAnyExtend(id->idInsOpt()));
381             assert(emitGetInsSC(id) >= 0);
382             assert(emitGetInsSC(id) <= 4);
383             if (insOptsLSL(id->idInsOpt()))
384             {
385                 assert(emitGetInsSC(id) > 0);
386             }
387             break;
388
389         case IF_DR_2D: // DR_2D   X..........nnnnn cccc..nnnnnmmmmm      Rd Rn    cond
390             assert(isValidGeneralDatasize(id->idOpSize()));
391             assert(isGeneralRegister(id->idReg1()));
392             assert(isGeneralRegister(id->idReg2()));
393             assert(isValidImmCond(emitGetInsSC(id)));
394             break;
395
396         case IF_DR_2E: // DR_2E   X..........mmmmm ...........ddddd      Rd    Rm
397             assert(isValidGeneralDatasize(id->idOpSize()));
398             assert(isGeneralRegister(id->idReg1()));
399             assert(isIntegerRegister(id->idReg2())); // ZR
400             break;
401
402         case IF_DR_2F: // DR_2F   X.......sh.mmmmm ssssss.....ddddd      Rd    Rm {LSL,LSR,ASR} imm(0-63)
403             assert(isValidGeneralDatasize(id->idOpSize()));
404             assert(isGeneralRegister(id->idReg1()));
405             assert(isGeneralRegister(id->idReg2()));
406             assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
407             assert(insOptsNone(id->idInsOpt()) || insOptsAluShift(id->idInsOpt()));
408             assert(insOptsNone(id->idInsOpt()) || (emitGetInsSC(id) > 0));
409             break;
410
411         case IF_DR_2G: // DR_2G   X............... ......nnnnnddddd      Rd    Rm
412             assert(isValidGeneralDatasize(id->idOpSize()));
413             assert(isIntegerRegister(id->idReg1())); // SP
414             assert(isIntegerRegister(id->idReg2())); // SP
415             break;
416
417         case IF_DR_2H: // DR_2H   X........X...... ......nnnnnddddd      Rd Rn
418             assert(isValidGeneralDatasize(id->idOpSize()));
419             assert(isGeneralRegister(id->idReg1()));
420             assert(isGeneralRegister(id->idReg2()));
421             break;
422
423         case IF_DR_2I: // DR_2I   X..........mmmmm cccc..nnnnn.nzcv      Rn Rm    nzcv cond
424             assert(isValidGeneralDatasize(id->idOpSize()));
425             assert(isGeneralRegister(id->idReg1()));
426             assert(isGeneralRegister(id->idReg2()));
427             assert(isValidImmCondFlags(emitGetInsSC(id)));
428             break;
429
430         case IF_DR_3A: // DR_3A   X..........mmmmm ......nnnnnmmmmm      Rd Rn Rm
431             assert(isValidGeneralDatasize(id->idOpSize()));
432             assert(isIntegerRegister(id->idReg1())); // SP
433             assert(isIntegerRegister(id->idReg2())); // SP
434             if (id->idIsLclVar())
435             {
436                 assert(isGeneralRegister(codeGen->rsGetRsvdReg()));
437             }
438             else
439             {
440                 assert(isGeneralRegister(id->idReg3()));
441             }
442             assert(insOptsNone(id->idInsOpt()));
443             break;
444
445         case IF_DR_3B: // DR_3B   X.......sh.mmmmm ssssssnnnnnddddd      Rd Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
446             assert(isValidGeneralDatasize(id->idOpSize()));
447             assert(isGeneralRegister(id->idReg1()));
448             assert(isGeneralRegister(id->idReg2()));
449             assert(isGeneralRegister(id->idReg3()));
450             assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
451             assert(insOptsNone(id->idInsOpt()) || insOptsAnyShift(id->idInsOpt()));
452             assert(insOptsNone(id->idInsOpt()) || (emitGetInsSC(id) > 0));
453             break;
454
455         case IF_DR_3C: // DR_3C   X..........mmmmm ooosssnnnnnddddd      Rd Rn Rm ext(Rm) LSL imm(0-4)
456             assert(isValidGeneralDatasize(id->idOpSize()));
457             assert(isIntegerRegister(id->idReg1())); // SP
458             assert(isIntegerRegister(id->idReg2())); // SP
459             assert(isGeneralRegister(id->idReg3()));
460             assert(insOptsNone(id->idInsOpt()) || insOptsLSL(id->idInsOpt()) || insOptsAnyExtend(id->idInsOpt()));
461             assert(emitGetInsSC(id) >= 0);
462             assert(emitGetInsSC(id) <= 4);
463             if (insOptsLSL(id->idInsOpt()))
464             {
465                 assert((emitGetInsSC(id) > 0) ||
466                        (id->idReg2() == REG_ZR)); // REG_ZR encodes SP and we allow a shift of zero
467             }
468             break;
469
470         case IF_DR_3D: // DR_3D   X..........mmmmm cccc..nnnnnmmmmm      Rd Rn Rm cond
471             assert(isValidGeneralDatasize(id->idOpSize()));
472             assert(isGeneralRegister(id->idReg1()));
473             assert(isGeneralRegister(id->idReg2()));
474             assert(isGeneralRegister(id->idReg3()));
475             assert(isValidImmCond(emitGetInsSC(id)));
476             break;
477
478         case IF_DR_3E: // DR_3E   X........X.mmmmm ssssssnnnnnddddd      Rd Rn Rm imm(0-63)
479             assert(isValidGeneralDatasize(id->idOpSize()));
480             assert(isGeneralRegister(id->idReg1()));
481             assert(isGeneralRegister(id->idReg2()));
482             assert(isGeneralRegister(id->idReg3()));
483             assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
484             assert(insOptsNone(id->idInsOpt()));
485             break;
486
487         case IF_DR_4A: // DR_4A   X..........mmmmm .aaaaannnnnddddd      Rd Rn Rm Ra
488             assert(isValidGeneralDatasize(id->idOpSize()));
489             assert(isGeneralRegister(id->idReg1()));
490             assert(isGeneralRegister(id->idReg2()));
491             assert(isGeneralRegister(id->idReg3()));
492             assert(isGeneralRegister(id->idReg4()));
493             break;
494
495         case IF_DV_1A: // DV_1A   .........X.iiiii iii........ddddd      Vd imm8    (fmov - immediate scalar)
496             assert(insOptsNone(id->idInsOpt()));
497             elemsize = id->idOpSize();
498             assert(isValidVectorElemsizeFloat(elemsize));
499             assert(isVectorRegister(id->idReg1()));
500             assert(isValidUimm8(emitGetInsSC(id)));
501             break;
502
503         case IF_DV_1B: // DV_1B   .QX..........iii cmod..iiiiiddddd      Vd imm8    (immediate vector)
504             ins      = id->idIns();
505             imm      = emitGetInsSC(id) & 0x0ff;
506             immShift = (emitGetInsSC(id) & 0x700) >> 8;
507             assert(immShift >= 0);
508             datasize = id->idOpSize();
509             assert(isValidVectorDatasize(datasize));
510             assert(isValidArrangement(datasize, id->idInsOpt()));
511             elemsize = optGetElemsize(id->idInsOpt());
512             if (ins == INS_fmov)
513             {
514                 assert(isValidVectorElemsizeFloat(elemsize));
515                 assert(id->idInsOpt() != INS_OPTS_1D); // Reserved encoding
516                 assert(immShift == 0);
517             }
518             else
519             {
520                 assert(isValidVectorElemsize(elemsize));
521                 assert((immShift != 4) && (immShift != 7)); // always invalid values
522                 if (ins != INS_movi)                        // INS_mvni, INS_orr, INS_bic
523                 {
524                     assert((elemsize != EA_1BYTE) && (elemsize != EA_8BYTE)); // only H or S
525                     if (elemsize == EA_2BYTE)
526                     {
527                         assert(immShift < 2);
528                     }
529                     else // (elemsize == EA_4BYTE)
530                     {
531                         if (ins != INS_mvni)
532                         {
533                             assert(immShift < 4);
534                         }
535                     }
536                 }
537             }
538             assert(isVectorRegister(id->idReg1()));
539             assert(isValidUimm8(imm));
540             break;
541
542         case IF_DV_1C: // DV_1C   .........X...... ......nnnnn.....      Vn #0.0    (fcmp - with zero)
543             assert(insOptsNone(id->idInsOpt()));
544             elemsize = id->idOpSize();
545             assert(isValidVectorElemsizeFloat(elemsize));
546             assert(isVectorRegister(id->idReg1()));
547             break;
548
549         case IF_DV_2A: // DV_2A   .Q.......X...... ......nnnnnddddd      Vd Vn      (fabs, fcvt - vector)
550         case IF_DV_2M: // DV_2M   .Q......XX...... ......nnnnnddddd      Vd Vn      (abs, neg   - vector)
551             assert(isValidVectorDatasize(id->idOpSize()));
552             assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
553             assert(isVectorRegister(id->idReg1()));
554             assert(isVectorRegister(id->idReg2()));
555             break;
556
557         case IF_DV_2N: // DV_2N   .........iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - scalar)
558             assert(id->idOpSize() == EA_8BYTE);
559             assert(insOptsNone(id->idInsOpt()));
560             assert(isVectorRegister(id->idReg1()));
561             assert(isVectorRegister(id->idReg2()));
562             assert(isValidImmShift(emitGetInsSC(id), EA_8BYTE));
563             break;
564
565         case IF_DV_2O: // DV_2O   .Q.......iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - vector)
566             assert(isValidVectorDatasize(id->idOpSize()));
567             assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
568             assert(isVectorRegister(id->idReg1()));
569             assert(isVectorRegister(id->idReg2()));
570             elemsize = optGetElemsize(id->idInsOpt());
571             assert(isValidImmShift(emitGetInsSC(id), elemsize));
572             break;
573
574         case IF_DV_2B: // DV_2B   .Q.........iiiii ......nnnnnddddd      Rd Vn[]  (umov/smov    - to general)
575             elemsize = id->idOpSize();
576             index    = emitGetInsSC(id);
577             assert(insOptsNone(id->idInsOpt()));
578             assert(isValidVectorIndex(EA_16BYTE, elemsize, index));
579             assert(isValidVectorElemsize(elemsize));
580             assert(isGeneralRegister(id->idReg1()));
581             assert(isVectorRegister(id->idReg2()));
582             break;
583
584         case IF_DV_2C: // DV_2C   .Q.........iiiii ......nnnnnddddd      Vd Rn    (dup/ins - vector from general)
585             if (id->idIns() == INS_dup)
586             {
587                 datasize = id->idOpSize();
588                 assert(isValidVectorDatasize(datasize));
589                 assert(isValidArrangement(datasize, id->idInsOpt()));
590                 elemsize = optGetElemsize(id->idInsOpt());
591             }
592             else // INS_ins
593             {
594                 datasize = EA_16BYTE;
595                 elemsize = id->idOpSize();
596                 assert(isValidVectorElemsize(elemsize));
597             }
598             assert(isVectorRegister(id->idReg1()));
599             assert(isGeneralRegisterOrZR(id->idReg2()));
600             break;
601
602         case IF_DV_2D: // DV_2D   .Q.........iiiii ......nnnnnddddd      Vd Vn[]  (dup - vector)
603             datasize = id->idOpSize();
604             assert(isValidVectorDatasize(datasize));
605             assert(isValidArrangement(datasize, id->idInsOpt()));
606             elemsize = optGetElemsize(id->idInsOpt());
607             index    = emitGetInsSC(id);
608             assert(isValidVectorIndex(datasize, elemsize, index));
609             assert(isVectorRegister(id->idReg1()));
610             assert(isVectorRegister(id->idReg2()));
611             break;
612
613         case IF_DV_2E: // DV_2E   ...........iiiii ......nnnnnddddd      Vd Vn[]  (dup - scalar)
614             elemsize = id->idOpSize();
615             index    = emitGetInsSC(id);
616             assert(isValidVectorIndex(EA_16BYTE, elemsize, index));
617             assert(isValidVectorElemsize(elemsize));
618             assert(isVectorRegister(id->idReg1()));
619             assert(isVectorRegister(id->idReg2()));
620             break;
621
622         case IF_DV_2F: // DV_2F   ...........iiiii .jjjj.nnnnnddddd      Vd[] Vn[] (ins - element)
623             imm      = emitGetInsSC(id);
624             index    = (imm >> 4) & 0xf;
625             index2   = imm & 0xf;
626             elemsize = id->idOpSize();
627             assert(isValidVectorElemsize(elemsize));
628             assert(isValidVectorIndex(EA_16BYTE, elemsize, index));
629             assert(isValidVectorIndex(EA_16BYTE, elemsize, index2));
630             assert(isVectorRegister(id->idReg1()));
631             assert(isVectorRegister(id->idReg2()));
632             break;
633
634         case IF_DV_2L: // DV_2L   ........XX...... ......nnnnnddddd      Vd Vn      (abs, neg - scalar)
635             assert(id->idOpSize() == EA_8BYTE); // only type D is supported
636             __fallthrough;
637
638         case IF_DV_2G: // DV_2G   .........X...... ......nnnnnddddd      Vd Vn      (fmov, fcvtXX - register)
639         case IF_DV_2K: // DV_2K   .........X.mmmmm ......nnnnn.....      Vn Vm      (fcmp)
640             assert(insOptsNone(id->idInsOpt()));
641             assert(isValidVectorElemsizeFloat(id->idOpSize()));
642             assert(isVectorRegister(id->idReg1()));
643             assert(isVectorRegister(id->idReg2()));
644             break;
645
646         case IF_DV_2H: // DV_2H   X........X...... ......nnnnnddddd      Rd Vn      (fmov/fcvtXX - to general)
647             assert(insOptsConvertFloatToInt(id->idInsOpt()));
648             dstsize = optGetDstsize(id->idInsOpt());
649             srcsize = optGetSrcsize(id->idInsOpt());
650             assert(isValidGeneralDatasize(dstsize));
651             assert(isValidVectorElemsizeFloat(srcsize));
652             assert(dstsize == id->idOpSize());
653             assert(isGeneralRegister(id->idReg1()));
654             assert(isVectorRegister(id->idReg2()));
655             break;
656
657         case IF_DV_2I: // DV_2I   X........X...... ......nnnnnddddd      Vd Rn      (fmov/Xcvtf - from general)
658             assert(insOptsConvertIntToFloat(id->idInsOpt()));
659             dstsize = optGetDstsize(id->idInsOpt());
660             srcsize = optGetSrcsize(id->idInsOpt());
661             assert(isValidGeneralDatasize(srcsize));
662             assert(isValidVectorElemsizeFloat(dstsize));
663             assert(dstsize == id->idOpSize());
664             assert(isVectorRegister(id->idReg1()));
665             assert(isGeneralRegister(id->idReg2()));
666             break;
667
668         case IF_DV_2J: // DV_2J   ........SS.....D D.....nnnnnddddd      Vd Vn      (fcvt)
669             assert(insOptsConvertFloatToFloat(id->idInsOpt()));
670             dstsize = optGetDstsize(id->idInsOpt());
671             srcsize = optGetSrcsize(id->idInsOpt());
672             assert(isValidVectorFcvtsize(srcsize));
673             assert(isValidVectorFcvtsize(dstsize));
674             assert(dstsize == id->idOpSize());
675             assert(isVectorRegister(id->idReg1()));
676             assert(isVectorRegister(id->idReg2()));
677             break;
678
679         case IF_DV_3A: // DV_3A   .Q......XX.mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
680             assert(isValidVectorDatasize(id->idOpSize()));
681             assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
682             assert(isVectorRegister(id->idReg1()));
683             assert(isVectorRegister(id->idReg2()));
684             assert(isVectorRegister(id->idReg3()));
685             elemsize = optGetElemsize(id->idInsOpt());
686             ins      = id->idIns();
687             if (ins == INS_mul)
688             {
689                 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
690             }
691             else if (ins == INS_pmul)
692             {
693                 assert(elemsize == EA_1BYTE); // only supports 8B or 16B
694             }
695             break;
696
697         case IF_DV_3AI: // DV_3AI  .Q......XXLMmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector by elem)
698             assert(isValidVectorDatasize(id->idOpSize()));
699             assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
700             assert(isVectorRegister(id->idReg1()));
701             assert(isVectorRegister(id->idReg2()));
702             assert(isVectorRegister(id->idReg3()));
703             elemsize = optGetElemsize(id->idInsOpt());
704             assert(isValidVectorIndex(EA_16BYTE, elemsize, emitGetInsSC(id)));
705             // Only has encodings for H or S elemsize
706             assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE));
707             break;
708
709         case IF_DV_3B: // DV_3B   .Q.......X.mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
710             assert(isValidVectorDatasize(id->idOpSize()));
711             assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
712             assert(isVectorRegister(id->idReg1()));
713             assert(isVectorRegister(id->idReg2()));
714             assert(isVectorRegister(id->idReg3()));
715             break;
716
717         case IF_DV_3BI: // DV_3BI  .Q.......XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector by elem)
718             assert(isValidVectorDatasize(id->idOpSize()));
719             assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
720             assert(isVectorRegister(id->idReg1()));
721             assert(isVectorRegister(id->idReg2()));
722             assert(isVectorRegister(id->idReg3()));
723             elemsize = optGetElemsize(id->idInsOpt());
724             assert(isValidVectorIndex(id->idOpSize(), elemsize, emitGetInsSC(id)));
725             break;
726
727         case IF_DV_3C: // DV_3C   .Q.........mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
728             assert(isValidVectorDatasize(id->idOpSize()));
729             assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
730             assert(isVectorRegister(id->idReg1()));
731             assert(isVectorRegister(id->idReg2()));
732             assert(isVectorRegister(id->idReg3()));
733             break;
734
735         case IF_DV_3D: // DV_3D   .........X.mmmmm ......nnnnnddddd      Vd Vn Vm   (scalar)
736             assert(isValidScalarDatasize(id->idOpSize()));
737             assert(insOptsNone(id->idInsOpt()));
738             assert(isVectorRegister(id->idReg1()));
739             assert(isVectorRegister(id->idReg2()));
740             assert(isVectorRegister(id->idReg3()));
741             break;
742
743         case IF_DV_3DI: // DV_3DI  .........XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (scalar by elem)
744             assert(isValidScalarDatasize(id->idOpSize()));
745             assert(insOptsNone(id->idInsOpt()));
746             assert(isVectorRegister(id->idReg1()));
747             assert(isVectorRegister(id->idReg2()));
748             assert(isVectorRegister(id->idReg3()));
749             elemsize = id->idOpSize();
750             assert(isValidVectorIndex(EA_16BYTE, elemsize, emitGetInsSC(id)));
751             break;
752
753         case IF_DV_3E: // DV_3E   ...........mmmmm ......nnnnnddddd      Vd Vn Vm  (scalar)
754             assert(insOptsNone(id->idInsOpt()));
755             assert(id->idOpSize() == EA_8BYTE);
756             assert(isVectorRegister(id->idReg1()));
757             assert(isVectorRegister(id->idReg2()));
758             assert(isVectorRegister(id->idReg3()));
759             break;
760
761         case IF_DV_4A: // DR_4A   .........X.mmmmm .aaaaannnnnddddd      Rd Rn Rm Ra (scalar)
762             assert(isValidGeneralDatasize(id->idOpSize()));
763             assert(isVectorRegister(id->idReg1()));
764             assert(isVectorRegister(id->idReg2()));
765             assert(isVectorRegister(id->idReg3()));
766             assert(isVectorRegister(id->idReg4()));
767             break;
768
769         case IF_SN_0A: // SN_0A   ................ ................
770         case IF_SI_0A: // SI_0A   ...........iiiii iiiiiiiiiii.....               imm16
771         case IF_SI_0B: // SI_0B   ................ ....bbbb........               imm4 - barrier
772             break;
773
774         default:
775             printf("unexpected format %s\n", emitIfName(id->idInsFmt()));
776             assert(!"Unexpected format");
777             break;
778     }
779 }
780 #endif // DEBUG
781
782 bool emitter::emitInsMayWriteToGCReg(instrDesc* id)
783 {
784     instruction ins = id->idIns();
785     insFormat   fmt = id->idInsFmt();
786
787     switch (fmt)
788     {
789
790         // These are the formats with "destination" registers:
791
792         case IF_DI_1B: // DI_1B   X........hwiiiii iiiiiiiiiiiddddd      Rd       imm(i16,hw)
793         case IF_DI_1D: // DI_1D   X........Nrrrrrr ssssss.....ddddd      Rd       imm(N,r,s)
794         case IF_DI_1E: // DI_1E   .ii.....iiiiiiii iiiiiiiiiiiddddd      Rd       simm21
795
796         case IF_DI_2A: // DI_2A   X.......shiiiiii iiiiiinnnnnddddd      Rd Rn    imm(i12,sh)
797         case IF_DI_2B: // DI_2B   X.........Xnnnnn ssssssnnnnnddddd      Rd Rn    imm(0-63)
798         case IF_DI_2C: // DI_2C   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imm(N,r,s)
799         case IF_DI_2D: // DI_2D   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imr, imms   (N,r,s)
800
801         case IF_DR_1D: // DR_1D   X............... cccc.......ddddd      Rd       cond
802
803         case IF_DR_2D: // DR_2D   X..........nnnnn cccc..nnnnnddddd      Rd Rn    cond
804         case IF_DR_2E: // DR_2E   X..........mmmmm ...........ddddd      Rd    Rm
805         case IF_DR_2F: // DR_2F   X.......sh.mmmmm ssssss.....ddddd      Rd    Rm {LSL,LSR,ASR} imm(0-63)
806         case IF_DR_2G: // DR_2G   X............... ......nnnnnddddd      Rd Rn
807         case IF_DR_2H: // DR_2H   X........X...... ......nnnnnddddd      Rd Rn
808
809         case IF_DR_3A: // DR_3A   X..........mmmmm ......nnnnnddddd      Rd Rn Rm
810         case IF_DR_3B: // DR_3B   X.......sh.mmmmm ssssssnnnnnddddd      Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
811         case IF_DR_3C: // DR_3C   X..........mmmmm xxxsssnnnnnddddd      Rd Rn Rm ext(Rm) LSL imm(0-4)
812         case IF_DR_3D: // DR_3D   X..........mmmmm cccc..nnnnnddddd      Rd Rn Rm cond
813         case IF_DR_3E: // DR_3E   X........X.mmmmm ssssssnnnnnddddd      Rd Rn Rm imm(0-63)
814
815         case IF_DR_4A: // DR_4A   X..........mmmmm .aaaaannnnnddddd      Rd Rn Rm Ra
816
817         case IF_DV_2B: // DV_2B   .Q.........iiiii ......nnnnnddddd      Rd Vn[]    (umov - to general)
818         case IF_DV_2H: // DV_2H   X........X...... ......nnnnnddddd      Rd Vn      (fmov - to general)
819
820             return true;
821
822         case IF_DV_2C:  // DV_2C   .Q.........iiiii ......nnnnnddddd      Vd Rn      (dup/ins - vector from general)
823         case IF_DV_2D:  // DV_2D   .Q.........iiiii ......nnnnnddddd      Vd Vn[]    (dup - vector)
824         case IF_DV_2E:  // DV_2E   ...........iiiii ......nnnnnddddd      Vd Vn[]    (dup - scalar)
825         case IF_DV_2F:  // DV_2F   ...........iiiii .jjjj.nnnnnddddd      Vd[] Vn[]  (ins - element)
826         case IF_DV_2G:  // DV_2G   .........X...... ......nnnnnddddd      Vd Vn      (fmov, fcvtXX - register)
827         case IF_DV_2I:  // DV_2I   X........X...... ......nnnnnddddd      Vd Rn      (fmov - from general)
828         case IF_DV_2J:  // DV_2J   ........SS.....D D.....nnnnnddddd      Vd Vn      (fcvt)
829         case IF_DV_2K:  // DV_2K   .........X.mmmmm ......nnnnn.....      Vn Vm      (fcmp)
830         case IF_DV_2L:  // DV_2L   ........XX...... ......nnnnnddddd      Vd Vn      (abs, neg - scalar)
831         case IF_DV_2M:  // DV_2M   .Q......XX...... ......nnnnnddddd      Vd Vn      (abs, neg - vector)
832         case IF_DV_3A:  // DV_3A   .Q......XX.mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
833         case IF_DV_3AI: // DV_3AI  .Q......XXLMmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector)
834         case IF_DV_3B:  // DV_3B   .Q.......X.mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
835         case IF_DV_3BI: // DV_3BI  .Q.......XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector by elem)
836         case IF_DV_3C:  // DV_3C   .Q.........mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
837         case IF_DV_3D:  // DV_3D   .........X.mmmmm ......nnnnnddddd      Vd Vn Vm   (scalar)
838         case IF_DV_3DI: // DV_3DI  .........XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (scalar by elem)
839         case IF_DV_3E:  // DV_3E   ...........mmmmm ......nnnnnddddd      Vd Vn Vm   (scalar)
840         case IF_DV_4A:  // DV_4A   .........X.mmmmm .aaaaannnnnddddd      Vd Va Vn Vm (scalar)
841             // Tracked GC pointers cannot be placed into the SIMD registers.
842             return false;
843
844         // These are the load/store formats with "target" registers:
845
846         case IF_LS_1A: // LS_1A   XX...V..iiiiiiii iiiiiiiiiiittttt      Rt    PC imm(1MB)
847         case IF_LS_2A: // LS_2A   .X.......X...... ......nnnnnttttt      Rt Rn
848         case IF_LS_2B: // LS_2B   .X.......Xiiiiii iiiiiinnnnnttttt      Rt Rn    imm(0-4095)
849         case IF_LS_2C: // LS_2C   .X.......X.iiiii iiiiP.nnnnnttttt      Rt Rn    imm(-256..+255) pre/post inc
850         case IF_LS_3A: // LS_3A   .X.......X.mmmmm xxxS..nnnnnttttt      Rt Rn Rm ext(Rm) LSL {}
851         case IF_LS_3B: // LS_3B   X............... .aaaaannnnnttttt      Rt Ra Rn
852         case IF_LS_3C: // LS_3C   X.........iiiiii iaaaaannnnnttttt      Rt Ra Rn imm(im7,sh)
853         case IF_LS_3D: // LS_3D   .X.......X.mmmmm ......nnnnnttttt      Wm Rt Rn
854
855             // For the Store instructions the "target" register is actually a "source" value
856
857             if (emitInsIsStore(ins))
858             {
859                 return false;
860             }
861             else
862             {
863                 assert(emitInsIsLoad(ins));
864                 return true;
865             }
866
867         default:
868             return false;
869     }
870 }
871
872 bool emitter::emitInsWritesToLclVarStackLoc(instrDesc* id)
873 {
874     if (!id->idIsLclVar())
875         return false;
876
877     instruction ins = id->idIns();
878
879     // This list is related to the list of instructions used to store local vars in emitIns_S_R().
880     // We don't accept writing to float local vars.
881
882     switch (ins)
883     {
884         case INS_strb:
885         case INS_strh:
886         case INS_str:
887         case INS_stur:
888         case INS_sturb:
889         case INS_sturh:
890             return true;
891         default:
892             return false;
893     }
894 }
895
896 bool emitter::emitInsWritesToLclVarStackLocPair(instrDesc* id)
897 {
898     if (!id->idIsLclVar())
899         return false;
900
901     instruction ins = id->idIns();
902
903     // This list is related to the list of instructions used to store local vars in emitIns_S_S_R_R().
904     // We don't accept writing to float local vars.
905
906     switch (ins)
907     {
908         case INS_stnp:
909         case INS_stp:
910             return true;
911         default:
912             return false;
913     }
914 }
915
916 bool emitter::emitInsMayWriteMultipleRegs(instrDesc* id)
917 {
918     instruction ins = id->idIns();
919
920     switch (ins)
921     {
922         case INS_ldp:
923         case INS_ldpsw:
924         case INS_ldnp:
925             return true;
926         default:
927             return false;
928     }
929 }
930
931 // For the small loads/store instruction we adjust the size 'attr'
932 // depending upon whether we have a load or a store
933 //
934 emitAttr emitter::emitInsAdjustLoadStoreAttr(instruction ins, emitAttr attr)
935 {
936     if (EA_SIZE(attr) <= EA_4BYTE)
937     {
938         if (emitInsIsLoad(ins))
939         {
940             // The value of 'ins' encodes the size to load
941             // we use EA_8BYTE here because it is the size we will write (into dataReg)
942             // it is also required when ins is INS_ldrsw
943             //
944             attr = EA_8BYTE;
945         }
946         else
947         {
948             assert(emitInsIsStore(ins));
949
950             // The value of 'ins' encodes the size to store
951             // we use EA_4BYTE here because it is the size of the register
952             // that we want to display when storing small values
953             //
954             attr = EA_4BYTE;
955         }
956     }
957     return attr;
958 }
959
960 // Takes an instrDesc 'id' and uses the instruction 'ins' to determine the
961 // size of the target register that is written or read by the instruction.
962 // Note that even if EA_4BYTE is returned a load instruction will still
963 // always zero the upper 4 bytes of the target register.
964 // This method is required so that we can distinguish between loads that are
965 // sign-extending as they can have two different sizes for their target register.
966 // Additionally for instructions like 'ldr' and 'str' these can load/store
967 // either 4 byte or 8 bytes to/from the target register.
968 // By convention the small unsigned load instructions are considered to write
969 // a 4 byte sized target register, though since these also zero the upper 4 bytes
970 // they could equally be considered to write the unsigned value to full 8 byte register.
971 //
972 emitAttr emitter::emitInsTargetRegSize(instrDesc* id)
973 {
974     instruction ins    = id->idIns();
975     emitAttr    result = EA_UNKNOWN;
976
977     // This is used to determine the size of the target registers for a load/store instruction
978
979     switch (ins)
980     {
981         case INS_ldxrb:
982         case INS_ldarb:
983         case INS_ldaxrb:
984         case INS_stxrb:
985         case INS_stlrb:
986         case INS_stlxrb:
987         case INS_ldrb:
988         case INS_strb:
989         case INS_ldurb:
990         case INS_sturb:
991             result = EA_4BYTE;
992             break;
993
994         case INS_ldxrh:
995         case INS_ldarh:
996         case INS_ldaxrh:
997         case INS_stxrh:
998         case INS_stlrh:
999         case INS_stlxrh:
1000         case INS_ldrh:
1001         case INS_strh:
1002         case INS_ldurh:
1003         case INS_sturh:
1004             result = EA_4BYTE;
1005             break;
1006
1007         case INS_ldrsb:
1008         case INS_ldursb:
1009         case INS_ldrsh:
1010         case INS_ldursh:
1011             if (id->idOpSize() == EA_8BYTE)
1012                 result = EA_8BYTE;
1013             else
1014                 result = EA_4BYTE;
1015             break;
1016
1017         case INS_ldrsw:
1018         case INS_ldursw:
1019         case INS_ldpsw:
1020             result = EA_8BYTE;
1021             break;
1022
1023         case INS_ldp:
1024         case INS_stp:
1025         case INS_ldnp:
1026         case INS_stnp:
1027             result = id->idOpSize();
1028             break;
1029
1030         case INS_ldxr:
1031         case INS_ldar:
1032         case INS_ldaxr:
1033         case INS_stxr:
1034         case INS_stlr:
1035         case INS_stlxr:
1036         case INS_ldr:
1037         case INS_str:
1038         case INS_ldur:
1039         case INS_stur:
1040             result = id->idOpSize();
1041             break;
1042
1043         default:
1044             NO_WAY("unexpected instruction");
1045             break;
1046     }
1047     return result;
1048 }
1049
1050 // Takes an instrDesc and uses the instruction to determine the 'size' of the
1051 // data that is loaded from memory.
1052 //
1053 emitAttr emitter::emitInsLoadStoreSize(instrDesc* id)
1054 {
1055     instruction ins    = id->idIns();
1056     emitAttr    result = EA_UNKNOWN;
1057
1058     // The 'result' returned is the 'size' of the data that is loaded from memory.
1059
1060     switch (ins)
1061     {
1062         case INS_ldarb:
1063         case INS_stlrb:
1064         case INS_ldrb:
1065         case INS_strb:
1066         case INS_ldurb:
1067         case INS_sturb:
1068         case INS_ldrsb:
1069         case INS_ldursb:
1070             result = EA_1BYTE;
1071             break;
1072
1073         case INS_ldarh:
1074         case INS_stlrh:
1075         case INS_ldrh:
1076         case INS_strh:
1077         case INS_ldurh:
1078         case INS_sturh:
1079         case INS_ldrsh:
1080         case INS_ldursh:
1081             result = EA_2BYTE;
1082             break;
1083
1084         case INS_ldrsw:
1085         case INS_ldursw:
1086         case INS_ldpsw:
1087             result = EA_4BYTE;
1088             break;
1089
1090         case INS_ldp:
1091         case INS_stp:
1092         case INS_ldnp:
1093         case INS_stnp:
1094             result = id->idOpSize();
1095             break;
1096
1097         case INS_ldar:
1098         case INS_stlr:
1099         case INS_ldr:
1100         case INS_str:
1101         case INS_ldur:
1102         case INS_stur:
1103             result = id->idOpSize();
1104             break;
1105
1106         default:
1107             NO_WAY("unexpected instruction");
1108             break;
1109     }
1110     return result;
1111 }
1112
1113 /*****************************************************************************/
1114 #ifdef DEBUG
1115
1116 // clang-format off
1117 static const char * const  xRegNames[] =
1118 {
1119     #define REGDEF(name, rnum, mask, xname, wname) xname,
1120     #include "register.h"
1121 };
1122
1123 static const char * const  wRegNames[] =
1124 {
1125     #define REGDEF(name, rnum, mask, xname, wname) wname,
1126     #include "register.h"
1127 };
1128
1129 static const char * const  vRegNames[] =
1130 {
1131     "v0",  "v1",  "v2",  "v3",  "v4", 
1132     "v5",  "v6",  "v7",  "v8",  "v9", 
1133     "v10", "v11", "v12", "v13", "v14", 
1134     "v15", "v16", "v17", "v18", "v19", 
1135     "v20", "v21", "v22", "v23", "v24", 
1136     "v25", "v26", "v27", "v28", "v29",
1137     "v30", "v31"
1138 };
1139
1140 static const char * const  qRegNames[] =
1141 {
1142     "q0",  "q1",  "q2",  "q3",  "q4", 
1143     "q5",  "q6",  "q7",  "q8",  "q9", 
1144     "q10", "q11", "q12", "q13", "q14", 
1145     "q15", "q16", "q17", "q18", "q19", 
1146     "q20", "q21", "q22", "q23", "q24", 
1147     "q25", "q26", "q27", "q28", "q29",
1148     "q30", "q31"
1149 };
1150
1151 static const char * const  hRegNames[] =
1152 {
1153     "h0",  "h1",  "h2",  "h3",  "h4", 
1154     "h5",  "h6",  "h7",  "h8",  "h9", 
1155     "h10", "h11", "h12", "h13", "h14", 
1156     "h15", "h16", "h17", "h18", "h19", 
1157     "h20", "h21", "h22", "h23", "h24", 
1158     "h25", "h26", "h27", "h28", "h29",
1159     "h30", "h31"
1160 };
1161 static const char * const  bRegNames[] =
1162 {
1163     "b0",  "b1",  "b2",  "b3",  "b4", 
1164     "b5",  "b6",  "b7",  "b8",  "b9", 
1165     "b10", "b11", "b12", "b13", "b14", 
1166     "b15", "b16", "b17", "b18", "b19", 
1167     "b20", "b21", "b22", "b23", "b24", 
1168     "b25", "b26", "b27", "b28", "b29",
1169     "b30", "b31"
1170 };
1171 // clang-format on
1172
1173 /*****************************************************************************
1174  *
1175  *  Return a string that represents the given register.
1176  */
1177
1178 const char* emitter::emitRegName(regNumber reg, emitAttr size, bool varName)
1179 {
1180     assert(reg < REG_COUNT);
1181
1182     const char* rn = nullptr;
1183
1184     if (size == EA_8BYTE)
1185     {
1186         rn = xRegNames[reg];
1187     }
1188     else if (size == EA_4BYTE)
1189     {
1190         rn = wRegNames[reg];
1191     }
1192     else if (isVectorRegister(reg))
1193     {
1194         if (size == EA_16BYTE)
1195         {
1196             rn = qRegNames[reg - REG_V0];
1197         }
1198         else if (size == EA_2BYTE)
1199         {
1200             rn = hRegNames[reg - REG_V0];
1201         }
1202         else if (size == EA_1BYTE)
1203         {
1204             rn = bRegNames[reg - REG_V0];
1205         }
1206     }
1207
1208     assert(rn != nullptr);
1209
1210     return rn;
1211 }
1212
1213 /*****************************************************************************
1214  *
1215  *  Return a string that represents the given register.
1216  */
1217
1218 const char* emitter::emitVectorRegName(regNumber reg)
1219 {
1220     assert((reg >= REG_V0) && (reg <= REG_V31));
1221
1222     int index = (int)reg - (int)REG_V0;
1223
1224     return vRegNames[index];
1225 }
1226 #endif // DEBUG
1227
1228 /*****************************************************************************
1229  *
1230  *  Returns the base encoding of the given CPU instruction.
1231  */
1232
1233 emitter::insFormat emitter::emitInsFormat(instruction ins)
1234 {
1235     // clang-format off
1236     const static insFormat insFormats[] =
1237     {
1238         #define INST1(id, nm, fp, ldst, fmt, e1                                ) fmt,
1239         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            ) fmt,
1240         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        ) fmt,
1241         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    ) fmt,
1242         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                ) fmt,
1243         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            ) fmt,
1244         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) fmt,
1245         #include "instrs.h"
1246     };
1247     // clang-format on
1248
1249     assert(ins < ArrLen(insFormats));
1250     assert((insFormats[ins] != IF_NONE));
1251
1252     return insFormats[ins];
1253 }
1254
1255 // INST_FP is 1
1256 #define LD 2
1257 #define ST 4
1258 #define CMP 8
1259
1260 // clang-format off
1261 /*static*/ const BYTE CodeGenInterface::instInfo[] =
1262 {
1263     #define INST1(id, nm, fp, ldst, fmt, e1                                ) ldst | INST_FP*fp,
1264     #define INST2(id, nm, fp, ldst, fmt, e1, e2                            ) ldst | INST_FP*fp,
1265     #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        ) ldst | INST_FP*fp,
1266     #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    ) ldst | INST_FP*fp,
1267     #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                ) ldst | INST_FP*fp,
1268     #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            ) ldst | INST_FP*fp,
1269     #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) ldst | INST_FP*fp,
1270     #include "instrs.h"
1271 };
1272 // clang-format on
1273
1274 /*****************************************************************************
1275  *
1276  *  Returns true if the instruction is some kind of compare or test instruction
1277  */
1278
1279 bool emitter::emitInsIsCompare(instruction ins)
1280 {
1281     // We have pseudo ins like lea which are not included in emitInsLdStTab.
1282     if (ins < ArrLen(CodeGenInterface::instInfo))
1283         return (CodeGenInterface::instInfo[ins] & CMP) ? true : false;
1284     else
1285         return false;
1286 }
1287
1288 /*****************************************************************************
1289  *
1290  *  Returns true if the instruction is some kind of load instruction
1291  */
1292
1293 bool emitter::emitInsIsLoad(instruction ins)
1294 {
1295     // We have pseudo ins like lea which are not included in emitInsLdStTab.
1296     if (ins < ArrLen(CodeGenInterface::instInfo))
1297         return (CodeGenInterface::instInfo[ins] & LD) ? true : false;
1298     else
1299         return false;
1300 }
1301 /*****************************************************************************
1302  *
1303  *  Returns true if the instruction is some kind of store instruction
1304  */
1305
1306 bool emitter::emitInsIsStore(instruction ins)
1307 {
1308     // We have pseudo ins like lea which are not included in emitInsLdStTab.
1309     if (ins < ArrLen(CodeGenInterface::instInfo))
1310         return (CodeGenInterface::instInfo[ins] & ST) ? true : false;
1311     else
1312         return false;
1313 }
1314
1315 /*****************************************************************************
1316  *
1317  *  Returns true if the instruction is some kind of load/store instruction
1318  */
1319
1320 bool emitter::emitInsIsLoadOrStore(instruction ins)
1321 {
1322     // We have pseudo ins like lea which are not included in emitInsLdStTab.
1323     if (ins < ArrLen(CodeGenInterface::instInfo))
1324         return (CodeGenInterface::instInfo[ins] & (LD | ST)) ? true : false;
1325     else
1326         return false;
1327 }
1328
1329 #undef LD
1330 #undef ST
1331 #undef CMP
1332
1333 /*****************************************************************************
1334  *
1335  *  Returns the specific encoding of the given CPU instruction and format
1336  */
1337
1338 emitter::code_t emitter::emitInsCode(instruction ins, insFormat fmt)
1339 {
1340     // clang-format off
1341     const static code_t insCodes1[] =
1342     {
1343         #define INST1(id, nm, fp, ldst, fmt, e1                                ) e1,
1344         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            ) e1,
1345         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        ) e1,
1346         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    ) e1,
1347         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                ) e1,
1348         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            ) e1,
1349         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e1,
1350         #include "instrs.h"
1351     };
1352     const static code_t insCodes2[] =
1353     {
1354         #define INST1(id, nm, fp, ldst, fmt, e1                                )
1355         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            ) e2,
1356         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        ) e2,
1357         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    ) e2,
1358         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                ) e2,
1359         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            ) e2,
1360         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e2,
1361         #include "instrs.h"
1362     };
1363     const static code_t insCodes3[] =
1364     {
1365         #define INST1(id, nm, fp, ldst, fmt, e1                                )
1366         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            )
1367         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        ) e3,
1368         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    ) e3,
1369         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                ) e3,
1370         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            ) e3,
1371         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e3,
1372         #include "instrs.h"
1373     };
1374     const static code_t insCodes4[] =
1375     {
1376         #define INST1(id, nm, fp, ldst, fmt, e1                                )
1377         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            )
1378         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        )
1379         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    ) e4,
1380         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                ) e4,
1381         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            ) e4,
1382         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e4,
1383         #include "instrs.h"
1384     };
1385     const static code_t insCodes5[] =
1386     {
1387         #define INST1(id, nm, fp, ldst, fmt, e1                                )
1388         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            )
1389         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        )
1390         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    )
1391         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                ) e5,
1392         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            ) e5,
1393         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e5,
1394         #include "instrs.h"
1395     };
1396     const static code_t insCodes6[] =
1397     {
1398         #define INST1(id, nm, fp, ldst, fmt, e1                                )
1399         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            )
1400         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        )
1401         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    )
1402         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                )
1403         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            ) e6,
1404         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e6,
1405         #include "instrs.h"
1406     };
1407     const static code_t insCodes7[] =
1408     {
1409         #define INST1(id, nm, fp, ldst, fmt, e1                                )
1410         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            )
1411         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        )
1412         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    )
1413         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                )
1414         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            )
1415         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e7,
1416         #include "instrs.h"
1417     };
1418     const static code_t insCodes8[] =
1419     {
1420         #define INST1(id, nm, fp, ldst, fmt, e1                                )
1421         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            )
1422         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        )
1423         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    )
1424         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                )
1425         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            )
1426         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e8,
1427         #include "instrs.h"
1428     };
1429     const static code_t insCodes9[] =
1430     {
1431         #define INST1(id, nm, fp, ldst, fmt, e1                                )
1432         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            )
1433         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        )
1434         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    )
1435         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                )
1436         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            )
1437         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e9,
1438         #include "instrs.h"
1439     };
1440     // clang-format on
1441
1442     const static insFormat formatEncode9[9] = {IF_DR_2E, IF_DR_2G, IF_DI_1B, IF_DI_1D, IF_DV_3C,
1443                                                IF_DV_2B, IF_DV_2C, IF_DV_2E, IF_DV_2F};
1444     const static insFormat formatEncode6A[6] = {IF_DR_3A, IF_DR_3B, IF_DR_3C, IF_DI_2A, IF_DV_3A, IF_DV_3E};
1445     const static insFormat formatEncode5A[5] = {IF_LS_2A, IF_LS_2B, IF_LS_2C, IF_LS_3A, IF_LS_1A};
1446     const static insFormat formatEncode5B[5] = {IF_DV_2G, IF_DV_2H, IF_DV_2I, IF_DV_1A, IF_DV_1B};
1447     const static insFormat formatEncode5C[5] = {IF_DR_3A, IF_DR_3B, IF_DI_2C, IF_DV_3C, IF_DV_1B};
1448     const static insFormat formatEncode4A[4] = {IF_LS_2A, IF_LS_2B, IF_LS_2C, IF_LS_3A};
1449     const static insFormat formatEncode4B[4] = {IF_DR_3A, IF_DR_3B, IF_DR_3C, IF_DI_2A};
1450     const static insFormat formatEncode4C[4] = {IF_DR_2A, IF_DR_2B, IF_DR_2C, IF_DI_1A};
1451     const static insFormat formatEncode4D[4] = {IF_DV_3B, IF_DV_3D, IF_DV_3BI, IF_DV_3DI};
1452     const static insFormat formatEncode4E[4] = {IF_DR_3A, IF_DR_3B, IF_DI_2C, IF_DV_3C};
1453     const static insFormat formatEncode4F[4] = {IF_DR_3A, IF_DR_3B, IF_DV_3C, IF_DV_1B};
1454     const static insFormat formatEncode4G[4] = {IF_DR_2E, IF_DR_2F, IF_DV_2M, IF_DV_2L};
1455     const static insFormat formatEncode4H[4] = {IF_DV_3E, IF_DV_3A, IF_DV_2L, IF_DV_2M};
1456     const static insFormat formatEncode4I[4] = {IF_DV_3D, IF_DV_3B, IF_DV_2G, IF_DV_2A};
1457     const static insFormat formatEncode3A[3] = {IF_DR_3A, IF_DR_3B, IF_DI_2C};
1458     const static insFormat formatEncode3B[3] = {IF_DR_2A, IF_DR_2B, IF_DI_1C};
1459     const static insFormat formatEncode3C[3] = {IF_DR_3A, IF_DR_3B, IF_DV_3C};
1460     const static insFormat formatEncode3D[3] = {IF_DV_2C, IF_DV_2D, IF_DV_2E};
1461     const static insFormat formatEncode3E[3] = {IF_DV_3B, IF_DV_3BI, IF_DV_3DI};
1462     const static insFormat formatEncode3F[3] = {IF_DV_2A, IF_DV_2G, IF_DV_2H};
1463     const static insFormat formatEncode3G[3] = {IF_DV_2A, IF_DV_2G, IF_DV_2I};
1464     const static insFormat formatEncode3H[3] = {IF_DR_3A, IF_DV_3A, IF_DV_3AI};
1465     const static insFormat formatEncode3I[3] = {IF_DR_2E, IF_DR_2F, IF_DV_2M};
1466     const static insFormat formatEncode2A[2] = {IF_DR_2E, IF_DR_2F};
1467     const static insFormat formatEncode2B[2] = {IF_DR_3A, IF_DR_3B};
1468     const static insFormat formatEncode2C[2] = {IF_DR_3A, IF_DI_2D};
1469     const static insFormat formatEncode2D[2] = {IF_DR_3A, IF_DI_2B};
1470     const static insFormat formatEncode2E[2] = {IF_LS_3B, IF_LS_3C};
1471     const static insFormat formatEncode2F[2] = {IF_DR_2I, IF_DI_1F};
1472     const static insFormat formatEncode2G[2] = {IF_DV_3B, IF_DV_3D};
1473     const static insFormat formatEncode2H[2] = {IF_DV_2C, IF_DV_2F};
1474     const static insFormat formatEncode2I[2] = {IF_DV_2K, IF_DV_1C};
1475     const static insFormat formatEncode2J[2] = {IF_DV_2A, IF_DV_2G};
1476     const static insFormat formatEncode2K[2] = {IF_DV_2M, IF_DV_2L};
1477     const static insFormat formatEncode2L[2] = {IF_DV_2G, IF_DV_2M};
1478     const static insFormat formatEncode2M[2] = {IF_DV_3A, IF_DV_3AI};
1479     const static insFormat formatEncode2N[2] = {IF_DV_2N, IF_DV_2O};
1480     const static insFormat formatEncode2O[2] = {IF_DV_3E, IF_DV_3A};
1481     const static insFormat formatEncode2P[2] = {IF_DV_2G, IF_DV_3B};
1482
1483     code_t    code           = BAD_CODE;
1484     insFormat insFmt         = emitInsFormat(ins);
1485     bool      encoding_found = false;
1486     int       index          = -1;
1487
1488     switch (insFmt)
1489     {
1490         case IF_EN9:
1491             for (index = 0; index < 9; index++)
1492             {
1493                 if (fmt == formatEncode9[index])
1494                 {
1495                     encoding_found = true;
1496                     break;
1497                 }
1498             }
1499             break;
1500
1501         case IF_EN6A:
1502             for (index = 0; index < 6; index++)
1503             {
1504                 if (fmt == formatEncode6A[index])
1505                 {
1506                     encoding_found = true;
1507                     break;
1508                 }
1509             }
1510             break;
1511
1512         case IF_EN5A:
1513             for (index = 0; index < 5; index++)
1514             {
1515                 if (fmt == formatEncode5A[index])
1516                 {
1517                     encoding_found = true;
1518                     break;
1519                 }
1520             }
1521             break;
1522
1523         case IF_EN5B:
1524             for (index = 0; index < 5; index++)
1525             {
1526                 if (fmt == formatEncode5B[index])
1527                 {
1528                     encoding_found = true;
1529                     break;
1530                 }
1531             }
1532             break;
1533
1534         case IF_EN5C:
1535             for (index = 0; index < 5; index++)
1536             {
1537                 if (fmt == formatEncode5C[index])
1538                 {
1539                     encoding_found = true;
1540                     break;
1541                 }
1542             }
1543             break;
1544
1545         case IF_EN4A:
1546             for (index = 0; index < 4; index++)
1547             {
1548                 if (fmt == formatEncode4A[index])
1549                 {
1550                     encoding_found = true;
1551                     break;
1552                 }
1553             }
1554             break;
1555
1556         case IF_EN4B:
1557             for (index = 0; index < 4; index++)
1558             {
1559                 if (fmt == formatEncode4B[index])
1560                 {
1561                     encoding_found = true;
1562                     break;
1563                 }
1564             }
1565             break;
1566
1567         case IF_EN4C:
1568             for (index = 0; index < 4; index++)
1569             {
1570                 if (fmt == formatEncode4C[index])
1571                 {
1572                     encoding_found = true;
1573                     break;
1574                 }
1575             }
1576             break;
1577
1578         case IF_EN4D:
1579             for (index = 0; index < 4; index++)
1580             {
1581                 if (fmt == formatEncode4D[index])
1582                 {
1583                     encoding_found = true;
1584                     break;
1585                 }
1586             }
1587             break;
1588
1589         case IF_EN4E:
1590             for (index = 0; index < 4; index++)
1591             {
1592                 if (fmt == formatEncode4E[index])
1593                 {
1594                     encoding_found = true;
1595                     break;
1596                 }
1597             }
1598             break;
1599
1600         case IF_EN4F:
1601             for (index = 0; index < 4; index++)
1602             {
1603                 if (fmt == formatEncode4F[index])
1604                 {
1605                     encoding_found = true;
1606                     break;
1607                 }
1608             }
1609             break;
1610
1611         case IF_EN4G:
1612             for (index = 0; index < 4; index++)
1613             {
1614                 if (fmt == formatEncode4G[index])
1615                 {
1616                     encoding_found = true;
1617                     break;
1618                 }
1619             }
1620             break;
1621
1622         case IF_EN4H:
1623             for (index = 0; index < 4; index++)
1624             {
1625                 if (fmt == formatEncode4H[index])
1626                 {
1627                     encoding_found = true;
1628                     break;
1629                 }
1630             }
1631             break;
1632
1633         case IF_EN4I:
1634             for (index = 0; index < 4; index++)
1635             {
1636                 if (fmt == formatEncode4I[index])
1637                 {
1638                     encoding_found = true;
1639                     break;
1640                 }
1641             }
1642             break;
1643
1644         case IF_EN3A:
1645             for (index = 0; index < 3; index++)
1646             {
1647                 if (fmt == formatEncode3A[index])
1648                 {
1649                     encoding_found = true;
1650                     break;
1651                 }
1652             }
1653             break;
1654
1655         case IF_EN3B:
1656             for (index = 0; index < 3; index++)
1657             {
1658                 if (fmt == formatEncode3B[index])
1659                 {
1660                     encoding_found = true;
1661                     break;
1662                 }
1663             }
1664             break;
1665
1666         case IF_EN3C:
1667             for (index = 0; index < 3; index++)
1668             {
1669                 if (fmt == formatEncode3C[index])
1670                 {
1671                     encoding_found = true;
1672                     break;
1673                 }
1674             }
1675             break;
1676
1677         case IF_EN3D:
1678             for (index = 0; index < 3; index++)
1679             {
1680                 if (fmt == formatEncode3D[index])
1681                 {
1682                     encoding_found = true;
1683                     break;
1684                 }
1685             }
1686             break;
1687
1688         case IF_EN3E:
1689             for (index = 0; index < 3; index++)
1690             {
1691                 if (fmt == formatEncode3E[index])
1692                 {
1693                     encoding_found = true;
1694                     break;
1695                 }
1696             }
1697             break;
1698
1699         case IF_EN3F:
1700             for (index = 0; index < 3; index++)
1701             {
1702                 if (fmt == formatEncode3F[index])
1703                 {
1704                     encoding_found = true;
1705                     break;
1706                 }
1707             }
1708             break;
1709
1710         case IF_EN3G:
1711             for (index = 0; index < 3; index++)
1712             {
1713                 if (fmt == formatEncode3G[index])
1714                 {
1715                     encoding_found = true;
1716                     break;
1717                 }
1718             }
1719             break;
1720
1721         case IF_EN3H:
1722             for (index = 0; index < 3; index++)
1723             {
1724                 if (fmt == formatEncode3H[index])
1725                 {
1726                     encoding_found = true;
1727                     break;
1728                 }
1729             }
1730             break;
1731
1732         case IF_EN3I:
1733             for (index = 0; index < 3; index++)
1734             {
1735                 if (fmt == formatEncode3I[index])
1736                 {
1737                     encoding_found = true;
1738                     break;
1739                 }
1740             }
1741             break;
1742
1743         case IF_EN2A:
1744             for (index = 0; index < 2; index++)
1745             {
1746                 if (fmt == formatEncode2A[index])
1747                 {
1748                     encoding_found = true;
1749                     break;
1750                 }
1751             }
1752             break;
1753
1754         case IF_EN2B:
1755             for (index = 0; index < 2; index++)
1756             {
1757                 if (fmt == formatEncode2B[index])
1758                 {
1759                     encoding_found = true;
1760                     break;
1761                 }
1762             }
1763             break;
1764
1765         case IF_EN2C:
1766             for (index = 0; index < 2; index++)
1767             {
1768                 if (fmt == formatEncode2C[index])
1769                 {
1770                     encoding_found = true;
1771                     break;
1772                 }
1773             }
1774             break;
1775
1776         case IF_EN2D:
1777             for (index = 0; index < 2; index++)
1778             {
1779                 if (fmt == formatEncode2D[index])
1780                 {
1781                     encoding_found = true;
1782                     break;
1783                 }
1784             }
1785             break;
1786
1787         case IF_EN2E:
1788             for (index = 0; index < 2; index++)
1789             {
1790                 if (fmt == formatEncode2E[index])
1791                 {
1792                     encoding_found = true;
1793                     break;
1794                 }
1795             }
1796             break;
1797
1798         case IF_EN2F:
1799             for (index = 0; index < 2; index++)
1800             {
1801                 if (fmt == formatEncode2F[index])
1802                 {
1803                     encoding_found = true;
1804                     break;
1805                 }
1806             }
1807             break;
1808
1809         case IF_EN2G:
1810             for (index = 0; index < 2; index++)
1811             {
1812                 if (fmt == formatEncode2G[index])
1813                 {
1814                     encoding_found = true;
1815                     break;
1816                 }
1817             }
1818             break;
1819
1820         case IF_EN2H:
1821             for (index = 0; index < 2; index++)
1822             {
1823                 if (fmt == formatEncode2H[index])
1824                 {
1825                     encoding_found = true;
1826                     break;
1827                 }
1828             }
1829             break;
1830
1831         case IF_EN2I:
1832             for (index = 0; index < 2; index++)
1833             {
1834                 if (fmt == formatEncode2I[index])
1835                 {
1836                     encoding_found = true;
1837                     break;
1838                 }
1839             }
1840             break;
1841
1842         case IF_EN2J:
1843             for (index = 0; index < 2; index++)
1844             {
1845                 if (fmt == formatEncode2J[index])
1846                 {
1847                     encoding_found = true;
1848                     break;
1849                 }
1850             }
1851             break;
1852
1853         case IF_EN2K:
1854             for (index = 0; index < 2; index++)
1855             {
1856                 if (fmt == formatEncode2K[index])
1857                 {
1858                     encoding_found = true;
1859                     break;
1860                 }
1861             }
1862             break;
1863
1864         case IF_EN2L:
1865             for (index = 0; index < 2; index++)
1866             {
1867                 if (fmt == formatEncode2L[index])
1868                 {
1869                     encoding_found = true;
1870                     break;
1871                 }
1872             }
1873             break;
1874
1875         case IF_EN2M:
1876             for (index = 0; index < 2; index++)
1877             {
1878                 if (fmt == formatEncode2M[index])
1879                 {
1880                     encoding_found = true;
1881                     break;
1882                 }
1883             }
1884             break;
1885
1886         case IF_EN2N:
1887             for (index = 0; index < 2; index++)
1888             {
1889                 if (fmt == formatEncode2N[index])
1890                 {
1891                     encoding_found = true;
1892                     break;
1893                 }
1894             }
1895             break;
1896
1897         case IF_EN2O:
1898             for (index = 0; index < 2; index++)
1899             {
1900                 if (fmt == formatEncode2O[index])
1901                 {
1902                     encoding_found = true;
1903                     break;
1904                 }
1905             }
1906             break;
1907
1908         case IF_EN2P:
1909             for (index = 0; index < 2; index++)
1910             {
1911                 if (fmt == formatEncode2P[index])
1912                 {
1913                     encoding_found = true;
1914                     break;
1915                 }
1916             }
1917             break;
1918
1919         case IF_BI_0A:
1920         case IF_BI_0B:
1921         case IF_BI_0C:
1922         case IF_BI_1A:
1923         case IF_BI_1B:
1924         case IF_BR_1A:
1925         case IF_BR_1B:
1926         case IF_LS_1A:
1927         case IF_LS_2A:
1928         case IF_LS_2B:
1929         case IF_LS_2C:
1930         case IF_LS_3A:
1931         case IF_LS_3B:
1932         case IF_LS_3C:
1933         case IF_LS_3D:
1934         case IF_DI_1A:
1935         case IF_DI_1B:
1936         case IF_DI_1C:
1937         case IF_DI_1D:
1938         case IF_DI_1E:
1939         case IF_DI_1F:
1940         case IF_DI_2A:
1941         case IF_DI_2B:
1942         case IF_DI_2C:
1943         case IF_DI_2D:
1944         case IF_DR_1D:
1945         case IF_DR_2A:
1946         case IF_DR_2B:
1947         case IF_DR_2C:
1948         case IF_DR_2D:
1949         case IF_DR_2E:
1950         case IF_DR_2F:
1951         case IF_DR_2G:
1952         case IF_DR_2H:
1953         case IF_DR_2I:
1954         case IF_DR_3A:
1955         case IF_DR_3B:
1956         case IF_DR_3C:
1957         case IF_DR_3D:
1958         case IF_DR_3E:
1959         case IF_DR_4A:
1960         case IF_DV_1A:
1961         case IF_DV_1B:
1962         case IF_DV_1C:
1963         case IF_DV_2A:
1964         case IF_DV_2B:
1965         case IF_DV_2C:
1966         case IF_DV_2D:
1967         case IF_DV_2E:
1968         case IF_DV_2F:
1969         case IF_DV_2G:
1970         case IF_DV_2H:
1971         case IF_DV_2I:
1972         case IF_DV_2J:
1973         case IF_DV_2K:
1974         case IF_DV_2L:
1975         case IF_DV_2M:
1976         case IF_DV_2N:
1977         case IF_DV_2O:
1978         case IF_DV_3A:
1979         case IF_DV_3AI:
1980         case IF_DV_3B:
1981         case IF_DV_3BI:
1982         case IF_DV_3C:
1983         case IF_DV_3D:
1984         case IF_DV_3DI:
1985         case IF_DV_3E:
1986         case IF_DV_4A:
1987         case IF_SN_0A:
1988         case IF_SI_0A:
1989         case IF_SI_0B:
1990
1991             index          = 0;
1992             encoding_found = true;
1993             break;
1994
1995         default:
1996
1997             encoding_found = false;
1998             break;
1999     }
2000
2001     assert(encoding_found);
2002
2003     switch (index)
2004     {
2005         case 0:
2006             assert(ins < ArrLen(insCodes1));
2007             code = insCodes1[ins];
2008             break;
2009         case 1:
2010             assert(ins < ArrLen(insCodes2));
2011             code = insCodes2[ins];
2012             break;
2013         case 2:
2014             assert(ins < ArrLen(insCodes3));
2015             code = insCodes3[ins];
2016             break;
2017         case 3:
2018             assert(ins < ArrLen(insCodes4));
2019             code = insCodes4[ins];
2020             break;
2021         case 4:
2022             assert(ins < ArrLen(insCodes5));
2023             code = insCodes5[ins];
2024             break;
2025         case 5:
2026             assert(ins < ArrLen(insCodes6));
2027             code = insCodes6[ins];
2028             break;
2029         case 6:
2030             assert(ins < ArrLen(insCodes7));
2031             code = insCodes7[ins];
2032             break;
2033         case 7:
2034             assert(ins < ArrLen(insCodes8));
2035             code = insCodes8[ins];
2036             break;
2037         case 8:
2038             assert(ins < ArrLen(insCodes9));
2039             code = insCodes9[ins];
2040             break;
2041     }
2042
2043     assert((code != BAD_CODE));
2044
2045     return code;
2046 }
2047
2048 // true if this 'imm' can be encoded as a input operand to a mov instruction
2049 /*static*/ bool emitter::emitIns_valid_imm_for_mov(INT64 imm, emitAttr size)
2050 {
2051     // Check for "MOV (wide immediate)".
2052     if (canEncodeHalfwordImm(imm, size))
2053         return true;
2054
2055     // Next try the ones-complement form of 'halfword immediate' imm(i16,hw),
2056     // namely "MOV (inverted wide immediate)".
2057     ssize_t notOfImm = NOT_helper(imm, getBitWidth(size));
2058     if (canEncodeHalfwordImm(notOfImm, size))
2059         return true;
2060
2061     // Finally try "MOV (bitmask immediate)" imm(N,r,s)
2062     if (canEncodeBitMaskImm(imm, size))
2063         return true;
2064
2065     return false;
2066 }
2067
2068 // true if this 'imm' can be encoded as a input operand to a vector movi instruction
2069 /*static*/ bool emitter::emitIns_valid_imm_for_movi(INT64 imm, emitAttr elemsize)
2070 {
2071     if (elemsize == EA_8BYTE)
2072     {
2073         UINT64 uimm = imm;
2074         while (uimm != 0)
2075         {
2076             INT64 loByte = uimm & 0xFF;
2077             if ((loByte == 0) || (loByte == 0xFF))
2078             {
2079                 uimm >>= 8;
2080             }
2081             else
2082             {
2083                 return false;
2084             }
2085         }
2086         assert(uimm == 0);
2087         return true;
2088     }
2089     else
2090     {
2091         // First try the standard 'byteShifted immediate' imm(i8,bySh)
2092         if (canEncodeByteShiftedImm(imm, elemsize, true))
2093             return true;
2094
2095         // Next try the ones-complement form of the 'immediate' imm(i8,bySh)
2096         ssize_t notOfImm = NOT_helper(imm, getBitWidth(elemsize));
2097         if (canEncodeByteShiftedImm(notOfImm, elemsize, true))
2098             return true;
2099     }
2100     return false;
2101 }
2102
2103 // true if this 'imm' can be encoded as a input operand to a fmov instruction
2104 /*static*/ bool emitter::emitIns_valid_imm_for_fmov(double immDbl)
2105 {
2106     if (canEncodeFloatImm8(immDbl))
2107         return true;
2108
2109     return false;
2110 }
2111
2112 // true if this 'imm' can be encoded as a input operand to an add instruction
2113 /*static*/ bool emitter::emitIns_valid_imm_for_add(INT64 imm, emitAttr size)
2114 {
2115     if (unsigned_abs(imm) <= 0x0fff)
2116         return true;
2117     else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
2118         return true;
2119
2120     return false;
2121 }
2122
2123 // true if this 'imm' can be encoded as a input operand to an non-add/sub alu instruction
2124 /*static*/ bool emitter::emitIns_valid_imm_for_cmp(INT64 imm, emitAttr size)
2125 {
2126     return emitIns_valid_imm_for_add(imm, size);
2127 }
2128
2129 // true if this 'imm' can be encoded as a input operand to an non-add/sub alu instruction
2130 /*static*/ bool emitter::emitIns_valid_imm_for_alu(INT64 imm, emitAttr size)
2131 {
2132     if (canEncodeBitMaskImm(imm, size))
2133         return true;
2134
2135     return false;
2136 }
2137
2138 // true if this 'imm' can be encoded as the offset in a ldr/str instruction
2139 /*static*/ bool emitter::emitIns_valid_imm_for_ldst_offset(INT64 imm, emitAttr attr)
2140 {
2141     if (imm == 0)
2142         return true; // Encodable using IF_LS_2A
2143
2144     if ((imm >= -256) && (imm <= 255))
2145         return true; // Encodable using IF_LS_2C (or possibly IF_LS_2B)
2146
2147     if (imm < 0)
2148         return false; // not encodable
2149
2150     emitAttr size  = EA_SIZE(attr);
2151     unsigned scale = NaturalScale_helper(size);
2152     ssize_t  mask  = size - 1; // the mask of low bits that must be zero to encode the immediate
2153
2154     if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
2155         return true; // Encodable using IF_LS_2B
2156
2157     return false; // not encodable
2158 }
2159
2160 /************************************************************************
2161  *
2162  *   A helper method to return the natural scale for an EA 'size'
2163  */
2164
2165 /*static*/ unsigned emitter::NaturalScale_helper(emitAttr size)
2166 {
2167     assert(size == EA_1BYTE || size == EA_2BYTE || size == EA_4BYTE || size == EA_8BYTE || size == EA_16BYTE);
2168
2169     unsigned result = 0;
2170     unsigned utemp  = (unsigned)size;
2171
2172     // Compute log base 2 of utemp (aka 'size')
2173     while (utemp > 1)
2174     {
2175         result++;
2176         utemp >>= 1;
2177     }
2178
2179     return result;
2180 }
2181
2182 /************************************************************************
2183  *
2184  *  A helper method to perform a Rotate-Right shift operation
2185  *  the source is 'value' and it is rotated right by 'sh' bits
2186  *  'value' is considered to be a fixed size 'width' set of bits.
2187  *
2188  *  Example
2189  *      value is '00001111', sh is 2 and width is 8
2190  *     result is '11000011'
2191  */
2192
2193 /*static*/ UINT64 emitter::ROR_helper(UINT64 value, unsigned sh, unsigned width)
2194 {
2195     assert(width <= 64);
2196     // Check that 'value' fits in 'width' bits
2197     assert((width == 64) || (value < (1ULL << width)));
2198     // We don't support shifts >= width
2199     assert(sh < width);
2200
2201     UINT64 result;
2202
2203     unsigned rsh = sh;
2204     unsigned lsh = width - rsh;
2205
2206     result = (value >> rsh);
2207     result |= (value << lsh);
2208
2209     if (width < 64)
2210     {
2211         // mask off any extra bits that we got from the left shift
2212         result &= ((1ULL << width) - 1);
2213     }
2214     return result;
2215 }
2216 /************************************************************************
2217  *
2218  *  A helper method to perform a 'NOT' bitwise complement operation.
2219  *  'value' is considered to be a fixed size 'width' set of bits.
2220  *
2221  *  Example
2222  *      value is '01001011', and width is 8
2223  *     result is '10110100'
2224  */
2225
2226 /*static*/ UINT64 emitter::NOT_helper(UINT64 value, unsigned width)
2227 {
2228     assert(width <= 64);
2229
2230     UINT64 result = ~value;
2231
2232     if (width < 64)
2233     {
2234         // Check that 'value' fits in 'width' bits. Don't consider "sign" bits above width.
2235         UINT64 maxVal       = 1ULL << width;
2236         UINT64 lowBitsMask  = maxVal - 1;
2237         UINT64 signBitsMask = ~lowBitsMask | (1ULL << (width - 1)); // The high bits must be set, and the top bit
2238                                                                     // (sign bit) must be set.
2239         assert((value < maxVal) || ((value & signBitsMask) == signBitsMask));
2240
2241         // mask off any extra bits that we got from the complement operation
2242         result &= lowBitsMask;
2243     }
2244
2245     return result;
2246 }
2247
2248 /************************************************************************
2249  *
2250  *  A helper method to perform a bit Replicate operation
2251  *  the source is 'value' with a fixed size 'width' set of bits.
2252  *  value is replicated to fill out 32 or 64 bits as determined by 'size'.
2253  *
2254  *  Example
2255  *      value is '11000011' (0xE3), width is 8 and size is EA_8BYTE
2256  *     result is '11000011 11000011 11000011 11000011 11000011 11000011 11000011 11000011'
2257  *               0xE3E3E3E3E3E3E3E3
2258  */
2259
2260 /*static*/ UINT64 emitter::Replicate_helper(UINT64 value, unsigned width, emitAttr size)
2261 {
2262     assert(emitter::isValidGeneralDatasize(size));
2263
2264     unsigned immWidth = (size == EA_8BYTE) ? 64 : 32;
2265     assert(width <= immWidth);
2266
2267     UINT64   result     = value;
2268     unsigned filledBits = width;
2269
2270     while (filledBits < immWidth)
2271     {
2272         value <<= width;
2273         result |= value;
2274         filledBits += width;
2275     }
2276     return result;
2277 }
2278
2279 /************************************************************************
2280  *
2281  *  Convert an imm(N,r,s) into a 64-bit immediate
2282  *  inputs 'bmImm' a bitMaskImm struct
2283  *         'size' specifies the size of the result (64 or 32 bits)
2284  */
2285
2286 /*static*/ INT64 emitter::emitDecodeBitMaskImm(const emitter::bitMaskImm bmImm, emitAttr size)
2287 {
2288     assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2289
2290     unsigned N = bmImm.immN; // read the N,R and S values from the 'bitMaskImm' encoding
2291     unsigned R = bmImm.immR;
2292     unsigned S = bmImm.immS;
2293
2294     unsigned elemWidth = 64; // used when immN == 1
2295
2296     if (bmImm.immN == 0) // find the smaller elemWidth when immN == 0
2297     {
2298         // Scan S for the highest bit not set
2299         elemWidth = 32;
2300         for (unsigned bitNum = 5; bitNum > 0; bitNum--)
2301         {
2302             unsigned oneBit = elemWidth;
2303             if ((S & oneBit) == 0)
2304                 break;
2305             elemWidth /= 2;
2306         }
2307     }
2308     else
2309     {
2310         assert(size == EA_8BYTE);
2311     }
2312
2313     unsigned maskSR = elemWidth - 1;
2314
2315     S &= maskSR;
2316     R &= maskSR;
2317
2318     // encoding for S is one less than the number of consecutive one bits
2319     S++; // Number of consecutive ones to generate in 'welem'
2320
2321     // At this point:
2322     //
2323     //    'elemWidth' is the number of bits that we will use for the ROR and Replicate operations
2324     //    'S'         is the number of consecutive 1 bits for the immediate
2325     //    'R'         is the number of bits that we will Rotate Right the immediate
2326     //    'size'      selects the final size of the immedate that we return (64 or 32 bits)
2327
2328     assert(S < elemWidth); // 'elemWidth' consecutive one's is a reserved encoding
2329
2330     UINT64 welem;
2331     UINT64 wmask;
2332
2333     welem = (1ULL << S) - 1;
2334
2335     wmask = ROR_helper(welem, R, elemWidth);
2336     wmask = Replicate_helper(wmask, elemWidth, size);
2337
2338     return wmask;
2339 }
2340
2341 /*****************************************************************************
2342  *
2343  *  Check if an immediate can use the left shifted by 12 bits encoding
2344  */
2345
2346 /*static*/ bool emitter::canEncodeWithShiftImmBy12(INT64 imm)
2347 {
2348     if (imm < 0)
2349     {
2350         imm = -imm; // convert to unsigned
2351     }
2352
2353     if (imm < 0)
2354     {
2355         return false; // Must be MIN_INT64
2356     }
2357
2358     if ((imm & 0xfff) != 0) // Now the low 12 bits all have to be zero
2359     {
2360         return false;
2361     }
2362
2363     imm >>= 12; // shift right by 12 bits
2364
2365     return (imm <= 0x0fff); // Does it fit in 12 bits
2366 }
2367
2368 /*****************************************************************************
2369  *
2370  *  Normalize the 'imm' so that the upper bits, as defined by 'size' are zero
2371  */
2372
2373 /*static*/ INT64 emitter::normalizeImm64(INT64 imm, emitAttr size)
2374 {
2375     unsigned immWidth = getBitWidth(size);
2376     INT64    result   = imm;
2377
2378     if (immWidth < 64)
2379     {
2380         // Check that 'imm' fits in 'immWidth' bits. Don't consider "sign" bits above width.
2381         INT64 maxVal      = 1LL << immWidth;
2382         INT64 lowBitsMask = maxVal - 1;
2383         INT64 hiBitsMask  = ~lowBitsMask;
2384         INT64 signBitsMask =
2385             hiBitsMask | (1LL << (immWidth - 1)); // The high bits must be set, and the top bit (sign bit) must be set.
2386         assert((imm < maxVal) || ((imm & signBitsMask) == signBitsMask));
2387
2388         // mask off the hiBits
2389         result &= lowBitsMask;
2390     }
2391     return result;
2392 }
2393
2394 /*****************************************************************************
2395  *
2396  *  Normalize the 'imm' so that the upper bits, as defined by 'size' are zero
2397  */
2398
2399 /*static*/ INT32 emitter::normalizeImm32(INT32 imm, emitAttr size)
2400 {
2401     unsigned immWidth = getBitWidth(size);
2402     INT32    result   = imm;
2403
2404     if (immWidth < 32)
2405     {
2406         // Check that 'imm' fits in 'immWidth' bits. Don't consider "sign" bits above width.
2407         INT32 maxVal       = 1 << immWidth;
2408         INT32 lowBitsMask  = maxVal - 1;
2409         INT32 hiBitsMask   = ~lowBitsMask;
2410         INT32 signBitsMask = hiBitsMask | (1 << (immWidth - 1)); // The high bits must be set, and the top bit
2411                                                                  // (sign bit) must be set.
2412         assert((imm < maxVal) || ((imm & signBitsMask) == signBitsMask));
2413
2414         // mask off the hiBits
2415         result &= lowBitsMask;
2416     }
2417     return result;
2418 }
2419
2420 /************************************************************************
2421  *
2422  *  returns true if 'imm' of 'size bits (32/64) can be encoded
2423  *  using the ARM64 'bitmask immediate' form.
2424  *  When a non-null value is passed for 'wbBMI' then this method
2425  *  writes back the 'N','S' and 'R' values use to encode this immediate
2426  *
2427  */
2428
2429 /*static*/ bool emitter::canEncodeBitMaskImm(INT64 imm, emitAttr size, emitter::bitMaskImm* wbBMI)
2430 {
2431     assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2432
2433     unsigned immWidth = (size == EA_8BYTE) ? 64 : 32;
2434     unsigned maxLen   = (size == EA_8BYTE) ? 6 : 5;
2435
2436     imm = normalizeImm64(imm, size);
2437
2438     // Starting with len=1, elemWidth is 2 bits
2439     //               len=2, elemWidth is 4 bits
2440     //               len=3, elemWidth is 8 bits
2441     //               len=4, elemWidth is 16 bits
2442     //               len=5, elemWidth is 32 bits
2443     // (optionally)  len=6, elemWidth is 64 bits
2444     //
2445     for (unsigned len = 1; (len <= maxLen); len++)
2446     {
2447         unsigned elemWidth = 1 << len;
2448         UINT64   elemMask  = ((UINT64)-1) >> (64 - elemWidth);
2449         UINT64   tempImm   = (UINT64)imm;        // A working copy of 'imm' that we can mutate
2450         UINT64   elemVal   = tempImm & elemMask; // The low 'elemWidth' bits of 'imm'
2451
2452         // Check for all 1's or 0's as these can't be encoded
2453         if ((elemVal == 0) || (elemVal == elemMask))
2454             continue;
2455
2456         // 'checkedBits' is the count of bits that are known to match 'elemVal' when replicated
2457         unsigned checkedBits = elemWidth; // by definition the first 'elemWidth' bits match
2458
2459         // Now check to see if each of the next bits match...
2460         //
2461         while (checkedBits < immWidth)
2462         {
2463             tempImm >>= elemWidth;
2464
2465             UINT64 nextElem = tempImm & elemMask;
2466             if (nextElem != elemVal)
2467             {
2468                 // Not matching, exit this loop and checkedBits will not be equal to immWidth
2469                 break;
2470             }
2471
2472             // The 'nextElem' is matching, so increment 'checkedBits'
2473             checkedBits += elemWidth;
2474         }
2475
2476         // Did the full immediate contain bits that can be formed by repeating 'elemVal'?
2477         if (checkedBits == immWidth)
2478         {
2479             // We are not quite done, since the only values that we can encode as a
2480             // 'bitmask immediate' are those that can be formed by starting with a
2481             // bit string of 0*1* that is rotated by some number of bits.
2482             //
2483             // We check to see if 'elemVal' can be formed using these restrictions.
2484             //
2485             // Observation:
2486             // Rotating by one bit any value that passes these restrictions
2487             // can be xor-ed with the original value and will result it a string
2488             // of bits that have exactly two 1 bits: 'elemRorXor'
2489             // Further the distance between the two one bits tells us the value
2490             // of S and the location of the 1 bits tells us the value of R
2491             //
2492             // Some examples:   (immWidth is 8)
2493             //
2494             // S=4,R=0   S=5,R=3   S=3,R=6
2495             // elemVal:        00001111  11100011  00011100
2496             // elemRor:        10000111  11110001  00001110
2497             // elemRorXor:     10001000  00010010  00010010
2498             //      compute S  45678---  ---5678-  ---3210-
2499             //      compute R  01234567  ---34567  ------67
2500
2501             UINT64 elemRor    = ROR_helper(elemVal, 1, elemWidth); // Rotate 'elemVal' Right by one bit
2502             UINT64 elemRorXor = elemVal ^ elemRor;                 // Xor elemVal and elemRor
2503
2504             // If we only have a two-bit change in elemROR then we can form a mask for this value
2505             unsigned bitCount = 0;
2506             UINT64   oneBit   = 0x1;
2507             unsigned R        = elemWidth; // R is shift count for ROR (rotate right shift)
2508             unsigned S        = 0;         // S is number of consecutive one bits
2509             int      incr     = -1;
2510
2511             // Loop over the 'elemWidth' bits in 'elemRorXor'
2512             //
2513             for (unsigned bitNum = 0; bitNum < elemWidth; bitNum++)
2514             {
2515                 if (incr == -1)
2516                 {
2517                     R--; // We decrement R by one whenever incr is -1
2518                 }
2519                 if (bitCount == 1)
2520                 {
2521                     S += incr; // We incr/decr S, after we find the first one bit in 'elemRorXor'
2522                 }
2523
2524                 // Is this bit position a 1 bit in 'elemRorXor'?
2525                 //
2526                 if (oneBit & elemRorXor)
2527                 {
2528                     bitCount++;
2529                     // Is this the first 1 bit that we found in 'elemRorXor'?
2530                     if (bitCount == 1)
2531                     {
2532                         // Does this 1 bit represent a transition to zero bits?
2533                         bool toZeros = ((oneBit & elemVal) != 0);
2534                         if (toZeros)
2535                         {
2536                             // S :: Count down from elemWidth
2537                             S    = elemWidth;
2538                             incr = -1;
2539                         }
2540                         else // this 1 bit represent a transition to one bits.
2541                         {
2542                             // S :: Count up from zero
2543                             S    = 0;
2544                             incr = +1;
2545                         }
2546                     }
2547                     else // bitCount > 1
2548                     {
2549                         // We found the second (or third...) 1 bit in 'elemRorXor'
2550                         incr = 0; // stop decrementing 'R'
2551
2552                         if (bitCount > 2)
2553                         {
2554                             // More than 2 transitions from 0/1 in 'elemVal'
2555                             // This means that 'elemVal' can't be encoded
2556                             // using a 'bitmask immediate'.
2557                             //
2558                             // Furthermore, it will continue to fail
2559                             // with any larger 'len' that we try.
2560                             // so just return false.
2561                             //
2562                             return false;
2563                         }
2564                     }
2565                 }
2566
2567                 // shift oneBit left by one bit to test the next position
2568                 oneBit <<= 1;
2569             }
2570
2571             // We expect that bitCount will always be two at this point
2572             // but just in case return false for any bad cases.
2573             //
2574             assert(bitCount == 2);
2575             if (bitCount != 2)
2576                 return false;
2577
2578             // Perform some sanity checks on the values of 'S' and 'R'
2579             assert(S > 0);
2580             assert(S < elemWidth);
2581             assert(R < elemWidth);
2582
2583             // Does the caller want us to return the N,R,S encoding values?
2584             //
2585             if (wbBMI != nullptr)
2586             {
2587
2588                 // The encoding used for S is one less than the
2589                 //  number of consecutive one bits
2590                 S--;
2591
2592                 if (len == 6)
2593                 {
2594                     wbBMI->immN = 1;
2595                 }
2596                 else
2597                 {
2598                     wbBMI->immN = 0;
2599                     // The encoding used for 'S' here is a bit peculiar.
2600                     //
2601                     // The upper bits need to be complemented, followed by a zero bit
2602                     // then the value of 'S-1'
2603                     //
2604                     unsigned upperBitsOfS = 64 - (1 << (len + 1));
2605                     S |= upperBitsOfS;
2606                 }
2607                 wbBMI->immR = R;
2608                 wbBMI->immS = S;
2609
2610                 // Verify that what we are returning is correct.
2611                 assert(imm == emitDecodeBitMaskImm(*wbBMI, size));
2612             }
2613             // Tell the caller that we can successfully encode this immediate
2614             // using a 'bitmask immediate'.
2615             //
2616             return true;
2617         }
2618     }
2619     return false;
2620 }
2621
2622 /************************************************************************
2623  *
2624  *  Convert a 64-bit immediate into its 'bitmask immediate' representation imm(N,r,s)
2625  */
2626
2627 /*static*/ emitter::bitMaskImm emitter::emitEncodeBitMaskImm(INT64 imm, emitAttr size)
2628 {
2629     emitter::bitMaskImm result;
2630     result.immNRS = 0;
2631
2632     bool canEncode = canEncodeBitMaskImm(imm, size, &result);
2633     assert(canEncode);
2634
2635     return result;
2636 }
2637
2638 /************************************************************************
2639  *
2640  *  Convert an imm(i16,hw) into a 32/64-bit immediate
2641  *  inputs 'hwImm' a halfwordImm struct
2642  *         'size' specifies the size of the result (64 or 32 bits)
2643  */
2644
2645 /*static*/ INT64 emitter::emitDecodeHalfwordImm(const emitter::halfwordImm hwImm, emitAttr size)
2646 {
2647     assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2648
2649     unsigned hw  = hwImm.immHW;
2650     INT64    val = (INT64)hwImm.immVal;
2651
2652     assert((hw <= 1) || (size == EA_8BYTE));
2653
2654     INT64 result = val << (16 * hw);
2655     return result;
2656 }
2657
2658 /************************************************************************
2659  *
2660  *  returns true if 'imm' of 'size' bits (32/64) can be encoded
2661  *  using the ARM64 'halfword immediate' form.
2662  *  When a non-null value is passed for 'wbHWI' then this method
2663  *  writes back the 'immHW' and 'immVal' values use to encode this immediate
2664  *
2665  */
2666
2667 /*static*/ bool emitter::canEncodeHalfwordImm(INT64 imm, emitAttr size, emitter::halfwordImm* wbHWI)
2668 {
2669     assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2670
2671     unsigned immWidth = (size == EA_8BYTE) ? 64 : 32;
2672     unsigned maxHW    = (size == EA_8BYTE) ? 4 : 2;
2673
2674     // setup immMask to a (EA_4BYTE) 0x00000000_FFFFFFFF or (EA_8BYTE) 0xFFFFFFFF_FFFFFFFF
2675     const UINT64 immMask = ((UINT64)-1) >> (64 - immWidth);
2676     const INT64  mask16  = (INT64)0xFFFF;
2677
2678     imm = normalizeImm64(imm, size);
2679
2680     // Try each of the valid hw shift sizes
2681     for (unsigned hw = 0; (hw < maxHW); hw++)
2682     {
2683         INT64 curMask   = mask16 << (hw * 16); // Represents the mask of the bits in the current halfword
2684         INT64 checkBits = immMask & ~curMask;
2685
2686         // Excluding the current halfword (using ~curMask)
2687         //  does the immediate have zero bits in every other bit that we care about?
2688         //  note we care about all 64-bits for EA_8BYTE
2689         //  and we care about the lowest 32 bits for EA_4BYTE
2690         //
2691         if ((imm & checkBits) == 0)
2692         {
2693             // Does the caller want us to return the imm(i16,hw) encoding values?
2694             //
2695             if (wbHWI != nullptr)
2696             {
2697                 INT64 val     = ((imm & curMask) >> (hw * 16)) & mask16;
2698                 wbHWI->immHW  = hw;
2699                 wbHWI->immVal = val;
2700
2701                 // Verify that what we are returning is correct.
2702                 assert(imm == emitDecodeHalfwordImm(*wbHWI, size));
2703             }
2704             // Tell the caller that we can successfully encode this immediate
2705             // using a 'halfword immediate'.
2706             //
2707             return true;
2708         }
2709     }
2710     return false;
2711 }
2712
2713 /************************************************************************
2714  *
2715  *  Convert a 64-bit immediate into its 'halfword immediate' representation imm(i16,hw)
2716  */
2717
2718 /*static*/ emitter::halfwordImm emitter::emitEncodeHalfwordImm(INT64 imm, emitAttr size)
2719 {
2720     emitter::halfwordImm result;
2721     result.immHWVal = 0;
2722
2723     bool canEncode = canEncodeHalfwordImm(imm, size, &result);
2724     assert(canEncode);
2725
2726     return result;
2727 }
2728
2729 /************************************************************************
2730  *
2731  *  Convert an imm(i8,sh) into a 16/32-bit immediate
2732  *  inputs 'bsImm' a byteShiftedImm struct
2733  *         'size' specifies the size of the result (16 or 32 bits)
2734  */
2735
2736 /*static*/ INT32 emitter::emitDecodeByteShiftedImm(const emitter::byteShiftedImm bsImm, emitAttr size)
2737 {
2738     bool     onesShift = (bsImm.immOnes == 1);
2739     unsigned bySh      = bsImm.immBY;         // Num Bytes to shift 0,1,2,3
2740     INT32    val       = (INT32)bsImm.immVal; // 8-bit immediate
2741     INT32    result    = val;
2742
2743     if (bySh > 0)
2744     {
2745         assert((size == EA_2BYTE) || (size == EA_4BYTE)); // Only EA_2BYTE or EA_4BYTE forms
2746         if (size == EA_2BYTE)
2747         {
2748             assert(bySh < 2);
2749         }
2750         else
2751         {
2752             assert(bySh < 4);
2753         }
2754
2755         result <<= (8 * bySh);
2756
2757         if (onesShift)
2758         {
2759             result |= ((1 << (8 * bySh)) - 1);
2760         }
2761     }
2762     return result;
2763 }
2764
2765 /************************************************************************
2766  *
2767  *  returns true if 'imm' of 'size' bits (16/32) can be encoded
2768  *  using the ARM64 'byteShifted immediate' form.
2769  *  When a non-null value is passed for 'wbBSI' then this method
2770  *  writes back the 'immBY' and 'immVal' values use to encode this immediate
2771  *
2772  */
2773
2774 /*static*/ bool emitter::canEncodeByteShiftedImm(INT64                    imm,
2775                                                  emitAttr                 size,
2776                                                  bool                     allow_MSL,
2777                                                  emitter::byteShiftedImm* wbBSI)
2778 {
2779     bool     canEncode = false;
2780     bool     onesShift = false; // true if we use the shifting ones variant
2781     unsigned bySh      = 0;     // number of bytes to shift: 0, 1, 2, 3
2782     unsigned imm8      = 0;     // immediate to use in the encoding
2783
2784     imm = normalizeImm64(imm, size);
2785
2786     if (size == EA_1BYTE)
2787     {
2788         imm8 = (unsigned)imm;
2789         assert(imm8 < 0x100);
2790         canEncode = true;
2791     }
2792     else if (size == EA_8BYTE)
2793     {
2794         imm8 = (unsigned)imm;
2795         assert(imm8 < 0x100);
2796         canEncode = true;
2797     }
2798     else
2799     {
2800         assert((size == EA_2BYTE) || (size == EA_4BYTE)); // Only EA_2BYTE or EA_4BYTE forms
2801
2802         unsigned immWidth = (size == EA_4BYTE) ? 32 : 16;
2803         unsigned maxBY    = (size == EA_4BYTE) ? 4 : 2;
2804
2805         // setup immMask to a (EA_2BYTE) 0x0000FFFF or (EA_4BYTE) 0xFFFFFFFF
2806         const UINT32 immMask = ((UINT32)-1) >> (32 - immWidth);
2807         const INT32  mask8   = (INT32)0xFF;
2808
2809         // Try each of the valid by shift sizes
2810         for (bySh = 0; (bySh < maxBY); bySh++)
2811         {
2812             INT32 curMask   = mask8 << (bySh * 8); // Represents the mask of the bits in the current byteShifted
2813             INT32 checkBits = immMask & ~curMask;
2814             INT32 immCheck  = (imm & checkBits);
2815
2816             // Excluding the current byte (using ~curMask)
2817             //  does the immediate have zero bits in every other bit that we care about?
2818             //  or can be use the shifted one variant?
2819             //  note we care about all 32-bits for EA_4BYTE
2820             //  and we care about the lowest 16 bits for EA_2BYTE
2821             //
2822             if (immCheck == 0)
2823             {
2824                 canEncode = true;
2825             }
2826             if (allow_MSL)
2827             {
2828                 if ((bySh == 1) && (immCheck == 0xFF))
2829                 {
2830                     canEncode = true;
2831                     onesShift = true;
2832                 }
2833                 else if ((bySh == 2) && (immCheck == 0xFFFF))
2834                 {
2835                     canEncode = true;
2836                     onesShift = true;
2837                 }
2838             }
2839             if (canEncode)
2840             {
2841                 imm8 = (unsigned)(((imm & curMask) >> (bySh * 8)) & mask8);
2842                 break;
2843             }
2844         }
2845     }
2846
2847     if (canEncode)
2848     {
2849         // Does the caller want us to return the imm(i8,bySh) encoding values?
2850         //
2851         if (wbBSI != nullptr)
2852         {
2853             wbBSI->immOnes = onesShift;
2854             wbBSI->immBY   = bySh;
2855             wbBSI->immVal  = imm8;
2856
2857             // Verify that what we are returning is correct.
2858             assert(imm == emitDecodeByteShiftedImm(*wbBSI, size));
2859         }
2860         // Tell the caller that we can successfully encode this immediate
2861         // using a 'byteShifted immediate'.
2862         //
2863         return true;
2864     }
2865     return false;
2866 }
2867
2868 /************************************************************************
2869  *
2870  *  Convert a 32-bit immediate into its 'byteShifted immediate' representation imm(i8,by)
2871  */
2872
2873 /*static*/ emitter::byteShiftedImm emitter::emitEncodeByteShiftedImm(INT64 imm, emitAttr size, bool allow_MSL)
2874 {
2875     emitter::byteShiftedImm result;
2876     result.immBSVal = 0;
2877
2878     bool canEncode = canEncodeByteShiftedImm(imm, size, allow_MSL, &result);
2879     assert(canEncode);
2880
2881     return result;
2882 }
2883
2884 /************************************************************************
2885  *
2886  *  Convert a 'float 8-bit immediate' into a double.
2887  *  inputs 'fpImm' a floatImm8 struct
2888  */
2889
2890 /*static*/ double emitter::emitDecodeFloatImm8(const emitter::floatImm8 fpImm)
2891 {
2892     unsigned sign  = fpImm.immSign;
2893     unsigned exp   = fpImm.immExp ^ 0x4;
2894     unsigned mant  = fpImm.immMant + 16;
2895     unsigned scale = 16 * 8;
2896
2897     while (exp > 0)
2898     {
2899         scale /= 2;
2900         exp--;
2901     }
2902
2903     double result = ((double)mant) / ((double)scale);
2904     if (sign == 1)
2905     {
2906         result = -result;
2907     }
2908
2909     return result;
2910 }
2911
2912 /************************************************************************
2913  *
2914  *  returns true if the 'immDbl' can be encoded using the 'float 8-bit immediate' form.
2915  *  also returns the encoding if wbFPI is non-null
2916  *
2917  */
2918
2919 /*static*/ bool emitter::canEncodeFloatImm8(double immDbl, emitter::floatImm8* wbFPI)
2920 {
2921     bool   canEncode = false;
2922     double val       = immDbl;
2923
2924     int sign = 0;
2925     if (val < 0.0)
2926     {
2927         val  = -val;
2928         sign = 1;
2929     }
2930
2931     int exp = 0;
2932     while ((val < 1.0) && (exp >= -4))
2933     {
2934         val *= 2.0;
2935         exp--;
2936     }
2937     while ((val >= 2.0) && (exp <= 5))
2938     {
2939         val *= 0.5;
2940         exp++;
2941     }
2942     exp += 3;
2943     val *= 16.0;
2944     int ival = (int)val;
2945
2946     if ((exp >= 0) && (exp <= 7))
2947     {
2948         if (val == (double)ival)
2949         {
2950             canEncode = true;
2951
2952             if (wbFPI != nullptr)
2953             {
2954                 ival -= 16;
2955                 assert((ival >= 0) && (ival <= 15));
2956
2957                 wbFPI->immSign = sign;
2958                 wbFPI->immExp  = exp ^ 0x4;
2959                 wbFPI->immMant = ival;
2960                 unsigned imm8  = wbFPI->immFPIVal;
2961                 assert((imm8 >= 0) && (imm8 <= 0xff));
2962             }
2963         }
2964     }
2965
2966     return canEncode;
2967 }
2968
2969 /************************************************************************
2970  *
2971  *  Convert a double into its 'float 8-bit immediate' representation
2972  */
2973
2974 /*static*/ emitter::floatImm8 emitter::emitEncodeFloatImm8(double immDbl)
2975 {
2976     emitter::floatImm8 result;
2977     result.immFPIVal = 0;
2978
2979     bool canEncode = canEncodeFloatImm8(immDbl, &result);
2980     assert(canEncode);
2981
2982     return result;
2983 }
2984
2985 /*****************************************************************************
2986  *
2987  *  For the given 'ins' returns the reverse instruction
2988  *  if one exists, otherwise returns INS_INVALID
2989  */
2990
2991 /*static*/ instruction emitter::insReverse(instruction ins)
2992 {
2993     switch (ins)
2994     {
2995         case INS_add:
2996             return INS_sub;
2997         case INS_adds:
2998             return INS_subs;
2999
3000         case INS_sub:
3001             return INS_add;
3002         case INS_subs:
3003             return INS_adds;
3004
3005         case INS_cmp:
3006             return INS_cmn;
3007         case INS_cmn:
3008             return INS_cmp;
3009
3010         case INS_ccmp:
3011             return INS_ccmn;
3012         case INS_ccmn:
3013             return INS_ccmp;
3014
3015         default:
3016             return INS_invalid;
3017     }
3018 }
3019
3020 /*****************************************************************************
3021  *
3022  *  For the given 'datasize' and 'elemsize', make the proper arrangement option
3023  *  returns the insOpts that specifies the vector register arrangement
3024  *  if one does not exist returns INS_OPTS_NONE
3025  */
3026
3027 /*static*/ insOpts emitter::optMakeArrangement(emitAttr datasize, emitAttr elemsize)
3028 {
3029     insOpts result = INS_OPTS_NONE;
3030
3031     if (datasize == EA_8BYTE)
3032     {
3033         switch (elemsize)
3034         {
3035             case EA_1BYTE:
3036                 result = INS_OPTS_8B;
3037                 break;
3038             case EA_2BYTE:
3039                 result = INS_OPTS_4H;
3040                 break;
3041             case EA_4BYTE:
3042                 result = INS_OPTS_2S;
3043                 break;
3044             case EA_8BYTE:
3045                 result = INS_OPTS_1D;
3046                 break;
3047             default:
3048                 unreached();
3049                 break;
3050         }
3051     }
3052     else if (datasize == EA_16BYTE)
3053     {
3054         switch (elemsize)
3055         {
3056             case EA_1BYTE:
3057                 result = INS_OPTS_16B;
3058                 break;
3059             case EA_2BYTE:
3060                 result = INS_OPTS_8H;
3061                 break;
3062             case EA_4BYTE:
3063                 result = INS_OPTS_4S;
3064                 break;
3065             case EA_8BYTE:
3066                 result = INS_OPTS_2D;
3067                 break;
3068             default:
3069                 unreached();
3070                 break;
3071         }
3072     }
3073     return result;
3074 }
3075
3076 /*****************************************************************************
3077  *
3078  *  For the given 'datasize' and arrangement 'opts'
3079  *  returns true is the pair spcifies a valid arrangement
3080  */
3081 /*static*/ bool emitter::isValidArrangement(emitAttr datasize, insOpts opt)
3082 {
3083     if (datasize == EA_8BYTE)
3084     {
3085         if ((opt == INS_OPTS_8B) || (opt == INS_OPTS_4H) || (opt == INS_OPTS_2S) || (opt == INS_OPTS_1D))
3086         {
3087             return true;
3088         }
3089     }
3090     else if (datasize == EA_16BYTE)
3091     {
3092         if ((opt == INS_OPTS_16B) || (opt == INS_OPTS_8H) || (opt == INS_OPTS_4S) || (opt == INS_OPTS_2D))
3093         {
3094             return true;
3095         }
3096     }
3097     return false;
3098 }
3099
3100 //  For the given 'arrangement' returns the 'datasize' specified by the vector register arrangement
3101 //  asserts and returns EA_UNKNOWN if an invalid 'arrangement' value is passed
3102 //
3103 /*static*/ emitAttr emitter::optGetDatasize(insOpts arrangement)
3104 {
3105     if ((arrangement == INS_OPTS_8B) || (arrangement == INS_OPTS_4H) || (arrangement == INS_OPTS_2S) ||
3106         (arrangement == INS_OPTS_1D))
3107     {
3108         return EA_8BYTE;
3109     }
3110     else if ((arrangement == INS_OPTS_16B) || (arrangement == INS_OPTS_8H) || (arrangement == INS_OPTS_4S) ||
3111              (arrangement == INS_OPTS_2D))
3112     {
3113         return EA_16BYTE;
3114     }
3115     else
3116     {
3117         assert(!" invalid 'arrangement' value");
3118         return EA_UNKNOWN;
3119     }
3120 }
3121
3122 //  For the given 'arrangement' returns the 'elemsize' specified by the vector register arrangement
3123 //  asserts and returns EA_UNKNOWN if an invalid 'arrangement' value is passed
3124 //
3125 /*static*/ emitAttr emitter::optGetElemsize(insOpts arrangement)
3126 {
3127     if ((arrangement == INS_OPTS_8B) || (arrangement == INS_OPTS_16B))
3128     {
3129         return EA_1BYTE;
3130     }
3131     else if ((arrangement == INS_OPTS_4H) || (arrangement == INS_OPTS_8H))
3132     {
3133         return EA_2BYTE;
3134     }
3135     else if ((arrangement == INS_OPTS_2S) || (arrangement == INS_OPTS_4S))
3136     {
3137         return EA_4BYTE;
3138     }
3139     else if ((arrangement == INS_OPTS_1D) || (arrangement == INS_OPTS_2D))
3140     {
3141         return EA_8BYTE;
3142     }
3143     else
3144     {
3145         assert(!" invalid 'arrangement' value");
3146         return EA_UNKNOWN;
3147     }
3148 }
3149
3150 //  For the given 'arrangement' returns the 'widen-arrangement' specified by the vector register arrangement
3151 //  asserts and returns INS_OPTS_NONE if an invalid 'arrangement' value is passed
3152 //
3153 /*static*/ insOpts emitter::optWidenElemsize(insOpts arrangement)
3154 {
3155     if ((arrangement == INS_OPTS_8B) || (arrangement == INS_OPTS_16B))
3156     {
3157         return INS_OPTS_8H;
3158     }
3159     else if ((arrangement == INS_OPTS_4H) || (arrangement == INS_OPTS_8H))
3160     {
3161         return INS_OPTS_4S;
3162     }
3163     else if ((arrangement == INS_OPTS_2S) || (arrangement == INS_OPTS_4S))
3164     {
3165         return INS_OPTS_2D;
3166     }
3167     else
3168     {
3169         assert(!" invalid 'arrangement' value");
3170         return INS_OPTS_NONE;
3171     }
3172 }
3173
3174 //  For the given 'conversion' returns the 'dstsize' specified by the conversion option
3175 /*static*/ emitAttr emitter::optGetDstsize(insOpts conversion)
3176 {
3177     switch (conversion)
3178     {
3179         case INS_OPTS_S_TO_8BYTE:
3180         case INS_OPTS_D_TO_8BYTE:
3181         case INS_OPTS_4BYTE_TO_D:
3182         case INS_OPTS_8BYTE_TO_D:
3183         case INS_OPTS_S_TO_D:
3184         case INS_OPTS_H_TO_D:
3185
3186             return EA_8BYTE;
3187
3188         case INS_OPTS_S_TO_4BYTE:
3189         case INS_OPTS_D_TO_4BYTE:
3190         case INS_OPTS_4BYTE_TO_S:
3191         case INS_OPTS_8BYTE_TO_S:
3192         case INS_OPTS_D_TO_S:
3193         case INS_OPTS_H_TO_S:
3194
3195             return EA_4BYTE;
3196
3197         case INS_OPTS_S_TO_H:
3198         case INS_OPTS_D_TO_H:
3199
3200             return EA_2BYTE;
3201
3202         default:
3203             assert(!" invalid 'conversion' value");
3204             return EA_UNKNOWN;
3205     }
3206 }
3207
3208 //  For the given 'conversion' returns the 'srcsize' specified by the conversion option
3209 /*static*/ emitAttr emitter::optGetSrcsize(insOpts conversion)
3210 {
3211     switch (conversion)
3212     {
3213         case INS_OPTS_D_TO_8BYTE:
3214         case INS_OPTS_D_TO_4BYTE:
3215         case INS_OPTS_8BYTE_TO_D:
3216         case INS_OPTS_8BYTE_TO_S:
3217         case INS_OPTS_D_TO_S:
3218         case INS_OPTS_D_TO_H:
3219
3220             return EA_8BYTE;
3221
3222         case INS_OPTS_S_TO_8BYTE:
3223         case INS_OPTS_S_TO_4BYTE:
3224         case INS_OPTS_4BYTE_TO_S:
3225         case INS_OPTS_4BYTE_TO_D:
3226         case INS_OPTS_S_TO_D:
3227         case INS_OPTS_S_TO_H:
3228
3229             return EA_4BYTE;
3230
3231         case INS_OPTS_H_TO_S:
3232         case INS_OPTS_H_TO_D:
3233
3234             return EA_2BYTE;
3235
3236         default:
3237             assert(!" invalid 'conversion' value");
3238             return EA_UNKNOWN;
3239     }
3240 }
3241
3242 //    For the given 'size' and 'index' returns true if it specifies a valid index for a vector register of 'size'
3243 /*static*/ bool emitter::isValidVectorIndex(emitAttr datasize, emitAttr elemsize, ssize_t index)
3244 {
3245     assert(isValidVectorDatasize(datasize));
3246     assert(isValidVectorElemsize(elemsize));
3247
3248     bool result = false;
3249     if (index >= 0)
3250     {
3251         if (datasize == EA_8BYTE)
3252         {
3253             switch (elemsize)
3254             {
3255                 case EA_1BYTE:
3256                     result = (index < 8);
3257                     break;
3258                 case EA_2BYTE:
3259                     result = (index < 4);
3260                     break;
3261                 case EA_4BYTE:
3262                     result = (index < 2);
3263                     break;
3264                 case EA_8BYTE:
3265                     result = (index < 1);
3266                     break;
3267                 default:
3268                     unreached();
3269                     break;
3270             }
3271         }
3272         else if (datasize == EA_16BYTE)
3273         {
3274             switch (elemsize)
3275             {
3276                 case EA_1BYTE:
3277                     result = (index < 16);
3278                     break;
3279                 case EA_2BYTE:
3280                     result = (index < 8);
3281                     break;
3282                 case EA_4BYTE:
3283                     result = (index < 4);
3284                     break;
3285                 case EA_8BYTE:
3286                     result = (index < 2);
3287                     break;
3288                 default:
3289                     unreached();
3290                     break;
3291             }
3292         }
3293     }
3294     return result;
3295 }
3296
3297 /*****************************************************************************
3298  *
3299  *  Add an instruction with no operands.
3300  */
3301
3302 void emitter::emitIns(instruction ins)
3303 {
3304     instrDesc* id  = emitNewInstrSmall(EA_8BYTE);
3305     insFormat  fmt = emitInsFormat(ins);
3306
3307     assert(fmt == IF_SN_0A);
3308
3309     id->idIns(ins);
3310     id->idInsFmt(fmt);
3311
3312     dispIns(id);
3313     appendToCurIG(id);
3314 }
3315
3316 /*****************************************************************************
3317  *
3318  *  Add an instruction with a single immediate value.
3319  */
3320
3321 void emitter::emitIns_I(instruction ins, emitAttr attr, ssize_t imm)
3322 {
3323     insFormat fmt = IF_NONE;
3324
3325     /* Figure out the encoding format of the instruction */
3326     switch (ins)
3327     {
3328         case INS_brk:
3329             if ((imm & 0x0000ffff) == imm)
3330             {
3331                 fmt = IF_SI_0A;
3332             }
3333             else
3334             {
3335                 assert(!"Instruction cannot be encoded: IF_SI_0A");
3336             }
3337             break;
3338         default:
3339             unreached();
3340             break;
3341     }
3342     assert(fmt != IF_NONE);
3343
3344     instrDesc* id = emitNewInstrSC(attr, imm);
3345
3346     id->idIns(ins);
3347     id->idInsFmt(fmt);
3348
3349     dispIns(id);
3350     appendToCurIG(id);
3351 }
3352
3353 /*****************************************************************************
3354  *
3355  *  Add an instruction referencing a single register.
3356  */
3357
3358 void emitter::emitIns_R(instruction ins, emitAttr attr, regNumber reg)
3359 {
3360     emitAttr   size = EA_SIZE(attr);
3361     insFormat  fmt  = IF_NONE;
3362     instrDesc* id   = nullptr;
3363
3364     /* Figure out the encoding format of the instruction */
3365     switch (ins)
3366     {
3367         case INS_br:
3368         case INS_ret:
3369             assert(isGeneralRegister(reg));
3370             id = emitNewInstrSmall(attr);
3371             id->idReg1(reg);
3372             fmt = IF_BR_1A;
3373             break;
3374
3375         default:
3376             unreached();
3377     }
3378
3379     assert(fmt != IF_NONE);
3380
3381     id->idIns(ins);
3382     id->idInsFmt(fmt);
3383
3384     dispIns(id);
3385     appendToCurIG(id);
3386 }
3387
3388 /*****************************************************************************
3389  *
3390  *  Add an instruction referencing a register and a constant.
3391  */
3392
3393 void emitter::emitIns_R_I(instruction ins, emitAttr attr, regNumber reg, ssize_t imm, insOpts opt /* = INS_OPTS_NONE */)
3394 {
3395     emitAttr  size      = EA_SIZE(attr);
3396     emitAttr  elemsize  = EA_UNKNOWN;
3397     insFormat fmt       = IF_NONE;
3398     bool      canEncode = false;
3399
3400     /* Figure out the encoding format of the instruction */
3401     switch (ins)
3402     {
3403         bitMaskImm     bmi;
3404         halfwordImm    hwi;
3405         byteShiftedImm bsi;
3406         ssize_t        notOfImm;
3407
3408         case INS_tst:
3409             assert(insOptsNone(opt));
3410             assert(isGeneralRegister(reg));
3411             bmi.immNRS = 0;
3412             canEncode  = canEncodeBitMaskImm(imm, size, &bmi);
3413             if (canEncode)
3414             {
3415                 imm = bmi.immNRS;
3416                 assert(isValidImmNRS(imm, size));
3417                 fmt = IF_DI_1C;
3418             }
3419             break;
3420
3421         case INS_movk:
3422         case INS_movn:
3423         case INS_movz:
3424             assert(isValidGeneralDatasize(size));
3425             assert(insOptsNone(opt)); // No LSL here (you must use emitIns_R_I_I if a shift is needed)
3426             assert(isGeneralRegister(reg));
3427             assert(isValidUimm16(imm));
3428
3429             hwi.immHW  = 0;
3430             hwi.immVal = imm;
3431             assert(imm == emitDecodeHalfwordImm(hwi, size));
3432
3433             imm       = hwi.immHWVal;
3434             canEncode = true;
3435             fmt       = IF_DI_1B;
3436             break;
3437
3438         case INS_mov:
3439             assert(isValidGeneralDatasize(size));
3440             assert(insOptsNone(opt)); // No explicit LSL here
3441             // We will automatically determine the shift based upon the imm
3442
3443             // First try the standard 'halfword immediate' imm(i16,hw)
3444             hwi.immHWVal = 0;
3445             canEncode    = canEncodeHalfwordImm(imm, size, &hwi);
3446             if (canEncode)
3447             {
3448                 // uses a movz encoding
3449                 assert(isGeneralRegister(reg));
3450                 imm = hwi.immHWVal;
3451                 assert(isValidImmHWVal(imm, size));
3452                 fmt = IF_DI_1B;
3453                 break;
3454             }
3455
3456             // Next try the ones-complement form of 'halfword immediate' imm(i16,hw)
3457             notOfImm  = NOT_helper(imm, getBitWidth(size));
3458             canEncode = canEncodeHalfwordImm(notOfImm, size, &hwi);
3459             if (canEncode)
3460             {
3461                 assert(isGeneralRegister(reg));
3462                 imm = hwi.immHWVal;
3463                 ins = INS_movn; // uses a movn encoding
3464                 assert(isValidImmHWVal(imm, size));
3465                 fmt = IF_DI_1B;
3466                 break;
3467             }
3468
3469             // Finally try the 'bitmask immediate' imm(N,r,s)
3470             bmi.immNRS = 0;
3471             canEncode  = canEncodeBitMaskImm(imm, size, &bmi);
3472             if (canEncode)
3473             {
3474                 assert(isGeneralRegisterOrSP(reg));
3475                 reg = encodingSPtoZR(reg);
3476                 imm = bmi.immNRS;
3477                 assert(isValidImmNRS(imm, size));
3478                 fmt = IF_DI_1D;
3479                 break;
3480             }
3481             else
3482             {
3483                 assert(!"Instruction cannot be encoded: mov imm");
3484             }
3485
3486             break;
3487
3488         case INS_movi:
3489             assert(isValidVectorDatasize(size));
3490             assert(isVectorRegister(reg));
3491             if (insOptsNone(opt) && (size == EA_8BYTE))
3492             {
3493                 opt = INS_OPTS_1D;
3494             }
3495             assert(isValidArrangement(size, opt));
3496             elemsize = optGetElemsize(opt);
3497
3498             if (elemsize == EA_8BYTE)
3499             {
3500                 size_t   uimm = imm;
3501                 ssize_t  imm8 = 0;
3502                 unsigned pos  = 0;
3503                 canEncode     = true;
3504                 bool failed   = false;
3505                 while (uimm != 0)
3506                 {
3507                     INT64 loByte = uimm & 0xFF;
3508                     if (((loByte == 0) || (loByte == 0xFF)) && (pos < 8))
3509                     {
3510                         if (loByte == 0xFF)
3511                         {
3512                             imm8 |= (1 << pos);
3513                         }
3514                         uimm >>= 8;
3515                         pos++;
3516                     }
3517                     else
3518                     {
3519                         canEncode = false;
3520                         break;
3521                     }
3522                 }
3523                 imm = imm8;
3524                 assert(isValidUimm8(imm));
3525                 fmt = IF_DV_1B;
3526                 break;
3527             }
3528             else
3529             {
3530                 // Vector operation
3531
3532                 // No explicit LSL/MSL is used for the immediate
3533                 // We will automatically determine the shift based upon the value of imm
3534
3535                 // First try the standard 'byteShifted immediate' imm(i8,bySh)
3536                 bsi.immBSVal = 0;
3537                 canEncode    = canEncodeByteShiftedImm(imm, elemsize, true, &bsi);
3538                 if (canEncode)
3539                 {
3540                     imm = bsi.immBSVal;
3541                     assert(isValidImmBSVal(imm, size));
3542                     fmt = IF_DV_1B;
3543                     break;
3544                 }
3545
3546                 // Next try the ones-complement form of the 'immediate' imm(i8,bySh)
3547                 if ((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE)) // Only EA_2BYTE or EA_4BYTE forms
3548                 {
3549                     notOfImm  = NOT_helper(imm, getBitWidth(elemsize));
3550                     canEncode = canEncodeByteShiftedImm(notOfImm, elemsize, true, &bsi);
3551                     if (canEncode)
3552                     {
3553                         imm = bsi.immBSVal;
3554                         ins = INS_mvni; // uses a mvni encoding
3555                         assert(isValidImmBSVal(imm, size));
3556                         fmt = IF_DV_1B;
3557                         break;
3558                     }
3559                 }
3560             }
3561             break;
3562
3563         case INS_orr:
3564         case INS_bic:
3565         case INS_mvni:
3566             assert(isValidVectorDatasize(size));
3567             assert(isVectorRegister(reg));
3568             assert(isValidArrangement(size, opt));
3569             elemsize = optGetElemsize(opt);
3570             assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE)); // Only EA_2BYTE or EA_4BYTE forms
3571
3572             // Vector operation
3573
3574             // No explicit LSL/MSL is used for the immediate
3575             // We will automatically determine the shift based upon the value of imm
3576
3577             // First try the standard 'byteShifted immediate' imm(i8,bySh)
3578             bsi.immBSVal = 0;
3579             canEncode    = canEncodeByteShiftedImm(imm, elemsize,
3580                                                 (ins == INS_mvni), // mvni supports the ones shifting variant (aka MSL)
3581                                                 &bsi);
3582             if (canEncode)
3583             {
3584                 imm = bsi.immBSVal;
3585                 assert(isValidImmBSVal(imm, size));
3586                 fmt = IF_DV_1B;
3587                 break;
3588             }
3589             break;
3590
3591         case INS_cmp:
3592         case INS_cmn:
3593             assert(insOptsNone(opt));
3594             assert(isGeneralRegister(reg));
3595
3596             if (unsigned_abs(imm) <= 0x0fff)
3597             {
3598                 if (imm < 0)
3599                 {
3600                     ins = insReverse(ins);
3601                     imm = -imm;
3602                 }
3603                 assert(isValidUimm12(imm));
3604                 canEncode = true;
3605                 fmt       = IF_DI_1A;
3606             }
3607             else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
3608             {
3609                 // Encoding will use a 12-bit left shift of the immediate
3610                 opt = INS_OPTS_LSL12;
3611                 if (imm < 0)
3612                 {
3613                     ins = insReverse(ins);
3614                     imm = -imm;
3615                 }
3616                 assert((imm & 0xfff) == 0);
3617                 imm >>= 12;
3618                 assert(isValidUimm12(imm));
3619                 canEncode = true;
3620                 fmt       = IF_DI_1A;
3621             }
3622             else
3623             {
3624                 assert(!"Instruction cannot be encoded: IF_DI_1A");
3625             }
3626             break;
3627
3628         default:
3629             unreached();
3630             break;
3631
3632     } // end switch (ins)
3633
3634     assert(canEncode);
3635     assert(fmt != IF_NONE);
3636
3637     instrDesc* id = emitNewInstrSC(attr, imm);
3638
3639     id->idIns(ins);
3640     id->idInsFmt(fmt);
3641     id->idInsOpt(opt);
3642
3643     id->idReg1(reg);
3644
3645     dispIns(id);
3646     appendToCurIG(id);
3647 }
3648
3649 /*****************************************************************************
3650  *
3651  *  Add an instruction referencing a register and a floating point constant.
3652  */
3653
3654 void emitter::emitIns_R_F(
3655     instruction ins, emitAttr attr, regNumber reg, double immDbl, insOpts opt /* = INS_OPTS_NONE */)
3656
3657 {
3658     emitAttr  size      = EA_SIZE(attr);
3659     emitAttr  elemsize  = EA_UNKNOWN;
3660     insFormat fmt       = IF_NONE;
3661     ssize_t   imm       = 0;
3662     bool      canEncode = false;
3663
3664     /* Figure out the encoding format of the instruction */
3665     switch (ins)
3666     {
3667         floatImm8 fpi;
3668
3669         case INS_fcmp:
3670         case INS_fcmpe:
3671             assert(insOptsNone(opt));
3672             assert(isValidVectorElemsizeFloat(size));
3673             assert(isVectorRegister(reg));
3674             if (immDbl == 0.0)
3675             {
3676                 canEncode = true;
3677                 fmt       = IF_DV_1C;
3678             }
3679             break;
3680
3681         case INS_fmov:
3682             assert(isVectorRegister(reg));
3683             fpi.immFPIVal = 0;
3684             canEncode     = canEncodeFloatImm8(immDbl, &fpi);
3685
3686             if (insOptsAnyArrangement(opt))
3687             {
3688                 // Vector operation
3689                 assert(isValidVectorDatasize(size));
3690                 assert(isValidArrangement(size, opt));
3691                 elemsize = optGetElemsize(opt);
3692                 assert(isValidVectorElemsizeFloat(elemsize));
3693                 assert(opt != INS_OPTS_1D); // Reserved encoding
3694
3695                 if (canEncode)
3696                 {
3697                     imm = fpi.immFPIVal;
3698                     assert((imm >= 0) && (imm <= 0xff));
3699                     fmt = IF_DV_1B;
3700                 }
3701             }
3702             else
3703             {
3704                 // Scalar operation
3705                 assert(insOptsNone(opt));
3706                 assert(isValidVectorElemsizeFloat(size));
3707
3708                 if (canEncode)
3709                 {
3710                     imm = fpi.immFPIVal;
3711                     assert((imm >= 0) && (imm <= 0xff));
3712                     fmt = IF_DV_1A;
3713                 }
3714             }
3715             break;
3716
3717         default:
3718             unreached();
3719             break;
3720
3721     } // end switch (ins)
3722
3723     assert(canEncode);
3724     assert(fmt != IF_NONE);
3725
3726     instrDesc* id = emitNewInstrSC(attr, imm);
3727
3728     id->idIns(ins);
3729     id->idInsFmt(fmt);
3730     id->idInsOpt(opt);
3731
3732     id->idReg1(reg);
3733
3734     dispIns(id);
3735     appendToCurIG(id);
3736 }
3737
3738 /*****************************************************************************
3739  *
3740  *  Add an instruction referencing two registers
3741  */
3742
3743 void emitter::emitIns_R_R(
3744     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insOpts opt /* = INS_OPTS_NONE */)
3745 {
3746     emitAttr  size     = EA_SIZE(attr);
3747     emitAttr  elemsize = EA_UNKNOWN;
3748     insFormat fmt      = IF_NONE;
3749
3750     /* Figure out the encoding format of the instruction */
3751     switch (ins)
3752     {
3753         case INS_mov:
3754             assert(insOptsNone(opt));
3755             // Is the mov even necessary?
3756             if (reg1 == reg2)
3757             {
3758                 // A mov with a EA_4BYTE has the side-effect of clearing the upper bits
3759                 // So only eliminate mov instructions that are not clearing the upper bits
3760                 //
3761                 if (isGeneralRegisterOrSP(reg1) && (size == EA_8BYTE))
3762                 {
3763                     return;
3764                 }
3765                 else if (isVectorRegister(reg1) && (size == EA_16BYTE))
3766                 {
3767                     return;
3768                 }
3769             }
3770
3771             // Check for the 'mov' aliases for the vector registers
3772             if (isVectorRegister(reg1))
3773             {
3774                 if (isVectorRegister(reg2) && isValidVectorDatasize(size))
3775                 {
3776                     return emitIns_R_R_R(INS_mov, size, reg1, reg2, reg2);
3777                 }
3778                 else
3779                 {
3780                     return emitIns_R_R_I(INS_mov, size, reg1, reg2, 0);
3781                 }
3782             }
3783             else
3784             {
3785                 if (isVectorRegister(reg2))
3786                 {
3787                     assert(isGeneralRegister(reg1));
3788                     return emitIns_R_R_I(INS_mov, size, reg1, reg2, 0);
3789                 }
3790             }
3791
3792             // Is this a MOV to/from SP instruction?
3793             if ((reg1 == REG_SP) || (reg2 == REG_SP))
3794             {
3795                 assert(isGeneralRegisterOrSP(reg1));
3796                 assert(isGeneralRegisterOrSP(reg2));
3797                 reg1 = encodingSPtoZR(reg1);
3798                 reg2 = encodingSPtoZR(reg2);
3799                 fmt  = IF_DR_2G;
3800             }
3801             else
3802             {
3803                 assert(insOptsNone(opt));
3804                 assert(isGeneralRegister(reg1));
3805                 assert(isGeneralRegisterOrZR(reg2));
3806                 fmt = IF_DR_2E;
3807             }
3808             break;
3809
3810         case INS_dup:
3811             // Vector operation
3812             assert(insOptsAnyArrangement(opt));
3813             assert(isVectorRegister(reg1));
3814             assert(isGeneralRegisterOrZR(reg2));
3815             assert(isValidVectorDatasize(size));
3816             assert(isValidArrangement(size, opt));
3817             fmt = IF_DV_2C;
3818             break;
3819
3820         case INS_abs:
3821         case INS_not:
3822             assert(isVectorRegister(reg1));
3823             assert(isVectorRegister(reg2));
3824             // for 'NOT' we can construct the arrangement: 8B or 16B
3825             if ((ins == INS_not) && insOptsNone(opt))
3826             {
3827                 assert(isValidVectorDatasize(size));
3828                 elemsize = EA_1BYTE;
3829                 opt      = optMakeArrangement(size, elemsize);
3830             }
3831             if (insOptsNone(opt))
3832             {
3833                 // Scalar operation
3834                 assert(size == EA_8BYTE); // Only type D is supported
3835                 fmt = IF_DV_2L;
3836             }
3837             else
3838             {
3839                 // Vector operation
3840                 assert(insOptsAnyArrangement(opt));
3841                 assert(isValidVectorDatasize(size));
3842                 assert(isValidArrangement(size, opt));
3843                 elemsize = optGetElemsize(opt);
3844                 if (ins == INS_not)
3845                 {
3846                     assert(elemsize == EA_1BYTE);
3847                 }
3848                 fmt = IF_DV_2M;
3849             }
3850             break;
3851
3852         case INS_mvn:
3853         case INS_neg:
3854             if (isVectorRegister(reg1))
3855             {
3856                 assert(isVectorRegister(reg2));
3857                 // for 'mvn' we can construct the arrangement: 8B or 16b
3858                 if ((ins == INS_mvn) && insOptsNone(opt))
3859                 {
3860                     assert(isValidVectorDatasize(size));
3861                     elemsize = EA_1BYTE;
3862                     opt      = optMakeArrangement(size, elemsize);
3863                 }
3864                 if (insOptsNone(opt))
3865                 {
3866                     // Scalar operation
3867                     assert(size == EA_8BYTE); // Only type D is supported
3868                     fmt = IF_DV_2L;
3869                 }
3870                 else
3871                 {
3872                     // Vector operation
3873                     assert(isValidVectorDatasize(size));
3874                     assert(isValidArrangement(size, opt));
3875                     elemsize = optGetElemsize(opt);
3876                     if (ins == INS_mvn)
3877                     {
3878                         assert(elemsize == EA_1BYTE); // Only supports 8B or 16B
3879                     }
3880                     fmt = IF_DV_2M;
3881                 }
3882                 break;
3883             }
3884             __fallthrough;
3885
3886         case INS_negs:
3887             assert(insOptsNone(opt));
3888             assert(isGeneralRegister(reg1));
3889             assert(isGeneralRegisterOrZR(reg2));
3890             fmt = IF_DR_2E;
3891             break;
3892
3893         case INS_sxtw:
3894             assert(size == EA_8BYTE);
3895             __fallthrough;
3896
3897         case INS_sxtb:
3898         case INS_sxth:
3899         case INS_uxtb:
3900         case INS_uxth:
3901             assert(insOptsNone(opt));
3902             assert(isValidGeneralDatasize(size));
3903             assert(isGeneralRegister(reg1));
3904             assert(isGeneralRegister(reg2));
3905             fmt = IF_DR_2H;
3906             break;
3907
3908         case INS_sxtl:
3909         case INS_sxtl2:
3910         case INS_uxtl:
3911         case INS_uxtl2:
3912             return emitIns_R_R_I(ins, size, reg1, reg2, 0, opt);
3913
3914         case INS_cls:
3915         case INS_clz:
3916         case INS_rbit:
3917         case INS_rev16:
3918         case INS_rev32:
3919         case INS_cnt:
3920             if (isVectorRegister(reg1))
3921             {
3922                 assert(isVectorRegister(reg2));
3923                 assert(isValidVectorDatasize(size));
3924                 assert(isValidArrangement(size, opt));
3925                 elemsize = optGetElemsize(opt);
3926                 if ((ins == INS_cls) || (ins == INS_clz))
3927                 {
3928                     assert(elemsize != EA_8BYTE); // No encoding for type D
3929                 }
3930                 else if (ins == INS_rev32)
3931                 {
3932                     assert((elemsize == EA_2BYTE) || (elemsize == EA_1BYTE));
3933                 }
3934                 else
3935                 {
3936                     assert(elemsize == EA_1BYTE); // Only supports 8B or 16B
3937                 }
3938                 fmt = IF_DV_2M;
3939                 break;
3940             }
3941             if (ins == INS_cnt)
3942             {
3943                 // Doesn't have general register version(s)
3944                 break;
3945             }
3946
3947             __fallthrough;
3948
3949         case INS_rev:
3950             assert(insOptsNone(opt));
3951             assert(isGeneralRegister(reg1));
3952             assert(isGeneralRegister(reg2));
3953             if (ins == INS_rev32)
3954             {
3955                 assert(size == EA_8BYTE);
3956             }
3957             else
3958             {
3959                 assert(isValidGeneralDatasize(size));
3960             }
3961             fmt = IF_DR_2G;
3962             break;
3963
3964         case INS_addv:
3965         case INS_saddlv:
3966         case INS_smaxv:
3967         case INS_sminv:
3968         case INS_uaddlv:
3969         case INS_umaxv:
3970         case INS_uminv:
3971         case INS_rev64:
3972             assert(isVectorRegister(reg1));
3973             assert(isVectorRegister(reg2));
3974             assert(isValidVectorDatasize(size));
3975             assert(isValidArrangement(size, opt));
3976             elemsize = optGetElemsize(opt);
3977             assert(elemsize != EA_8BYTE); // No encoding for type D
3978             fmt = IF_DV_2M;
3979             break;
3980
3981         case INS_xtn:
3982         case INS_xtn2:
3983             assert(isVectorRegister(reg1));
3984             assert(isVectorRegister(reg2));
3985             assert(isValidVectorDatasize(size));
3986             assert(isValidArrangement(size, opt));
3987             elemsize = optGetElemsize(opt);
3988             assert(size == (ins == INS_xtn) ? EA_8BYTE : EA_16BYTE); // Size is determined by instruction
3989             assert(elemsize != EA_8BYTE);                            // Narrowing must not end with 8 byte data
3990             fmt = IF_DV_2M;
3991             break;
3992
3993         case INS_ldar:
3994         case INS_ldaxr:
3995         case INS_ldxr:
3996         case INS_stlr:
3997             assert(isValidGeneralDatasize(size));
3998
3999             __fallthrough;
4000
4001         case INS_ldarb:
4002         case INS_ldaxrb:
4003         case INS_ldxrb:
4004         case INS_ldarh:
4005         case INS_ldaxrh:
4006         case INS_ldxrh:
4007         case INS_stlrb:
4008         case INS_stlrh:
4009             assert(isValidGeneralLSDatasize(size));
4010             assert(isGeneralRegisterOrZR(reg1));
4011             assert(isGeneralRegisterOrSP(reg2));
4012             assert(insOptsNone(opt));
4013
4014             reg2 = encodingSPtoZR(reg2);
4015
4016             fmt = IF_LS_2A;
4017             break;
4018
4019         case INS_ldr:
4020         case INS_ldrb:
4021         case INS_ldrh:
4022         case INS_ldrsb:
4023         case INS_ldrsh:
4024         case INS_ldrsw:
4025         case INS_str:
4026         case INS_strb:
4027         case INS_strh:
4028
4029         case INS_cmp:
4030         case INS_cmn:
4031         case INS_tst:
4032             assert(insOptsNone(opt));
4033             emitIns_R_R_I(ins, attr, reg1, reg2, 0, INS_OPTS_NONE);
4034             return;
4035
4036         case INS_fmov:
4037             assert(isValidVectorElemsizeFloat(size));
4038
4039             // Is the mov even necessary?
4040             if (reg1 == reg2)
4041             {
4042                 return;
4043             }
4044
4045             if (isVectorRegister(reg1))
4046             {
4047                 if (isVectorRegister(reg2))
4048                 {
4049                     assert(insOptsNone(opt));
4050                     fmt = IF_DV_2G;
4051                 }
4052                 else
4053                 {
4054                     assert(isGeneralRegister(reg2));
4055
4056                     // if the optional conversion specifier is not present we calculate it
4057                     if (opt == INS_OPTS_NONE)
4058                     {
4059                         opt = (size == EA_4BYTE) ? INS_OPTS_4BYTE_TO_S : INS_OPTS_8BYTE_TO_D;
4060                     }
4061                     assert(insOptsConvertIntToFloat(opt));
4062
4063                     fmt = IF_DV_2I;
4064                 }
4065             }
4066             else
4067             {
4068                 assert(isGeneralRegister(reg1));
4069                 assert(isVectorRegister(reg2));
4070
4071                 // if the optional conversion specifier is not present we calculate it
4072                 if (opt == INS_OPTS_NONE)
4073                 {
4074                     opt = (size == EA_4BYTE) ? INS_OPTS_S_TO_4BYTE : INS_OPTS_D_TO_8BYTE;
4075                 }
4076                 assert(insOptsConvertFloatToInt(opt));
4077
4078                 fmt = IF_DV_2H;
4079             }
4080             break;
4081
4082         case INS_fcmp:
4083         case INS_fcmpe:
4084             assert(insOptsNone(opt));
4085             assert(isValidVectorElemsizeFloat(size));
4086             assert(isVectorRegister(reg1));
4087             assert(isVectorRegister(reg2));
4088             fmt = IF_DV_2K;
4089             break;
4090
4091         case INS_fcvtns:
4092         case INS_fcvtnu:
4093         case INS_fcvtas:
4094         case INS_fcvtau:
4095         case INS_fcvtps:
4096         case INS_fcvtpu:
4097         case INS_fcvtms:
4098         case INS_fcvtmu:
4099         case INS_fcvtzs:
4100         case INS_fcvtzu:
4101             if (insOptsAnyArrangement(opt))
4102             {
4103                 // Vector operation
4104                 assert(isVectorRegister(reg1));
4105                 assert(isVectorRegister(reg2));
4106                 assert(isValidVectorDatasize(size));
4107                 assert(isValidArrangement(size, opt));
4108                 elemsize = optGetElemsize(opt);
4109                 assert(isValidVectorElemsizeFloat(elemsize));
4110                 assert(opt != INS_OPTS_1D); // Reserved encoding
4111                 fmt = IF_DV_2A;
4112             }
4113             else
4114             {
4115                 // Scalar operation
4116                 assert(isVectorRegister(reg2));
4117                 if (isVectorRegister(reg1))
4118                 {
4119                     assert(insOptsNone(opt));
4120                     assert(isValidVectorElemsizeFloat(size));
4121                     fmt = IF_DV_2G;
4122                 }
4123                 else
4124                 {
4125                     assert(isGeneralRegister(reg1));
4126                     assert(insOptsConvertFloatToInt(opt));
4127                     assert(isValidVectorElemsizeFloat(size));
4128                     fmt = IF_DV_2H;
4129                 }
4130             }
4131             break;
4132
4133         case INS_fcvtl:
4134         case INS_fcvtl2:
4135         case INS_fcvtn:
4136         case INS_fcvtn2:
4137             assert(isVectorRegister(reg1));
4138             assert(isVectorRegister(reg2));
4139             assert(isValidVectorDatasize(size));
4140             assert(insOptsNone(opt));
4141             assert(size == EA_8BYTE); // Narrowing from Double or Widening to Double (Half not supported)
4142             fmt = IF_DV_2G;
4143             break;
4144
4145         case INS_scvtf:
4146         case INS_ucvtf:
4147             if (insOptsAnyArrangement(opt))
4148             {
4149                 // Vector operation
4150                 assert(isVectorRegister(reg1));
4151                 assert(isVectorRegister(reg2));
4152                 assert(isValidVectorDatasize(size));
4153                 assert(isValidArrangement(size, opt));
4154                 elemsize = optGetElemsize(opt);
4155                 assert(isValidVectorElemsizeFloat(elemsize));
4156                 assert(opt != INS_OPTS_1D); // Reserved encoding
4157                 fmt = IF_DV_2A;
4158             }
4159             else
4160             {
4161                 // Scalar operation
4162                 assert(isVectorRegister(reg1));
4163                 if (isVectorRegister(reg2))
4164                 {
4165                     assert(insOptsNone(opt));
4166                     assert(isValidVectorElemsizeFloat(size));
4167                     fmt = IF_DV_2G;
4168                 }
4169                 else
4170                 {
4171                     assert(isGeneralRegister(reg2));
4172                     assert(insOptsConvertIntToFloat(opt));
4173                     assert(isValidVectorElemsizeFloat(size));
4174                     fmt = IF_DV_2I;
4175                 }
4176             }
4177             break;
4178
4179         case INS_fabs:
4180         case INS_fneg:
4181         case INS_fsqrt:
4182         case INS_frinta:
4183         case INS_frinti:
4184         case INS_frintm:
4185         case INS_frintn:
4186         case INS_frintp:
4187         case INS_frintx:
4188         case INS_frintz:
4189             if (insOptsAnyArrangement(opt))
4190             {
4191                 // Vector operation
4192                 assert(isVectorRegister(reg1));
4193                 assert(isVectorRegister(reg2));
4194                 assert(isValidVectorDatasize(size));
4195                 assert(isValidArrangement(size, opt));
4196                 elemsize = optGetElemsize(opt);
4197                 assert(isValidVectorElemsizeFloat(elemsize));
4198                 assert(opt != INS_OPTS_1D); // Reserved encoding
4199                 fmt = IF_DV_2A;
4200             }
4201             else
4202             {
4203                 // Scalar operation
4204                 assert(insOptsNone(opt));
4205                 assert(isValidVectorElemsizeFloat(size));
4206                 assert(isVectorRegister(reg1));
4207                 assert(isVectorRegister(reg2));
4208                 fmt = IF_DV_2G;
4209             }
4210             break;
4211
4212         case INS_faddp:
4213             // Scalar operation
4214             assert(insOptsNone(opt));
4215             assert(isValidVectorElemsizeFloat(size));
4216             assert(isVectorRegister(reg1));
4217             assert(isVectorRegister(reg2));
4218             fmt = IF_DV_2G;
4219             break;
4220
4221         case INS_fcvt:
4222             assert(insOptsConvertFloatToFloat(opt));
4223             assert(isValidVectorFcvtsize(size));
4224             assert(isVectorRegister(reg1));
4225             assert(isVectorRegister(reg2));
4226             fmt = IF_DV_2J;
4227             break;
4228
4229         default:
4230             unreached();
4231             break;
4232
4233     } // end switch (ins)
4234
4235     assert(fmt != IF_NONE);
4236
4237     instrDesc* id = emitNewInstrSmall(attr);
4238
4239     id->idIns(ins);
4240     id->idInsFmt(fmt);
4241     id->idInsOpt(opt);
4242
4243     id->idReg1(reg1);
4244     id->idReg2(reg2);
4245
4246     dispIns(id);
4247     appendToCurIG(id);
4248 }
4249
4250 /*****************************************************************************
4251  *
4252  *  Add an instruction referencing a register and two constants.
4253  */
4254
4255 void emitter::emitIns_R_I_I(
4256     instruction ins, emitAttr attr, regNumber reg, ssize_t imm1, ssize_t imm2, insOpts opt /* = INS_OPTS_NONE */)
4257 {
4258     emitAttr  size   = EA_SIZE(attr);
4259     insFormat fmt    = IF_NONE;
4260     size_t    immOut = 0; // composed from imm1 and imm2 and stored in the instrDesc
4261
4262     /* Figure out the encoding format of the instruction */
4263     switch (ins)
4264     {
4265         bool        canEncode;
4266         halfwordImm hwi;
4267
4268         case INS_mov:
4269             ins = INS_movz; // INS_mov with LSL is an alias for INS_movz LSL
4270             __fallthrough;
4271
4272         case INS_movk:
4273         case INS_movn:
4274         case INS_movz:
4275             assert(isValidGeneralDatasize(size));
4276             assert(isGeneralRegister(reg));
4277             assert(isValidUimm16(imm1));
4278             assert(insOptsLSL(opt)); // Must be INS_OPTS_LSL
4279
4280             if (size == EA_8BYTE)
4281             {
4282                 assert((imm2 == 0) || (imm2 == 16) || // shift amount: 0, 16, 32 or 48
4283                        (imm2 == 32) || (imm2 == 48));
4284             }
4285             else // EA_4BYTE
4286             {
4287                 assert((imm2 == 0) || (imm2 == 16)); // shift amount: 0 or 16
4288             }
4289
4290             hwi.immHWVal = 0;
4291
4292             switch (imm2)
4293             {
4294                 case 0:
4295                     hwi.immHW = 0;
4296                     canEncode = true;
4297                     break;
4298
4299                 case 16:
4300                     hwi.immHW = 1;
4301                     canEncode = true;
4302                     break;
4303
4304                 case 32:
4305                     hwi.immHW = 2;
4306                     canEncode = true;
4307                     break;
4308
4309                 case 48:
4310                     hwi.immHW = 3;
4311                     canEncode = true;
4312                     break;
4313
4314                 default:
4315                     canEncode = false;
4316             }
4317
4318             if (canEncode)
4319             {
4320                 hwi.immVal = imm1;
4321
4322                 immOut = hwi.immHWVal;
4323                 assert(isValidImmHWVal(immOut, size));
4324                 fmt = IF_DI_1B;
4325             }
4326             break;
4327
4328         default:
4329             unreached();
4330             break;
4331
4332     } // end switch (ins)
4333
4334     assert(fmt != IF_NONE);
4335
4336     instrDesc* id = emitNewInstrSC(attr, immOut);
4337
4338     id->idIns(ins);
4339     id->idInsFmt(fmt);
4340
4341     id->idReg1(reg);
4342
4343     dispIns(id);
4344     appendToCurIG(id);
4345 }
4346
4347 /*****************************************************************************
4348  *
4349  *  Add an instruction referencing two registers and a constant.
4350  */
4351
4352 void emitter::emitIns_R_R_I(
4353     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm, insOpts opt /* = INS_OPTS_NONE */)
4354 {
4355     emitAttr  size       = EA_SIZE(attr);
4356     emitAttr  elemsize   = EA_UNKNOWN;
4357     insFormat fmt        = IF_NONE;
4358     bool      isLdSt     = false;
4359     bool      isSIMD     = false;
4360     bool      isAddSub   = false;
4361     bool      setFlags   = false;
4362     unsigned  scale      = 0;
4363     bool      unscaledOp = false;
4364
4365     /* Figure out the encoding format of the instruction */
4366     switch (ins)
4367     {
4368         bool       canEncode;
4369         bitMaskImm bmi;
4370
4371         case INS_mov:
4372             // Check for the 'mov' aliases for the vector registers
4373             assert(insOptsNone(opt));
4374             assert(isValidVectorElemsize(size));
4375             elemsize = size;
4376             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4377
4378             if (isVectorRegister(reg1))
4379             {
4380                 if (isGeneralRegisterOrZR(reg2))
4381                 {
4382                     fmt = IF_DV_2C; // Alias for 'ins'
4383                     break;
4384                 }
4385                 else if (isVectorRegister(reg2))
4386                 {
4387                     fmt = IF_DV_2E; // Alias for 'dup'
4388                     break;
4389                 }
4390             }
4391             else // isGeneralRegister(reg1)
4392             {
4393                 assert(isGeneralRegister(reg1));
4394                 if (isVectorRegister(reg2))
4395                 {
4396                     fmt = IF_DV_2B; // Alias for 'umov'
4397                     break;
4398                 }
4399             }
4400             assert(!" invalid INS_mov operands");
4401             break;
4402
4403         case INS_lsl:
4404         case INS_lsr:
4405         case INS_asr:
4406             assert(insOptsNone(opt));
4407             assert(isValidGeneralDatasize(size));
4408             assert(isGeneralRegister(reg1));
4409             assert(isGeneralRegister(reg2));
4410             assert(isValidImmShift(imm, size));
4411             fmt = IF_DI_2D;
4412             break;
4413
4414         case INS_ror:
4415             assert(insOptsNone(opt));
4416             assert(isValidGeneralDatasize(size));
4417             assert(isGeneralRegister(reg1));
4418             assert(isGeneralRegister(reg2));
4419             assert(isValidImmShift(imm, size));
4420             fmt = IF_DI_2B;
4421             break;
4422
4423         case INS_sshr:
4424         case INS_ssra:
4425         case INS_srshr:
4426         case INS_srsra:
4427         case INS_shl:
4428         case INS_ushr:
4429         case INS_usra:
4430         case INS_urshr:
4431         case INS_ursra:
4432         case INS_sri:
4433         case INS_sli:
4434             assert(isVectorRegister(reg1));
4435             assert(isVectorRegister(reg2));
4436             if (insOptsAnyArrangement(opt))
4437             {
4438                 // Vector operation
4439                 assert(isValidVectorDatasize(size));
4440                 assert(isValidArrangement(size, opt));
4441                 elemsize = optGetElemsize(opt);
4442                 assert(isValidVectorElemsize(elemsize));
4443                 assert(isValidImmShift(imm, elemsize));
4444                 assert(opt != INS_OPTS_1D); // Reserved encoding
4445                 fmt = IF_DV_2O;
4446                 break;
4447             }
4448             else
4449             {
4450                 // Scalar operation
4451                 assert(insOptsNone(opt));
4452                 assert(size == EA_8BYTE); // only supported size
4453                 assert(isValidImmShift(imm, size));
4454                 fmt = IF_DV_2N;
4455             }
4456             break;
4457
4458         case INS_sxtl:
4459         case INS_uxtl:
4460             assert(imm == 0);
4461             __fallthrough;
4462
4463         case INS_shrn:
4464         case INS_rshrn:
4465         case INS_sshll:
4466         case INS_ushll:
4467             assert(isVectorRegister(reg1));
4468             assert(isVectorRegister(reg2));
4469             // Vector operation
4470             assert(size == EA_8BYTE);
4471             assert(isValidArrangement(size, opt));
4472             elemsize = optGetElemsize(opt);
4473             assert(elemsize != EA_8BYTE); // Reserved encodings
4474             assert(isValidVectorElemsize(elemsize));
4475             assert(isValidImmShift(imm, elemsize));
4476             fmt = IF_DV_2O;
4477             break;
4478
4479         case INS_sxtl2:
4480         case INS_uxtl2:
4481             assert(imm == 0);
4482             __fallthrough;
4483
4484         case INS_shrn2:
4485         case INS_rshrn2:
4486         case INS_sshll2:
4487         case INS_ushll2:
4488             assert(isVectorRegister(reg1));
4489             assert(isVectorRegister(reg2));
4490             // Vector operation
4491             assert(size == EA_16BYTE);
4492             assert(isValidArrangement(size, opt));
4493             elemsize = optGetElemsize(opt);
4494             assert(elemsize != EA_8BYTE); // Reserved encodings
4495             assert(isValidVectorElemsize(elemsize));
4496             assert(isValidImmShift(imm, elemsize));
4497             fmt = IF_DV_2O;
4498             break;
4499
4500         case INS_mvn:
4501         case INS_neg:
4502         case INS_negs:
4503             assert(isValidGeneralDatasize(size));
4504             assert(isGeneralRegister(reg1));
4505             assert(isGeneralRegisterOrZR(reg2));
4506
4507             if (imm == 0)
4508             {
4509                 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4510
4511                 fmt = IF_DR_2E;
4512             }
4513             else
4514             {
4515                 if (ins == INS_mvn)
4516                 {
4517                     assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
4518                 }
4519                 else // neg or negs
4520                 {
4521                     assert(insOptsAluShift(opt)); // a non-zero imm, must select shift kind, can't use ROR
4522                 }
4523                 assert(isValidImmShift(imm, size));
4524                 fmt = IF_DR_2F;
4525             }
4526             break;
4527
4528         case INS_tst:
4529             assert(isValidGeneralDatasize(size));
4530             assert(isGeneralRegisterOrZR(reg1));
4531             assert(isGeneralRegister(reg2));
4532
4533             if (insOptsAnyShift(opt))
4534             {
4535                 assert(isValidImmShift(imm, size) && (imm != 0));
4536                 fmt = IF_DR_2B;
4537             }
4538             else
4539             {
4540                 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4541                 assert(imm == 0);
4542                 fmt = IF_DR_2A;
4543             }
4544             break;
4545
4546         case INS_cmp:
4547         case INS_cmn:
4548             assert(isValidGeneralDatasize(size));
4549             assert(isGeneralRegisterOrSP(reg1));
4550             assert(isGeneralRegister(reg2));
4551
4552             reg1 = encodingSPtoZR(reg1);
4553             if (insOptsAnyExtend(opt))
4554             {
4555                 assert((imm >= 0) && (imm <= 4));
4556
4557                 fmt = IF_DR_2C;
4558             }
4559             else if (imm == 0)
4560             {
4561                 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4562
4563                 fmt = IF_DR_2A;
4564             }
4565             else
4566             {
4567                 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
4568                 assert(isValidImmShift(imm, size));
4569                 fmt = IF_DR_2B;
4570             }
4571             break;
4572
4573         case INS_ands:
4574         case INS_and:
4575         case INS_eor:
4576         case INS_orr:
4577             assert(insOptsNone(opt));
4578             assert(isGeneralRegister(reg2));
4579             if (ins == INS_ands)
4580             {
4581                 assert(isGeneralRegister(reg1));
4582             }
4583             else
4584             {
4585                 assert(isGeneralRegisterOrSP(reg1));
4586                 reg1 = encodingSPtoZR(reg1);
4587             }
4588
4589             bmi.immNRS = 0;
4590             canEncode  = canEncodeBitMaskImm(imm, size, &bmi);
4591             if (canEncode)
4592             {
4593                 imm = bmi.immNRS;
4594                 assert(isValidImmNRS(imm, size));
4595                 fmt = IF_DI_2C;
4596             }
4597             break;
4598
4599         case INS_dup: // by element, imm selects the element of reg2
4600             assert(isVectorRegister(reg1));
4601             if (isVectorRegister(reg2))
4602             {
4603                 if (insOptsAnyArrangement(opt))
4604                 {
4605                     // Vector operation
4606                     assert(isValidVectorDatasize(size));
4607                     assert(isValidArrangement(size, opt));
4608                     elemsize = optGetElemsize(opt);
4609                     assert(isValidVectorElemsize(elemsize));
4610                     assert(isValidVectorIndex(size, elemsize, imm));
4611                     assert(opt != INS_OPTS_1D); // Reserved encoding
4612                     fmt = IF_DV_2D;
4613                     break;
4614                 }
4615                 else
4616                 {
4617                     // Scalar operation
4618                     assert(insOptsNone(opt));
4619                     elemsize = size;
4620                     assert(isValidVectorElemsize(elemsize));
4621                     assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4622                     fmt = IF_DV_2E;
4623                     break;
4624                 }
4625             }
4626             __fallthrough;
4627
4628         case INS_ins: // (MOV from general)
4629             assert(insOptsNone(opt));
4630             assert(isValidVectorElemsize(size));
4631             assert(isVectorRegister(reg1));
4632             assert(isGeneralRegisterOrZR(reg2));
4633             elemsize = size;
4634             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4635             fmt = IF_DV_2C;
4636             break;
4637
4638         case INS_umov: // (MOV to general)
4639             assert(insOptsNone(opt));
4640             assert(isValidVectorElemsize(size));
4641             assert(isGeneralRegister(reg1));
4642             assert(isVectorRegister(reg2));
4643             elemsize = size;
4644             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4645             fmt = IF_DV_2B;
4646             break;
4647
4648         case INS_smov:
4649             assert(insOptsNone(opt));
4650             assert(isValidVectorElemsize(size));
4651             assert(size != EA_8BYTE); // no encoding, use INS_umov
4652             assert(isGeneralRegister(reg1));
4653             assert(isVectorRegister(reg2));
4654             elemsize = size;
4655             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4656             fmt = IF_DV_2B;
4657             break;
4658
4659         case INS_add:
4660         case INS_sub:
4661             setFlags = false;
4662             isAddSub = true;
4663             break;
4664
4665         case INS_adds:
4666         case INS_subs:
4667             setFlags = true;
4668             isAddSub = true;
4669             break;
4670
4671         case INS_ldrsb:
4672         case INS_ldursb:
4673             // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4674             assert(isValidGeneralDatasize(size));
4675             unscaledOp = (ins == INS_ldursb);
4676             scale      = 0;
4677             isLdSt     = true;
4678             break;
4679
4680         case INS_ldrsh:
4681         case INS_ldursh:
4682             // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4683             assert(isValidGeneralDatasize(size));
4684             unscaledOp = (ins == INS_ldursh);
4685             scale      = 1;
4686             isLdSt     = true;
4687             break;
4688
4689         case INS_ldrsw:
4690         case INS_ldursw:
4691             // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4692             assert(size == EA_8BYTE);
4693             unscaledOp = (ins == INS_ldursw);
4694             scale      = 2;
4695             isLdSt     = true;
4696             break;
4697
4698         case INS_ldrb:
4699         case INS_strb:
4700             // size is ignored
4701             unscaledOp = false;
4702             scale      = 0;
4703             isLdSt     = true;
4704             break;
4705
4706         case INS_ldurb:
4707         case INS_sturb:
4708             // size is ignored
4709             unscaledOp = true;
4710             scale      = 0;
4711             isLdSt     = true;
4712             break;
4713
4714         case INS_ldrh:
4715         case INS_strh:
4716             // size is ignored
4717             unscaledOp = false;
4718             scale      = 1;
4719             isLdSt     = true;
4720             break;
4721
4722         case INS_ldurh:
4723         case INS_sturh:
4724             // size is ignored
4725             unscaledOp = true;
4726             scale      = 0;
4727             isLdSt     = true;
4728             break;
4729
4730         case INS_ldr:
4731         case INS_str:
4732             // Is the target a vector register?
4733             if (isVectorRegister(reg1))
4734             {
4735                 assert(isValidVectorLSDatasize(size));
4736                 assert(isGeneralRegisterOrSP(reg2));
4737                 isSIMD = true;
4738             }
4739             else
4740             {
4741                 assert(isValidGeneralDatasize(size));
4742             }
4743             unscaledOp = false;
4744             scale      = NaturalScale_helper(size);
4745             isLdSt     = true;
4746             break;
4747
4748         case INS_ldur:
4749         case INS_stur:
4750             // Is the target a vector register?
4751             if (isVectorRegister(reg1))
4752             {
4753                 assert(isValidVectorLSDatasize(size));
4754                 assert(isGeneralRegisterOrSP(reg2));
4755                 isSIMD = true;
4756             }
4757             else
4758             {
4759                 assert(isValidGeneralDatasize(size));
4760             }
4761             unscaledOp = true;
4762             scale      = 0;
4763             isLdSt     = true;
4764             break;
4765
4766         default:
4767             unreached();
4768             break;
4769
4770     } // end switch (ins)
4771
4772     if (isLdSt)
4773     {
4774         assert(!isAddSub);
4775
4776         if (isSIMD)
4777         {
4778             assert(isValidVectorLSDatasize(size));
4779             assert(isVectorRegister(reg1));
4780             assert((scale >= 0) && (scale <= 4));
4781         }
4782         else
4783         {
4784             assert(isValidGeneralLSDatasize(size));
4785             assert(isGeneralRegisterOrZR(reg1));
4786             assert((scale >= 0) && (scale <= 3));
4787         }
4788
4789         assert(isGeneralRegisterOrSP(reg2));
4790
4791         // Load/Store reserved encodings:
4792         if (insOptsIndexed(opt))
4793         {
4794             assert(reg1 != reg2);
4795         }
4796
4797         reg2 = encodingSPtoZR(reg2);
4798
4799         ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
4800         if (imm == 0)
4801         {
4802             assert(insOptsNone(opt)); // PRE/POST Index doesn't make sense with an immediate of zero
4803
4804             fmt = IF_LS_2A;
4805         }
4806         else if (insOptsIndexed(opt) || unscaledOp || (imm < 0) || ((imm & mask) != 0))
4807         {
4808             if ((imm >= -256) && (imm <= 255))
4809             {
4810                 fmt = IF_LS_2C;
4811             }
4812             else
4813             {
4814                 assert(!"Instruction cannot be encoded: IF_LS_2C");
4815             }
4816         }
4817         else if (imm > 0)
4818         {
4819             assert(insOptsNone(opt));
4820             assert(!unscaledOp);
4821
4822             if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
4823             {
4824                 imm >>= scale; // The immediate is scaled by the size of the ld/st
4825
4826                 fmt = IF_LS_2B;
4827             }
4828             else
4829             {
4830                 assert(!"Instruction cannot be encoded: IF_LS_2B");
4831             }
4832         }
4833     }
4834     else if (isAddSub)
4835     {
4836         assert(!isLdSt);
4837         assert(insOptsNone(opt));
4838
4839         if (setFlags) // Can't encode SP with setFlags
4840         {
4841             assert(isGeneralRegister(reg1));
4842             assert(isGeneralRegister(reg2));
4843         }
4844         else
4845         {
4846             assert(isGeneralRegisterOrSP(reg1));
4847             assert(isGeneralRegisterOrSP(reg2));
4848
4849             // Is it just a mov?
4850             if (imm == 0)
4851             {
4852                 // Is the mov even necessary?
4853                 if (reg1 != reg2)
4854                 {
4855                     emitIns_R_R(INS_mov, attr, reg1, reg2);
4856                 }
4857                 return;
4858             }
4859
4860             reg1 = encodingSPtoZR(reg1);
4861             reg2 = encodingSPtoZR(reg2);
4862         }
4863
4864         if (unsigned_abs(imm) <= 0x0fff)
4865         {
4866             if (imm < 0)
4867             {
4868                 ins = insReverse(ins);
4869                 imm = -imm;
4870             }
4871             assert(isValidUimm12(imm));
4872             fmt = IF_DI_2A;
4873         }
4874         else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
4875         {
4876             // Encoding will use a 12-bit left shift of the immediate
4877             opt = INS_OPTS_LSL12;
4878             if (imm < 0)
4879             {
4880                 ins = insReverse(ins);
4881                 imm = -imm;
4882             }
4883             assert((imm & 0xfff) == 0);
4884             imm >>= 12;
4885             assert(isValidUimm12(imm));
4886             fmt = IF_DI_2A;
4887         }
4888         else
4889         {
4890             assert(!"Instruction cannot be encoded: IF_DI_2A");
4891         }
4892     }
4893
4894     assert(fmt != IF_NONE);
4895
4896     instrDesc* id = emitNewInstrSC(attr, imm);
4897
4898     id->idIns(ins);
4899     id->idInsFmt(fmt);
4900     id->idInsOpt(opt);
4901
4902     id->idReg1(reg1);
4903     id->idReg2(reg2);
4904
4905     dispIns(id);
4906     appendToCurIG(id);
4907 }
4908
4909 /*****************************************************************************
4910 *
4911 *  Add an instruction referencing two registers and a constant.
4912 *  Also checks for a large immediate that needs a second instruction
4913 *  and will load it in reg1
4914 *
4915 *  - Supports instructions: add, adds, sub, subs, and, ands, eor and orr
4916 *  - Requires that reg1 is a general register and not SP or ZR
4917 *  - Requires that reg1 != reg2
4918 */
4919 void emitter::emitIns_R_R_Imm(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm)
4920 {
4921     assert(isGeneralRegister(reg1));
4922     assert(reg1 != reg2);
4923
4924     bool immFits = true;
4925
4926     switch (ins)
4927     {
4928         case INS_add:
4929         case INS_adds:
4930         case INS_sub:
4931         case INS_subs:
4932             immFits = emitter::emitIns_valid_imm_for_add(imm, attr);
4933             break;
4934
4935         case INS_ands:
4936         case INS_and:
4937         case INS_eor:
4938         case INS_orr:
4939             immFits = emitter::emitIns_valid_imm_for_alu(imm, attr);
4940             break;
4941
4942         default:
4943             assert(!"Unsupported instruction in emitIns_R_R_Imm");
4944     }
4945
4946     if (immFits)
4947     {
4948         emitIns_R_R_I(ins, attr, reg1, reg2, imm);
4949     }
4950     else
4951     {
4952         // Load 'imm' into the reg1 register
4953         // then issue:   'ins'  reg1, reg2, reg1
4954         //
4955         codeGen->instGen_Set_Reg_To_Imm(attr, reg1, imm);
4956         emitIns_R_R_R(ins, attr, reg1, reg2, reg1);
4957     }
4958 }
4959
4960 /*****************************************************************************
4961  *
4962  *  Add an instruction referencing three registers.
4963  */
4964
4965 void emitter::emitIns_R_R_R(
4966     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insOpts opt) /* = INS_OPTS_NONE */
4967 {
4968     emitAttr  size     = EA_SIZE(attr);
4969     emitAttr  elemsize = EA_UNKNOWN;
4970     insFormat fmt      = IF_NONE;
4971
4972     /* Figure out the encoding format of the instruction */
4973     switch (ins)
4974     {
4975         case INS_lsl:
4976         case INS_lsr:
4977         case INS_asr:
4978         case INS_ror:
4979         case INS_adc:
4980         case INS_adcs:
4981         case INS_sbc:
4982         case INS_sbcs:
4983         case INS_udiv:
4984         case INS_sdiv:
4985         case INS_mneg:
4986         case INS_smull:
4987         case INS_smnegl:
4988         case INS_smulh:
4989         case INS_umull:
4990         case INS_umnegl:
4991         case INS_umulh:
4992         case INS_lslv:
4993         case INS_lsrv:
4994         case INS_asrv:
4995         case INS_rorv:
4996             assert(insOptsNone(opt));
4997             assert(isValidGeneralDatasize(size));
4998             assert(isGeneralRegister(reg1));
4999             assert(isGeneralRegister(reg2));
5000             assert(isGeneralRegister(reg3));
5001             fmt = IF_DR_3A;
5002             break;
5003
5004         case INS_mul:
5005             if (insOptsNone(opt))
5006             {
5007                 // general register
5008                 assert(isValidGeneralDatasize(size));
5009                 assert(isGeneralRegister(reg1));
5010                 assert(isGeneralRegister(reg2));
5011                 assert(isGeneralRegister(reg3));
5012                 fmt = IF_DR_3A;
5013                 break;
5014             }
5015             __fallthrough;
5016
5017         case INS_mla:
5018         case INS_mls:
5019         case INS_pmul:
5020             assert(insOptsAnyArrangement(opt));
5021             assert(isVectorRegister(reg1));
5022             assert(isVectorRegister(reg2));
5023             assert(isVectorRegister(reg3));
5024             assert(isValidVectorDatasize(size));
5025             assert(isValidArrangement(size, opt));
5026             elemsize = optGetElemsize(opt);
5027             if (ins == INS_pmul)
5028             {
5029                 assert(elemsize == EA_1BYTE); // only supports 8B or 16B
5030             }
5031             else // INS_mul, INS_mla, INS_mls
5032             {
5033                 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
5034             }
5035             fmt = IF_DV_3A;
5036             break;
5037
5038         case INS_add:
5039         case INS_sub:
5040             if (isVectorRegister(reg1))
5041             {
5042                 assert(isVectorRegister(reg2));
5043                 assert(isVectorRegister(reg3));
5044
5045                 if (insOptsAnyArrangement(opt))
5046                 {
5047                     // Vector operation
5048                     assert(opt != INS_OPTS_1D); // Reserved encoding
5049                     assert(isValidVectorDatasize(size));
5050                     assert(isValidArrangement(size, opt));
5051                     fmt = IF_DV_3A;
5052                 }
5053                 else
5054                 {
5055                     // Scalar operation
5056                     assert(insOptsNone(opt));
5057                     assert(size == EA_8BYTE);
5058                     fmt = IF_DV_3E;
5059                 }
5060                 break;
5061             }
5062             __fallthrough;
5063
5064         case INS_adds:
5065         case INS_subs:
5066             emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, INS_OPTS_NONE);
5067             return;
5068
5069         case INS_cmeq:
5070         case INS_cmge:
5071         case INS_cmgt:
5072         case INS_cmhi:
5073         case INS_cmhs:
5074         case INS_ctst:
5075             assert(isVectorRegister(reg1));
5076             assert(isVectorRegister(reg2));
5077             assert(isVectorRegister(reg3));
5078
5079             if (isValidVectorDatasize(size))
5080             {
5081                 // Vector operation
5082                 assert(insOptsAnyArrangement(opt));
5083                 assert(isValidArrangement(size, opt));
5084                 elemsize = optGetElemsize(opt);
5085                 fmt      = IF_DV_3A;
5086             }
5087             else
5088             {
5089                 NYI("Untested");
5090                 // Scalar operation
5091                 assert(size == EA_8BYTE); // Only Double supported
5092                 fmt = IF_DV_3E;
5093             }
5094             break;
5095
5096         case INS_fcmeq:
5097         case INS_fcmge:
5098         case INS_fcmgt:
5099             assert(isVectorRegister(reg1));
5100             assert(isVectorRegister(reg2));
5101             assert(isVectorRegister(reg3));
5102
5103             if (isValidVectorDatasize(size))
5104             {
5105                 // Vector operation
5106                 assert(insOptsAnyArrangement(opt));
5107                 assert(isValidArrangement(size, opt));
5108                 elemsize = optGetElemsize(opt);
5109                 assert((elemsize == EA_8BYTE) || (elemsize == EA_4BYTE)); // Only Double/Float supported
5110                 assert(opt != INS_OPTS_1D);                               // Reserved encoding
5111                 fmt = IF_DV_3B;
5112             }
5113             else
5114             {
5115                 NYI("Untested");
5116                 // Scalar operation
5117                 assert((size == EA_8BYTE) || (size == EA_4BYTE)); // Only Double/Float supported
5118                 fmt = IF_DV_3D;
5119             }
5120             break;
5121
5122         case INS_saba:
5123         case INS_sabd:
5124         case INS_smax:
5125         case INS_smin:
5126         case INS_uaba:
5127         case INS_uabd:
5128         case INS_umax:
5129         case INS_umin:
5130             assert(isVectorRegister(reg1));
5131             assert(isVectorRegister(reg2));
5132             assert(isVectorRegister(reg3));
5133             assert(insOptsAnyArrangement(opt));
5134
5135             // Vector operation
5136             assert(isValidVectorDatasize(size));
5137             assert(isValidArrangement(size, opt));
5138             elemsize = optGetElemsize(opt);
5139             assert(elemsize != EA_8BYTE); // can't use 2D or 1D
5140
5141             fmt = IF_DV_3A;
5142             break;
5143
5144         case INS_mov:
5145             assert(isVectorRegister(reg1));
5146             assert(isVectorRegister(reg2));
5147             assert(reg2 == reg3);
5148             assert(isValidVectorDatasize(size));
5149             // INS_mov is an alias for INS_orr (vector register)
5150             if (opt == INS_OPTS_NONE)
5151             {
5152                 elemsize = EA_1BYTE;
5153                 opt      = optMakeArrangement(size, elemsize);
5154             }
5155             assert(isValidArrangement(size, opt));
5156             fmt = IF_DV_3C;
5157             break;
5158
5159         case INS_and:
5160         case INS_bic:
5161         case INS_eor:
5162         case INS_orr:
5163         case INS_orn:
5164             if (isVectorRegister(reg1))
5165             {
5166                 assert(isValidVectorDatasize(size));
5167                 assert(isVectorRegister(reg2));
5168                 assert(isVectorRegister(reg3));
5169                 if (opt == INS_OPTS_NONE)
5170                 {
5171                     elemsize = EA_1BYTE;
5172                     opt      = optMakeArrangement(size, elemsize);
5173                 }
5174                 assert(isValidArrangement(size, opt));
5175                 fmt = IF_DV_3C;
5176                 break;
5177             }
5178             __fallthrough;
5179
5180         case INS_ands:
5181         case INS_bics:
5182         case INS_eon:
5183             emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, INS_OPTS_NONE);
5184             return;
5185
5186         case INS_bsl:
5187         case INS_bit:
5188         case INS_bif:
5189             assert(isValidVectorDatasize(size));
5190             assert(isVectorRegister(reg1));
5191             assert(isVectorRegister(reg2));
5192             assert(isVectorRegister(reg3));
5193             if (opt == INS_OPTS_NONE)
5194             {
5195                 elemsize = EA_1BYTE;
5196                 opt      = optMakeArrangement(size, elemsize);
5197             }
5198             assert(isValidArrangement(size, opt));
5199             fmt = IF_DV_3C;
5200             break;
5201
5202         case INS_fadd:
5203         case INS_fsub:
5204         case INS_fdiv:
5205         case INS_fmax:
5206         case INS_fmin:
5207         case INS_fabd:
5208         case INS_fmul:
5209         case INS_fmulx:
5210             assert(isVectorRegister(reg1));
5211             assert(isVectorRegister(reg2));
5212             assert(isVectorRegister(reg3));
5213             if (insOptsAnyArrangement(opt))
5214             {
5215                 // Vector operation
5216                 assert(isValidVectorDatasize(size));
5217                 assert(isValidArrangement(size, opt));
5218                 elemsize = optGetElemsize(opt);
5219                 assert(isValidVectorElemsizeFloat(elemsize));
5220                 assert(opt != INS_OPTS_1D); // Reserved encoding
5221                 fmt = IF_DV_3B;
5222             }
5223             else
5224             {
5225                 // Scalar operation
5226                 assert(insOptsNone(opt));
5227                 assert(isValidScalarDatasize(size));
5228                 fmt = IF_DV_3D;
5229             }
5230             break;
5231
5232         case INS_fnmul:
5233             // Scalar operation
5234             assert(insOptsNone(opt));
5235             assert(isVectorRegister(reg1));
5236             assert(isVectorRegister(reg2));
5237             assert(isVectorRegister(reg3));
5238             assert(isValidScalarDatasize(size));
5239             fmt = IF_DV_3D;
5240             break;
5241
5242         case INS_faddp:
5243         case INS_fmla:
5244         case INS_fmls:
5245             assert(isVectorRegister(reg1));
5246             assert(isVectorRegister(reg2));
5247             assert(isVectorRegister(reg3));
5248             assert(insOptsAnyArrangement(opt)); // no scalar encoding, use 4-operand 'fmadd' or 'fmsub'
5249
5250             // Vector operation
5251             assert(isValidVectorDatasize(size));
5252             assert(isValidArrangement(size, opt));
5253             elemsize = optGetElemsize(opt);
5254             assert(isValidVectorElemsizeFloat(elemsize));
5255             assert(opt != INS_OPTS_1D); // Reserved encoding
5256             fmt = IF_DV_3B;
5257             break;
5258
5259         case INS_ldr:
5260         case INS_ldrb:
5261         case INS_ldrh:
5262         case INS_ldrsb:
5263         case INS_ldrsh:
5264         case INS_ldrsw:
5265         case INS_str:
5266         case INS_strb:
5267         case INS_strh:
5268             emitIns_R_R_R_Ext(ins, attr, reg1, reg2, reg3, opt);
5269             return;
5270
5271         case INS_ldp:
5272         case INS_ldpsw:
5273         case INS_ldnp:
5274         case INS_stp:
5275         case INS_stnp:
5276             emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0);
5277             return;
5278
5279         case INS_stxr:
5280         case INS_stxrb:
5281         case INS_stxrh:
5282         case INS_stlxr:
5283         case INS_stlxrb:
5284         case INS_stlxrh:
5285             assert(isGeneralRegisterOrZR(reg1));
5286             assert(isGeneralRegisterOrZR(reg2));
5287             assert(isGeneralRegisterOrSP(reg3));
5288             fmt = IF_LS_3D;
5289             break;
5290
5291         default:
5292             unreached();
5293             break;
5294
5295     } // end switch (ins)
5296
5297     assert(fmt != IF_NONE);
5298
5299     instrDesc* id = emitNewInstr(attr);
5300
5301     id->idIns(ins);
5302     id->idInsFmt(fmt);
5303     id->idInsOpt(opt);
5304
5305     id->idReg1(reg1);
5306     id->idReg2(reg2);
5307     id->idReg3(reg3);
5308
5309     dispIns(id);
5310     appendToCurIG(id);
5311 }
5312
5313 /*****************************************************************************
5314  *
5315  *  Add an instruction referencing three registers and a constant.
5316  */
5317
5318 void emitter::emitIns_R_R_R_I(instruction ins,
5319                               emitAttr    attr,
5320                               regNumber   reg1,
5321                               regNumber   reg2,
5322                               regNumber   reg3,
5323                               ssize_t     imm,
5324                               insOpts     opt /* = INS_OPTS_NONE */,
5325                               emitAttr    attrReg2 /* = EA_UNKNOWN */)
5326 {
5327     emitAttr  size     = EA_SIZE(attr);
5328     emitAttr  elemsize = EA_UNKNOWN;
5329     insFormat fmt      = IF_NONE;
5330     bool      isLdSt   = false;
5331     bool      isSIMD   = false;
5332     bool      isAddSub = false;
5333     bool      setFlags = false;
5334     unsigned  scale    = 0;
5335
5336     /* Figure out the encoding format of the instruction */
5337     switch (ins)
5338     {
5339         case INS_extr:
5340             assert(insOptsNone(opt));
5341             assert(isValidGeneralDatasize(size));
5342             assert(isGeneralRegister(reg1));
5343             assert(isGeneralRegister(reg2));
5344             assert(isGeneralRegister(reg3));
5345             assert(isValidImmShift(imm, size));
5346             fmt = IF_DR_3E;
5347             break;
5348
5349         case INS_and:
5350         case INS_ands:
5351         case INS_eor:
5352         case INS_orr:
5353         case INS_bic:
5354         case INS_bics:
5355         case INS_eon:
5356         case INS_orn:
5357             assert(isValidGeneralDatasize(size));
5358             assert(isGeneralRegister(reg1));
5359             assert(isGeneralRegister(reg2));
5360             assert(isGeneralRegister(reg3));
5361             assert(isValidImmShift(imm, size));
5362             if (imm == 0)
5363             {
5364                 assert(insOptsNone(opt)); // a zero imm, means no shift kind
5365                 fmt = IF_DR_3A;
5366             }
5367             else
5368             {
5369                 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
5370                 fmt = IF_DR_3B;
5371             }
5372             break;
5373
5374         case INS_fmul: // by element, imm[0..3] selects the element of reg3
5375         case INS_fmla:
5376         case INS_fmls:
5377         case INS_fmulx:
5378             assert(isVectorRegister(reg1));
5379             assert(isVectorRegister(reg2));
5380             assert(isVectorRegister(reg3));
5381             if (insOptsAnyArrangement(opt))
5382             {
5383                 // Vector operation
5384                 assert(isValidVectorDatasize(size));
5385                 assert(isValidArrangement(size, opt));
5386                 elemsize = optGetElemsize(opt);
5387                 assert(isValidVectorElemsizeFloat(elemsize));
5388                 assert(isValidVectorIndex(size, elemsize, imm));
5389                 assert(opt != INS_OPTS_1D); // Reserved encoding
5390                 fmt = IF_DV_3BI;
5391             }
5392             else
5393             {
5394                 // Scalar operation
5395                 assert(insOptsNone(opt));
5396                 assert(isValidScalarDatasize(size));
5397                 elemsize = size;
5398                 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
5399                 fmt = IF_DV_3DI;
5400             }
5401             break;
5402
5403         case INS_mul: // by element, imm[0..7] selects the element of reg3
5404         case INS_mla:
5405         case INS_mls:
5406             assert(isVectorRegister(reg1));
5407             assert(isVectorRegister(reg2));
5408             assert(isVectorRegister(reg3));
5409             // Vector operation
5410             assert(insOptsAnyArrangement(opt));
5411             assert(isValidVectorDatasize(size));
5412             assert(isValidArrangement(size, opt));
5413             elemsize = optGetElemsize(opt);
5414             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
5415             // Only has encodings for H or S elemsize
5416             assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE));
5417             // Only has encodings for V0..V15
5418             if ((elemsize == EA_2BYTE) && (reg3 >= REG_V16))
5419             {
5420                 noway_assert(!"Invalid reg3");
5421             }
5422             fmt = IF_DV_3AI;
5423             break;
5424
5425         case INS_add:
5426         case INS_sub:
5427             setFlags = false;
5428             isAddSub = true;
5429             break;
5430
5431         case INS_adds:
5432         case INS_subs:
5433             setFlags = true;
5434             isAddSub = true;
5435             break;
5436
5437         case INS_ldpsw:
5438             scale  = 2;
5439             isLdSt = true;
5440             break;
5441
5442         case INS_ldnp:
5443         case INS_stnp:
5444             assert(insOptsNone(opt)); // Can't use Pre/Post index on these two instructions
5445             __fallthrough;
5446
5447         case INS_ldp:
5448         case INS_stp:
5449             // Is the target a vector register?
5450             if (isVectorRegister(reg1))
5451             {
5452                 scale  = NaturalScale_helper(size);
5453                 isSIMD = true;
5454             }
5455             else
5456             {
5457                 scale = (size == EA_8BYTE) ? 3 : 2;
5458             }
5459             isLdSt = true;
5460             break;
5461
5462         default:
5463             unreached();
5464             break;
5465
5466     } // end switch (ins)
5467
5468     if (isLdSt)
5469     {
5470         assert(!isAddSub);
5471         assert(isGeneralRegisterOrSP(reg3));
5472         assert(insOptsNone(opt) || insOptsIndexed(opt));
5473
5474         if (isSIMD)
5475         {
5476             assert(isValidVectorLSPDatasize(size));
5477             assert(isVectorRegister(reg1));
5478             assert(isVectorRegister(reg2));
5479             assert((scale >= 2) && (scale <= 4));
5480         }
5481         else
5482         {
5483             assert(isValidGeneralDatasize(size));
5484             assert(isGeneralRegisterOrZR(reg1));
5485             assert(isGeneralRegisterOrZR(reg2));
5486             assert((scale == 2) || (scale == 3));
5487         }
5488
5489         // Load/Store Pair reserved encodings:
5490         if (emitInsIsLoad(ins))
5491         {
5492             assert(reg1 != reg2);
5493         }
5494         if (insOptsIndexed(opt))
5495         {
5496             assert(reg1 != reg3);
5497             assert(reg2 != reg3);
5498         }
5499
5500         reg3 = encodingSPtoZR(reg3);
5501
5502         ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
5503         if (imm == 0)
5504         {
5505             assert(insOptsNone(opt)); // PRE/POST Index doesn't make sense with an immediate of zero
5506
5507             fmt = IF_LS_3B;
5508         }
5509         else
5510         {
5511             if ((imm & mask) == 0)
5512             {
5513                 imm >>= scale; // The immediate is scaled by the size of the ld/st
5514
5515                 if ((imm >= -64) && (imm <= 63))
5516                 {
5517                     fmt = IF_LS_3C;
5518                 }
5519             }
5520 #ifdef DEBUG
5521             if (fmt != IF_LS_3C)
5522             {
5523                 assert(!"Instruction cannot be encoded: IF_LS_3C");
5524             }
5525 #endif
5526         }
5527     }
5528     else if (isAddSub)
5529     {
5530         bool reg2IsSP = (reg2 == REG_SP);
5531         assert(!isLdSt);
5532         assert(isValidGeneralDatasize(size));
5533         assert(isGeneralRegister(reg3));
5534
5535         if (setFlags || insOptsAluShift(opt)) // Can't encode SP in reg1 with setFlags or AluShift option
5536         {
5537             assert(isGeneralRegisterOrZR(reg1));
5538         }
5539         else
5540         {
5541             assert(isGeneralRegisterOrSP(reg1));
5542             reg1 = encodingSPtoZR(reg1);
5543         }
5544
5545         if (insOptsAluShift(opt)) // Can't encode SP in reg2 with AluShift option
5546         {
5547             assert(isGeneralRegister(reg2));
5548         }
5549         else
5550         {
5551             assert(isGeneralRegisterOrSP(reg2));
5552             reg2 = encodingSPtoZR(reg2);
5553         }
5554
5555         if (insOptsAnyExtend(opt))
5556         {
5557             assert((imm >= 0) && (imm <= 4));
5558
5559             fmt = IF_DR_3C;
5560         }
5561         else if (insOptsAluShift(opt))
5562         {
5563             // imm should be non-zero and in [1..63]
5564             assert(isValidImmShift(imm, size) && (imm != 0));
5565             fmt = IF_DR_3B;
5566         }
5567         else if (imm == 0)
5568         {
5569             assert(insOptsNone(opt));
5570
5571             if (reg2IsSP)
5572             {
5573                 // To encode the SP register as reg2 we must use the IF_DR_3C encoding
5574                 // and also specify a LSL of zero (imm == 0)
5575                 opt = INS_OPTS_LSL;
5576                 fmt = IF_DR_3C;
5577             }
5578             else
5579             {
5580                 fmt = IF_DR_3A;
5581             }
5582         }
5583         else
5584         {
5585             assert(!"Instruction cannot be encoded: Add/Sub IF_DR_3A");
5586         }
5587     }
5588     assert(fmt != IF_NONE);
5589
5590     instrDesc* id = emitNewInstrCns(attr, imm);
5591
5592     id->idIns(ins);
5593     id->idInsFmt(fmt);
5594     id->idInsOpt(opt);
5595
5596     id->idReg1(reg1);
5597     id->idReg2(reg2);
5598     id->idReg3(reg3);
5599
5600     // Record the attribute for the second register in the pair
5601     id->idGCrefReg2(GCT_NONE);
5602     if (attrReg2 != EA_UNKNOWN)
5603     {
5604         // Record the attribute for the second register in the pair
5605         assert((fmt == IF_LS_3B) || (fmt == IF_LS_3C));
5606         if (EA_IS_GCREF(attrReg2))
5607         {
5608             id->idGCrefReg2(GCT_GCREF);
5609         }
5610         else if (EA_IS_BYREF(attrReg2))
5611         {
5612             id->idGCrefReg2(GCT_BYREF);
5613         }
5614     }
5615
5616     dispIns(id);
5617     appendToCurIG(id);
5618 }
5619
5620 /*****************************************************************************
5621  *
5622  *  Add an instruction referencing three registers, with an extend option
5623  */
5624
5625 void emitter::emitIns_R_R_R_Ext(instruction ins,
5626                                 emitAttr    attr,
5627                                 regNumber   reg1,
5628                                 regNumber   reg2,
5629                                 regNumber   reg3,
5630                                 insOpts     opt,         /* = INS_OPTS_NONE */
5631                                 int         shiftAmount) /* = -1 -- unset   */
5632 {
5633     emitAttr  size   = EA_SIZE(attr);
5634     insFormat fmt    = IF_NONE;
5635     bool      isSIMD = false;
5636     int       scale  = -1;
5637
5638     /* Figure out the encoding format of the instruction */
5639     switch (ins)
5640     {
5641         case INS_ldrb:
5642         case INS_ldrsb:
5643         case INS_strb:
5644             scale = 0;
5645             break;
5646
5647         case INS_ldrh:
5648         case INS_ldrsh:
5649         case INS_strh:
5650             scale = 1;
5651             break;
5652
5653         case INS_ldrsw:
5654             scale = 2;
5655             break;
5656
5657         case INS_ldr:
5658         case INS_str:
5659             // Is the target a vector register?
5660             if (isVectorRegister(reg1))
5661             {
5662                 assert(isValidVectorLSDatasize(size));
5663                 scale  = NaturalScale_helper(size);
5664                 isSIMD = true;
5665             }
5666             else
5667             {
5668                 assert(isValidGeneralDatasize(size));
5669                 scale = (size == EA_8BYTE) ? 3 : 2;
5670             }
5671
5672             break;
5673
5674         default:
5675             unreached();
5676             break;
5677
5678     } // end switch (ins)
5679
5680     assert(scale != -1);
5681     assert(insOptsLSExtend(opt));
5682
5683     if (isSIMD)
5684     {
5685         assert(isValidVectorLSDatasize(size));
5686         assert(isVectorRegister(reg1));
5687     }
5688     else
5689     {
5690         assert(isValidGeneralLSDatasize(size));
5691         assert(isGeneralRegisterOrZR(reg1));
5692     }
5693
5694     assert(isGeneralRegisterOrSP(reg2));
5695     assert(isGeneralRegister(reg3));
5696
5697     // Load/Store reserved encodings:
5698     if (insOptsIndexed(opt))
5699     {
5700         assert(reg1 != reg2);
5701     }
5702
5703     if (shiftAmount == -1)
5704     {
5705         shiftAmount = insOptsLSL(opt) ? scale : 0;
5706     }
5707     assert((shiftAmount == scale) || (shiftAmount == 0));
5708
5709     reg2 = encodingSPtoZR(reg2);
5710     fmt  = IF_LS_3A;
5711
5712     instrDesc* id = emitNewInstr(attr);
5713
5714     id->idIns(ins);
5715     id->idInsFmt(fmt);
5716     id->idInsOpt(opt);
5717
5718     id->idReg1(reg1);
5719     id->idReg2(reg2);
5720     id->idReg3(reg3);
5721     id->idReg3Scaled(shiftAmount == scale);
5722
5723     dispIns(id);
5724     appendToCurIG(id);
5725 }
5726
5727 /*****************************************************************************
5728  *
5729  *  Add an instruction referencing two registers and two constants.
5730  */
5731
5732 void emitter::emitIns_R_R_I_I(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, int imm1, int imm2)
5733 {
5734     emitAttr  size     = EA_SIZE(attr);
5735     emitAttr  elemsize = EA_UNKNOWN;
5736     insFormat fmt      = IF_NONE;
5737     size_t    immOut   = 0; // composed from imm1 and imm2 and stored in the instrDesc
5738
5739     /* Figure out the encoding format of the instruction */
5740     switch (ins)
5741     {
5742         int        lsb;
5743         int        width;
5744         bitMaskImm bmi;
5745
5746         case INS_bfm:
5747         case INS_sbfm:
5748         case INS_ubfm:
5749             assert(isGeneralRegister(reg1));
5750             assert(isGeneralRegister(reg2));
5751             assert(isValidImmShift(imm1, size));
5752             assert(isValidImmShift(imm2, size));
5753             bmi.immNRS = 0;
5754             bmi.immN   = (size == EA_8BYTE);
5755             bmi.immR   = imm1;
5756             bmi.immS   = imm2;
5757             immOut     = bmi.immNRS;
5758             fmt        = IF_DI_2D;
5759             break;
5760
5761         case INS_bfi:
5762         case INS_sbfiz:
5763         case INS_ubfiz:
5764             assert(isGeneralRegister(reg1));
5765             assert(isGeneralRegister(reg2));
5766             lsb   = getBitWidth(size) - imm1;
5767             width = imm2 - 1;
5768             assert(isValidImmShift(lsb, size));
5769             assert(isValidImmShift(width, size));
5770             bmi.immNRS = 0;
5771             bmi.immN   = (size == EA_8BYTE);
5772             bmi.immR   = lsb;
5773             bmi.immS   = width;
5774             immOut     = bmi.immNRS;
5775             fmt        = IF_DI_2D;
5776             break;
5777
5778         case INS_bfxil:
5779         case INS_sbfx:
5780         case INS_ubfx:
5781             assert(isGeneralRegister(reg1));
5782             assert(isGeneralRegister(reg2));
5783             lsb   = imm1;
5784             width = imm2 + imm1 - 1;
5785             assert(isValidImmShift(lsb, size));
5786             assert(isValidImmShift(width, size));
5787             bmi.immNRS = 0;
5788             bmi.immN   = (size == EA_8BYTE);
5789             bmi.immR   = imm1;
5790             bmi.immS   = imm2 + imm1 - 1;
5791             immOut     = bmi.immNRS;
5792             fmt        = IF_DI_2D;
5793             break;
5794
5795         case INS_mov:
5796         case INS_ins:
5797             assert(isVectorRegister(reg1));
5798             assert(isVectorRegister(reg2));
5799             elemsize = size;
5800             assert(isValidVectorElemsize(elemsize));
5801             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm1));
5802             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm2));
5803             immOut = (imm1 << 4) + imm2;
5804             fmt    = IF_DV_2F;
5805             break;
5806
5807         default:
5808             unreached();
5809             break;
5810     }
5811     assert(fmt != IF_NONE);
5812
5813     instrDesc* id = emitNewInstrSC(attr, immOut);
5814
5815     id->idIns(ins);
5816     id->idInsFmt(fmt);
5817
5818     id->idReg1(reg1);
5819     id->idReg2(reg2);
5820
5821     dispIns(id);
5822     appendToCurIG(id);
5823 }
5824
5825 /*****************************************************************************
5826  *
5827  *  Add an instruction referencing four registers.
5828  */
5829
5830 void emitter::emitIns_R_R_R_R(
5831     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, regNumber reg4)
5832 {
5833     emitAttr  size = EA_SIZE(attr);
5834     insFormat fmt  = IF_NONE;
5835
5836     /* Figure out the encoding format of the instruction */
5837     switch (ins)
5838     {
5839         case INS_madd:
5840         case INS_msub:
5841         case INS_smaddl:
5842         case INS_smsubl:
5843         case INS_umaddl:
5844         case INS_umsubl:
5845             assert(isValidGeneralDatasize(size));
5846             assert(isGeneralRegister(reg1));
5847             assert(isGeneralRegister(reg2));
5848             assert(isGeneralRegister(reg3));
5849             assert(isGeneralRegister(reg4));
5850             fmt = IF_DR_4A;
5851             break;
5852
5853         case INS_fmadd:
5854         case INS_fmsub:
5855         case INS_fnmadd:
5856         case INS_fnmsub:
5857             // Scalar operation
5858             assert(isValidScalarDatasize(size));
5859             assert(isVectorRegister(reg1));
5860             assert(isVectorRegister(reg2));
5861             assert(isVectorRegister(reg3));
5862             assert(isVectorRegister(reg4));
5863             fmt = IF_DV_4A;
5864             break;
5865
5866         case INS_invalid:
5867             fmt = IF_NONE;
5868             break;
5869
5870         default:
5871             unreached();
5872             break;
5873     }
5874     assert(fmt != IF_NONE);
5875
5876     instrDesc* id = emitNewInstr(attr);
5877
5878     id->idIns(ins);
5879     id->idInsFmt(fmt);
5880
5881     id->idReg1(reg1);
5882     id->idReg2(reg2);
5883     id->idReg3(reg3);
5884     id->idReg4(reg4);
5885
5886     dispIns(id);
5887     appendToCurIG(id);
5888 }
5889
5890 /*****************************************************************************
5891  *
5892  *  Add an instruction referencing a register and a condition code
5893  */
5894
5895 void emitter::emitIns_R_COND(instruction ins, emitAttr attr, regNumber reg, insCond cond)
5896 {
5897     emitAttr     size = EA_SIZE(attr);
5898     insFormat    fmt  = IF_NONE;
5899     condFlagsImm cfi;
5900     cfi.immCFVal = 0;
5901
5902     /* Figure out the encoding format of the instruction */
5903     switch (ins)
5904     {
5905         case INS_cset:
5906         case INS_csetm:
5907             assert(isGeneralRegister(reg));
5908             cfi.cond = cond;
5909             fmt      = IF_DR_1D;
5910             break;
5911
5912         default:
5913             unreached();
5914             break;
5915
5916     } // end switch (ins)
5917
5918     assert(fmt != IF_NONE);
5919     assert(isValidImmCond(cfi.immCFVal));
5920
5921     instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
5922
5923     id->idIns(ins);
5924     id->idInsFmt(fmt);
5925     id->idInsOpt(INS_OPTS_NONE);
5926
5927     id->idReg1(reg);
5928
5929     dispIns(id);
5930     appendToCurIG(id);
5931 }
5932
5933 /*****************************************************************************
5934  *
5935  *  Add an instruction referencing two registers and a condition code
5936  */
5937
5938 void emitter::emitIns_R_R_COND(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insCond cond)
5939 {
5940     emitAttr     size = EA_SIZE(attr);
5941     insFormat    fmt  = IF_NONE;
5942     condFlagsImm cfi;
5943     cfi.immCFVal = 0;
5944
5945     /* Figure out the encoding format of the instruction */
5946     switch (ins)
5947     {
5948         case INS_cinc:
5949         case INS_cinv:
5950         case INS_cneg:
5951             assert(isGeneralRegister(reg1));
5952             assert(isGeneralRegister(reg2));
5953             cfi.cond = cond;
5954             fmt      = IF_DR_2D;
5955             break;
5956         default:
5957             unreached();
5958             break;
5959
5960     } // end switch (ins)
5961
5962     assert(fmt != IF_NONE);
5963     assert(isValidImmCond(cfi.immCFVal));
5964
5965     instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
5966
5967     id->idIns(ins);
5968     id->idInsFmt(fmt);
5969     id->idInsOpt(INS_OPTS_NONE);
5970
5971     id->idReg1(reg1);
5972     id->idReg2(reg2);
5973
5974     dispIns(id);
5975     appendToCurIG(id);
5976 }
5977
5978 /*****************************************************************************
5979  *
5980  *  Add an instruction referencing two registers and a condition code
5981  */
5982
5983 void emitter::emitIns_R_R_R_COND(
5984     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insCond cond)
5985 {
5986     emitAttr     size = EA_SIZE(attr);
5987     insFormat    fmt  = IF_NONE;
5988     condFlagsImm cfi;
5989     cfi.immCFVal = 0;
5990
5991     /* Figure out the encoding format of the instruction */
5992     switch (ins)
5993     {
5994         case INS_csel:
5995         case INS_csinc:
5996         case INS_csinv:
5997         case INS_csneg:
5998             assert(isGeneralRegister(reg1));
5999             assert(isGeneralRegister(reg2));
6000             assert(isGeneralRegister(reg3));
6001             cfi.cond = cond;
6002             fmt      = IF_DR_3D;
6003             break;
6004
6005         default:
6006             unreached();
6007             break;
6008
6009     } // end switch (ins)
6010
6011     assert(fmt != IF_NONE);
6012     assert(isValidImmCond(cfi.immCFVal));
6013
6014     instrDesc* id = emitNewInstr(attr);
6015
6016     id->idIns(ins);
6017     id->idInsFmt(fmt);
6018     id->idInsOpt(INS_OPTS_NONE);
6019
6020     id->idReg1(reg1);
6021     id->idReg2(reg2);
6022     id->idReg3(reg3);
6023     id->idSmallCns(cfi.immCFVal);
6024
6025     dispIns(id);
6026     appendToCurIG(id);
6027 }
6028
6029 /*****************************************************************************
6030  *
6031  *  Add an instruction referencing two registers the flags and a condition code
6032  */
6033
6034 void emitter::emitIns_R_R_FLAGS_COND(
6035     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insCflags flags, insCond cond)
6036 {
6037     emitAttr     size = EA_SIZE(attr);
6038     insFormat    fmt  = IF_NONE;
6039     condFlagsImm cfi;
6040     cfi.immCFVal = 0;
6041
6042     /* Figure out the encoding format of the instruction */
6043     switch (ins)
6044     {
6045         case INS_ccmp:
6046         case INS_ccmn:
6047             assert(isGeneralRegister(reg1));
6048             assert(isGeneralRegister(reg2));
6049             cfi.flags = flags;
6050             cfi.cond  = cond;
6051             fmt       = IF_DR_2I;
6052             break;
6053         default:
6054             unreached();
6055             break;
6056     } // end switch (ins)
6057
6058     assert(fmt != IF_NONE);
6059     assert(isValidImmCondFlags(cfi.immCFVal));
6060
6061     instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6062
6063     id->idIns(ins);
6064     id->idInsFmt(fmt);
6065     id->idInsOpt(INS_OPTS_NONE);
6066
6067     id->idReg1(reg1);
6068     id->idReg2(reg2);
6069
6070     dispIns(id);
6071     appendToCurIG(id);
6072 }
6073
6074 /*****************************************************************************
6075  *
6076  *  Add an instruction referencing a register, an immediate, the flags and a condition code
6077  */
6078
6079 void emitter::emitIns_R_I_FLAGS_COND(
6080     instruction ins, emitAttr attr, regNumber reg, int imm, insCflags flags, insCond cond)
6081 {
6082     emitAttr     size = EA_SIZE(attr);
6083     insFormat    fmt  = IF_NONE;
6084     condFlagsImm cfi;
6085     cfi.immCFVal = 0;
6086
6087     /* Figure out the encoding format of the instruction */
6088     switch (ins)
6089     {
6090         case INS_ccmp:
6091         case INS_ccmn:
6092             assert(isGeneralRegister(reg));
6093             if (imm < 0)
6094             {
6095                 ins = insReverse(ins);
6096                 imm = -imm;
6097             }
6098             if ((imm >= 0) && (imm <= 31))
6099             {
6100                 cfi.imm5  = imm;
6101                 cfi.flags = flags;
6102                 cfi.cond  = cond;
6103                 fmt       = IF_DI_1F;
6104             }
6105             else
6106             {
6107                 assert(!"Instruction cannot be encoded: ccmp/ccmn imm5");
6108             }
6109             break;
6110         default:
6111             unreached();
6112             break;
6113     } // end switch (ins)
6114
6115     assert(fmt != IF_NONE);
6116     assert(isValidImmCondFlagsImm5(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 a memory barrier instruction with a 'barrier' immediate
6133  */
6134
6135 void emitter::emitIns_BARR(instruction ins, insBarrier barrier)
6136 {
6137     insFormat fmt = IF_NONE;
6138     ssize_t   imm = 0;
6139
6140     /* Figure out the encoding format of the instruction */
6141     switch (ins)
6142     {
6143         case INS_dsb:
6144         case INS_dmb:
6145         case INS_isb:
6146
6147             fmt = IF_SI_0B;
6148             imm = (ssize_t)barrier;
6149             break;
6150         default:
6151             unreached();
6152             break;
6153     } // end switch (ins)
6154
6155     assert(fmt != IF_NONE);
6156
6157     instrDesc* id = emitNewInstrSC(EA_8BYTE, imm);
6158
6159     id->idIns(ins);
6160     id->idInsFmt(fmt);
6161     id->idInsOpt(INS_OPTS_NONE);
6162
6163     dispIns(id);
6164     appendToCurIG(id);
6165 }
6166
6167 /*****************************************************************************
6168  *
6169  *  Add an instruction with a static data member operand. If 'size' is 0, the
6170  *  instruction operates on the address of the static member instead of its
6171  *  value (e.g. "push offset clsvar", rather than "push dword ptr [clsvar]").
6172  */
6173
6174 void emitter::emitIns_C(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, int offs)
6175 {
6176     NYI("emitIns_C");
6177 }
6178
6179 /*****************************************************************************
6180  *
6181  *  Add an instruction referencing stack-based local variable.
6182  */
6183
6184 void emitter::emitIns_S(instruction ins, emitAttr attr, int varx, int offs)
6185 {
6186     NYI("emitIns_S");
6187 }
6188
6189 /*****************************************************************************
6190  *
6191  *  Add an instruction referencing a register and a stack-based local variable.
6192  */
6193 void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
6194 {
6195     emitAttr  size  = EA_SIZE(attr);
6196     insFormat fmt   = IF_NONE;
6197     int       disp  = 0;
6198     unsigned  scale = 0;
6199
6200     assert(offs >= 0);
6201
6202     // TODO-ARM64-CQ: use unscaled loads?
6203     /* Figure out the encoding format of the instruction */
6204     switch (ins)
6205     {
6206         case INS_strb:
6207         case INS_ldrb:
6208         case INS_ldrsb:
6209             scale = 0;
6210             break;
6211
6212         case INS_strh:
6213         case INS_ldrh:
6214         case INS_ldrsh:
6215             scale = 1;
6216             break;
6217
6218         case INS_ldrsw:
6219             scale = 2;
6220             break;
6221
6222         case INS_str:
6223         case INS_ldr:
6224             assert(isValidGeneralDatasize(size) || isValidVectorDatasize(size));
6225             scale = genLog2(EA_SIZE_IN_BYTES(size));
6226             break;
6227
6228         case INS_lea:
6229             assert(size == EA_8BYTE);
6230             scale = 0;
6231             break;
6232
6233         default:
6234             NYI("emitIns_R_S"); // FP locals?
6235             return;
6236
6237     } // end switch (ins)
6238
6239     /* Figure out the variable's frame position */
6240     ssize_t imm;
6241     int     base;
6242     bool    FPbased;
6243
6244     base = emitComp->lvaFrameAddress(varx, &FPbased);
6245     disp = base + offs;
6246     assert((scale >= 0) && (scale <= 4));
6247
6248     regNumber reg2 = FPbased ? REG_FPBASE : REG_SPBASE;
6249     reg2           = encodingSPtoZR(reg2);
6250
6251     if (ins == INS_lea)
6252     {
6253         if (disp >= 0)
6254         {
6255             ins = INS_add;
6256             imm = disp;
6257         }
6258         else
6259         {
6260             ins = INS_sub;
6261             imm = -disp;
6262         }
6263
6264         if (imm <= 0x0fff)
6265         {
6266             fmt = IF_DI_2A; // add reg1,reg2,#disp
6267         }
6268         else
6269         {
6270             regNumber rsvdReg = codeGen->rsGetRsvdReg();
6271             codeGen->instGen_Set_Reg_To_Imm(size, rsvdReg, imm);
6272             fmt = IF_DR_3A; // add reg1,reg2,rsvdReg
6273         }
6274     }
6275     else
6276     {
6277         bool    useRegForImm = false;
6278         ssize_t mask         = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6279
6280         imm = disp;
6281         if (imm == 0)
6282         {
6283             fmt = IF_LS_2A;
6284         }
6285         else if ((imm < 0) || ((imm & mask) != 0))
6286         {
6287             if ((imm >= -256) && (imm <= 255))
6288             {
6289                 fmt = IF_LS_2C;
6290             }
6291             else
6292             {
6293                 useRegForImm = true;
6294             }
6295         }
6296         else if (imm > 0)
6297         {
6298             if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
6299             {
6300                 imm >>= scale; // The immediate is scaled by the size of the ld/st
6301
6302                 fmt = IF_LS_2B;
6303             }
6304             else
6305             {
6306                 useRegForImm = true;
6307             }
6308         }
6309
6310         if (useRegForImm)
6311         {
6312             regNumber rsvdReg = codeGen->rsGetRsvdReg();
6313             codeGen->instGen_Set_Reg_To_Imm(size, rsvdReg, imm);
6314             fmt = IF_LS_3A;
6315         }
6316     }
6317
6318     assert(fmt != IF_NONE);
6319
6320     instrDesc* id = emitNewInstrCns(attr, imm);
6321
6322     id->idIns(ins);
6323     id->idInsFmt(fmt);
6324     id->idInsOpt(INS_OPTS_NONE);
6325
6326     id->idReg1(reg1);
6327     id->idReg2(reg2);
6328     id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6329     id->idSetIsLclVar();
6330
6331 #ifdef DEBUG
6332     id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6333 #endif
6334
6335     dispIns(id);
6336     appendToCurIG(id);
6337 }
6338
6339 /*****************************************************************************
6340  *
6341  *  Add an instruction referencing two register and consectutive stack-based local variable slots.
6342  */
6343 void emitter::emitIns_R_R_S_S(
6344     instruction ins, emitAttr attr1, emitAttr attr2, regNumber reg1, regNumber reg2, int varx, int offs)
6345 {
6346     assert((ins == INS_ldp) || (ins == INS_ldnp));
6347     assert(EA_8BYTE == EA_SIZE(attr1));
6348     assert(EA_8BYTE == EA_SIZE(attr2));
6349     assert(isGeneralRegisterOrZR(reg1));
6350     assert(isGeneralRegisterOrZR(reg2));
6351     assert(offs >= 0);
6352
6353     emitAttr       size  = EA_SIZE(attr1);
6354     insFormat      fmt   = IF_LS_3B;
6355     int            disp  = 0;
6356     const unsigned scale = 3;
6357
6358     /* Figure out the variable's frame position */
6359     int  base;
6360     bool FPbased;
6361
6362     base = emitComp->lvaFrameAddress(varx, &FPbased);
6363     disp = base + offs;
6364
6365     // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6366     regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE;
6367     reg3           = encodingSPtoZR(reg3);
6368
6369     bool    useRegForAdr = true;
6370     ssize_t imm          = disp;
6371     ssize_t mask         = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6372     if (imm == 0)
6373     {
6374         useRegForAdr = false;
6375     }
6376     else
6377     {
6378         if ((imm & mask) == 0)
6379         {
6380             ssize_t immShift = imm >> scale; // The immediate is scaled by the size of the ld/st
6381
6382             if ((immShift >= -64) && (immShift <= 63))
6383             {
6384                 fmt          = IF_LS_3C;
6385                 useRegForAdr = false;
6386                 imm          = immShift;
6387             }
6388         }
6389     }
6390
6391     if (useRegForAdr)
6392     {
6393         regNumber rsvd = codeGen->rsGetRsvdReg();
6394         emitIns_R_R_Imm(INS_add, EA_8BYTE, rsvd, reg3, imm);
6395         reg3 = rsvd;
6396         imm  = 0;
6397     }
6398
6399     assert(fmt != IF_NONE);
6400
6401     instrDesc* id = emitNewInstrCns(attr1, imm);
6402
6403     id->idIns(ins);
6404     id->idInsFmt(fmt);
6405     id->idInsOpt(INS_OPTS_NONE);
6406
6407     // Record the attribute for the second register in the pair
6408     if (EA_IS_GCREF(attr2))
6409     {
6410         id->idGCrefReg2(GCT_GCREF);
6411     }
6412     else if (EA_IS_BYREF(attr2))
6413     {
6414         id->idGCrefReg2(GCT_BYREF);
6415     }
6416     else
6417     {
6418         id->idGCrefReg2(GCT_NONE);
6419     }
6420
6421     id->idReg1(reg1);
6422     id->idReg2(reg2);
6423     id->idReg3(reg3);
6424     id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6425     id->idSetIsLclVar();
6426
6427 #ifdef DEBUG
6428     id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6429 #endif
6430
6431     dispIns(id);
6432     appendToCurIG(id);
6433 }
6434
6435 /*****************************************************************************
6436  *
6437  *  Add an instruction referencing a stack-based local variable and a register
6438  */
6439 void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
6440 {
6441     assert(offs >= 0);
6442     emitAttr  size          = EA_SIZE(attr);
6443     insFormat fmt           = IF_NONE;
6444     int       disp          = 0;
6445     unsigned  scale         = 0;
6446     bool      isVectorStore = false;
6447
6448     // TODO-ARM64-CQ: use unscaled loads?
6449     /* Figure out the encoding format of the instruction */
6450     switch (ins)
6451     {
6452         case INS_strb:
6453             scale = 0;
6454             assert(isGeneralRegisterOrZR(reg1));
6455             break;
6456
6457         case INS_strh:
6458             scale = 1;
6459             assert(isGeneralRegisterOrZR(reg1));
6460             break;
6461
6462         case INS_str:
6463             if (isGeneralRegisterOrZR(reg1))
6464             {
6465                 assert(isValidGeneralDatasize(size));
6466                 scale = (size == EA_8BYTE) ? 3 : 2;
6467             }
6468             else
6469             {
6470                 assert(isVectorRegister(reg1));
6471                 assert(isValidVectorLSDatasize(size));
6472                 scale         = NaturalScale_helper(size);
6473                 isVectorStore = true;
6474             }
6475             break;
6476
6477         default:
6478             NYI("emitIns_S_R"); // FP locals?
6479             return;
6480
6481     } // end switch (ins)
6482
6483     /* Figure out the variable's frame position */
6484     int  base;
6485     bool FPbased;
6486
6487     base = emitComp->lvaFrameAddress(varx, &FPbased);
6488     disp = base + offs;
6489     assert(scale >= 0);
6490     if (isVectorStore)
6491     {
6492         assert(scale <= 4);
6493     }
6494     else
6495     {
6496         assert(scale <= 3);
6497     }
6498
6499     // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6500     regNumber reg2 = FPbased ? REG_FPBASE : REG_SPBASE;
6501     reg2           = encodingSPtoZR(reg2);
6502
6503     bool    useRegForImm = false;
6504     ssize_t imm          = disp;
6505     ssize_t mask         = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6506     if (imm == 0)
6507     {
6508         fmt = IF_LS_2A;
6509     }
6510     else if ((imm < 0) || ((imm & mask) != 0))
6511     {
6512         if ((imm >= -256) && (imm <= 255))
6513         {
6514             fmt = IF_LS_2C;
6515         }
6516         else
6517         {
6518             useRegForImm = true;
6519         }
6520     }
6521     else if (imm > 0)
6522     {
6523         if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
6524         {
6525             imm >>= scale; // The immediate is scaled by the size of the ld/st
6526
6527             fmt = IF_LS_2B;
6528         }
6529         else
6530         {
6531             useRegForImm = true;
6532         }
6533     }
6534
6535     if (useRegForImm)
6536     {
6537         // The reserved register is not stored in idReg3() since that field overlaps with iiaLclVar.
6538         // It is instead implicit when idSetIsLclVar() is set, with this encoding format.
6539         regNumber rsvdReg = codeGen->rsGetRsvdReg();
6540         codeGen->instGen_Set_Reg_To_Imm(size, rsvdReg, imm);
6541         fmt = IF_LS_3A;
6542     }
6543
6544     assert(fmt != IF_NONE);
6545
6546     instrDesc* id = emitNewInstrCns(attr, imm);
6547
6548     id->idIns(ins);
6549     id->idInsFmt(fmt);
6550     id->idInsOpt(INS_OPTS_NONE);
6551
6552     id->idReg1(reg1);
6553     id->idReg2(reg2);
6554     id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6555     id->idSetIsLclVar();
6556
6557 #ifdef DEBUG
6558     id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6559 #endif
6560
6561     dispIns(id);
6562     appendToCurIG(id);
6563 }
6564
6565 /*****************************************************************************
6566  *
6567  *  Add an instruction referencing consecutive stack-based local variable slots and two registers
6568  */
6569 void emitter::emitIns_S_S_R_R(
6570     instruction ins, emitAttr attr1, emitAttr attr2, regNumber reg1, regNumber reg2, int varx, int offs)
6571 {
6572     assert((ins == INS_stp) || (ins == INS_stnp));
6573     assert(EA_8BYTE == EA_SIZE(attr1));
6574     assert(EA_8BYTE == EA_SIZE(attr2));
6575     assert(isGeneralRegisterOrZR(reg1));
6576     assert(isGeneralRegisterOrZR(reg2));
6577     assert(offs >= 0);
6578
6579     emitAttr       size  = EA_SIZE(attr1);
6580     insFormat      fmt   = IF_LS_3B;
6581     int            disp  = 0;
6582     const unsigned scale = 3;
6583
6584     /* Figure out the variable's frame position */
6585     int  base;
6586     bool FPbased;
6587
6588     base = emitComp->lvaFrameAddress(varx, &FPbased);
6589     disp = base + offs;
6590
6591     // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6592     regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE;
6593     reg3           = encodingSPtoZR(reg3);
6594
6595     bool    useRegForAdr = true;
6596     ssize_t imm          = disp;
6597     ssize_t mask         = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6598     if (imm == 0)
6599     {
6600         useRegForAdr = false;
6601     }
6602     else
6603     {
6604         if ((imm & mask) == 0)
6605         {
6606             ssize_t immShift = imm >> scale; // The immediate is scaled by the size of the ld/st
6607
6608             if ((immShift >= -64) && (immShift <= 63))
6609             {
6610                 fmt          = IF_LS_3C;
6611                 useRegForAdr = false;
6612                 imm          = immShift;
6613             }
6614         }
6615     }
6616
6617     if (useRegForAdr)
6618     {
6619         regNumber rsvd = codeGen->rsGetRsvdReg();
6620         emitIns_R_R_Imm(INS_add, EA_8BYTE, rsvd, reg3, imm);
6621         reg3 = rsvd;
6622         imm  = 0;
6623     }
6624
6625     assert(fmt != IF_NONE);
6626
6627     instrDesc* id = emitNewInstrCns(attr1, imm);
6628
6629     id->idIns(ins);
6630     id->idInsFmt(fmt);
6631     id->idInsOpt(INS_OPTS_NONE);
6632
6633     // Record the attribute for the second register in the pair
6634     if (EA_IS_GCREF(attr2))
6635     {
6636         id->idGCrefReg2(GCT_GCREF);
6637     }
6638     else if (EA_IS_BYREF(attr2))
6639     {
6640         id->idGCrefReg2(GCT_BYREF);
6641     }
6642     else
6643     {
6644         id->idGCrefReg2(GCT_NONE);
6645     }
6646
6647     id->idReg1(reg1);
6648     id->idReg2(reg2);
6649     id->idReg3(reg3);
6650     id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6651     id->idSetIsLclVar();
6652
6653 #ifdef DEBUG
6654     id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6655 #endif
6656
6657     dispIns(id);
6658     appendToCurIG(id);
6659 }
6660
6661 /*****************************************************************************
6662  *
6663  *  Add an instruction referencing stack-based local variable and an immediate
6664  */
6665 void emitter::emitIns_S_I(instruction ins, emitAttr attr, int varx, int offs, int val)
6666 {
6667     NYI("emitIns_S_I");
6668 }
6669
6670 /*****************************************************************************
6671  *
6672  *  Add an instruction with a register + static member operands.
6673  *  Constant is stored into JIT data which is adjacent to code.
6674  *  No relocation is needed. PC-relative offset will be encoded directly into instruction.
6675  *
6676  */
6677 void emitter::emitIns_R_C(
6678     instruction ins, emitAttr attr, regNumber reg, regNumber addrReg, CORINFO_FIELD_HANDLE fldHnd, int offs)
6679 {
6680     assert(offs >= 0);
6681     assert(instrDesc::fitsInSmallCns(offs));
6682
6683     emitAttr      size = EA_SIZE(attr);
6684     insFormat     fmt  = IF_NONE;
6685     int           disp = 0;
6686     instrDescJmp* id   = emitNewInstrJmp();
6687
6688     switch (ins)
6689     {
6690         case INS_adr:
6691             // This is case to get address to the constant data.
6692             fmt = IF_LARGEADR;
6693             assert(isGeneralRegister(reg));
6694             assert(isValidGeneralDatasize(size));
6695             break;
6696
6697         case INS_ldr:
6698             fmt = IF_LARGELDC;
6699             if (isVectorRegister(reg))
6700             {
6701                 assert(isValidScalarDatasize(size));
6702                 // For vector (float/double) register, we should have an integer address reg to
6703                 // compute long address which consists of page address and page offset.
6704                 // For integer constant, this is not needed since the dest reg can be used to
6705                 // compute address as well as contain the final contents.
6706                 assert(isGeneralRegister(reg) || (addrReg != REG_NA));
6707             }
6708             else
6709             {
6710                 assert(isGeneralRegister(reg));
6711                 assert(isValidGeneralDatasize(size));
6712             }
6713             break;
6714         default:
6715             unreached();
6716     }
6717
6718     assert(fmt != IF_NONE);
6719
6720     id->idIns(ins);
6721     id->idInsFmt(fmt);
6722     id->idInsOpt(INS_OPTS_NONE);
6723     id->idSmallCns(offs);
6724     id->idOpSize(size);
6725     id->idAddr()->iiaFieldHnd = fldHnd;
6726     id->idSetIsBound(); // We won't patch address since we will know the exact distance once JIT code and data are
6727                         // allocated together.
6728
6729     id->idReg1(reg); // destination register that will get the constant value.
6730     if (addrReg != REG_NA)
6731     {
6732         id->idReg2(addrReg); // integer register to compute long address (used for vector dest when we end up with long
6733                              // address)
6734     }
6735     id->idjShort = false; // Assume loading constant from long address
6736
6737     // Keep it long if it's in cold code.
6738     id->idjKeepLong = emitComp->fgIsBlockCold(emitComp->compCurBB);
6739
6740 #ifdef DEBUG
6741     if (emitComp->opts.compLongAddress)
6742         id->idjKeepLong = 1;
6743 #endif // DEBUG
6744
6745     // If it's possible to be shortened, then put it in jump list
6746     // to be revisited by emitJumpDistBind.
6747     if (!id->idjKeepLong)
6748     {
6749         /* Record the jump's IG and offset within it */
6750         id->idjIG   = emitCurIG;
6751         id->idjOffs = emitCurIGsize;
6752
6753         /* Append this jump to this IG's jump list */
6754         id->idjNext      = emitCurIGjmpList;
6755         emitCurIGjmpList = id;
6756
6757 #if EMITTER_STATS
6758         emitTotalIGjmps++;
6759 #endif
6760     }
6761
6762     dispIns(id);
6763     appendToCurIG(id);
6764 }
6765
6766 /*****************************************************************************
6767  *
6768  *  Add an instruction with a static member + constant.
6769  */
6770
6771 void emitter::emitIns_C_I(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, ssize_t offs, ssize_t val)
6772 {
6773     NYI("emitIns_C_I");
6774 }
6775
6776 /*****************************************************************************
6777  *
6778  *  Add an instruction with a static member + register operands.
6779  */
6780
6781 void emitter::emitIns_C_R(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, regNumber reg, int offs)
6782 {
6783     assert(!"emitIns_C_R not supported for RyuJIT backend");
6784 }
6785
6786 void emitter::emitIns_R_AR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
6787 {
6788     NYI("emitIns_R_AR");
6789 }
6790
6791 // This computes address from the immediate which is relocatable.
6792 void emitter::emitIns_R_AI(instruction ins, emitAttr attr, regNumber ireg, ssize_t addr)
6793 {
6794     assert(EA_IS_RELOC(attr));
6795     emitAttr      size    = EA_SIZE(attr);
6796     insFormat     fmt     = IF_DI_1E;
6797     bool          needAdd = false;
6798     instrDescJmp* id      = emitNewInstrJmp();
6799
6800     switch (ins)
6801     {
6802         case INS_adrp:
6803             // This computes page address.
6804             // page offset is needed using add.
6805             needAdd = true;
6806             break;
6807         case INS_adr:
6808             break;
6809         default:
6810             unreached();
6811     }
6812
6813     id->idIns(ins);
6814     id->idInsFmt(fmt);
6815     id->idInsOpt(INS_OPTS_NONE);
6816     id->idOpSize(size);
6817     id->idAddr()->iiaAddr = (BYTE*)addr;
6818     id->idReg1(ireg);
6819     id->idSetIsDspReloc();
6820
6821     dispIns(id);
6822     appendToCurIG(id);
6823
6824     if (needAdd)
6825     {
6826         // add reg, reg, imm
6827         ins           = INS_add;
6828         fmt           = IF_DI_2A;
6829         instrDesc* id = emitAllocInstr(attr);
6830         assert(id->idIsReloc());
6831
6832         id->idIns(ins);
6833         id->idInsFmt(fmt);
6834         id->idInsOpt(INS_OPTS_NONE);
6835         id->idOpSize(size);
6836         id->idAddr()->iiaAddr = (BYTE*)addr;
6837         id->idReg1(ireg);
6838         id->idReg2(ireg);
6839
6840         dispIns(id);
6841         appendToCurIG(id);
6842     }
6843 }
6844
6845 void emitter::emitIns_AR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
6846 {
6847     NYI("emitIns_AR_R");
6848 }
6849
6850 void emitter::emitIns_R_ARR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
6851 {
6852     NYI("emitIns_R_ARR");
6853 }
6854
6855 void emitter::emitIns_ARR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
6856 {
6857     NYI("emitIns_R_ARR");
6858 }
6859
6860 void emitter::emitIns_R_ARX(
6861     instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, unsigned mul, int disp)
6862 {
6863     NYI("emitIns_R_ARR");
6864 }
6865
6866 /*****************************************************************************
6867  *
6868  *  Record that a jump instruction uses the short encoding
6869  *
6870  */
6871 void emitter::emitSetShortJump(instrDescJmp* id)
6872 {
6873     if (id->idjKeepLong)
6874         return;
6875
6876     insFormat fmt = IF_NONE;
6877     if (emitIsCondJump(id))
6878     {
6879         switch (id->idIns())
6880         {
6881             case INS_cbz:
6882             case INS_cbnz:
6883                 fmt = IF_BI_1A;
6884                 break;
6885             case INS_tbz:
6886             case INS_tbnz:
6887                 fmt = IF_BI_1B;
6888                 break;
6889             default:
6890                 fmt = IF_BI_0B;
6891                 break;
6892         }
6893     }
6894     else if (emitIsLoadLabel(id))
6895     {
6896         fmt = IF_DI_1E;
6897     }
6898     else if (emitIsLoadConstant(id))
6899     {
6900         fmt = IF_LS_1A;
6901     }
6902     else
6903     {
6904         unreached();
6905     }
6906
6907     id->idInsFmt(fmt);
6908     id->idjShort = true;
6909 }
6910
6911 /*****************************************************************************
6912  *
6913  *  Add a label instruction.
6914  */
6915
6916 void emitter::emitIns_R_L(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
6917 {
6918     assert(dst->bbFlags & BBF_JMP_TARGET);
6919
6920     insFormat fmt = IF_NONE;
6921
6922     switch (ins)
6923     {
6924         case INS_adr:
6925             fmt = IF_LARGEADR;
6926             break;
6927         default:
6928             unreached();
6929     }
6930
6931     instrDescJmp* id = emitNewInstrJmp();
6932
6933     id->idIns(ins);
6934     id->idInsFmt(fmt);
6935     id->idjShort             = false;
6936     id->idAddr()->iiaBBlabel = dst;
6937     id->idReg1(reg);
6938     id->idOpSize(EA_PTRSIZE);
6939
6940 #ifdef DEBUG
6941     // Mark the catch return
6942     if (emitComp->compCurBB->bbJumpKind == BBJ_EHCATCHRET)
6943     {
6944         id->idDebugOnlyInfo()->idCatchRet = true;
6945     }
6946 #endif // DEBUG
6947
6948     id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
6949
6950 #ifdef DEBUG
6951     if (emitComp->opts.compLongAddress)
6952         id->idjKeepLong = 1;
6953 #endif // DEBUG
6954
6955     /* Record the jump's IG and offset within it */
6956
6957     id->idjIG   = emitCurIG;
6958     id->idjOffs = emitCurIGsize;
6959
6960     /* Append this jump to this IG's jump list */
6961
6962     id->idjNext      = emitCurIGjmpList;
6963     emitCurIGjmpList = id;
6964
6965 #if EMITTER_STATS
6966     emitTotalIGjmps++;
6967 #endif
6968
6969     dispIns(id);
6970     appendToCurIG(id);
6971 }
6972
6973 /*****************************************************************************
6974  *
6975  *  Add a data label instruction.
6976  */
6977
6978 void emitter::emitIns_R_D(instruction ins, emitAttr attr, unsigned offs, regNumber reg)
6979 {
6980     NYI("emitIns_R_D");
6981 }
6982
6983 void emitter::emitIns_J_R(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
6984 {
6985     assert((ins == INS_cbz) || (ins == INS_cbnz));
6986
6987     assert(dst != nullptr);
6988     assert((dst->bbFlags & BBF_JMP_TARGET) != 0);
6989
6990     insFormat fmt = IF_LARGEJMP;
6991
6992     instrDescJmp* id = emitNewInstrJmp();
6993
6994     id->idIns(ins);
6995     id->idInsFmt(fmt);
6996     id->idReg1(reg);
6997     id->idjShort = false;
6998     id->idOpSize(EA_SIZE(attr));
6999
7000     id->idAddr()->iiaBBlabel = dst;
7001     id->idjKeepLong          = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7002
7003     /* Record the jump's IG and offset within it */
7004
7005     id->idjIG   = emitCurIG;
7006     id->idjOffs = emitCurIGsize;
7007
7008     /* Append this jump to this IG's jump list */
7009
7010     id->idjNext      = emitCurIGjmpList;
7011     emitCurIGjmpList = id;
7012
7013 #if EMITTER_STATS
7014     emitTotalIGjmps++;
7015 #endif
7016
7017     dispIns(id);
7018     appendToCurIG(id);
7019 }
7020
7021 void emitter::emitIns_J_R_I(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg, int imm)
7022 {
7023     assert((ins == INS_tbz) || (ins == INS_tbnz));
7024
7025     assert(dst != nullptr);
7026     assert((dst->bbFlags & BBF_JMP_TARGET) != 0);
7027     assert((EA_SIZE(attr) == EA_4BYTE) || (EA_SIZE(attr) == EA_8BYTE));
7028     assert(imm < ((EA_SIZE(attr) == EA_4BYTE) ? 32 : 64));
7029
7030     insFormat fmt = IF_LARGEJMP;
7031
7032     instrDescJmp* id = emitNewInstrJmp();
7033
7034     id->idIns(ins);
7035     id->idInsFmt(fmt);
7036     id->idReg1(reg);
7037     id->idjShort = false;
7038     id->idSmallCns(imm);
7039     id->idOpSize(EA_SIZE(attr));
7040
7041     id->idAddr()->iiaBBlabel = dst;
7042     id->idjKeepLong          = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7043
7044     /* Record the jump's IG and offset within it */
7045
7046     id->idjIG   = emitCurIG;
7047     id->idjOffs = emitCurIGsize;
7048
7049     /* Append this jump to this IG's jump list */
7050
7051     id->idjNext      = emitCurIGjmpList;
7052     emitCurIGjmpList = id;
7053
7054 #if EMITTER_STATS
7055     emitTotalIGjmps++;
7056 #endif
7057
7058     dispIns(id);
7059     appendToCurIG(id);
7060 }
7061
7062 void emitter::emitIns_J(instruction ins, BasicBlock* dst, int instrCount)
7063 {
7064     insFormat fmt = IF_NONE;
7065
7066     if (dst != nullptr)
7067     {
7068         assert(dst->bbFlags & BBF_JMP_TARGET);
7069     }
7070     else
7071     {
7072         assert(instrCount != 0);
7073     }
7074
7075     /* Figure out the encoding format of the instruction */
7076
7077     bool idjShort = false;
7078     switch (ins)
7079     {
7080         case INS_bl_local:
7081         case INS_b:
7082             // Unconditional jump is a single form.
7083             idjShort = true;
7084             fmt      = IF_BI_0A;
7085             break;
7086
7087         case INS_beq:
7088         case INS_bne:
7089         case INS_bhs:
7090         case INS_blo:
7091         case INS_bmi:
7092         case INS_bpl:
7093         case INS_bvs:
7094         case INS_bvc:
7095         case INS_bhi:
7096         case INS_bls:
7097         case INS_bge:
7098         case INS_blt:
7099         case INS_bgt:
7100         case INS_ble:
7101             // Assume conditional jump is long.
7102             fmt = IF_LARGEJMP;
7103             break;
7104
7105         default:
7106             unreached();
7107             break;
7108     }
7109
7110     instrDescJmp* id = emitNewInstrJmp();
7111
7112     id->idIns(ins);
7113     id->idInsFmt(fmt);
7114     id->idjShort = idjShort;
7115
7116 #ifdef DEBUG
7117     // Mark the finally call
7118     if (ins == INS_bl_local && emitComp->compCurBB->bbJumpKind == BBJ_CALLFINALLY)
7119     {
7120         id->idDebugOnlyInfo()->idFinallyCall = true;
7121     }
7122 #endif // DEBUG
7123
7124     if (dst != nullptr)
7125     {
7126         id->idAddr()->iiaBBlabel = dst;
7127
7128         // Skip unconditional jump that has a single form.
7129         // TODO-ARM64-NYI: enable hot/cold splittingNYI.
7130         // The target needs to be relocated.
7131         if (!idjShort)
7132         {
7133             id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7134
7135 #ifdef DEBUG
7136             if (emitComp->opts.compLongAddress) // Force long branches
7137                 id->idjKeepLong = 1;
7138 #endif // DEBUG
7139         }
7140     }
7141     else
7142     {
7143         id->idAddr()->iiaSetInstrCount(instrCount);
7144         id->idjKeepLong = false;
7145         /* This jump must be short */
7146         emitSetShortJump(id);
7147         id->idSetIsBound();
7148     }
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 call instruction (direct or indirect).
7171  *      argSize<0 means that the caller will pop the arguments
7172  *
7173  * The other arguments are interpreted depending on callType as shown:
7174  * Unless otherwise specified, ireg,xreg,xmul,disp should have default values.
7175  *
7176  * EC_FUNC_TOKEN       : addr is the method address
7177  * EC_FUNC_ADDR        : addr is the absolute address of the function
7178  *
7179  * If callType is one of these emitCallTypes, addr has to be NULL.
7180  * EC_INDIR_R          : "call ireg".
7181  *
7182  * For ARM xreg, xmul and disp are never used and should always be 0/REG_NA.
7183  *
7184  *  Please consult the "debugger team notification" comment in genFnProlog().
7185  */
7186
7187 void emitter::emitIns_Call(EmitCallType          callType,
7188                            CORINFO_METHOD_HANDLE methHnd,
7189                            INDEBUG_LDISASM_COMMA(CORINFO_SIG_INFO* sigInfo) // used to report call sites to the EE
7190                            void*            addr,
7191                            ssize_t          argSize,
7192                            emitAttr         retSize,
7193                            emitAttr         secondRetSize,
7194                            VARSET_VALARG_TP ptrVars,
7195                            regMaskTP        gcrefRegs,
7196                            regMaskTP        byrefRegs,
7197                            IL_OFFSETX       ilOffset /* = BAD_IL_OFFSET */,
7198                            regNumber        ireg /* = REG_NA */,
7199                            regNumber        xreg /* = REG_NA */,
7200                            unsigned         xmul /* = 0     */,
7201                            ssize_t          disp /* = 0     */,
7202                            bool             isJump /* = false */,
7203                            bool             isNoGC /* = false */,
7204                            bool             isProfLeaveCB /* = false */)
7205 {
7206     /* Sanity check the arguments depending on callType */
7207
7208     assert(callType < EC_COUNT);
7209     assert((callType != EC_FUNC_TOKEN && callType != EC_FUNC_ADDR) ||
7210            (ireg == REG_NA && xreg == REG_NA && xmul == 0 && disp == 0));
7211     assert(callType < EC_INDIR_R || addr == NULL);
7212     assert(callType != EC_INDIR_R || (ireg < REG_COUNT && xreg == REG_NA && xmul == 0 && disp == 0));
7213
7214     // ARM never uses these
7215     assert(xreg == REG_NA && xmul == 0 && disp == 0);
7216
7217     // Our stack level should be always greater than the bytes of arguments we push. Just
7218     // a sanity test.
7219     assert((unsigned)abs(argSize) <= codeGen->genStackLevel);
7220
7221     int        argCnt;
7222     instrDesc* id;
7223
7224     /* This is the saved set of registers after a normal call */
7225     regMaskTP savedSet = RBM_CALLEE_SAVED;
7226
7227     /* some special helper calls have a different saved set registers */
7228
7229     if (isNoGC)
7230     {
7231         assert(emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
7232
7233         // Get the set of registers that this call kills and remove it from the saved set.
7234         savedSet = RBM_ALLINT & ~emitComp->compNoGCHelperCallKillSet(Compiler::eeGetHelperNum(methHnd));
7235
7236         // In case of Leave profiler callback, we need to preserve liveness of REG_PROFILER_RET_SCRATCH
7237         if (isProfLeaveCB)
7238         {
7239             savedSet |= RBM_PROFILER_RET_SCRATCH;
7240         }
7241     }
7242     else
7243     {
7244         assert(!emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
7245     }
7246
7247     /* Trim out any callee-trashed registers from the live set */
7248
7249     gcrefRegs &= savedSet;
7250     byrefRegs &= savedSet;
7251
7252 #ifdef DEBUG
7253     if (EMIT_GC_VERBOSE)
7254     {
7255         printf("Call: GCvars=%s ", VarSetOps::ToString(emitComp, ptrVars));
7256         dumpConvertedVarSet(emitComp, ptrVars);
7257         printf(", gcrefRegs=");
7258         printRegMaskInt(gcrefRegs);
7259         emitDispRegSet(gcrefRegs);
7260         printf(", byrefRegs=");
7261         printRegMaskInt(byrefRegs);
7262         emitDispRegSet(byrefRegs);
7263         printf("\n");
7264     }
7265 #endif
7266
7267     assert(argSize % REGSIZE_BYTES == 0);
7268     argCnt = (int)(argSize / (int)sizeof(void*));
7269
7270     /* Managed RetVal: emit sequence point for the call */
7271     if (emitComp->opts.compDbgInfo && ilOffset != BAD_IL_OFFSET)
7272     {
7273         codeGen->genIPmappingAdd(ilOffset, false);
7274     }
7275
7276     /*
7277         We need to allocate the appropriate instruction descriptor based
7278         on whether this is a direct/indirect call, and whether we need to
7279         record an updated set of live GC variables.
7280      */
7281
7282     if (callType >= EC_INDIR_R)
7283     {
7284         /* Indirect call, virtual calls */
7285
7286         assert(callType == EC_INDIR_R);
7287
7288         id = emitNewInstrCallInd(argCnt, disp, ptrVars, gcrefRegs, byrefRegs, retSize, secondRetSize);
7289     }
7290     else
7291     {
7292         /* Helper/static/nonvirtual/function calls (direct or through handle),
7293            and calls to an absolute addr. */
7294
7295         assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
7296
7297         id = emitNewInstrCallDir(argCnt, ptrVars, gcrefRegs, byrefRegs, retSize, secondRetSize);
7298     }
7299
7300     /* Update the emitter's live GC ref sets */
7301
7302     VarSetOps::Assign(emitComp, emitThisGCrefVars, ptrVars);
7303     emitThisGCrefRegs = gcrefRegs;
7304     emitThisByrefRegs = byrefRegs;
7305
7306     /* Set the instruction - special case jumping a function */
7307     instruction ins;
7308     insFormat   fmt = IF_NONE;
7309
7310     id->idSetIsNoGC(isNoGC);
7311
7312     /* Record the address: method, indirection, or funcptr */
7313
7314     if (callType > EC_FUNC_ADDR)
7315     {
7316         /* This is an indirect call (either a virtual call or func ptr call) */
7317
7318         switch (callType)
7319         {
7320             case EC_INDIR_R: // the address is in a register
7321
7322                 id->idSetIsCallRegPtr();
7323
7324                 if (isJump)
7325                 {
7326                     ins = INS_br_tail; // INS_br_tail  Reg
7327                 }
7328                 else
7329                 {
7330                     ins = INS_blr; // INS_blr Reg
7331                 }
7332                 fmt = IF_BR_1B;
7333
7334                 id->idIns(ins);
7335                 id->idInsFmt(fmt);
7336
7337                 id->idReg3(ireg);
7338                 assert(xreg == REG_NA);
7339                 break;
7340
7341             default:
7342                 NO_WAY("unexpected instruction");
7343                 break;
7344         }
7345     }
7346     else
7347     {
7348         /* This is a simple direct call: "call helper/method/addr" */
7349
7350         assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
7351
7352         assert(addr != NULL);
7353
7354         if (isJump)
7355         {
7356             ins = INS_b_tail; // INS_b_tail imm28
7357         }
7358         else
7359         {
7360             ins = INS_bl; // INS_bl imm28
7361         }
7362         fmt = IF_BI_0C;
7363
7364         id->idIns(ins);
7365         id->idInsFmt(fmt);
7366
7367         id->idAddr()->iiaAddr = (BYTE*)addr;
7368
7369         if (callType == EC_FUNC_ADDR)
7370         {
7371             id->idSetIsCallAddr();
7372         }
7373
7374         if (emitComp->opts.compReloc)
7375         {
7376             id->idSetIsDspReloc();
7377         }
7378     }
7379
7380 #ifdef DEBUG
7381     if (EMIT_GC_VERBOSE)
7382     {
7383         if (id->idIsLargeCall())
7384         {
7385             printf("[%02u] Rec call GC vars = %s\n", id->idDebugOnlyInfo()->idNum,
7386                    VarSetOps::ToString(emitComp, ((instrDescCGCA*)id)->idcGCvars));
7387         }
7388     }
7389
7390     id->idDebugOnlyInfo()->idMemCookie = (size_t)methHnd; // method token
7391     id->idDebugOnlyInfo()->idCallSig   = sigInfo;
7392 #endif // DEBUG
7393
7394 #ifdef LATE_DISASM
7395     if (addr != nullptr)
7396     {
7397         codeGen->getDisAssembler().disSetMethod((size_t)addr, methHnd);
7398     }
7399 #endif // LATE_DISASM
7400
7401     dispIns(id);
7402     appendToCurIG(id);
7403 }
7404
7405 /*****************************************************************************
7406  *
7407  *  Returns true if 'imm' is valid Cond encoding
7408  */
7409
7410 /*static*/ bool emitter::isValidImmCond(ssize_t imm)
7411 {
7412     // range check the ssize_t value, to make sure it is a small unsigned value
7413     // and that only the bits in the cfi.cond are set
7414     if ((imm < 0) || (imm > 0xF))
7415         return false;
7416
7417     condFlagsImm cfi;
7418     cfi.immCFVal = (unsigned)imm;
7419
7420     return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7421 }
7422
7423 /*****************************************************************************
7424  *
7425  *  Returns true if 'imm' is valid Cond/Flags encoding
7426  */
7427
7428 /*static*/ bool emitter::isValidImmCondFlags(ssize_t imm)
7429 {
7430     // range check the ssize_t value, to make sure it is a small unsigned value
7431     // and that only the bits in the cfi.cond or cfi.flags are set
7432     if ((imm < 0) || (imm > 0xFF))
7433         return false;
7434
7435     condFlagsImm cfi;
7436     cfi.immCFVal = (unsigned)imm;
7437
7438     return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7439 }
7440
7441 /*****************************************************************************
7442  *
7443  *  Returns true if 'imm' is valid Cond/Flags/Imm5 encoding
7444  */
7445
7446 /*static*/ bool emitter::isValidImmCondFlagsImm5(ssize_t imm)
7447 {
7448     // range check the ssize_t value, to make sure it is a small unsigned value
7449     // and that only the bits in the cfi.cond, cfi.flags or cfi.imm5 are set
7450     if ((imm < 0) || (imm > 0x1FFF))
7451         return false;
7452
7453     condFlagsImm cfi;
7454     cfi.immCFVal = (unsigned)imm;
7455
7456     return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7457 }
7458
7459 /*****************************************************************************
7460  *
7461  *  Returns an encoding for the specified register used in the 'Rd' position
7462  */
7463
7464 /*static*/ emitter::code_t emitter::insEncodeReg_Rd(regNumber reg)
7465 {
7466     assert(isIntegerRegister(reg));
7467     emitter::code_t ureg = (emitter::code_t)reg;
7468     assert((ureg >= 0) && (ureg <= 31));
7469     return ureg;
7470 }
7471
7472 /*****************************************************************************
7473  *
7474  *  Returns an encoding for the specified register used in the 'Rt' position
7475  */
7476
7477 /*static*/ emitter::code_t emitter::insEncodeReg_Rt(regNumber reg)
7478 {
7479     assert(isIntegerRegister(reg));
7480     emitter::code_t ureg = (emitter::code_t)reg;
7481     assert((ureg >= 0) && (ureg <= 31));
7482     return ureg;
7483 }
7484
7485 /*****************************************************************************
7486  *
7487  *  Returns an encoding for the specified register used in the 'Rn' position
7488  */
7489
7490 /*static*/ emitter::code_t emitter::insEncodeReg_Rn(regNumber reg)
7491 {
7492     assert(isIntegerRegister(reg));
7493     emitter::code_t ureg = (emitter::code_t)reg;
7494     assert((ureg >= 0) && (ureg <= 31));
7495     return ureg << 5;
7496 }
7497
7498 /*****************************************************************************
7499  *
7500  *  Returns an encoding for the specified register used in the 'Rm' position
7501  */
7502
7503 /*static*/ emitter::code_t emitter::insEncodeReg_Rm(regNumber reg)
7504 {
7505     assert(isIntegerRegister(reg));
7506     emitter::code_t ureg = (emitter::code_t)reg;
7507     assert((ureg >= 0) && (ureg <= 31));
7508     return ureg << 16;
7509 }
7510
7511 /*****************************************************************************
7512  *
7513  *  Returns an encoding for the specified register used in the 'Ra' position
7514  */
7515
7516 /*static*/ emitter::code_t emitter::insEncodeReg_Ra(regNumber reg)
7517 {
7518     assert(isIntegerRegister(reg));
7519     emitter::code_t ureg = (emitter::code_t)reg;
7520     assert((ureg >= 0) && (ureg <= 31));
7521     return ureg << 10;
7522 }
7523
7524 /*****************************************************************************
7525  *
7526  *  Returns an encoding for the specified register used in the 'Vd' position
7527  */
7528
7529 /*static*/ emitter::code_t emitter::insEncodeReg_Vd(regNumber reg)
7530 {
7531     assert(emitter::isVectorRegister(reg));
7532     emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7533     assert((ureg >= 0) && (ureg <= 31));
7534     return ureg;
7535 }
7536
7537 /*****************************************************************************
7538  *
7539  *  Returns an encoding for the specified register used in the 'Vt' position
7540  */
7541
7542 /*static*/ emitter::code_t emitter::insEncodeReg_Vt(regNumber reg)
7543 {
7544     assert(emitter::isVectorRegister(reg));
7545     emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7546     assert((ureg >= 0) && (ureg <= 31));
7547     return ureg;
7548 }
7549
7550 /*****************************************************************************
7551  *
7552  *  Returns an encoding for the specified register used in the 'Vn' position
7553  */
7554
7555 /*static*/ emitter::code_t emitter::insEncodeReg_Vn(regNumber reg)
7556 {
7557     assert(emitter::isVectorRegister(reg));
7558     emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7559     assert((ureg >= 0) && (ureg <= 31));
7560     return ureg << 5;
7561 }
7562
7563 /*****************************************************************************
7564  *
7565  *  Returns an encoding for the specified register used in the 'Vm' position
7566  */
7567
7568 /*static*/ emitter::code_t emitter::insEncodeReg_Vm(regNumber reg)
7569 {
7570     assert(emitter::isVectorRegister(reg));
7571     emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7572     assert((ureg >= 0) && (ureg <= 31));
7573     return ureg << 16;
7574 }
7575
7576 /*****************************************************************************
7577  *
7578  *  Returns an encoding for the specified register used in the 'Va' position
7579  */
7580
7581 /*static*/ emitter::code_t emitter::insEncodeReg_Va(regNumber reg)
7582 {
7583     assert(emitter::isVectorRegister(reg));
7584     emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7585     assert((ureg >= 0) && (ureg <= 31));
7586     return ureg << 10;
7587 }
7588
7589 /*****************************************************************************
7590  *
7591  *  Returns an encoding for the specified condition code.
7592  */
7593
7594 /*static*/ emitter::code_t emitter::insEncodeCond(insCond cond)
7595 {
7596     emitter::code_t uimm = (emitter::code_t)cond;
7597     return uimm << 12;
7598 }
7599
7600 /*****************************************************************************
7601  *
7602  *  Returns an encoding for the condition code with the lowest bit inverted (marked by invert(<cond>) in the
7603  *  architecture manual).
7604  */
7605
7606 /*static*/ emitter::code_t emitter::insEncodeInvertedCond(insCond cond)
7607 {
7608     emitter::code_t uimm = (emitter::code_t)cond;
7609     uimm ^= 1; // invert the lowest bit
7610     return uimm << 12;
7611 }
7612
7613 /*****************************************************************************
7614  *
7615  *  Returns an encoding for the specified flags.
7616  */
7617
7618 /*static*/ emitter::code_t emitter::insEncodeFlags(insCflags flags)
7619 {
7620     emitter::code_t uimm = (emitter::code_t)flags;
7621     return uimm;
7622 }
7623
7624 /*****************************************************************************
7625  *
7626  *  Returns the encoding for the Shift Count bits to be used for Arm64 encodings
7627  */
7628
7629 /*static*/ emitter::code_t emitter::insEncodeShiftCount(ssize_t imm, emitAttr size)
7630 {
7631     assert((imm & 0x003F) == imm);
7632     assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
7633
7634     return (emitter::code_t)imm << 10;
7635 }
7636
7637 /*****************************************************************************
7638  *
7639  *  Returns the encoding to select a 64-bit datasize for an Arm64 instruction
7640  */
7641
7642 /*static*/ emitter::code_t emitter::insEncodeDatasize(emitAttr size)
7643 {
7644     if (size == EA_8BYTE)
7645     {
7646         return 0x80000000; // set the bit at location 31
7647     }
7648     else
7649     {
7650         assert(size == EA_4BYTE);
7651         return 0;
7652     }
7653 }
7654
7655 /*****************************************************************************
7656  *
7657  *  Returns the encoding to select the datasize for the general load/store Arm64 instructions
7658  *
7659  */
7660
7661 /*static*/ emitter::code_t emitter::insEncodeDatasizeLS(emitter::code_t code, emitAttr size)
7662 {
7663     bool exclusive = ((code & 0x35000000) == 0);
7664
7665     if ((code & 0x00800000) && !exclusive) // Is this a sign-extending opcode? (i.e. ldrsw, ldrsh, ldrsb)
7666     {
7667         if ((code & 0x80000000) == 0) // Is it a ldrsh or ldrsb and not ldrsw ?
7668         {
7669             if (EA_SIZE(size) != EA_8BYTE) // Do we need to encode the 32-bit Rt size bit?
7670             {
7671                 return 0x00400000; // set the bit at location 22
7672             }
7673         }
7674     }
7675     else if (code & 0x80000000) // Is this a ldr/str/ldur/stur opcode?
7676     {
7677         if (EA_SIZE(size) == EA_8BYTE) // Do we need to encode the 64-bit size bit?
7678         {
7679             return 0x40000000; // set the bit at location 30
7680         }
7681     }
7682     return 0;
7683 }
7684
7685 /*****************************************************************************
7686  *
7687  *  Returns the encoding to select the datasize for the vector load/store Arm64 instructions
7688  *
7689  */
7690
7691 /*static*/ emitter::code_t emitter::insEncodeDatasizeVLS(emitter::code_t code, emitAttr size)
7692 {
7693     code_t result = 0;
7694
7695     // Check bit 29
7696     if ((code & 0x20000000) == 0)
7697     {
7698         // LDR literal
7699
7700         if (size == EA_16BYTE)
7701         {
7702             // set the operation size in bit 31
7703             result = 0x80000000;
7704         }
7705         else if (size == EA_8BYTE)
7706         {
7707             // set the operation size in bit 30
7708             result = 0x40000000;
7709         }
7710         else
7711         {
7712             assert(size == EA_4BYTE);
7713             // no bits are set
7714             result = 0x00000000;
7715         }
7716     }
7717     else
7718     {
7719         // LDR non-literal
7720
7721         if (size == EA_16BYTE)
7722         {
7723             // The operation size in bits 31 and 30 are zero
7724             // Bit 23 specifies a 128-bit Load/Store
7725             result = 0x00800000;
7726         }
7727         else if (size == EA_8BYTE)
7728         {
7729             // set the operation size in bits 31 and 30
7730             result = 0xC0000000;
7731         }
7732         else if (size == EA_4BYTE)
7733         {
7734             // set the operation size in bit 31
7735             result = 0x80000000;
7736         }
7737         else if (size == EA_2BYTE)
7738         {
7739             // set the operation size in bit 30
7740             result = 0x40000000;
7741         }
7742         else
7743         {
7744             assert(size == EA_1BYTE);
7745             // The operation size in bits 31 and 30 are zero
7746             result = 0x00000000;
7747         }
7748     }
7749
7750     // Or in bit 26 to indicate a Vector register is used as 'target'
7751     result |= 0x04000000;
7752
7753     return result;
7754 }
7755
7756 /*****************************************************************************
7757  *
7758  *  Returns the encoding to select the datasize for the vector load/store Arm64 instructions
7759  *
7760  */
7761
7762 /*static*/ emitter::code_t emitter::insEncodeDatasizeVPLS(emitter::code_t code, emitAttr size)
7763 {
7764     code_t result = 0;
7765
7766     if (size == EA_16BYTE)
7767     {
7768         // The operation size in bits 31 and 30 are zero
7769         // Bit 23 specifies a 128-bit Load/Store
7770         result = 0x80000000;
7771     }
7772     else if (size == EA_8BYTE)
7773     {
7774         // set the operation size in bits 31 and 30
7775         result = 0x40000000;
7776     }
7777     else if (size == EA_4BYTE)
7778     {
7779         // set the operation size in bit 31
7780         result = 0x00000000;
7781     }
7782
7783     // Or in bit 26 to indicate a Vector register is used as 'target'
7784     result |= 0x04000000;
7785
7786     return result;
7787 }
7788
7789 /*****************************************************************************
7790  *
7791  *  Returns the encoding to set the size bit and the N bits for a 'bitfield' instruction
7792  *
7793  */
7794
7795 /*static*/ emitter::code_t emitter::insEncodeDatasizeBF(emitter::code_t code, emitAttr size)
7796 {
7797     // is bit 30 equal to 0?
7798     if ((code & 0x40000000) == 0) // is the opcode one of extr, sxtb, sxth or sxtw
7799     {
7800         if (size == EA_8BYTE) // Do we need to set the sf and N bits?
7801         {
7802             return 0x80400000; // set the sf-bit at location 31 and the N-bit at location 22
7803         }
7804     }
7805     return 0; // don't set any bits
7806 }
7807
7808 /*****************************************************************************
7809  *
7810  *  Returns the encoding to select the 64/128-bit datasize for an Arm64 vector instruction
7811  */
7812
7813 /*static*/ emitter::code_t emitter::insEncodeVectorsize(emitAttr size)
7814 {
7815     if (size == EA_16BYTE)
7816     {
7817         return 0x40000000; // set the bit at location 30
7818     }
7819     else
7820     {
7821         assert(size == EA_8BYTE);
7822         return 0;
7823     }
7824 }
7825
7826 /*****************************************************************************
7827  *
7828  *  Returns the encoding to select 'index' for an Arm64 vector elem instruction
7829  */
7830 /*static*/ emitter::code_t emitter::insEncodeVectorIndex(emitAttr elemsize, ssize_t index)
7831 {
7832     code_t bits = (code_t)index;
7833     if (elemsize == EA_1BYTE)
7834     {
7835         bits <<= 1;
7836         bits |= 1;
7837     }
7838     else if (elemsize == EA_2BYTE)
7839     {
7840         bits <<= 2;
7841         bits |= 2;
7842     }
7843     else if (elemsize == EA_4BYTE)
7844     {
7845         bits <<= 3;
7846         bits |= 4;
7847     }
7848     else
7849     {
7850         assert(elemsize == EA_8BYTE);
7851         bits <<= 4;
7852         bits |= 8;
7853     }
7854     assert((bits >= 1) && (bits <= 0x1f));
7855
7856     return (bits << 16); // bits at locations [20,19,18,17,16]
7857 }
7858
7859 /*****************************************************************************
7860  *
7861  *  Returns the encoding to select 'index2' for an Arm64 'ins' elem instruction
7862  */
7863 /*static*/ emitter::code_t emitter::insEncodeVectorIndex2(emitAttr elemsize, ssize_t index2)
7864 {
7865     code_t bits = (code_t)index2;
7866     if (elemsize == EA_1BYTE)
7867     {
7868         // bits are correct
7869     }
7870     else if (elemsize == EA_2BYTE)
7871     {
7872         bits <<= 1;
7873     }
7874     else if (elemsize == EA_4BYTE)
7875     {
7876         bits <<= 2;
7877     }
7878     else
7879     {
7880         assert(elemsize == EA_8BYTE);
7881         bits <<= 3;
7882     }
7883     assert((bits >= 0) && (bits <= 0xf));
7884
7885     return (bits << 11); // bits at locations [14,13,12,11]
7886 }
7887
7888 /*****************************************************************************
7889  *
7890  *  Returns the encoding to select the 'index' for an Arm64 'mul' by elem instruction
7891  */
7892 /*static*/ emitter::code_t emitter::insEncodeVectorIndexLMH(emitAttr elemsize, ssize_t index)
7893 {
7894     code_t bits = 0;
7895
7896     if (elemsize == EA_2BYTE)
7897     {
7898         assert((index >= 0) && (index <= 7));
7899         if (index & 0x4)
7900         {
7901             bits |= (1 << 11); // set bit 11 'H'
7902         }
7903         if (index & 0x2)
7904         {
7905             bits |= (1 << 21); // set bit 21 'L'
7906         }
7907         if (index & 0x1)
7908         {
7909             bits |= (1 << 20); // set bit 20 'M'
7910         }
7911     }
7912     else if (elemsize == EA_4BYTE)
7913     {
7914         assert((index >= 0) && (index <= 3));
7915         if (index & 0x2)
7916         {
7917             bits |= (1 << 11); // set bit 11 'H'
7918         }
7919         if (index & 0x1)
7920         {
7921             bits |= (1 << 21); // set bit 21 'L'
7922         }
7923     }
7924     else
7925     {
7926         assert(!"Invalid 'elemsize' value");
7927     }
7928
7929     return bits;
7930 }
7931
7932 /*****************************************************************************
7933  *
7934  *   Returns the encoding to shift by 'shift' for an Arm64 vector or scalar instruction
7935  */
7936
7937 /*static*/ emitter::code_t emitter::insEncodeVectorShift(emitAttr size, ssize_t shift)
7938 {
7939     assert(shift < getBitWidth(size));
7940
7941     code_t imm = (code_t)(getBitWidth(size) + shift);
7942
7943     return imm << 16;
7944 }
7945
7946 /*****************************************************************************
7947  *
7948  *  Returns the encoding to select the 1/2/4/8 byte elemsize for an Arm64 vector instruction
7949  */
7950
7951 /*static*/ emitter::code_t emitter::insEncodeElemsize(emitAttr size)
7952 {
7953     if (size == EA_8BYTE)
7954     {
7955         return 0x00C00000; // set the bit at location 23 and 22
7956     }
7957     else if (size == EA_4BYTE)
7958     {
7959         return 0x00800000; // set the bit at location 23
7960     }
7961     else if (size == EA_2BYTE)
7962     {
7963         return 0x00400000; // set the bit at location 22
7964     }
7965     assert(size == EA_1BYTE);
7966     return 0x00000000;
7967 }
7968
7969 /*****************************************************************************
7970  *
7971  *  Returns the encoding to select the 4/8 byte elemsize for an Arm64 float vector instruction
7972  */
7973
7974 /*static*/ emitter::code_t emitter::insEncodeFloatElemsize(emitAttr size)
7975 {
7976     if (size == EA_8BYTE)
7977     {
7978         return 0x00400000; // set the bit at location 22
7979     }
7980     assert(size == EA_4BYTE);
7981     return 0x00000000;
7982 }
7983
7984 // Returns the encoding to select the index for an Arm64 float vector by elem instruction
7985 /*static*/ emitter::code_t emitter::insEncodeFloatIndex(emitAttr elemsize, ssize_t index)
7986 {
7987     code_t result = 0x00000000;
7988     if (elemsize == EA_8BYTE)
7989     {
7990         assert((index >= 0) && (index <= 1));
7991         if (index == 1)
7992         {
7993             result |= 0x00000800; // 'H' - set the bit at location 11
7994         }
7995     }
7996     else
7997     {
7998         assert(elemsize == EA_4BYTE);
7999         assert((index >= 0) && (index <= 3));
8000         if (index & 2)
8001         {
8002             result |= 0x00000800; // 'H' - set the bit at location 11
8003         }
8004         if (index & 1)
8005         {
8006             result |= 0x00200000; // 'L' - set the bit at location 21
8007         }
8008     }
8009     return result;
8010 }
8011
8012 /*****************************************************************************
8013  *
8014  *  Returns the encoding to select the fcvt operation for Arm64 instructions
8015  */
8016 /*static*/ emitter::code_t emitter::insEncodeConvertOpt(insFormat fmt, insOpts conversion)
8017 {
8018     code_t result = 0;
8019     switch (conversion)
8020     {
8021         case INS_OPTS_S_TO_D: // Single to Double
8022             assert(fmt == IF_DV_2J);
8023             result = 0x00008000; // type=00, opc=01
8024             break;
8025
8026         case INS_OPTS_D_TO_S: // Double to Single
8027             assert(fmt == IF_DV_2J);
8028             result = 0x00400000; // type=01, opc=00
8029             break;
8030
8031         case INS_OPTS_H_TO_S: // Half to Single
8032             assert(fmt == IF_DV_2J);
8033             result = 0x00C00000; // type=11, opc=00
8034             break;
8035
8036         case INS_OPTS_H_TO_D: // Half to Double
8037             assert(fmt == IF_DV_2J);
8038             result = 0x00C08000; // type=11, opc=01
8039             break;
8040
8041         case INS_OPTS_S_TO_H: // Single to Half
8042             assert(fmt == IF_DV_2J);
8043             result = 0x00018000; // type=00, opc=11
8044             break;
8045
8046         case INS_OPTS_D_TO_H: // Double to Half
8047             assert(fmt == IF_DV_2J);
8048             result = 0x00418000; // type=01, opc=11
8049             break;
8050
8051         case INS_OPTS_S_TO_4BYTE: // Single to INT32
8052             assert(fmt == IF_DV_2H);
8053             result = 0x00000000; // sf=0, type=00
8054             break;
8055
8056         case INS_OPTS_D_TO_4BYTE: // Double to INT32
8057             assert(fmt == IF_DV_2H);
8058             result = 0x00400000; // sf=0, type=01
8059             break;
8060
8061         case INS_OPTS_S_TO_8BYTE: // Single to INT64
8062             assert(fmt == IF_DV_2H);
8063             result = 0x80000000; // sf=1, type=00
8064             break;
8065
8066         case INS_OPTS_D_TO_8BYTE: // Double to INT64
8067             assert(fmt == IF_DV_2H);
8068             result = 0x80400000; // sf=1, type=01
8069             break;
8070
8071         case INS_OPTS_4BYTE_TO_S: // INT32 to Single
8072             assert(fmt == IF_DV_2I);
8073             result = 0x00000000; // sf=0, type=00
8074             break;
8075
8076         case INS_OPTS_4BYTE_TO_D: // INT32 to Double
8077             assert(fmt == IF_DV_2I);
8078             result = 0x00400000; // sf=0, type=01
8079             break;
8080
8081         case INS_OPTS_8BYTE_TO_S: // INT64 to Single
8082             assert(fmt == IF_DV_2I);
8083             result = 0x80000000; // sf=1, type=00
8084             break;
8085
8086         case INS_OPTS_8BYTE_TO_D: // INT64 to Double
8087             assert(fmt == IF_DV_2I);
8088             result = 0x80400000; // sf=1, type=01
8089             break;
8090
8091         default:
8092             assert(!"Invalid 'conversion' value");
8093             break;
8094     }
8095     return result;
8096 }
8097
8098 /*****************************************************************************
8099  *
8100  *  Returns the encoding to have the Rn register be updated Pre/Post indexed
8101  *  or not updated
8102  */
8103
8104 /*static*/ emitter::code_t emitter::insEncodeIndexedOpt(insOpts opt)
8105 {
8106     assert(emitter::insOptsNone(opt) || emitter::insOptsIndexed(opt));
8107
8108     if (emitter::insOptsIndexed(opt))
8109     {
8110         if (emitter::insOptsPostIndex(opt))
8111         {
8112             return 0x00000400; // set the bit at location 10
8113         }
8114         else
8115         {
8116             assert(emitter::insOptsPreIndex(opt));
8117             return 0x00000C00; // set the bit at location 10 and 11
8118         }
8119     }
8120     else
8121     {
8122         assert(emitter::insOptsNone(opt));
8123         return 0; // bits 10 and 11 are zero
8124     }
8125 }
8126
8127 /*****************************************************************************
8128  *
8129  *  Returns the encoding for a ldp/stp instruction to have the Rn register
8130  *  be updated Pre/Post indexed or not updated
8131  */
8132
8133 /*static*/ emitter::code_t emitter::insEncodePairIndexedOpt(instruction ins, insOpts opt)
8134 {
8135     assert(emitter::insOptsNone(opt) || emitter::insOptsIndexed(opt));
8136
8137     if ((ins == INS_ldnp) || (ins == INS_stnp))
8138     {
8139         assert(emitter::insOptsNone(opt));
8140         return 0; // bits 23 and 24 are zero
8141     }
8142     else
8143     {
8144         if (emitter::insOptsIndexed(opt))
8145         {
8146             if (emitter::insOptsPostIndex(opt))
8147             {
8148                 return 0x00800000; // set the bit at location 23
8149             }
8150             else
8151             {
8152                 assert(emitter::insOptsPreIndex(opt));
8153                 return 0x01800000; // set the bit at location 24 and 23
8154             }
8155         }
8156         else
8157         {
8158             assert(emitter::insOptsNone(opt));
8159             return 0x01000000; // set the bit at location 24
8160         }
8161     }
8162 }
8163
8164 /*****************************************************************************
8165  *
8166  *  Returns the encoding to apply a Shift Type on the Rm register
8167  */
8168
8169 /*static*/ emitter::code_t emitter::insEncodeShiftType(insOpts opt)
8170 {
8171     if (emitter::insOptsNone(opt))
8172     {
8173         // None implies the we encode LSL (with a zero immediate)
8174         opt = INS_OPTS_LSL;
8175     }
8176     assert(emitter::insOptsAnyShift(opt));
8177
8178     emitter::code_t option = (emitter::code_t)opt - (emitter::code_t)INS_OPTS_LSL;
8179     assert(option <= 3);
8180
8181     return option << 22; // bits 23, 22
8182 }
8183
8184 /*****************************************************************************
8185  *
8186  *  Returns the encoding to apply a 12 bit left shift to the immediate
8187  */
8188
8189 /*static*/ emitter::code_t emitter::insEncodeShiftImm12(insOpts opt)
8190 {
8191     if (emitter::insOptsLSL12(opt))
8192     {
8193         return 0x00400000; // set the bit at location 22
8194     }
8195     return 0;
8196 }
8197
8198 /*****************************************************************************
8199  *
8200  *  Returns the encoding to have the Rm register use an extend operation
8201  */
8202
8203 /*static*/ emitter::code_t emitter::insEncodeExtend(insOpts opt)
8204 {
8205     if (emitter::insOptsNone(opt) || (opt == INS_OPTS_LSL))
8206     {
8207         // None or LSL implies the we encode UXTX
8208         opt = INS_OPTS_UXTX;
8209     }
8210     assert(emitter::insOptsAnyExtend(opt));
8211
8212     emitter::code_t option = (emitter::code_t)opt - (emitter::code_t)INS_OPTS_UXTB;
8213     assert(option <= 7);
8214
8215     return option << 13; // bits 15,14,13
8216 }
8217
8218 /*****************************************************************************
8219  *
8220  *  Returns the encoding to scale the Rm register by {0,1,2,3,4}
8221  *  when using an extend operation
8222  */
8223
8224 /*static*/ emitter::code_t emitter::insEncodeExtendScale(ssize_t imm)
8225 {
8226     assert((imm >= 0) && (imm <= 4));
8227
8228     return (emitter::code_t)imm << 10; // bits 12,11,10
8229 }
8230
8231 /*****************************************************************************
8232  *
8233  *  Returns the encoding to have the Rm register be auto scaled by the ld/st size
8234  */
8235
8236 /*static*/ emitter::code_t emitter::insEncodeReg3Scale(bool isScaled)
8237 {
8238     if (isScaled)
8239     {
8240         return 0x00001000; // set the bit at location 12
8241     }
8242     else
8243     {
8244         return 0;
8245     }
8246 }
8247
8248 BYTE* emitter::emitOutputLoadLabel(BYTE* dst, BYTE* srcAddr, BYTE* dstAddr, instrDescJmp* id)
8249 {
8250     instruction ins    = id->idIns();
8251     insFormat   fmt    = id->idInsFmt();
8252     regNumber   dstReg = id->idReg1();
8253     if (id->idjShort)
8254     {
8255         // adr x, [rel addr] --  compute address: current addr(ip) + rel addr.
8256         assert(ins == INS_adr);
8257         assert(fmt == IF_DI_1E);
8258         ssize_t distVal = (ssize_t)(dstAddr - srcAddr);
8259         dst             = emitOutputShortAddress(dst, ins, fmt, distVal, dstReg);
8260     }
8261     else
8262     {
8263         // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8264         assert(fmt == IF_LARGEADR);
8265         ssize_t relPageAddr =
8266             (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8267         dst = emitOutputShortAddress(dst, INS_adrp, IF_DI_1E, relPageAddr, dstReg);
8268
8269         // add x, x, page offs -- compute address = page addr + page offs
8270         ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8271         assert(isValidUimm12(imm12));
8272         code_t code =
8273             emitInsCode(INS_add, IF_DI_2A);  // DI_2A  X0010001shiiiiii iiiiiinnnnnddddd   1100 0000   imm(i12, sh)
8274         code |= insEncodeDatasize(EA_8BYTE); // X
8275         code |= ((code_t)imm12 << 10);       // iiiiiiiiiiii
8276         code |= insEncodeReg_Rd(dstReg);     // ddddd
8277         code |= insEncodeReg_Rn(dstReg);     // nnnnn
8278         dst += emitOutput_Instr(dst, code);
8279     }
8280     return dst;
8281 }
8282
8283 /*****************************************************************************
8284  *
8285  *  Output a local jump or other instruction with a pc-relative immediate.
8286  *  Note that this may be invoked to overwrite an existing jump instruction at 'dst'
8287  *  to handle forward branch patching.
8288  */
8289
8290 BYTE* emitter::emitOutputLJ(insGroup* ig, BYTE* dst, instrDesc* i)
8291 {
8292     instrDescJmp* id = (instrDescJmp*)i;
8293
8294     unsigned srcOffs;
8295     unsigned dstOffs;
8296     BYTE*    srcAddr;
8297     BYTE*    dstAddr;
8298     ssize_t  distVal;
8299     ssize_t  loBits;
8300
8301     // Set default ins/fmt from id.
8302     instruction ins = id->idIns();
8303     insFormat   fmt = id->idInsFmt();
8304
8305     bool loadLabel    = false;
8306     bool isJump       = false;
8307     bool loadConstant = false;
8308
8309     switch (ins)
8310     {
8311         default:
8312             isJump = true;
8313             break;
8314
8315         case INS_tbz:
8316         case INS_tbnz:
8317         case INS_cbz:
8318         case INS_cbnz:
8319             isJump = true;
8320             break;
8321
8322         case INS_ldr:
8323         case INS_ldrsw:
8324             loadConstant = true;
8325             break;
8326
8327         case INS_adr:
8328         case INS_adrp:
8329             loadLabel = true;
8330             break;
8331     }
8332
8333     /* Figure out the distance to the target */
8334
8335     srcOffs = emitCurCodeOffs(dst);
8336     srcAddr = emitOffsetToPtr(srcOffs);
8337
8338     if (id->idAddr()->iiaIsJitDataOffset())
8339     {
8340         assert(loadConstant || loadLabel);
8341         int doff = id->idAddr()->iiaGetJitDataOffset();
8342         assert(doff >= 0);
8343         ssize_t imm = emitGetInsSC(id);
8344         assert((imm >= 0) && (imm < 0x1000)); // 0x1000 is arbitrary, currently 'imm' is always 0
8345
8346         unsigned dataOffs = (unsigned)(doff + imm);
8347         assert(dataOffs < emitDataSize());
8348         dstAddr = emitDataOffsetToPtr(dataOffs);
8349
8350         regNumber dstReg  = id->idReg1();
8351         regNumber addrReg = dstReg; // an integer register to compute long address.
8352         emitAttr  opSize  = id->idOpSize();
8353
8354         if (loadConstant)
8355         {
8356             if (id->idjShort)
8357             {
8358                 // ldr x/v, [rel addr] -- load constant from current addr(ip) + rel addr.
8359                 assert(ins == INS_ldr);
8360                 assert(fmt == IF_LS_1A);
8361                 distVal = (ssize_t)(dstAddr - srcAddr);
8362                 dst     = emitOutputShortConstant(dst, ins, fmt, distVal, dstReg, opSize);
8363             }
8364             else
8365             {
8366                 // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8367                 assert(fmt == IF_LARGELDC);
8368                 ssize_t relPageAddr =
8369                     (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8370                 if (isVectorRegister(dstReg))
8371                 {
8372                     // Update addrReg with the reserved integer register
8373                     // since we cannot use dstReg (vector) to load constant directly from memory.
8374                     addrReg = id->idReg2();
8375                     assert(isGeneralRegister(addrReg));
8376                 }
8377                 ins = INS_adrp;
8378                 fmt = IF_DI_1E;
8379                 dst = emitOutputShortAddress(dst, ins, fmt, relPageAddr, addrReg);
8380
8381                 // ldr x, [x, page offs] -- load constant from page address + page offset into integer register.
8382                 ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8383                 assert(isValidUimm12(imm12));
8384                 ins = INS_ldr;
8385                 fmt = IF_LS_2B;
8386                 dst = emitOutputShortConstant(dst, ins, fmt, imm12, addrReg, opSize);
8387
8388                 // fmov v, d -- copy constant in integer register to vector register.
8389                 // This is needed only for vector constant.
8390                 if (addrReg != dstReg)
8391                 {
8392                     //  fmov    Vd,Rn                DV_2I  X00111100X100111 000000nnnnnddddd   1E27 0000   Vd,Rn
8393                     //  (scalar, from general)
8394                     assert(isVectorRegister(dstReg) && isGeneralRegister(addrReg));
8395                     ins         = INS_fmov;
8396                     fmt         = IF_DV_2I;
8397                     code_t code = emitInsCode(ins, fmt);
8398
8399                     code |= insEncodeReg_Vd(dstReg);  // ddddd
8400                     code |= insEncodeReg_Rn(addrReg); // nnnnn
8401                     if (id->idOpSize() == EA_8BYTE)
8402                     {
8403                         code |= 0x80400000; // X ... X
8404                     }
8405                     dst += emitOutput_Instr(dst, code);
8406                 }
8407             }
8408         }
8409         else
8410         {
8411             assert(loadLabel);
8412             dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8413         }
8414
8415         return dst;
8416     }
8417
8418     assert(loadLabel || isJump);
8419
8420     if (id->idAddr()->iiaHasInstrCount())
8421     {
8422         assert(ig != NULL);
8423         int      instrCount = id->idAddr()->iiaGetInstrCount();
8424         unsigned insNum     = emitFindInsNum(ig, id);
8425         if (instrCount < 0)
8426         {
8427             // Backward branches using instruction count must be within the same instruction group.
8428             assert(insNum + 1 >= (unsigned)(-instrCount));
8429         }
8430         dstOffs = ig->igOffs + emitFindOffset(ig, (insNum + 1 + instrCount));
8431         dstAddr = emitOffsetToPtr(dstOffs);
8432     }
8433     else
8434     {
8435         dstOffs = id->idAddr()->iiaIGlabel->igOffs;
8436         dstAddr = emitOffsetToPtr(dstOffs);
8437     }
8438
8439     distVal = (ssize_t)(dstAddr - srcAddr);
8440
8441     if (dstOffs <= srcOffs)
8442     {
8443 #if DEBUG_EMIT
8444         /* This is a backward jump - distance is known at this point */
8445
8446         if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8447         {
8448             size_t blkOffs = id->idjIG->igOffs;
8449
8450             if (INTERESTING_JUMP_NUM == 0)
8451                 printf("[3] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8452             printf("[3] Jump  block is at %08X - %02X = %08X\n", blkOffs, emitOffsAdj, blkOffs - emitOffsAdj);
8453             printf("[3] Jump        is at %08X - %02X = %08X\n", srcOffs, emitOffsAdj, srcOffs - emitOffsAdj);
8454             printf("[3] Label block is at %08X - %02X = %08X\n", dstOffs, emitOffsAdj, dstOffs - emitOffsAdj);
8455         }
8456 #endif
8457     }
8458     else
8459     {
8460         /* This is a  forward jump - distance will be an upper limit */
8461
8462         emitFwdJumps = true;
8463
8464         /* The target offset will be closer by at least 'emitOffsAdj', but only if this
8465            jump doesn't cross the hot-cold boundary. */
8466
8467         if (!emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8468         {
8469             dstOffs -= emitOffsAdj;
8470             distVal -= emitOffsAdj;
8471         }
8472
8473         /* Record the location of the jump for later patching */
8474
8475         id->idjOffs = dstOffs;
8476
8477         /* Are we overflowing the id->idjOffs bitfield? */
8478         if (id->idjOffs != dstOffs)
8479             IMPL_LIMITATION("Method is too large");
8480
8481 #if DEBUG_EMIT
8482         if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8483         {
8484             size_t blkOffs = id->idjIG->igOffs;
8485
8486             if (INTERESTING_JUMP_NUM == 0)
8487                 printf("[4] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8488             printf("[4] Jump  block is at %08X\n", blkOffs);
8489             printf("[4] Jump        is at %08X\n", srcOffs);
8490             printf("[4] Label block is at %08X - %02X = %08X\n", dstOffs + emitOffsAdj, emitOffsAdj, dstOffs);
8491         }
8492 #endif
8493     }
8494
8495 #ifdef DEBUG
8496     if (0 && emitComp->verbose)
8497     {
8498         size_t sz          = 4;
8499         int    distValSize = id->idjShort ? 4 : 8;
8500         printf("; %s jump [%08X/%03u] from %0*X to %0*X: dist = %08XH\n", (dstOffs <= srcOffs) ? "Fwd" : "Bwd",
8501                dspPtr(id), id->idDebugOnlyInfo()->idNum, distValSize, srcOffs + sz, distValSize, dstOffs, distVal);
8502     }
8503 #endif
8504
8505     /* For forward jumps, record the address of the distance value */
8506     id->idjTemp.idjAddr = (distVal > 0) ? dst : NULL;
8507
8508     if (emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8509     {
8510         assert(!id->idjShort);
8511         NYI_ARM64("Relocation Support for long address");
8512     }
8513
8514     assert(insOptsNone(id->idInsOpt()));
8515
8516     if (isJump)
8517     {
8518         if (id->idjShort)
8519         {
8520             // Short conditional/unconditional jump
8521             assert(!id->idjKeepLong);
8522             assert(emitJumpCrossHotColdBoundary(srcOffs, dstOffs) == false);
8523             assert((fmt == IF_BI_0A) || (fmt == IF_BI_0B) || (fmt == IF_BI_1A) || (fmt == IF_BI_1B));
8524         }
8525         else
8526         {
8527             // Long conditional jump
8528             assert(fmt == IF_LARGEJMP);
8529             // This is a pseudo-instruction format representing a large conditional branch, to allow
8530             // us to get a greater branch target range than we can get by using a straightforward conditional
8531             // branch. It is encoded as a short conditional branch that branches around a long unconditional
8532             // branch.
8533             //
8534             // Conceptually, we have:
8535             //
8536             //      b<cond> L_target
8537             //
8538             // The code we emit is:
8539             //
8540             //      b<!cond> L_not  // 4 bytes. Note that we reverse the condition.
8541             //      b L_target      // 4 bytes
8542             //   L_not:
8543             //
8544             // Note that we don't actually insert any blocks: we simply encode "b <!cond> L_not" as a branch with
8545             // the correct offset. Note also that this works for both integer and floating-point conditions, because
8546             // the condition inversion takes ordered/unordered into account, preserving NaN behavior. For example,
8547             // "GT" (greater than) is inverted to "LE" (less than, equal, or unordered).
8548
8549             instruction reverseIns;
8550             insFormat   reverseFmt;
8551
8552             switch (ins)
8553             {
8554                 case INS_cbz:
8555                     reverseIns = INS_cbnz;
8556                     reverseFmt = IF_BI_1A;
8557                     break;
8558                 case INS_cbnz:
8559                     reverseIns = INS_cbz;
8560                     reverseFmt = IF_BI_1A;
8561                     break;
8562                 case INS_tbz:
8563                     reverseIns = INS_tbnz;
8564                     reverseFmt = IF_BI_1B;
8565                     break;
8566                 case INS_tbnz:
8567                     reverseIns = INS_tbz;
8568                     reverseFmt = IF_BI_1B;
8569                     break;
8570                 default:
8571                     reverseIns = emitJumpKindToIns(emitReverseJumpKind(emitInsToJumpKind(ins)));
8572                     reverseFmt = IF_BI_0B;
8573             }
8574
8575             dst =
8576                 emitOutputShortBranch(dst,
8577                                       reverseIns, // reverse the conditional instruction
8578                                       reverseFmt,
8579                                       8, /* 8 bytes from start of this large conditional pseudo-instruction to L_not. */
8580                                       id);
8581
8582             // Now, pretend we've got a normal unconditional branch, and fall through to the code to emit that.
8583             ins = INS_b;
8584             fmt = IF_BI_0A;
8585
8586             // The distVal was computed based on the beginning of the pseudo-instruction,
8587             // So subtract the size of the conditional branch so that it is relative to the
8588             // unconditional branch.
8589             distVal -= 4;
8590         }
8591
8592         dst = emitOutputShortBranch(dst, ins, fmt, distVal, id);
8593     }
8594     else if (loadLabel)
8595     {
8596         dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8597     }
8598
8599     return dst;
8600 }
8601
8602 /*****************************************************************************
8603 *
8604 *  Output a short branch instruction.
8605 */
8606 BYTE* emitter::emitOutputShortBranch(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, instrDescJmp* id)
8607 {
8608     code_t code = emitInsCode(ins, fmt);
8609
8610     ssize_t loBits = (distVal & 3);
8611     noway_assert(loBits == 0);
8612     distVal >>= 2; // branch offset encodings are scaled by 4.
8613
8614     if (fmt == IF_BI_0A)
8615     {
8616         // INS_b or INS_bl_local
8617         noway_assert(isValidSimm26(distVal));
8618         distVal &= 0x3FFFFFFLL;
8619         code |= distVal;
8620     }
8621     else if (fmt == IF_BI_0B) // BI_0B   01010100iiiiiiii iiiiiiiiiiiXXXXX      simm19:00
8622     {
8623         // INS_beq, INS_bne, etc...
8624         noway_assert(isValidSimm19(distVal));
8625         distVal &= 0x7FFFFLL;
8626         code |= distVal << 5;
8627     }
8628     else if (fmt == IF_BI_1A) // BI_1A   X.......iiiiiiii iiiiiiiiiiittttt      Rt simm19:00
8629     {
8630         // INS_cbz or INS_cbnz
8631         assert(id != nullptr);
8632         code |= insEncodeDatasize(id->idOpSize()); // X
8633         code |= insEncodeReg_Rt(id->idReg1());     // ttttt
8634
8635         noway_assert(isValidSimm19(distVal));
8636         distVal &= 0x7FFFFLL; // 19 bits
8637         code |= distVal << 5;
8638     }
8639     else if (fmt == IF_BI_1B) // BI_1B   B.......bbbbbiii iiiiiiiiiiittttt      Rt imm6, simm14:00
8640     {
8641         // INS_tbz or INS_tbnz
8642         assert(id != nullptr);
8643         ssize_t imm = emitGetInsSC(id);
8644         assert(isValidImmShift(imm, id->idOpSize()));
8645
8646         if (imm & 0x20) // test bit 32-63 ?
8647         {
8648             code |= 0x80000000; // B
8649         }
8650         code |= ((imm & 0x1F) << 19);          // bbbbb
8651         code |= insEncodeReg_Rt(id->idReg1()); // ttttt
8652
8653         noway_assert(isValidSimm14(distVal));
8654         distVal &= 0x3FFFLL; // 14 bits
8655         code |= distVal << 5;
8656     }
8657     else
8658     {
8659         assert(!"Unknown fmt for emitOutputShortBranch");
8660     }
8661
8662     dst += emitOutput_Instr(dst, code);
8663
8664     return dst;
8665 }
8666
8667 /*****************************************************************************
8668 *
8669 *  Output a short address instruction.
8670 */
8671 BYTE* emitter::emitOutputShortAddress(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, regNumber reg)
8672 {
8673     ssize_t loBits = (distVal & 3);
8674     distVal >>= 2;
8675
8676     code_t code = emitInsCode(ins, fmt);
8677     if (fmt == IF_DI_1E) // DI_1E   .ii.....iiiiiiii iiiiiiiiiiiddddd      Rd simm21
8678     {
8679         // INS_adr or INS_adrp
8680         code |= insEncodeReg_Rd(reg); // ddddd
8681
8682         noway_assert(isValidSimm19(distVal));
8683         distVal &= 0x7FFFFLL; // 19 bits
8684         code |= distVal << 5;
8685         code |= loBits << 29; //  2 bits
8686     }
8687     else
8688     {
8689         assert(!"Unknown fmt for emitOutputShortAddress");
8690     }
8691
8692     dst += emitOutput_Instr(dst, code);
8693
8694     return dst;
8695 }
8696
8697 /*****************************************************************************
8698 *
8699 *  Output a short constant instruction.
8700 */
8701 BYTE* emitter::emitOutputShortConstant(
8702     BYTE* dst, instruction ins, insFormat fmt, ssize_t imm, regNumber reg, emitAttr opSize)
8703 {
8704     code_t code = emitInsCode(ins, fmt);
8705
8706     if (fmt == IF_LS_1A)
8707     {
8708         // LS_1A   XX...V..iiiiiiii iiiiiiiiiiittttt      Rt simm21
8709         // INS_ldr or INS_ldrsw (PC-Relative)
8710
8711         ssize_t loBits = (imm & 3);
8712         noway_assert(loBits == 0);
8713         ssize_t distVal = imm >>= 2; // load offset encodings are scaled by 4.
8714
8715         noway_assert(isValidSimm19(distVal));
8716
8717         // Is the target a vector register?
8718         if (isVectorRegister(reg))
8719         {
8720             code |= insEncodeDatasizeVLS(code, opSize); // XX V
8721             code |= insEncodeReg_Vt(reg);               // ttttt
8722         }
8723         else
8724         {
8725             assert(isGeneralRegister(reg));
8726             // insEncodeDatasizeLS is not quite right for this case.
8727             // So just specialize it.
8728             if ((ins == INS_ldr) && (opSize == EA_8BYTE))
8729             {
8730                 // set the operation size in bit 30
8731                 code |= 0x40000000;
8732             }
8733
8734             code |= insEncodeReg_Rt(reg); // ttttt
8735         }
8736
8737         distVal &= 0x7FFFFLL; // 19 bits
8738         code |= distVal << 5;
8739     }
8740     else if (fmt == IF_LS_2B)
8741     {
8742         //  ldr     Rt,[Xn+pimm12]       LS_2B  1X11100101iiiiii iiiiiinnnnnttttt   B940 0000   imm(0-4095<<{2,3})
8743         // INS_ldr or INS_ldrsw (PC-Relative)
8744         noway_assert(isValidUimm12(imm));
8745         assert(isGeneralRegister(reg));
8746
8747         if (opSize == EA_8BYTE)
8748         {
8749             // insEncodeDatasizeLS is not quite right for this case.
8750             // So just specialize it.
8751             if (ins == INS_ldr)
8752             {
8753                 // set the operation size in bit 30
8754                 code |= 0x40000000;
8755             }
8756             // Low 3 bits should be 0 -- 8 byte JIT data should be aligned on 8 byte.
8757             assert((imm & 7) == 0);
8758             imm >>= 3;
8759         }
8760         else
8761         {
8762             assert(opSize == EA_4BYTE);
8763             // Low 2 bits should be 0 -- 4 byte aligned data.
8764             assert((imm & 3) == 0);
8765             imm >>= 2;
8766         }
8767
8768         code |= insEncodeReg_Rt(reg); // ttttt
8769         code |= insEncodeReg_Rn(reg); // nnnnn
8770         code |= imm << 10;
8771     }
8772     else
8773     {
8774         assert(!"Unknown fmt for emitOutputShortConstant");
8775     }
8776
8777     dst += emitOutput_Instr(dst, code);
8778
8779     return dst;
8780 }
8781 /*****************************************************************************
8782  *
8783  *  Output a call instruction.
8784  */
8785
8786 unsigned emitter::emitOutputCall(insGroup* ig, BYTE* dst, instrDesc* id, code_t code)
8787 {
8788     const unsigned char callInstrSize = sizeof(code_t); // 4 bytes
8789     regMaskTP           gcrefRegs;
8790     regMaskTP           byrefRegs;
8791
8792     VARSET_TP GCvars(VarSetOps::UninitVal());
8793
8794     // Is this a "fat" call descriptor?
8795     if (id->idIsLargeCall())
8796     {
8797         instrDescCGCA* idCall = (instrDescCGCA*)id;
8798         gcrefRegs             = idCall->idcGcrefRegs;
8799         byrefRegs             = idCall->idcByrefRegs;
8800         VarSetOps::Assign(emitComp, GCvars, idCall->idcGCvars);
8801     }
8802     else
8803     {
8804         assert(!id->idIsLargeDsp());
8805         assert(!id->idIsLargeCns());
8806
8807         gcrefRegs = emitDecodeCallGCregs(id);
8808         byrefRegs = 0;
8809         VarSetOps::AssignNoCopy(emitComp, GCvars, VarSetOps::MakeEmpty(emitComp));
8810     }
8811
8812     /* We update the GC info before the call as the variables cannot be
8813         used by the call. Killing variables before the call helps with
8814         boundary conditions if the call is CORINFO_HELP_THROW - see bug 50029.
8815         If we ever track aliased variables (which could be used by the
8816         call), we would have to keep them alive past the call. */
8817
8818     emitUpdateLiveGCvars(GCvars, dst);
8819
8820     // Now output the call instruction and update the 'dst' pointer
8821     //
8822     unsigned outputInstrSize = emitOutput_Instr(dst, code);
8823     dst += outputInstrSize;
8824
8825     // All call instructions are 4-byte in size on ARM64
8826     //
8827     assert(outputInstrSize == callInstrSize);
8828
8829     // If the method returns a GC ref, mark INTRET (R0) appropriately.
8830     if (id->idGCref() == GCT_GCREF)
8831     {
8832         gcrefRegs |= RBM_INTRET;
8833     }
8834     else if (id->idGCref() == GCT_BYREF)
8835     {
8836         byrefRegs |= RBM_INTRET;
8837     }
8838
8839     // If is a multi-register return method is called, mark INTRET_1 (X1) appropriately
8840     if (id->idIsLargeCall())
8841     {
8842         instrDescCGCA* idCall = (instrDescCGCA*)id;
8843         if (idCall->idSecondGCref() == GCT_GCREF)
8844         {
8845             gcrefRegs |= RBM_INTRET_1;
8846         }
8847         else if (idCall->idSecondGCref() == GCT_BYREF)
8848         {
8849             byrefRegs |= RBM_INTRET_1;
8850         }
8851     }
8852
8853     // If the GC register set has changed, report the new set.
8854     if (gcrefRegs != emitThisGCrefRegs)
8855     {
8856         emitUpdateLiveGCregs(GCT_GCREF, gcrefRegs, dst);
8857     }
8858     // If the Byref register set has changed, report the new set.
8859     if (byrefRegs != emitThisByrefRegs)
8860     {
8861         emitUpdateLiveGCregs(GCT_BYREF, byrefRegs, dst);
8862     }
8863
8864     // Some helper calls may be marked as not requiring GC info to be recorded.
8865     if ((!id->idIsNoGC()))
8866     {
8867         // On ARM64, as on AMD64, we don't change the stack pointer to push/pop args.
8868         // So we're not really doing a "stack pop" here (note that "args" is 0), but we use this mechanism
8869         // to record the call for GC info purposes.  (It might be best to use an alternate call,
8870         // and protect "emitStackPop" under the EMIT_TRACK_STACK_DEPTH preprocessor variable.)
8871         emitStackPop(dst, /*isCall*/ true, callInstrSize, /*args*/ 0);
8872
8873         // Do we need to record a call location for GC purposes?
8874         //
8875         if (!emitFullGCinfo)
8876         {
8877             emitRecordGCcall(dst, callInstrSize);
8878         }
8879     }
8880     return callInstrSize;
8881 }
8882
8883 /*****************************************************************************
8884  *
8885  *  Emit a 32-bit Arm64 instruction
8886  */
8887
8888 /*static*/ unsigned emitter::emitOutput_Instr(BYTE* dst, code_t code)
8889 {
8890     assert(sizeof(code_t) == 4);
8891     *((code_t*)dst) = code;
8892
8893     return sizeof(code_t);
8894 }
8895
8896 /*****************************************************************************
8897 *
8898  *  Append the machine code corresponding to the given instruction descriptor
8899  *  to the code block at '*dp'; the base of the code block is 'bp', and 'ig'
8900  *  is the instruction group that contains the instruction. Updates '*dp' to
8901  *  point past the generated code, and returns the size of the instruction
8902  *  descriptor in bytes.
8903  */
8904
8905 size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
8906 {
8907     BYTE*         dst  = *dp;
8908     BYTE*         odst = dst;
8909     code_t        code = 0;
8910     size_t        sz   = emitGetInstrDescSize(id); // TODO-ARM64-Cleanup: on ARM, this is set in each case. why?
8911     instruction   ins  = id->idIns();
8912     insFormat     fmt  = id->idInsFmt();
8913     emitAttr      size = id->idOpSize();
8914     unsigned char callInstrSize = 0;
8915     unsigned      condcode;
8916
8917 #ifdef DEBUG
8918 #if DUMP_GC_TABLES
8919     bool dspOffs = emitComp->opts.dspGCtbls;
8920 #else
8921     bool dspOffs = !emitComp->opts.disDiffable;
8922 #endif
8923 #endif // DEBUG
8924
8925     assert(REG_NA == (int)REG_NA);
8926
8927     VARSET_TP GCvars(VarSetOps::UninitVal());
8928
8929     /* What instruction format have we got? */
8930
8931     switch (fmt)
8932     {
8933         ssize_t  imm;
8934         ssize_t  index;
8935         ssize_t  index2;
8936         unsigned scale;
8937         unsigned cmode;
8938         unsigned immShift;
8939         bool     hasShift;
8940         emitAttr extSize;
8941         emitAttr elemsize;
8942         emitAttr datasize;
8943
8944         case IF_BI_0A: // BI_0A   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
8945         case IF_BI_0B: // BI_0B   ......iiiiiiiiii iiiiiiiiiii.....               simm19:00
8946         case IF_LARGEJMP:
8947             assert(id->idGCref() == GCT_NONE);
8948             assert(id->idIsBound());
8949             dst = emitOutputLJ(ig, dst, id);
8950             sz  = sizeof(instrDescJmp);
8951             break;
8952
8953         case IF_BI_0C: // BI_0C   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
8954             code = emitInsCode(ins, fmt);
8955             sz   = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
8956             dst += emitOutputCall(ig, dst, id, code);
8957             // Always call RecordRelocation so that we wire in a JumpStub when we don't reach
8958             emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_BRANCH26);
8959             break;
8960
8961         case IF_BI_1A: // BI_1A   ......iiiiiiiiii iiiiiiiiiiittttt      Rt       simm19:00
8962             assert(insOptsNone(id->idInsOpt()));
8963             assert(id->idIsBound());
8964
8965             dst = emitOutputLJ(ig, dst, id);
8966             sz  = sizeof(instrDescJmp);
8967             break;
8968
8969         case IF_BI_1B: // BI_1B   B.......bbbbbiii iiiiiiiiiiittttt      Rt imm6, simm14:00
8970             assert(insOptsNone(id->idInsOpt()));
8971             assert(id->idIsBound());
8972
8973             dst = emitOutputLJ(ig, dst, id);
8974             sz  = sizeof(instrDescJmp);
8975             break;
8976
8977         case IF_BR_1A: // BR_1A   ................ ......nnnnn.....         Rn
8978             assert(insOptsNone(id->idInsOpt()));
8979             assert((ins == INS_ret) || (ins == INS_br));
8980             code = emitInsCode(ins, fmt);
8981             code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
8982
8983             dst += emitOutput_Instr(dst, code);
8984             break;
8985
8986         case IF_BR_1B: // BR_1B   ................ ......nnnnn.....         Rn
8987             assert(insOptsNone(id->idInsOpt()));
8988             assert((ins == INS_br_tail) || (ins == INS_blr));
8989             code = emitInsCode(ins, fmt);
8990             code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
8991
8992             sz = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
8993             dst += emitOutputCall(ig, dst, id, code);
8994             break;
8995
8996         case IF_LS_1A: // LS_1A   XX...V..iiiiiiii iiiiiiiiiiittttt      Rt    PC imm(1MB)
8997         case IF_LARGELDC:
8998             assert(insOptsNone(id->idInsOpt()));
8999             assert(id->idIsBound());
9000
9001             dst = emitOutputLJ(ig, dst, id);
9002             sz  = sizeof(instrDescJmp);
9003             break;
9004
9005         case IF_LS_2A: // LS_2A   .X.......X...... ......nnnnnttttt      Rt Rn
9006             assert(insOptsNone(id->idInsOpt()));
9007             code = emitInsCode(ins, fmt);
9008             // Is the target a vector register?
9009             if (isVectorRegister(id->idReg1()))
9010             {
9011                 code &= 0x3FFFFFFF;                                 // clear the size bits
9012                 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9013                 code |= insEncodeReg_Vt(id->idReg1());              // ttttt
9014             }
9015             else
9016             {
9017                 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9018                 code |= insEncodeReg_Rt(id->idReg1());             // ttttt
9019             }
9020             code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9021             dst += emitOutput_Instr(dst, code);
9022             break;
9023
9024         case IF_LS_2B: // LS_2B   .X.......Xiiiiii iiiiiinnnnnttttt      Rt Rn    imm(0-4095)
9025             assert(insOptsNone(id->idInsOpt()));
9026             imm = emitGetInsSC(id);
9027             assert(isValidUimm12(imm));
9028             code = emitInsCode(ins, fmt);
9029             // Is the target a vector register?
9030             if (isVectorRegister(id->idReg1()))
9031             {
9032                 code &= 0x3FFFFFFF;                                 // clear the size bits
9033                 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9034                 code |= insEncodeReg_Vt(id->idReg1());              // ttttt
9035             }
9036             else
9037             {
9038                 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9039                 code |= insEncodeReg_Rt(id->idReg1());             // ttttt
9040             }
9041             code |= ((code_t)imm << 10);           // iiiiiiiiiiii
9042             code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9043             dst += emitOutput_Instr(dst, code);
9044             break;
9045
9046         case IF_LS_2C: // LS_2C   .X.......X.iiiii iiiiPPnnnnnttttt      Rt Rn    imm(-256..+255) no/pre/post inc
9047             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9048             imm = emitGetInsSC(id);
9049             assert((imm >= -256) && (imm <= 255)); // signed 9 bits
9050             imm &= 0x1ff;                          // force into unsigned 9 bit representation
9051             code = emitInsCode(ins, fmt);
9052             // Is the target a vector register?
9053             if (isVectorRegister(id->idReg1()))
9054             {
9055                 code &= 0x3FFFFFFF;                                 // clear the size bits
9056                 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9057                 code |= insEncodeReg_Vt(id->idReg1());              // ttttt
9058             }
9059             else
9060             {
9061                 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9062                 code |= insEncodeReg_Rt(id->idReg1());             // ttttt
9063             }
9064             code |= insEncodeIndexedOpt(id->idInsOpt()); // PP
9065             code |= ((code_t)imm << 12);                 // iiiiiiiii
9066             code |= insEncodeReg_Rn(id->idReg2());       // nnnnn
9067             dst += emitOutput_Instr(dst, code);
9068             break;
9069
9070         case IF_LS_3A: // LS_3A   .X.......X.mmmmm oooS..nnnnnttttt      Rt Rn Rm ext(Rm) LSL {}
9071             assert(insOptsLSExtend(id->idInsOpt()));
9072             code = emitInsCode(ins, fmt);
9073             // Is the target a vector register?
9074             if (isVectorRegister(id->idReg1()))
9075             {
9076                 code &= 0x3FFFFFFF;                                 // clear the size bits
9077                 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9078                 code |= insEncodeReg_Vt(id->idReg1());              // ttttt
9079             }
9080             else
9081             {
9082                 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9083                 code |= insEncodeReg_Rt(id->idReg1());             // ttttt
9084             }
9085             code |= insEncodeExtend(id->idInsOpt()); // ooo
9086             code |= insEncodeReg_Rn(id->idReg2());   // nnnnn
9087             if (id->idIsLclVar())
9088             {
9089                 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9090             }
9091             else
9092             {
9093                 code |= insEncodeReg3Scale(id->idReg3Scaled()); // S
9094                 code |= insEncodeReg_Rm(id->idReg3());          // mmmmm
9095             }
9096             dst += emitOutput_Instr(dst, code);
9097             break;
9098
9099         case IF_LS_3B: // LS_3B   X............... .aaaaannnnnddddd      Rd Ra Rn
9100             assert(insOptsNone(id->idInsOpt()));
9101             code = emitInsCode(ins, fmt);
9102             // Is the target a vector register?
9103             if (isVectorRegister(id->idReg1()))
9104             {
9105                 code &= 0x3FFFFFFF;                                  // clear the size bits
9106                 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9107                 code |= insEncodeReg_Vt(id->idReg1());               // ttttt
9108                 code |= insEncodeReg_Va(id->idReg2());               // aaaaa
9109             }
9110             else
9111             {
9112                 code |= insEncodeDatasize(id->idOpSize()); // X
9113                 code |= insEncodeReg_Rt(id->idReg1());     // ttttt
9114                 code |= insEncodeReg_Ra(id->idReg2());     // aaaaa
9115             }
9116             code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9117             dst += emitOutput_Instr(dst, code);
9118             break;
9119
9120         case IF_LS_3C: // LS_3C   X......PP.iiiiii iaaaaannnnnddddd      Rd Ra Rn imm(im7,sh)
9121             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9122             imm = emitGetInsSC(id);
9123             assert((imm >= -64) && (imm <= 63)); // signed 7 bits
9124             imm &= 0x7f;                         // force into unsigned 7 bit representation
9125             code = emitInsCode(ins, fmt);
9126             // Is the target a vector register?
9127             if (isVectorRegister(id->idReg1()))
9128             {
9129                 code &= 0x3FFFFFFF;                                  // clear the size bits
9130                 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9131                 code |= insEncodeReg_Vt(id->idReg1());               // ttttt
9132                 code |= insEncodeReg_Va(id->idReg2());               // aaaaa
9133             }
9134             else
9135             {
9136                 code |= insEncodeDatasize(id->idOpSize()); // X
9137                 code |= insEncodeReg_Rt(id->idReg1());     // ttttt
9138                 code |= insEncodeReg_Ra(id->idReg2());     // aaaaa
9139             }
9140             code |= insEncodePairIndexedOpt(ins, id->idInsOpt()); // PP
9141             code |= ((code_t)imm << 15);                          // iiiiiiiii
9142             code |= insEncodeReg_Rn(id->idReg3());                // nnnnn
9143             dst += emitOutput_Instr(dst, code);
9144             break;
9145
9146         case IF_LS_3D: // LS_3D   .X.......X.mmmmm ......nnnnnttttt      Wm Rt Rn
9147             code = emitInsCode(ins, fmt);
9148             // Arm64 store exclusive unpredictable cases
9149             assert(id->idReg1() != id->idReg2());
9150             assert(id->idReg1() != id->idReg3());
9151             code |= insEncodeDatasizeLS(code, id->idOpSize()); // X
9152             code |= insEncodeReg_Rm(id->idReg1());             // mmmmm
9153             code |= insEncodeReg_Rt(id->idReg2());             // ttttt
9154             code |= insEncodeReg_Rn(id->idReg3());             // nnnnn
9155             dst += emitOutput_Instr(dst, code);
9156             break;
9157
9158         case IF_DI_1A: // DI_1A   X.......shiiiiii iiiiiinnnnn.....         Rn    imm(i12,sh)
9159             assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9160             imm = emitGetInsSC(id);
9161             assert(isValidUimm12(imm));
9162             code = emitInsCode(ins, fmt);
9163             code |= insEncodeDatasize(id->idOpSize());   // X
9164             code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9165             code |= ((code_t)imm << 10);                 // iiiiiiiiiiii
9166             code |= insEncodeReg_Rn(id->idReg1());       // nnnnn
9167             dst += emitOutput_Instr(dst, code);
9168             break;
9169
9170         case IF_DI_1B: // DI_1B   X........hwiiiii iiiiiiiiiiiddddd      Rd       imm(i16,hw)
9171             imm = emitGetInsSC(id);
9172             assert(isValidImmHWVal(imm, id->idOpSize()));
9173             code = emitInsCode(ins, fmt);
9174             code |= insEncodeDatasize(id->idOpSize()); // X
9175             code |= ((code_t)imm << 5);                // hwiiiii iiiiiiiiiii
9176             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9177             dst += emitOutput_Instr(dst, code);
9178             break;
9179
9180         case IF_DI_1C: // DI_1C   X........Nrrrrrr ssssssnnnnn.....         Rn    imm(N,r,s)
9181             imm = emitGetInsSC(id);
9182             assert(isValidImmNRS(imm, id->idOpSize()));
9183             code = emitInsCode(ins, fmt);
9184             code |= ((code_t)imm << 10);               // Nrrrrrrssssss
9185             code |= insEncodeDatasize(id->idOpSize()); // X
9186             code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9187             dst += emitOutput_Instr(dst, code);
9188             break;
9189
9190         case IF_DI_1D: // DI_1D   X........Nrrrrrr ssssss.....ddddd      Rd       imm(N,r,s)
9191             imm = emitGetInsSC(id);
9192             assert(isValidImmNRS(imm, id->idOpSize()));
9193             code = emitInsCode(ins, fmt);
9194             code |= ((code_t)imm << 10);               // Nrrrrrrssssss
9195             code |= insEncodeDatasize(id->idOpSize()); // X
9196             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9197             dst += emitOutput_Instr(dst, code);
9198             break;
9199
9200         case IF_DI_1E: // DI_1E   .ii.....iiiiiiii iiiiiiiiiiiddddd      Rd       simm21
9201         case IF_LARGEADR:
9202             assert(insOptsNone(id->idInsOpt()));
9203             if (id->idIsReloc())
9204             {
9205                 code = emitInsCode(ins, fmt);
9206                 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9207                 dst += emitOutput_Instr(dst, code);
9208                 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEBASE_REL21);
9209             }
9210             else
9211             {
9212                 // Local jmp/load case which does not need a relocation.
9213                 assert(id->idIsBound());
9214                 dst = emitOutputLJ(ig, dst, id);
9215             }
9216             sz = sizeof(instrDescJmp);
9217             break;
9218
9219         case IF_DI_1F: // DI_1F   X..........iiiii cccc..nnnnn.nzcv      Rn imm5  nzcv cond
9220             imm = emitGetInsSC(id);
9221             assert(isValidImmCondFlagsImm5(imm));
9222             {
9223                 condFlagsImm cfi;
9224                 cfi.immCFVal = (unsigned)imm;
9225                 code         = emitInsCode(ins, fmt);
9226                 code |= insEncodeDatasize(id->idOpSize()); // X
9227                 code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9228                 code |= ((code_t)cfi.imm5 << 16);          // iiiii
9229                 code |= insEncodeFlags(cfi.flags);         // nzcv
9230                 code |= insEncodeCond(cfi.cond);           // cccc
9231                 dst += emitOutput_Instr(dst, code);
9232             }
9233             break;
9234
9235         case IF_DI_2A: // DI_2A   X.......shiiiiii iiiiiinnnnnddddd      Rd Rn    imm(i12,sh)
9236             assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9237             imm = emitGetInsSC(id);
9238             assert(isValidUimm12(imm));
9239             code = emitInsCode(ins, fmt);
9240             code |= insEncodeDatasize(id->idOpSize());   // X
9241             code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9242             code |= ((code_t)imm << 10);                 // iiiiiiiiiiii
9243             code |= insEncodeReg_Rd(id->idReg1());       // ddddd
9244             code |= insEncodeReg_Rn(id->idReg2());       // nnnnn
9245             dst += emitOutput_Instr(dst, code);
9246
9247             if (id->idIsReloc())
9248             {
9249                 assert(sz == sizeof(instrDesc));
9250                 assert(id->idAddr()->iiaAddr != nullptr);
9251                 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEOFFSET_12A);
9252             }
9253             break;
9254
9255         case IF_DI_2B: // DI_2B   X.........Xnnnnn ssssssnnnnnddddd      Rd Rn    imm(0-63)
9256             code = emitInsCode(ins, fmt);
9257             imm  = emitGetInsSC(id);
9258             assert(isValidImmShift(imm, id->idOpSize()));
9259             code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9260             code |= insEncodeReg_Rd(id->idReg1());             // ddddd
9261             code |= insEncodeReg_Rn(id->idReg2());             // nnnnn
9262             code |= insEncodeReg_Rm(id->idReg2());             // Reg2 also in mmmmm
9263             code |= insEncodeShiftCount(imm, id->idOpSize());  // ssssss
9264             dst += emitOutput_Instr(dst, code);
9265             break;
9266
9267         case IF_DI_2C: // DI_2C   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imm(N,r,s)
9268             imm = emitGetInsSC(id);
9269             assert(isValidImmNRS(imm, id->idOpSize()));
9270             code = emitInsCode(ins, fmt);
9271             code |= ((code_t)imm << 10);               // Nrrrrrrssssss
9272             code |= insEncodeDatasize(id->idOpSize()); // X
9273             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9274             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9275             dst += emitOutput_Instr(dst, code);
9276             break;
9277
9278         case IF_DI_2D: // DI_2D   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imr, imms   (N,r,s)
9279             if (ins == INS_asr || ins == INS_lsl || ins == INS_lsr)
9280             {
9281                 imm = emitGetInsSC(id);
9282                 assert(isValidImmShift(imm, id->idOpSize()));
9283
9284                 // Shift immediates are aliases of the SBFM/UBFM instructions
9285                 // that actually take 2 registers and 2 constants,
9286                 // Since we stored the shift immediate value
9287                 // we need to calculate the N,R and S values here.
9288
9289                 bitMaskImm bmi;
9290                 bmi.immNRS = 0;
9291
9292                 bmi.immN = (size == EA_8BYTE) ? 1 : 0;
9293                 bmi.immR = imm;
9294                 bmi.immS = (size == EA_8BYTE) ? 0x3f : 0x1f;
9295
9296                 // immR and immS are now set correctly for INS_asr and INS_lsr
9297                 // but for INS_lsl we have to adjust the values for immR and immS
9298                 //
9299                 if (ins == INS_lsl)
9300                 {
9301                     bmi.immR = -imm & bmi.immS;
9302                     bmi.immS = bmi.immS - imm;
9303                 }
9304
9305                 // setup imm with the proper 13 bit value N:R:S
9306                 //
9307                 imm = bmi.immNRS;
9308             }
9309             else
9310             {
9311                 // The other instructions have already have encoded N,R and S values
9312                 imm = emitGetInsSC(id);
9313             }
9314             assert(isValidImmNRS(imm, id->idOpSize()));
9315
9316             code = emitInsCode(ins, fmt);
9317             code |= ((code_t)imm << 10);               // Nrrrrrrssssss
9318             code |= insEncodeDatasize(id->idOpSize()); // X
9319             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9320             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9321             dst += emitOutput_Instr(dst, code);
9322             break;
9323
9324         case IF_DR_1D: // DR_1D   X............... cccc.......ddddd      Rd       cond
9325             imm = emitGetInsSC(id);
9326             assert(isValidImmCond(imm));
9327             {
9328                 condFlagsImm cfi;
9329                 cfi.immCFVal = (unsigned)imm;
9330                 code         = emitInsCode(ins, fmt);
9331                 code |= insEncodeDatasize(id->idOpSize()); // X
9332                 code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9333                 code |= insEncodeInvertedCond(cfi.cond);   // cccc
9334                 dst += emitOutput_Instr(dst, code);
9335             }
9336             break;
9337
9338         case IF_DR_2A: // DR_2A   X..........mmmmm ......nnnnn.....         Rn Rm
9339             assert(insOptsNone(id->idInsOpt()));
9340             code = emitInsCode(ins, fmt);
9341             code |= insEncodeDatasize(id->idOpSize()); // X
9342             code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9343             code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9344             dst += emitOutput_Instr(dst, code);
9345             break;
9346
9347         case IF_DR_2B: // DR_2B   X.......sh.mmmmm ssssssnnnnn.....         Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
9348             code = emitInsCode(ins, fmt);
9349             imm  = emitGetInsSC(id);
9350             assert(isValidImmShift(imm, id->idOpSize()));
9351             code |= insEncodeDatasize(id->idOpSize());        // X
9352             code |= insEncodeShiftType(id->idInsOpt());       // sh
9353             code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9354             code |= insEncodeReg_Rn(id->idReg1());            // nnnnn
9355             code |= insEncodeReg_Rm(id->idReg2());            // mmmmm
9356             dst += emitOutput_Instr(dst, code);
9357             break;
9358
9359         case IF_DR_2C: // DR_2C   X..........mmmmm ooosssnnnnn.....         Rn Rm ext(Rm) LSL imm(0-4)
9360             code = emitInsCode(ins, fmt);
9361             imm  = emitGetInsSC(id);
9362             assert((imm >= 0) && (imm <= 4));          // imm [0..4]
9363             code |= insEncodeDatasize(id->idOpSize()); // X
9364             code |= insEncodeExtend(id->idInsOpt());   // ooo
9365             code |= insEncodeExtendScale(imm);         // sss
9366             code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9367             code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9368             dst += emitOutput_Instr(dst, code);
9369             break;
9370
9371         case IF_DR_2D: // DR_2D   X..........nnnnn cccc..nnnnnddddd      Rd Rn    cond
9372             imm = emitGetInsSC(id);
9373             assert(isValidImmCond(imm));
9374             {
9375                 condFlagsImm cfi;
9376                 cfi.immCFVal = (unsigned)imm;
9377                 code         = emitInsCode(ins, fmt);
9378                 code |= insEncodeDatasize(id->idOpSize()); // X
9379                 code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9380                 code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9381                 code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9382                 code |= insEncodeInvertedCond(cfi.cond);   // cccc
9383                 dst += emitOutput_Instr(dst, code);
9384             }
9385             break;
9386
9387         case IF_DR_2E: // DR_2E   X..........mmmmm ...........ddddd      Rd    Rm
9388             code = emitInsCode(ins, fmt);
9389             code |= insEncodeDatasize(id->idOpSize()); // X
9390             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9391             code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9392             dst += emitOutput_Instr(dst, code);
9393             break;
9394
9395         case IF_DR_2F: // DR_2F   X.......sh.mmmmm ssssss.....ddddd      Rd    Rm {LSL,LSR,ASR} imm(0-63)
9396             code = emitInsCode(ins, fmt);
9397             imm  = emitGetInsSC(id);
9398             assert(isValidImmShift(imm, id->idOpSize()));
9399             code |= insEncodeDatasize(id->idOpSize());        // X
9400             code |= insEncodeShiftType(id->idInsOpt());       // sh
9401             code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9402             code |= insEncodeReg_Rd(id->idReg1());            // ddddd
9403             code |= insEncodeReg_Rm(id->idReg2());            // mmmmm
9404             dst += emitOutput_Instr(dst, code);
9405             break;
9406
9407         case IF_DR_2G: // DR_2G   X............... .....xnnnnnddddd      Rd Rn
9408             code = emitInsCode(ins, fmt);
9409             code |= insEncodeDatasize(id->idOpSize()); // X
9410             if (ins == INS_rev)
9411             {
9412                 if (size == EA_8BYTE)
9413                 {
9414                     code |= 0x00000400; // x - bit at location 10
9415                 }
9416             }
9417             code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9418             code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9419             dst += emitOutput_Instr(dst, code);
9420             break;
9421
9422         case IF_DR_2H: // DR_2H   X........X...... ......nnnnnddddd      Rd Rn
9423             code = emitInsCode(ins, fmt);
9424             code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9425             code |= insEncodeReg_Rd(id->idReg1());             // ddddd
9426             code |= insEncodeReg_Rn(id->idReg2());             // nnnnn
9427             dst += emitOutput_Instr(dst, code);
9428             break;
9429
9430         case IF_DR_2I: // DR_2I   X..........mmmmm cccc..nnnnn.nzcv      Rn Rm    nzcv cond
9431             imm = emitGetInsSC(id);
9432             assert(isValidImmCondFlags(imm));
9433             {
9434                 condFlagsImm cfi;
9435                 cfi.immCFVal = (unsigned)imm;
9436                 code         = emitInsCode(ins, fmt);
9437                 code |= insEncodeDatasize(id->idOpSize()); // X
9438                 code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9439                 code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9440                 code |= insEncodeFlags(cfi.flags);         // nzcv
9441                 code |= insEncodeCond(cfi.cond);           // cccc
9442                 dst += emitOutput_Instr(dst, code);
9443             }
9444             break;
9445
9446         case IF_DR_3A: // DR_3A   X..........mmmmm ......nnnnnmmmmm      Rd Rn Rm
9447             code = emitInsCode(ins, fmt);
9448             code |= insEncodeDatasize(id->idOpSize()); // X
9449             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9450             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9451             if (id->idIsLclVar())
9452             {
9453                 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9454             }
9455             else
9456             {
9457                 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9458             }
9459             dst += emitOutput_Instr(dst, code);
9460             break;
9461
9462         case IF_DR_3B: // DR_3B   X.......sh.mmmmm ssssssnnnnnddddd      Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
9463             code = emitInsCode(ins, fmt);
9464             imm  = emitGetInsSC(id);
9465             assert(isValidImmShift(imm, id->idOpSize()));
9466             code |= insEncodeDatasize(id->idOpSize());        // X
9467             code |= insEncodeReg_Rd(id->idReg1());            // ddddd
9468             code |= insEncodeReg_Rn(id->idReg2());            // nnnnn
9469             code |= insEncodeReg_Rm(id->idReg3());            // mmmmm
9470             code |= insEncodeShiftType(id->idInsOpt());       // sh
9471             code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9472             dst += emitOutput_Instr(dst, code);
9473             break;
9474
9475         case IF_DR_3C: // DR_3C   X..........mmmmm ooosssnnnnnddddd      Rd Rn Rm ext(Rm) LSL imm(0-4)
9476             code = emitInsCode(ins, fmt);
9477             imm  = emitGetInsSC(id);
9478             assert((imm >= 0) && (imm <= 4));          // imm [0..4]
9479             code |= insEncodeDatasize(id->idOpSize()); // X
9480             code |= insEncodeExtend(id->idInsOpt());   // ooo
9481             code |= insEncodeExtendScale(imm);         // sss
9482             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9483             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9484             code |= insEncodeReg_Rm(id->idReg3());     // mmmmm
9485             dst += emitOutput_Instr(dst, code);
9486             break;
9487
9488         case IF_DR_3D: // DR_3D   X..........mmmmm cccc..nnnnnddddd      Rd Rn Rm cond
9489             imm = emitGetInsSC(id);
9490             assert(isValidImmCond(imm));
9491             {
9492                 condFlagsImm cfi;
9493                 cfi.immCFVal = (unsigned)imm;
9494                 code         = emitInsCode(ins, fmt);
9495                 code |= insEncodeDatasize(id->idOpSize()); // X
9496                 code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9497                 code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9498                 code |= insEncodeReg_Rm(id->idReg3());     // mmmmm
9499                 code |= insEncodeCond(cfi.cond);           // cccc
9500                 dst += emitOutput_Instr(dst, code);
9501             }
9502             break;
9503
9504         case IF_DR_3E: // DR_3E   X........X.mmmmm ssssssnnnnnddddd      Rd Rn Rm imm(0-63)
9505             code = emitInsCode(ins, fmt);
9506             imm  = emitGetInsSC(id);
9507             assert(isValidImmShift(imm, id->idOpSize()));
9508             code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9509             code |= insEncodeReg_Rd(id->idReg1());             // ddddd
9510             code |= insEncodeReg_Rn(id->idReg2());             // nnnnn
9511             code |= insEncodeReg_Rm(id->idReg3());             // mmmmm
9512             code |= insEncodeShiftCount(imm, id->idOpSize());  // ssssss
9513             dst += emitOutput_Instr(dst, code);
9514             break;
9515
9516         case IF_DR_4A: // DR_4A   X..........mmmmm .aaaaannnnnmmmmm      Rd Rn Rm Ra
9517             code = emitInsCode(ins, fmt);
9518             code |= insEncodeDatasize(id->idOpSize()); // X
9519             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9520             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9521             code |= insEncodeReg_Rm(id->idReg3());     // mmmmm
9522             code |= insEncodeReg_Ra(id->idReg4());     // aaaaa
9523             dst += emitOutput_Instr(dst, code);
9524             break;
9525
9526         case IF_DV_1A: // DV_1A   .........X.iiiii iii........ddddd      Vd imm8    (fmov - immediate scalar)
9527             imm      = emitGetInsSC(id);
9528             elemsize = id->idOpSize();
9529             code     = emitInsCode(ins, fmt);
9530             code |= insEncodeFloatElemsize(elemsize); // X
9531             code |= ((code_t)imm << 13);              // iiiii iii
9532             code |= insEncodeReg_Vd(id->idReg1());    // ddddd
9533             dst += emitOutput_Instr(dst, code);
9534             break;
9535
9536         case IF_DV_1B: // DV_1B   .QX..........iii cmod..iiiiiddddd      Vd imm8    (immediate vector)
9537             imm      = emitGetInsSC(id) & 0x0ff;
9538             immShift = (emitGetInsSC(id) & 0x700) >> 8;
9539             elemsize = optGetElemsize(id->idInsOpt());
9540             cmode    = 0;
9541             switch (elemsize)
9542             { // cmode
9543                 case EA_1BYTE:
9544                     cmode = 0xE; // 1110
9545                     break;
9546                 case EA_2BYTE:
9547                     cmode = 0x8;
9548                     cmode |= (immShift << 1); // 10x0
9549                     break;
9550                 case EA_4BYTE:
9551                     if (immShift < 4)
9552                     {
9553                         cmode = 0x0;
9554                         cmode |= (immShift << 1); // 0xx0
9555                     }
9556                     else // MSL
9557                     {
9558                         cmode = 0xC;
9559                         if (immShift & 2)
9560                             cmode |= 1; // 110x
9561                     }
9562                     break;
9563                 case EA_8BYTE:
9564                     cmode = 0xE; // 1110
9565                     break;
9566                 default:
9567                     unreached();
9568                     break;
9569             }
9570
9571             code = emitInsCode(ins, fmt);
9572             code |= insEncodeVectorsize(id->idOpSize()); // Q
9573             if ((ins == INS_fmov) || (ins == INS_movi))
9574             {
9575                 if (elemsize == EA_8BYTE)
9576                 {
9577                     code |= 0x20000000; // X
9578                 }
9579             }
9580             if (ins != INS_fmov)
9581             {
9582                 assert((cmode >= 0) && (cmode <= 0xF));
9583                 code |= (cmode << 12); // cmod
9584             }
9585             code |= (((code_t)imm >> 5) << 16);    // iii
9586             code |= (((code_t)imm & 0x1f) << 5);   // iiiii
9587             code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9588             dst += emitOutput_Instr(dst, code);
9589             break;
9590
9591         case IF_DV_1C: // DV_1C   .........X...... ......nnnnn.....      Vn #0.0    (fcmp - with zero)
9592             elemsize = id->idOpSize();
9593             code     = emitInsCode(ins, fmt);
9594             code |= insEncodeFloatElemsize(elemsize); // X
9595             code |= insEncodeReg_Vn(id->idReg1());    // nnnnn
9596             dst += emitOutput_Instr(dst, code);
9597             break;
9598
9599         case IF_DV_2A: // DV_2A   .Q.......X...... ......nnnnnddddd      Vd Vn      (fabs, fcvt - vector)
9600             elemsize = optGetElemsize(id->idInsOpt());
9601             code     = emitInsCode(ins, fmt);
9602             code |= insEncodeVectorsize(id->idOpSize()); // Q
9603             code |= insEncodeFloatElemsize(elemsize);    // X
9604             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9605             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9606             dst += emitOutput_Instr(dst, code);
9607             break;
9608
9609         case IF_DV_2B: // DV_2B   .Q.........iiiii ......nnnnnddddd      Rd Vn[] (umov/smov    - to general)
9610             elemsize = id->idOpSize();
9611             index    = emitGetInsSC(id);
9612             datasize = (elemsize == EA_8BYTE) ? EA_16BYTE : EA_8BYTE;
9613             if (ins == INS_smov)
9614             {
9615                 datasize = EA_16BYTE;
9616             }
9617             code = emitInsCode(ins, fmt);
9618             code |= insEncodeVectorsize(datasize);         // Q
9619             code |= insEncodeVectorIndex(elemsize, index); // iiiii
9620             code |= insEncodeReg_Rd(id->idReg1());         // ddddd
9621             code |= insEncodeReg_Vn(id->idReg2());         // nnnnn
9622             dst += emitOutput_Instr(dst, code);
9623             break;
9624
9625         case IF_DV_2C: // DV_2C   .Q.........iiiii ......nnnnnddddd      Vd Rn   (dup/ins - vector from general)
9626             if (ins == INS_dup)
9627             {
9628                 datasize = id->idOpSize();
9629                 elemsize = optGetElemsize(id->idInsOpt());
9630                 index    = 0;
9631             }
9632             else // INS_ins
9633             {
9634                 datasize = EA_16BYTE;
9635                 elemsize = id->idOpSize();
9636                 index    = emitGetInsSC(id);
9637             }
9638             code = emitInsCode(ins, fmt);
9639             code |= insEncodeVectorsize(datasize);         // Q
9640             code |= insEncodeVectorIndex(elemsize, index); // iiiii
9641             code |= insEncodeReg_Vd(id->idReg1());         // ddddd
9642             code |= insEncodeReg_Rn(id->idReg2());         // nnnnn
9643             dst += emitOutput_Instr(dst, code);
9644             break;
9645
9646         case IF_DV_2D: // DV_2D   .Q.........iiiii ......nnnnnddddd      Vd Vn[]   (dup - vector)
9647             index    = emitGetInsSC(id);
9648             elemsize = optGetElemsize(id->idInsOpt());
9649             code     = emitInsCode(ins, fmt);
9650             code |= insEncodeVectorsize(id->idOpSize());   // Q
9651             code |= insEncodeVectorIndex(elemsize, index); // iiiii
9652             code |= insEncodeReg_Vd(id->idReg1());         // ddddd
9653             code |= insEncodeReg_Vn(id->idReg2());         // nnnnn
9654             dst += emitOutput_Instr(dst, code);
9655             break;
9656
9657         case IF_DV_2E: // DV_2E   ...........iiiii ......nnnnnddddd      Vd Vn[]   (dup - scalar)
9658             index    = emitGetInsSC(id);
9659             elemsize = id->idOpSize();
9660             code     = emitInsCode(ins, fmt);
9661             code |= insEncodeVectorIndex(elemsize, index); // iiiii
9662             code |= insEncodeReg_Vd(id->idReg1());         // ddddd
9663             code |= insEncodeReg_Vn(id->idReg2());         // nnnnn
9664             dst += emitOutput_Instr(dst, code);
9665             break;
9666
9667         case IF_DV_2F: // DV_2F   ...........iiiii .jjjj.nnnnnddddd      Vd[] Vn[] (ins - element)
9668             elemsize = id->idOpSize();
9669             imm      = emitGetInsSC(id);
9670             index    = (imm >> 4) & 0xf;
9671             index2   = imm & 0xf;
9672             code     = emitInsCode(ins, fmt);
9673             code |= insEncodeVectorIndex(elemsize, index);   // iiiii
9674             code |= insEncodeVectorIndex2(elemsize, index2); // jjjj
9675             code |= insEncodeReg_Vd(id->idReg1());           // ddddd
9676             code |= insEncodeReg_Vn(id->idReg2());           // nnnnn
9677             dst += emitOutput_Instr(dst, code);
9678             break;
9679
9680         case IF_DV_2G: // DV_2G   .........X...... ......nnnnnddddd      Vd Vn      (fmov,fcvtXX - register)
9681             elemsize = id->idOpSize();
9682             code     = emitInsCode(ins, fmt);
9683             code |= insEncodeFloatElemsize(elemsize); // X
9684             code |= insEncodeReg_Vd(id->idReg1());    // ddddd
9685             code |= insEncodeReg_Vn(id->idReg2());    // nnnnn
9686             dst += emitOutput_Instr(dst, code);
9687             break;
9688
9689         case IF_DV_2H: // DV_2H   X........X...... ......nnnnnddddd      Rd Vn      (fmov - to general)
9690             elemsize = id->idOpSize();
9691             code     = emitInsCode(ins, fmt);
9692             code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X   X
9693             code |= insEncodeReg_Rd(id->idReg1());            // ddddd
9694             code |= insEncodeReg_Vn(id->idReg2());            // nnnnn
9695             dst += emitOutput_Instr(dst, code);
9696             break;
9697
9698         case IF_DV_2I: // DV_2I   X........X...... ......nnnnnddddd      Vd Rn      (fmov - from general)
9699             elemsize = id->idOpSize();
9700             code     = emitInsCode(ins, fmt);
9701             code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X   X
9702             code |= insEncodeReg_Vd(id->idReg1());            // ddddd
9703             code |= insEncodeReg_Rn(id->idReg2());            // nnnnn
9704             dst += emitOutput_Instr(dst, code);
9705             break;
9706
9707         case IF_DV_2J: // DV_2J   ........SS.....D D.....nnnnnddddd      Vd Vn      (fcvt)
9708             code = emitInsCode(ins, fmt);
9709             code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // SS DD
9710             code |= insEncodeReg_Vd(id->idReg1());            // ddddd
9711             code |= insEncodeReg_Vn(id->idReg2());            // nnnnn
9712             dst += emitOutput_Instr(dst, code);
9713             break;
9714
9715         case IF_DV_2K: // DV_2K   .........X.mmmmm ......nnnnn.....      Vn Vm      (fcmp)
9716             elemsize = id->idOpSize();
9717             code     = emitInsCode(ins, fmt);
9718             code |= insEncodeFloatElemsize(elemsize); // X
9719             code |= insEncodeReg_Vn(id->idReg1());    // nnnnn
9720             code |= insEncodeReg_Vm(id->idReg2());    // mmmmm
9721             dst += emitOutput_Instr(dst, code);
9722             break;
9723
9724         case IF_DV_2L: // DV_2L   ........XX...... ......nnnnnddddd      Vd Vn      (abs, neg - scalar)
9725             elemsize = id->idOpSize();
9726             code     = emitInsCode(ins, fmt);
9727             code |= insEncodeElemsize(elemsize);   // XX
9728             code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9729             code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9730             dst += emitOutput_Instr(dst, code);
9731             break;
9732
9733         case IF_DV_2M: // DV_2M   .Q......XX...... ......nnnnnddddd      Vd Vn      (abs, neg   - vector)
9734             elemsize = optGetElemsize(id->idInsOpt());
9735             code     = emitInsCode(ins, fmt);
9736             code |= insEncodeVectorsize(id->idOpSize()); // Q
9737             code |= insEncodeElemsize(elemsize);         // XX
9738             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9739             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9740             dst += emitOutput_Instr(dst, code);
9741             break;
9742
9743         case IF_DV_2N: // DV_2N   .........iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - scalar)
9744             imm  = emitGetInsSC(id);
9745             code = emitInsCode(ins, fmt);
9746             code |= insEncodeVectorShift(EA_8BYTE, imm); // iiiiiii
9747             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9748             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9749             dst += emitOutput_Instr(dst, code);
9750             break;
9751
9752         case IF_DV_2O: // DV_2O   .Q.......iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - vector)
9753             imm      = emitGetInsSC(id);
9754             elemsize = optGetElemsize(id->idInsOpt());
9755             code     = emitInsCode(ins, fmt);
9756             code |= insEncodeVectorsize(id->idOpSize()); // Q
9757             code |= insEncodeVectorShift(elemsize, imm); // iiiiiii
9758             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9759             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9760             dst += emitOutput_Instr(dst, code);
9761             break;
9762
9763         case IF_DV_3A: // DV_3A   .Q......XX.mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
9764             code     = emitInsCode(ins, fmt);
9765             elemsize = optGetElemsize(id->idInsOpt());
9766             code |= insEncodeVectorsize(id->idOpSize()); // Q
9767             code |= insEncodeElemsize(elemsize);         // XX
9768             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9769             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9770             code |= insEncodeReg_Vm(id->idReg3());       // mmmmm
9771             dst += emitOutput_Instr(dst, code);
9772             break;
9773
9774         case IF_DV_3AI: // DV_3AI  .Q......XXLMmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector)
9775             code     = emitInsCode(ins, fmt);
9776             imm      = emitGetInsSC(id);
9777             elemsize = optGetElemsize(id->idInsOpt());
9778             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
9779             code |= insEncodeVectorsize(id->idOpSize());    // Q
9780             code |= insEncodeElemsize(elemsize);            // XX
9781             code |= insEncodeVectorIndexLMH(elemsize, imm); // LM H
9782             code |= insEncodeReg_Vd(id->idReg1());          // ddddd
9783             code |= insEncodeReg_Vn(id->idReg2());          // nnnnn
9784             code |= insEncodeReg_Vm(id->idReg3());          // mmmmm
9785             dst += emitOutput_Instr(dst, code);
9786             break;
9787
9788         case IF_DV_3B: // DV_3B   .Q.......X.mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
9789             code     = emitInsCode(ins, fmt);
9790             elemsize = optGetElemsize(id->idInsOpt());
9791             code |= insEncodeVectorsize(id->idOpSize()); // Q
9792             code |= insEncodeFloatElemsize(elemsize);    // X
9793             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9794             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9795             code |= insEncodeReg_Vm(id->idReg3());       // mmmmm
9796             dst += emitOutput_Instr(dst, code);
9797             break;
9798
9799         case IF_DV_3BI: // DV_3BI  .Q.......XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector by elem)
9800             code     = emitInsCode(ins, fmt);
9801             imm      = emitGetInsSC(id);
9802             elemsize = optGetElemsize(id->idInsOpt());
9803             assert(isValidVectorIndex(id->idOpSize(), elemsize, imm));
9804             code |= insEncodeVectorsize(id->idOpSize()); // Q
9805             code |= insEncodeFloatElemsize(elemsize);    // X
9806             code |= insEncodeFloatIndex(elemsize, imm);  // L H
9807             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9808             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9809             code |= insEncodeReg_Vm(id->idReg3());       // mmmmm
9810             dst += emitOutput_Instr(dst, code);
9811             break;
9812
9813         case IF_DV_3C: // DV_3C   .Q.........mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
9814             code = emitInsCode(ins, fmt);
9815             code |= insEncodeVectorsize(id->idOpSize()); // Q
9816             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9817             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9818             code |= insEncodeReg_Vm(id->idReg3());       // mmmmm
9819             dst += emitOutput_Instr(dst, code);
9820             break;
9821
9822         case IF_DV_3D: // DV_3D   .........X.mmmmm ......nnnnnddddd      Vd Vn Vm   (scalar)
9823             code = emitInsCode(ins, fmt);
9824             code |= insEncodeFloatElemsize(id->idOpSize()); // X
9825             code |= insEncodeReg_Vd(id->idReg1());          // ddddd
9826             code |= insEncodeReg_Vn(id->idReg2());          // nnnnn
9827             code |= insEncodeReg_Vm(id->idReg3());          // mmmmm
9828             dst += emitOutput_Instr(dst, code);
9829             break;
9830
9831         case IF_DV_3DI: // DV_3DI  .........XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (scalar by elem)
9832             code     = emitInsCode(ins, fmt);
9833             imm      = emitGetInsSC(id);
9834             elemsize = id->idOpSize();
9835             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
9836             code |= insEncodeFloatElemsize(elemsize);   // X
9837             code |= insEncodeFloatIndex(elemsize, imm); // L H
9838             code |= insEncodeReg_Vd(id->idReg1());      // ddddd
9839             code |= insEncodeReg_Vn(id->idReg2());      // nnnnn
9840             code |= insEncodeReg_Vm(id->idReg3());      // mmmmm
9841             dst += emitOutput_Instr(dst, code);
9842             break;
9843
9844         case IF_DV_3E: // DV_3E   ...........mmmmm ......nnnnnddddd      Vd Vn Vm   (scalar)
9845             code = emitInsCode(ins, fmt);
9846             code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9847             code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9848             code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9849             dst += emitOutput_Instr(dst, code);
9850             break;
9851
9852         case IF_DV_4A: // DV_4A   .........X.mmmmm .aaaaannnnnddddd      Vd Va Vn Vm (scalar)
9853             code     = emitInsCode(ins, fmt);
9854             elemsize = id->idOpSize();
9855             code |= insEncodeFloatElemsize(elemsize); // X
9856             code |= insEncodeReg_Vd(id->idReg1());    // ddddd
9857             code |= insEncodeReg_Vn(id->idReg2());    // nnnnn
9858             code |= insEncodeReg_Vm(id->idReg3());    // mmmmm
9859             code |= insEncodeReg_Va(id->idReg4());    // aaaaa
9860             dst += emitOutput_Instr(dst, code);
9861             break;
9862
9863         case IF_SN_0A: // SN_0A   ................ ................
9864             code = emitInsCode(ins, fmt);
9865             dst += emitOutput_Instr(dst, code);
9866             break;
9867
9868         case IF_SI_0A: // SI_0A   ...........iiiii iiiiiiiiiii.....               imm16
9869             imm = emitGetInsSC(id);
9870             assert(isValidUimm16(imm));
9871             code = emitInsCode(ins, fmt);
9872             code |= ((code_t)imm << 5); // iiiii iiiiiiiiiii
9873             dst += emitOutput_Instr(dst, code);
9874             break;
9875
9876         case IF_SI_0B: // SI_0B   ................ ....bbbb........               imm4 - barrier
9877             imm = emitGetInsSC(id);
9878             assert((imm >= 0) && (imm <= 15));
9879             code = emitInsCode(ins, fmt);
9880             code |= ((code_t)imm << 8); // bbbb
9881             dst += emitOutput_Instr(dst, code);
9882             break;
9883
9884         default:
9885             assert(!"Unexpected format");
9886             break;
9887     }
9888
9889     // Determine if any registers now hold GC refs, or whether a register that was overwritten held a GC ref.
9890     // We assume here that "id->idGCref()" is not GC_NONE only if the instruction described by "id" writes a
9891     // GC ref to register "id->idReg1()".  (It may, apparently, also not be GC_NONE in other cases, such as
9892     // for stores, but we ignore those cases here.)
9893     if (emitInsMayWriteToGCReg(id)) // True if "id->idIns()" writes to a register than can hold GC ref.
9894     {
9895         // We assume that "idReg1" is the primary destination register for all instructions
9896         if (id->idGCref() != GCT_NONE)
9897         {
9898             emitGCregLiveUpd(id->idGCref(), id->idReg1(), dst);
9899         }
9900         else
9901         {
9902             emitGCregDeadUpd(id->idReg1(), dst);
9903         }
9904
9905         if (emitInsMayWriteMultipleRegs(id))
9906         {
9907             // INS_ldp etc...
9908             // "idReg2" is the secondary destination register
9909             if (id->idGCrefReg2() != GCT_NONE)
9910             {
9911                 emitGCregLiveUpd(id->idGCrefReg2(), id->idReg2(), dst);
9912             }
9913             else
9914             {
9915                 emitGCregDeadUpd(id->idReg2(), dst);
9916             }
9917         }
9918     }
9919
9920     // Now we determine if the instruction has written to a (local variable) stack location, and either written a GC
9921     // ref or overwritten one.
9922     if (emitInsWritesToLclVarStackLoc(id) || emitInsWritesToLclVarStackLocPair(id))
9923     {
9924         int      varNum = id->idAddr()->iiaLclVar.lvaVarNum();
9925         unsigned ofs    = AlignDown(id->idAddr()->iiaLclVar.lvaOffset(), sizeof(size_t));
9926         bool     FPbased;
9927         int      adr = emitComp->lvaFrameAddress(varNum, &FPbased);
9928         if (id->idGCref() != GCT_NONE)
9929         {
9930             emitGCvarLiveUpd(adr + ofs, varNum, id->idGCref(), dst);
9931         }
9932         else
9933         {
9934             // If the type of the local is a gc ref type, update the liveness.
9935             var_types vt;
9936             if (varNum >= 0)
9937             {
9938                 // "Regular" (non-spill-temp) local.
9939                 vt = var_types(emitComp->lvaTable[varNum].lvType);
9940             }
9941             else
9942             {
9943                 TempDsc* tmpDsc = emitComp->tmpFindNum(varNum);
9944                 vt              = tmpDsc->tdTempType();
9945             }
9946             if (vt == TYP_REF || vt == TYP_BYREF)
9947                 emitGCvarDeadUpd(adr + ofs, dst);
9948         }
9949         if (emitInsWritesToLclVarStackLocPair(id))
9950         {
9951             unsigned ofs2 = ofs + sizeof(size_t);
9952             if (id->idGCrefReg2() != GCT_NONE)
9953             {
9954                 emitGCvarLiveUpd(adr + ofs2, varNum, id->idGCrefReg2(), dst);
9955             }
9956             else
9957             {
9958                 // If the type of the local is a gc ref type, update the liveness.
9959                 var_types vt;
9960                 if (varNum >= 0)
9961                 {
9962                     // "Regular" (non-spill-temp) local.
9963                     vt = var_types(emitComp->lvaTable[varNum].lvType);
9964                 }
9965                 else
9966                 {
9967                     TempDsc* tmpDsc = emitComp->tmpFindNum(varNum);
9968                     vt              = tmpDsc->tdTempType();
9969                 }
9970                 if (vt == TYP_REF || vt == TYP_BYREF)
9971                     emitGCvarDeadUpd(adr + ofs2, dst);
9972             }
9973         }
9974     }
9975
9976 #ifdef DEBUG
9977     /* Make sure we set the instruction descriptor size correctly */
9978
9979     size_t expected = emitSizeOfInsDsc(id);
9980     assert(sz == expected);
9981
9982     if (emitComp->opts.disAsm || emitComp->opts.dspEmit || emitComp->verbose)
9983     {
9984         emitDispIns(id, false, dspOffs, true, emitCurCodeOffs(odst), *dp, (dst - *dp), ig);
9985     }
9986
9987     if (emitComp->compDebugBreak)
9988     {
9989         // For example, set JitBreakEmitOutputInstr=a6 will break when this method is called for
9990         // emitting instruction a6, (i.e. IN00a6 in jitdump).
9991         if ((unsigned)JitConfig.JitBreakEmitOutputInstr() == id->idDebugOnlyInfo()->idNum)
9992         {
9993             assert(!"JitBreakEmitOutputInstr reached");
9994         }
9995     }
9996 #endif
9997
9998     /* All instructions are expected to generate code */
9999
10000     assert(*dp != dst);
10001
10002     *dp = dst;
10003
10004     return sz;
10005 }
10006
10007 /*****************************************************************************/
10008 /*****************************************************************************/
10009
10010 #ifdef DEBUG
10011
10012 /*****************************************************************************
10013  *
10014  *  Display the instruction name
10015  */
10016 void emitter::emitDispInst(instruction ins)
10017 {
10018     const char* insstr = codeGen->genInsName(ins);
10019     size_t      len    = strlen(insstr);
10020
10021     /* Display the instruction name */
10022
10023     printf("%s", insstr);
10024
10025     //
10026     // Add at least one space after the instruction name
10027     // and add spaces until we have reach the normal size of 8
10028     do
10029     {
10030         printf(" ");
10031         len++;
10032     } while (len < 8);
10033 }
10034
10035 /*****************************************************************************
10036  *
10037  *  Display an reloc value
10038  *  If we are formatting for an assembly listing don't print the hex value
10039  *  since it will prevent us from doing assembly diffs
10040  */
10041 void emitter::emitDispReloc(int value, bool addComma)
10042 {
10043     if (emitComp->opts.disAsm)
10044     {
10045         printf("(reloc)");
10046     }
10047     else
10048     {
10049         printf("(reloc 0x%x)", dspPtr(value));
10050     }
10051
10052     if (addComma)
10053         printf(", ");
10054 }
10055
10056 /*****************************************************************************
10057  *
10058  *  Display an immediate value
10059  */
10060 void emitter::emitDispImm(ssize_t imm, bool addComma, bool alwaysHex /* =false */)
10061 {
10062     if (strictArmAsm)
10063     {
10064         printf("#");
10065     }
10066
10067     // Munge any pointers if we want diff-able disassembly
10068     if (emitComp->opts.disDiffable)
10069     {
10070         ssize_t top44bits = (imm >> 20);
10071         if ((top44bits != 0) && (top44bits != -1))
10072             imm = 0xD1FFAB1E;
10073     }
10074
10075     if (!alwaysHex && (imm > -1000) && (imm < 1000))
10076     {
10077         printf("%d", imm);
10078     }
10079     else
10080     {
10081         if ((imm < 0) && ((imm & 0xFFFFFFFF00000000LL) == 0xFFFFFFFF00000000LL))
10082         {
10083             printf("-");
10084             imm = -imm;
10085         }
10086
10087         if ((imm & 0xFFFFFFFF00000000LL) != 0)
10088         {
10089             printf("0x%llx", imm);
10090         }
10091         else
10092         {
10093             printf("0x%02x", imm);
10094         }
10095     }
10096
10097     if (addComma)
10098         printf(", ");
10099 }
10100
10101 /*****************************************************************************
10102  *
10103  *  Display a float zero constant
10104  */
10105 void emitter::emitDispFloatZero()
10106 {
10107     if (strictArmAsm)
10108     {
10109         printf("#");
10110     }
10111     printf("0.0");
10112 }
10113
10114 /*****************************************************************************
10115  *
10116  *  Display an encoded float constant value
10117  */
10118 void emitter::emitDispFloatImm(ssize_t imm8)
10119 {
10120     assert((0 <= imm8) && (imm8 <= 0x0ff));
10121     if (strictArmAsm)
10122     {
10123         printf("#");
10124     }
10125
10126     floatImm8 fpImm;
10127     fpImm.immFPIVal = (unsigned)imm8;
10128     double result   = emitDecodeFloatImm8(fpImm);
10129
10130     printf("%.4f", result);
10131 }
10132
10133 /*****************************************************************************
10134  *
10135  *  Display an immediate that is optionally LSL12.
10136  */
10137 void emitter::emitDispImmOptsLSL12(ssize_t imm, insOpts opt)
10138 {
10139     if (!strictArmAsm && insOptsLSL12(opt))
10140     {
10141         imm <<= 12;
10142     }
10143     emitDispImm(imm, false);
10144     if (strictArmAsm && insOptsLSL12(opt))
10145     {
10146         printf(", LSL #12");
10147     }
10148 }
10149
10150 /*****************************************************************************
10151  *
10152  *  Display an ARM64 condition code for the conditional instructions
10153  */
10154 void emitter::emitDispCond(insCond cond)
10155 {
10156     const static char* armCond[16] = {"eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc",
10157                                       "hi", "ls", "ge", "lt", "gt", "le", "AL", "NV"}; // The last two are invalid
10158     unsigned imm = (unsigned)cond;
10159     assert((0 <= imm) && (imm < ArrLen(armCond)));
10160     printf(armCond[imm]);
10161 }
10162
10163 /*****************************************************************************
10164  *
10165  *  Display an ARM64 flags for the conditional instructions
10166  */
10167 void emitter::emitDispFlags(insCflags flags)
10168 {
10169     const static char* armFlags[16] = {"0", "v",  "c",  "cv",  "z",  "zv",  "zc",  "zcv",
10170                                        "n", "nv", "nc", "ncv", "nz", "nzv", "nzc", "nzcv"};
10171     unsigned imm = (unsigned)flags;
10172     assert((0 <= imm) && (imm < ArrLen(armFlags)));
10173     printf(armFlags[imm]);
10174 }
10175
10176 /*****************************************************************************
10177  *
10178  *  Display an ARM64 'barrier' for the memory barrier instructions
10179  */
10180 void emitter::emitDispBarrier(insBarrier barrier)
10181 {
10182     const static char* armBarriers[16] = {"#0", "oshld", "oshst", "osh", "#4",  "nshld", "nshst", "nsh",
10183                                           "#8", "ishld", "ishst", "ish", "#12", "ld",    "st",    "sy"};
10184     unsigned imm = (unsigned)barrier;
10185     assert((0 <= imm) && (imm < ArrLen(armBarriers)));
10186     printf(armBarriers[imm]);
10187 }
10188
10189 /*****************************************************************************
10190  *
10191  *  Prints the encoding for the Shift Type encoding
10192  */
10193
10194 void emitter::emitDispShiftOpts(insOpts opt)
10195 {
10196     if (opt == INS_OPTS_LSL)
10197         printf(" LSL ");
10198     else if (opt == INS_OPTS_LSR)
10199         printf(" LSR ");
10200     else if (opt == INS_OPTS_ASR)
10201         printf(" ASR ");
10202     else if (opt == INS_OPTS_ROR)
10203         printf(" ROR ");
10204     else if (opt == INS_OPTS_MSL)
10205         printf(" MSL ");
10206     else
10207         assert(!"Bad value");
10208 }
10209
10210 /*****************************************************************************
10211  *
10212  *  Prints the encoding for the Extend Type encoding
10213  */
10214
10215 void emitter::emitDispExtendOpts(insOpts opt)
10216 {
10217     if (opt == INS_OPTS_UXTB)
10218         printf("UXTB");
10219     else if (opt == INS_OPTS_UXTH)
10220         printf("UXTH");
10221     else if (opt == INS_OPTS_UXTW)
10222         printf("UXTW");
10223     else if (opt == INS_OPTS_UXTX)
10224         printf("UXTX");
10225     else if (opt == INS_OPTS_SXTB)
10226         printf("SXTB");
10227     else if (opt == INS_OPTS_SXTH)
10228         printf("SXTH");
10229     else if (opt == INS_OPTS_SXTW)
10230         printf("SXTW");
10231     else if (opt == INS_OPTS_SXTX)
10232         printf("SXTX");
10233     else
10234         assert(!"Bad value");
10235 }
10236
10237 /*****************************************************************************
10238  *
10239  *  Prints the encoding for the Extend Type encoding in loads/stores
10240  */
10241
10242 void emitter::emitDispLSExtendOpts(insOpts opt)
10243 {
10244     if (opt == INS_OPTS_LSL)
10245         printf("LSL");
10246     else if (opt == INS_OPTS_UXTW)
10247         printf("UXTW");
10248     else if (opt == INS_OPTS_UXTX)
10249         printf("UXTX");
10250     else if (opt == INS_OPTS_SXTW)
10251         printf("SXTW");
10252     else if (opt == INS_OPTS_SXTX)
10253         printf("SXTX");
10254     else
10255         assert(!"Bad value");
10256 }
10257
10258 /*****************************************************************************
10259  *
10260  *  Display a register
10261  */
10262 void emitter::emitDispReg(regNumber reg, emitAttr attr, bool addComma)
10263 {
10264     emitAttr size = EA_SIZE(attr);
10265     printf(emitRegName(reg, size));
10266
10267     if (addComma)
10268         printf(", ");
10269 }
10270
10271 /*****************************************************************************
10272  *
10273  *  Display a vector register with an arrangement suffix
10274  */
10275 void emitter::emitDispVectorReg(regNumber reg, insOpts opt, bool addComma)
10276 {
10277     assert(isVectorRegister(reg));
10278     printf(emitVectorRegName(reg));
10279     emitDispArrangement(opt);
10280
10281     if (addComma)
10282         printf(", ");
10283 }
10284
10285 /*****************************************************************************
10286  *
10287  *  Display an vector register index suffix
10288  */
10289 void emitter::emitDispVectorRegIndex(regNumber reg, emitAttr elemsize, ssize_t index, bool addComma)
10290 {
10291     assert(isVectorRegister(reg));
10292     printf(emitVectorRegName(reg));
10293
10294     switch (elemsize)
10295     {
10296         case EA_1BYTE:
10297             printf(".b");
10298             break;
10299         case EA_2BYTE:
10300             printf(".h");
10301             break;
10302         case EA_4BYTE:
10303             printf(".s");
10304             break;
10305         case EA_8BYTE:
10306             printf(".d");
10307             break;
10308         default:
10309             assert(!"invalid elemsize");
10310             break;
10311     }
10312
10313     printf("[%d]", index);
10314
10315     if (addComma)
10316         printf(", ");
10317 }
10318
10319 /*****************************************************************************
10320  *
10321  *  Display an arrangement suffix
10322  */
10323 void emitter::emitDispArrangement(insOpts opt)
10324 {
10325     const char* str = "???";
10326
10327     switch (opt)
10328     {
10329         case INS_OPTS_8B:
10330             str = "8b";
10331             break;
10332         case INS_OPTS_16B:
10333             str = "16b";
10334             break;
10335         case INS_OPTS_4H:
10336             str = "4h";
10337             break;
10338         case INS_OPTS_8H:
10339             str = "8h";
10340             break;
10341         case INS_OPTS_2S:
10342             str = "2s";
10343             break;
10344         case INS_OPTS_4S:
10345             str = "4s";
10346             break;
10347         case INS_OPTS_1D:
10348             str = "1d";
10349             break;
10350         case INS_OPTS_2D:
10351             str = "2d";
10352             break;
10353
10354         default:
10355             assert(!"Invalid insOpt for vector register");
10356     }
10357     printf(".");
10358     printf(str);
10359 }
10360
10361 /*****************************************************************************
10362  *
10363  *  Display a register with an optional shift operation
10364  */
10365 void emitter::emitDispShiftedReg(regNumber reg, insOpts opt, ssize_t imm, emitAttr attr)
10366 {
10367     emitAttr size = EA_SIZE(attr);
10368     assert((imm & 0x003F) == imm);
10369     assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
10370
10371     printf(emitRegName(reg, size));
10372
10373     if (imm > 0)
10374     {
10375         if (strictArmAsm)
10376         {
10377             printf(",");
10378         }
10379         emitDispShiftOpts(opt);
10380         emitDispImm(imm, false);
10381     }
10382 }
10383
10384 /*****************************************************************************
10385  *
10386  *  Display a register with an optional extend and scale operations
10387  */
10388 void emitter::emitDispExtendReg(regNumber reg, insOpts opt, ssize_t imm)
10389 {
10390     assert((imm >= 0) && (imm <= 4));
10391     assert(insOptsNone(opt) || insOptsAnyExtend(opt) || (opt == INS_OPTS_LSL));
10392
10393     // size is based on the extend option, not the instr size.
10394     emitAttr size = insOpts32BitExtend(opt) ? EA_4BYTE : EA_8BYTE;
10395
10396     if (strictArmAsm)
10397     {
10398         if (insOptsNone(opt))
10399         {
10400             emitDispReg(reg, size, false);
10401         }
10402         else
10403         {
10404             emitDispReg(reg, size, true);
10405             if (opt == INS_OPTS_LSL)
10406                 printf("LSL");
10407             else
10408                 emitDispExtendOpts(opt);
10409             if ((imm > 0) || (opt == INS_OPTS_LSL))
10410             {
10411                 printf(" ");
10412                 emitDispImm(imm, false);
10413             }
10414         }
10415     }
10416     else // !strictArmAsm
10417     {
10418         if (insOptsNone(opt))
10419         {
10420             emitDispReg(reg, size, false);
10421         }
10422         else
10423         {
10424             if (opt != INS_OPTS_LSL)
10425             {
10426                 emitDispExtendOpts(opt);
10427                 printf("(");
10428                 emitDispReg(reg, size, false);
10429                 printf(")");
10430             }
10431         }
10432         if (imm > 0)
10433         {
10434             printf("*");
10435             emitDispImm(1 << imm, false);
10436         }
10437     }
10438 }
10439
10440 /*****************************************************************************
10441  *
10442  *  Display an addressing operand [reg + imm]
10443  */
10444 void emitter::emitDispAddrRI(regNumber reg, insOpts opt, ssize_t imm)
10445 {
10446     reg = encodingZRtoSP(reg); // ZR (R31) encodes the SP register
10447
10448     if (strictArmAsm)
10449     {
10450         printf("[");
10451
10452         emitDispReg(reg, EA_8BYTE, false);
10453
10454         if (!insOptsPostIndex(opt) && (imm != 0))
10455         {
10456             printf(",");
10457             emitDispImm(imm, false);
10458         }
10459         printf("]");
10460
10461         if (insOptsPreIndex(opt))
10462         {
10463             printf("!");
10464         }
10465         else if (insOptsPostIndex(opt))
10466         {
10467             printf(",");
10468             emitDispImm(imm, false);
10469         }
10470     }
10471     else // !strictArmAsm
10472     {
10473         printf("[");
10474
10475         const char* operStr = "++";
10476         if (imm < 0)
10477         {
10478             operStr = "--";
10479             imm     = -imm;
10480         }
10481
10482         if (insOptsPreIndex(opt))
10483         {
10484             printf(operStr);
10485         }
10486
10487         emitDispReg(reg, EA_8BYTE, false);
10488
10489         if (insOptsPostIndex(opt))
10490         {
10491             printf(operStr);
10492         }
10493
10494         if (insOptsIndexed(opt))
10495         {
10496             printf(", ");
10497         }
10498         else
10499         {
10500             printf("%c", operStr[1]);
10501         }
10502         emitDispImm(imm, false);
10503         printf("]");
10504     }
10505 }
10506
10507 /*****************************************************************************
10508  *
10509  *  Display an addressing operand [reg + extended reg]
10510  */
10511 void emitter::emitDispAddrRRExt(regNumber reg1, regNumber reg2, insOpts opt, bool isScaled, emitAttr size)
10512 {
10513     reg1 = encodingZRtoSP(reg1); // ZR (R31) encodes the SP register
10514
10515     unsigned scale = 0;
10516     if (isScaled)
10517     {
10518         scale = NaturalScale_helper(size);
10519     }
10520
10521     printf("[");
10522
10523     if (strictArmAsm)
10524     {
10525         emitDispReg(reg1, EA_8BYTE, true);
10526         emitDispExtendReg(reg2, opt, scale);
10527     }
10528     else // !strictArmAsm
10529     {
10530         emitDispReg(reg1, EA_8BYTE, false);
10531         printf("+");
10532         emitDispExtendReg(reg2, opt, scale);
10533     }
10534
10535     printf("]");
10536 }
10537
10538 /*****************************************************************************
10539  *
10540  *  Display (optionally) the instruction encoding in hex
10541  */
10542
10543 void emitter::emitDispInsHex(BYTE* code, size_t sz)
10544 {
10545     // We do not display the instruction hex if we want diff-able disassembly
10546     if (!emitComp->opts.disDiffable)
10547     {
10548         if (sz == 4)
10549         {
10550             printf("  %08X    ", (*((code_t*)code)));
10551         }
10552         else
10553         {
10554             printf("              ");
10555         }
10556     }
10557 }
10558
10559 /****************************************************************************
10560  *
10561  *  Display the given instruction.
10562  */
10563
10564 void emitter::emitDispIns(
10565     instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* pCode, size_t sz, insGroup* ig)
10566 {
10567     if (EMITVERBOSE)
10568     {
10569         unsigned idNum =
10570             id->idDebugOnlyInfo()->idNum; // Do not remove this!  It is needed for VisualStudio conditional breakpoints
10571
10572         printf("IN%04x: ", idNum);
10573     }
10574
10575     if (pCode == NULL)
10576         sz = 0;
10577
10578     if (!emitComp->opts.dspEmit && !isNew && !asmfm && sz)
10579         doffs = true;
10580
10581     /* Display the instruction offset */
10582
10583     emitDispInsOffs(offset, doffs);
10584
10585     /* Display the instruction hex code */
10586
10587     emitDispInsHex(pCode, sz);
10588
10589     printf("      ");
10590
10591     /* Get the instruction and format */
10592
10593     instruction ins = id->idIns();
10594     insFormat   fmt = id->idInsFmt();
10595
10596     emitDispInst(ins);
10597
10598     /* If this instruction has just been added, check its size */
10599
10600     assert(isNew == false || (int)emitSizeOfInsDsc(id) == emitCurIGfreeNext - (BYTE*)id);
10601
10602     /* Figure out the operand size */
10603     emitAttr size = id->idOpSize();
10604     emitAttr attr = size;
10605     if (id->idGCref() == GCT_GCREF)
10606         attr = EA_GCREF;
10607     else if (id->idGCref() == GCT_BYREF)
10608         attr = EA_BYREF;
10609
10610     switch (fmt)
10611     {
10612         code_t       code;
10613         ssize_t      imm;
10614         int          doffs;
10615         bool         isExtendAlias;
10616         bool         canEncode;
10617         bitMaskImm   bmi;
10618         halfwordImm  hwi;
10619         condFlagsImm cfi;
10620         unsigned     scale;
10621         unsigned     immShift;
10622         bool         hasShift;
10623         ssize_t      offs;
10624         const char*  methodName;
10625         emitAttr     elemsize;
10626         emitAttr     datasize;
10627         emitAttr     srcsize;
10628         emitAttr     dstsize;
10629         ssize_t      index;
10630         ssize_t      index2;
10631
10632         case IF_BI_0A: // BI_0A   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
10633         case IF_BI_0B: // BI_0B   ......iiiiiiiiii iiiiiiiiiii.....               simm19:00
10634         case IF_LARGEJMP:
10635         {
10636             if (fmt == IF_LARGEJMP)
10637             {
10638                 printf("(LARGEJMP)");
10639             }
10640             if (id->idAddr()->iiaHasInstrCount())
10641             {
10642                 int instrCount = id->idAddr()->iiaGetInstrCount();
10643
10644                 if (ig == nullptr)
10645                 {
10646                     printf("pc%s%d instructions", (instrCount >= 0) ? "+" : "", instrCount);
10647                 }
10648                 else
10649                 {
10650                     unsigned       insNum  = emitFindInsNum(ig, id);
10651                     UNATIVE_OFFSET srcOffs = ig->igOffs + emitFindOffset(ig, insNum + 1);
10652                     UNATIVE_OFFSET dstOffs = ig->igOffs + emitFindOffset(ig, insNum + 1 + instrCount);
10653                     ssize_t        relOffs = (ssize_t)(emitOffsetToPtr(dstOffs) - emitOffsetToPtr(srcOffs));
10654                     printf("pc%s%d (%d instructions)", (relOffs >= 0) ? "+" : "", relOffs, instrCount);
10655                 }
10656             }
10657             else if (id->idIsBound())
10658             {
10659                 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10660             }
10661             else
10662             {
10663                 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10664             }
10665         }
10666         break;
10667
10668         case IF_BI_0C: // BI_0C   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
10669             if (id->idIsCallAddr())
10670             {
10671                 offs       = (ssize_t)id->idAddr()->iiaAddr;
10672                 methodName = "";
10673             }
10674             else
10675             {
10676                 offs       = 0;
10677                 methodName = emitComp->eeGetMethodFullName((CORINFO_METHOD_HANDLE)id->idDebugOnlyInfo()->idMemCookie);
10678             }
10679
10680             if (offs)
10681             {
10682                 if (id->idIsDspReloc())
10683                     printf("reloc ");
10684                 printf("%08X", offs);
10685             }
10686             else
10687             {
10688                 printf("%s", methodName);
10689             }
10690             break;
10691
10692         case IF_BI_1A: // BI_1A   ......iiiiiiiiii iiiiiiiiiiittttt      Rt       simm19:00
10693             assert(insOptsNone(id->idInsOpt()));
10694             emitDispReg(id->idReg1(), size, true);
10695             if (id->idIsBound())
10696             {
10697                 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10698             }
10699             else
10700             {
10701                 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10702             }
10703             break;
10704
10705         case IF_BI_1B: // BI_1B   B.......bbbbbiii iiiiiiiiiiittttt      Rt imm6, simm14:00
10706             assert(insOptsNone(id->idInsOpt()));
10707             emitDispReg(id->idReg1(), size, true);
10708             emitDispImm(emitGetInsSC(id), true);
10709             if (id->idIsBound())
10710             {
10711                 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10712             }
10713             else
10714             {
10715                 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10716             }
10717             break;
10718
10719         case IF_BR_1A: // BR_1A   ................ ......nnnnn.....         Rn
10720             assert(insOptsNone(id->idInsOpt()));
10721             emitDispReg(id->idReg1(), size, false);
10722             break;
10723
10724         case IF_BR_1B: // BR_1B   ................ ......nnnnn.....         Rn
10725             assert(insOptsNone(id->idInsOpt()));
10726             emitDispReg(id->idReg3(), size, false);
10727             break;
10728
10729         case IF_LS_1A: // LS_1A   XX...V..iiiiiiii iiiiiiiiiiittttt      Rt    PC imm(1MB)
10730         case IF_DI_1E: // DI_1E   .ii.....iiiiiiii iiiiiiiiiiiddddd      Rd       simm21
10731         case IF_LARGELDC:
10732         case IF_LARGEADR:
10733             assert(insOptsNone(id->idInsOpt()));
10734             emitDispReg(id->idReg1(), size, true);
10735             imm = emitGetInsSC(id);
10736
10737             /* Is this actually a reference to a data section? */
10738             if (fmt == IF_LARGEADR)
10739             {
10740                 printf("(LARGEADR)");
10741             }
10742             else if (fmt == IF_LARGELDC)
10743             {
10744                 printf("(LARGELDC)");
10745             }
10746
10747             printf("[");
10748             if (id->idAddr()->iiaIsJitDataOffset())
10749             {
10750                 doffs = Compiler::eeGetJitDataOffs(id->idAddr()->iiaFieldHnd);
10751                 /* Display a data section reference */
10752
10753                 if (doffs & 1)
10754                     printf("@CNS%02u", doffs - 1);
10755                 else
10756                     printf("@RWD%02u", doffs);
10757
10758                 if (imm != 0)
10759                     printf("%+Id", imm);
10760             }
10761             else
10762             {
10763                 assert(imm == 0);
10764                 if (id->idIsReloc())
10765                 {
10766                     printf("RELOC ");
10767                     emitDispImm((ssize_t)id->idAddr()->iiaAddr, false);
10768                 }
10769                 else if (id->idIsBound())
10770                 {
10771                     printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10772                 }
10773                 else
10774                 {
10775                     printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10776                 }
10777             }
10778             printf("]");
10779             break;
10780
10781         case IF_LS_2A: // LS_2A   .X.......X...... ......nnnnnttttt      Rt Rn
10782             assert(insOptsNone(id->idInsOpt()));
10783             assert(emitGetInsSC(id) == 0);
10784             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10785             emitDispAddrRI(id->idReg2(), id->idInsOpt(), 0);
10786             break;
10787
10788         case IF_LS_2B: // LS_2B   .X.......Xiiiiii iiiiiinnnnnttttt      Rt Rn    imm(0-4095)
10789             assert(insOptsNone(id->idInsOpt()));
10790             imm   = emitGetInsSC(id);
10791             scale = NaturalScale_helper(emitInsLoadStoreSize(id));
10792             imm <<= scale; // The immediate is scaled by the size of the ld/st
10793             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10794             emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
10795             break;
10796
10797         case IF_LS_2C: // LS_2C   .X.......X.iiiii iiiiPPnnnnnttttt      Rt Rn    imm(-256..+255) no/pre/post inc
10798             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
10799             imm = emitGetInsSC(id);
10800             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10801             emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
10802             break;
10803
10804         case IF_LS_3A: // LS_3A   .X.......X.mmmmm oooS..nnnnnttttt      Rt Rn Rm ext(Rm) LSL {}
10805             assert(insOptsLSExtend(id->idInsOpt()));
10806             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10807             if (id->idIsLclVar())
10808             {
10809                 emitDispAddrRRExt(id->idReg2(), codeGen->rsGetRsvdReg(), id->idInsOpt(), false, size);
10810             }
10811             else
10812             {
10813                 emitDispAddrRRExt(id->idReg2(), id->idReg3(), id->idInsOpt(), id->idReg3Scaled(), size);
10814             }
10815             break;
10816
10817         case IF_LS_3B: // LS_3B   X............... .aaaaannnnnddddd      Rt Ra Rn
10818             assert(insOptsNone(id->idInsOpt()));
10819             assert(emitGetInsSC(id) == 0);
10820             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10821             emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10822             emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
10823             break;
10824
10825         case IF_LS_3C: // LS_3C   X.........iiiiii iaaaaannnnnddddd      Rt Ra Rn imm(im7,sh)
10826             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
10827             imm   = emitGetInsSC(id);
10828             scale = NaturalScale_helper(emitInsLoadStoreSize(id));
10829             imm <<= scale;
10830             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10831             emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10832             emitDispAddrRI(id->idReg3(), id->idInsOpt(), imm);
10833             break;
10834
10835         case IF_LS_3D: // LS_3D   .X.......X.mmmmm ......nnnnnttttt      Wm Rt Rn
10836             assert(insOptsNone(id->idInsOpt()));
10837             emitDispReg(id->idReg1(), EA_4BYTE, true);
10838             emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10839             emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
10840             break;
10841
10842         case IF_DI_1A: // DI_1A   X.......shiiiiii iiiiiinnnnn.....      Rn       imm(i12,sh)
10843             emitDispReg(id->idReg1(), size, true);
10844             emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
10845             break;
10846
10847         case IF_DI_1B: // DI_1B   X........hwiiiii iiiiiiiiiiiddddd      Rd       imm(i16,hw)
10848             emitDispReg(id->idReg1(), size, true);
10849             hwi.immHWVal = (unsigned)emitGetInsSC(id);
10850             if (ins == INS_mov)
10851             {
10852                 emitDispImm(emitDecodeHalfwordImm(hwi, size), false);
10853             }
10854             else // movz, movn, movk
10855             {
10856                 emitDispImm(hwi.immVal, false);
10857                 if (hwi.immHW != 0)
10858                 {
10859                     emitDispShiftOpts(INS_OPTS_LSL);
10860                     emitDispImm(hwi.immHW * 16, false);
10861                 }
10862             }
10863             break;
10864
10865         case IF_DI_1C: // DI_1C   X........Nrrrrrr ssssssnnnnn.....         Rn    imm(N,r,s)
10866             emitDispReg(id->idReg1(), size, true);
10867             bmi.immNRS = (unsigned)emitGetInsSC(id);
10868             emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
10869             break;
10870
10871         case IF_DI_1D: // DI_1D   X........Nrrrrrr ssssss.....ddddd      Rd       imm(N,r,s)
10872             emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
10873             bmi.immNRS = (unsigned)emitGetInsSC(id);
10874             emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
10875             break;
10876
10877         case IF_DI_2A: // DI_2A   X.......shiiiiii iiiiiinnnnnddddd      Rd Rn    imm(i12,sh)
10878             if ((ins == INS_add) || (ins == INS_sub))
10879             {
10880                 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
10881                 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
10882             }
10883             else
10884             {
10885                 emitDispReg(id->idReg1(), size, true);
10886                 emitDispReg(id->idReg2(), size, true);
10887             }
10888             emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
10889             break;
10890
10891         case IF_DI_2B: // DI_2B   X........X.nnnnn ssssssnnnnnddddd      Rd Rn    imm(0-63)
10892             emitDispReg(id->idReg1(), size, true);
10893             emitDispReg(id->idReg2(), size, true);
10894             emitDispImm(emitGetInsSC(id), false);
10895             break;
10896
10897         case IF_DI_2C: // DI_2C   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imm(N,r,s)
10898             if (ins == INS_ands)
10899             {
10900                 emitDispReg(id->idReg1(), size, true);
10901             }
10902             else
10903             {
10904                 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
10905             }
10906             emitDispReg(id->idReg2(), size, true);
10907             bmi.immNRS = (unsigned)emitGetInsSC(id);
10908             emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
10909             break;
10910
10911         case IF_DI_2D: // DI_2D   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imr, ims   (N,r,s)
10912             emitDispReg(id->idReg1(), size, true);
10913             emitDispReg(id->idReg2(), size, true);
10914
10915             imm        = emitGetInsSC(id);
10916             bmi.immNRS = (unsigned)imm;
10917
10918             switch (ins)
10919             {
10920                 case INS_bfm:
10921                 case INS_sbfm:
10922                 case INS_ubfm:
10923                     emitDispImm(bmi.immR, true);
10924                     emitDispImm(bmi.immS, false);
10925                     break;
10926
10927                 case INS_bfi:
10928                 case INS_sbfiz:
10929                 case INS_ubfiz:
10930                     emitDispImm(getBitWidth(size) - bmi.immR, true);
10931                     emitDispImm(bmi.immS + 1, false);
10932                     break;
10933
10934                 case INS_bfxil:
10935                 case INS_sbfx:
10936                 case INS_ubfx:
10937                     emitDispImm(bmi.immR, true);
10938                     emitDispImm(bmi.immS - bmi.immR + 1, false);
10939                     break;
10940
10941                 case INS_asr:
10942                 case INS_lsr:
10943                 case INS_lsl:
10944                     emitDispImm(imm, false);
10945                     break;
10946
10947                 default:
10948                     assert(!"Unexpected instruction in IF_DI_2D");
10949             }
10950
10951             break;
10952
10953         case IF_DI_1F: // DI_1F   X..........iiiii cccc..nnnnn.nzcv      Rn imm5  nzcv cond
10954             emitDispReg(id->idReg1(), size, true);
10955             cfi.immCFVal = (unsigned)emitGetInsSC(id);
10956             emitDispImm(cfi.imm5, true);
10957             emitDispFlags(cfi.flags);
10958             printf(",");
10959             emitDispCond(cfi.cond);
10960             break;
10961
10962         case IF_DR_1D: // DR_1D   X............... cccc.......mmmmm      Rd       cond
10963             emitDispReg(id->idReg1(), size, true);
10964             cfi.immCFVal = (unsigned)emitGetInsSC(id);
10965             emitDispCond(cfi.cond);
10966             break;
10967
10968         case IF_DR_2A: // DR_2A   X..........mmmmm ......nnnnn.....         Rn Rm
10969             emitDispReg(id->idReg1(), size, true);
10970             emitDispReg(id->idReg2(), size, false);
10971             break;
10972
10973         case IF_DR_2B: // DR_2B   X.......sh.mmmmm ssssssnnnnn.....         Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
10974             emitDispReg(id->idReg1(), size, true);
10975             emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
10976             break;
10977
10978         case IF_DR_2C: // DR_2C   X..........mmmmm ooosssnnnnn.....         Rn Rm ext(Rm) LSL imm(0-4)
10979             emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
10980             imm = emitGetInsSC(id);
10981             emitDispExtendReg(id->idReg2(), id->idInsOpt(), imm);
10982             break;
10983
10984         case IF_DR_2D: // DR_2D   X..........nnnnn cccc..nnnnnddddd      Rd Rn    cond
10985             emitDispReg(id->idReg1(), size, true);
10986             emitDispReg(id->idReg2(), size, true);
10987             cfi.immCFVal = (unsigned)emitGetInsSC(id);
10988             emitDispCond(cfi.cond);
10989             break;
10990
10991         case IF_DR_2E: // DR_2E   X..........mmmmm ...........ddddd      Rd    Rm
10992             emitDispReg(id->idReg1(), size, true);
10993             emitDispReg(id->idReg2(), size, false);
10994             break;
10995
10996         case IF_DR_2F: // DR_2F   X.......sh.mmmmm ssssss.....ddddd      Rd    Rm {LSL,LSR,ASR} imm(0-63)
10997             emitDispReg(id->idReg1(), size, true);
10998             emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
10999             break;
11000
11001         case IF_DR_2G: // DR_2G   X............... ......nnnnnddddd      Rd Rn
11002             emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11003             emitDispReg(encodingZRtoSP(id->idReg2()), size, false);
11004             break;
11005
11006         case IF_DR_2H: // DR_2H   X........X...... ......nnnnnddddd      Rd Rn
11007             emitDispReg(id->idReg1(), size, true);
11008             emitDispReg(id->idReg2(), size, false);
11009             break;
11010
11011         case IF_DR_2I: // DR_2I   X..........mmmmm cccc..nnnnn.nzcv      Rn Rm    nzcv cond
11012             emitDispReg(id->idReg1(), size, true);
11013             emitDispReg(id->idReg2(), size, true);
11014             cfi.immCFVal = (unsigned)emitGetInsSC(id);
11015             emitDispFlags(cfi.flags);
11016             printf(",");
11017             emitDispCond(cfi.cond);
11018             break;
11019
11020         case IF_DR_3A: // DR_3A   X..........mmmmm ......nnnnnmmmmm      Rd Rn Rm
11021             if ((ins == INS_add) || (ins == INS_sub))
11022             {
11023                 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11024                 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11025             }
11026             else if ((ins == INS_smull) || (ins == INS_smulh))
11027             {
11028                 // Rd is always 8 bytes
11029                 emitDispReg(id->idReg1(), EA_8BYTE, true);
11030
11031                 // Rn, Rm effective size depends on instruction type
11032                 size = (ins == INS_smulh) ? EA_8BYTE : EA_4BYTE;
11033                 emitDispReg(id->idReg2(), size, true);
11034             }
11035             else
11036             {
11037                 emitDispReg(id->idReg1(), size, true);
11038                 emitDispReg(id->idReg2(), size, true);
11039             }
11040             if (id->idIsLclVar())
11041             {
11042                 emitDispReg(codeGen->rsGetRsvdReg(), size, false);
11043             }
11044             else
11045             {
11046                 emitDispReg(id->idReg3(), size, false);
11047             }
11048
11049             break;
11050
11051         case IF_DR_3B: // DR_3B   X.......sh.mmmmm ssssssnnnnnddddd      Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
11052             emitDispReg(id->idReg1(), size, true);
11053             emitDispReg(id->idReg2(), size, true);
11054             emitDispShiftedReg(id->idReg3(), id->idInsOpt(), emitGetInsSC(id), size);
11055             break;
11056
11057         case IF_DR_3C: // DR_3C   X..........mmmmm ooosssnnnnnddddd      Rd Rn Rm ext(Rm) LSL imm(0-4)
11058             emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11059             emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11060             imm = emitGetInsSC(id);
11061             emitDispExtendReg(id->idReg3(), id->idInsOpt(), imm);
11062             break;
11063
11064         case IF_DR_3D: // DR_3D   X..........mmmmm cccc..nnnnnmmmmm      Rd Rn Rm cond
11065             emitDispReg(id->idReg1(), size, true);
11066             emitDispReg(id->idReg2(), size, true);
11067             emitDispReg(id->idReg3(), size, true);
11068             cfi.immCFVal = (unsigned)emitGetInsSC(id);
11069             emitDispCond(cfi.cond);
11070             break;
11071
11072         case IF_DR_3E: // DR_3E   X........X.mmmmm ssssssnnnnnddddd      Rd Rn Rm imm(0-63)
11073             emitDispReg(id->idReg1(), size, true);
11074             emitDispReg(id->idReg2(), size, true);
11075             emitDispReg(id->idReg3(), size, true);
11076             emitDispImm(emitGetInsSC(id), false);
11077             break;
11078
11079         case IF_DR_4A: // DR_4A   X..........mmmmm .aaaaannnnnmmmmm      Rd Rn Rm Ra
11080             emitDispReg(id->idReg1(), size, true);
11081             emitDispReg(id->idReg2(), size, true);
11082             emitDispReg(id->idReg3(), size, true);
11083             emitDispReg(id->idReg4(), size, false);
11084             break;
11085
11086         case IF_DV_1A: // DV_1A   .........X.iiiii iii........ddddd      Vd imm8 (fmov - immediate scalar)
11087             elemsize = id->idOpSize();
11088             emitDispReg(id->idReg1(), elemsize, true);
11089             emitDispFloatImm(emitGetInsSC(id));
11090             break;
11091
11092         case IF_DV_1B: // DV_1B   .QX..........iii cmod..iiiiiddddd      Vd imm8 (immediate vector)
11093             imm      = emitGetInsSC(id) & 0x0ff;
11094             immShift = (emitGetInsSC(id) & 0x700) >> 8;
11095             hasShift = (immShift != 0);
11096             elemsize = optGetElemsize(id->idInsOpt());
11097             if (id->idInsOpt() == INS_OPTS_1D)
11098             {
11099                 assert(elemsize == size);
11100                 emitDispReg(id->idReg1(), size, true);
11101             }
11102             else
11103             {
11104                 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11105             }
11106             if (ins == INS_fmov)
11107             {
11108                 emitDispFloatImm(imm);
11109                 assert(hasShift == false);
11110             }
11111             else
11112             {
11113                 if (elemsize == EA_8BYTE)
11114                 {
11115                     assert(ins == INS_movi);
11116                     ssize_t       imm64 = 0;
11117                     const ssize_t mask8 = 0xFF;
11118                     for (unsigned b = 0; b < 8; b++)
11119                     {
11120                         if (imm & (1 << b))
11121                         {
11122                             imm64 |= (mask8 << (b * 8));
11123                         }
11124                     }
11125                     emitDispImm(imm64, hasShift, true);
11126                 }
11127                 else
11128                 {
11129                     emitDispImm(imm, hasShift, true);
11130                 }
11131                 if (hasShift)
11132                 {
11133                     insOpts  opt   = (immShift & 0x4) ? INS_OPTS_MSL : INS_OPTS_LSL;
11134                     unsigned shift = (immShift & 0x3) * 8;
11135                     emitDispShiftOpts(opt);
11136                     emitDispImm(shift, false);
11137                 }
11138             }
11139             break;
11140
11141         case IF_DV_1C: // DV_1C   .........X...... ......nnnnn.....      Vn #0.0 (fcmp - with zero)
11142             elemsize = id->idOpSize();
11143             emitDispReg(id->idReg1(), elemsize, true);
11144             emitDispFloatZero();
11145             break;
11146
11147         case IF_DV_2A: // DV_2A   .Q.......X...... ......nnnnnddddd      Vd Vn   (fabs, fcvt - vector)
11148         case IF_DV_2M: // DV_2M   .Q......XX...... ......nnnnnddddd      Vd Vn   (abs, neg   - vector)
11149             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11150             emitDispVectorReg(id->idReg2(), id->idInsOpt(), false);
11151             break;
11152
11153         case IF_DV_2N: // DV_2N   .........iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - scalar)
11154             elemsize = id->idOpSize();
11155             emitDispReg(id->idReg1(), elemsize, true);
11156             emitDispReg(id->idReg2(), elemsize, true);
11157             emitDispImm(emitGetInsSC(id), false);
11158             break;
11159
11160         case IF_DV_2O: // DV_2O   .Q.......iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - vector)
11161             imm = emitGetInsSC(id);
11162             // Do we have a sxtl or uxtl instruction?
11163             isExtendAlias = ((ins == INS_sxtl) || (ins == INS_sxtl2) || (ins == INS_uxtl) || (ins == INS_uxtl2));
11164             code          = emitInsCode(ins, fmt);
11165             if (code & 0x00008000) // widen/narrow opcodes
11166             {
11167                 if (code & 0x00002000) // SHL opcodes
11168                 {
11169                     emitDispVectorReg(id->idReg1(), optWidenElemsize(id->idInsOpt()), true);
11170                     emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11171                 }
11172                 else // SHR opcodes
11173                 {
11174                     emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11175                     emitDispVectorReg(id->idReg2(), optWidenElemsize(id->idInsOpt()), !isExtendAlias);
11176                 }
11177             }
11178             else
11179             {
11180                 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11181                 emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11182             }
11183             // Print the immediate unless we have a sxtl or uxtl instruction
11184             if (!isExtendAlias)
11185             {
11186                 emitDispImm(imm, false);
11187             }
11188             break;
11189
11190         case IF_DV_2B: // DV_2B   .Q.........iiiii ......nnnnnddddd      Rd Vn[] (umov/smov    - to general)
11191             srcsize = id->idOpSize();
11192             index   = emitGetInsSC(id);
11193             if (ins == INS_smov)
11194             {
11195                 dstsize = EA_8BYTE;
11196             }
11197             else // INS_umov or INS_mov
11198             {
11199                 dstsize = (srcsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE;
11200             }
11201             emitDispReg(id->idReg1(), dstsize, true);
11202             emitDispVectorRegIndex(id->idReg2(), srcsize, index, false);
11203             break;
11204
11205         case IF_DV_2C: // DV_2C   .Q.........iiiii ......nnnnnddddd      Vd Rn   (dup/ins - vector from general)
11206             if (ins == INS_dup)
11207             {
11208                 datasize = id->idOpSize();
11209                 assert(isValidVectorDatasize(datasize));
11210                 assert(isValidArrangement(datasize, id->idInsOpt()));
11211                 elemsize = optGetElemsize(id->idInsOpt());
11212                 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11213             }
11214             else // INS_ins
11215             {
11216                 elemsize = id->idOpSize();
11217                 index    = emitGetInsSC(id);
11218                 assert(isValidVectorElemsize(elemsize));
11219                 emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11220             }
11221             emitDispReg(id->idReg2(), (elemsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE, false);
11222             break;
11223
11224         case IF_DV_2D: // DV_2D   .Q.........iiiii ......nnnnnddddd      Vd Vn[]   (dup - vector)
11225             datasize = id->idOpSize();
11226             assert(isValidVectorDatasize(datasize));
11227             assert(isValidArrangement(datasize, id->idInsOpt()));
11228             elemsize = optGetElemsize(id->idInsOpt());
11229             index    = emitGetInsSC(id);
11230             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11231             emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11232             break;
11233
11234         case IF_DV_2E: // DV_2E   ...........iiiii ......nnnnnddddd      Vd Vn[]   (dup - scalar)
11235             elemsize = id->idOpSize();
11236             index    = emitGetInsSC(id);
11237             emitDispReg(id->idReg1(), elemsize, true);
11238             emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11239             break;
11240
11241         case IF_DV_2F: // DV_2F   ...........iiiii .jjjj.nnnnnddddd      Vd[] Vn[] (ins - element)
11242             imm      = emitGetInsSC(id);
11243             index    = (imm >> 4) & 0xf;
11244             index2   = imm & 0xf;
11245             elemsize = id->idOpSize();
11246             emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11247             emitDispVectorRegIndex(id->idReg2(), elemsize, index2, false);
11248             break;
11249
11250         case IF_DV_2G: // DV_2G   .........X...... ......nnnnnddddd      Vd Vn      (fmov, fcvtXX - register)
11251         case IF_DV_2K: // DV_2K   .........X.mmmmm ......nnnnn.....      Vn Vm      (fcmp)
11252         case IF_DV_2L: // DV_2L   ........XX...... ......nnnnnddddd      Vd Vn      (abs, neg - scalar)
11253             elemsize = id->idOpSize();
11254             emitDispReg(id->idReg1(), elemsize, true);
11255             emitDispReg(id->idReg2(), elemsize, false);
11256             break;
11257
11258         case IF_DV_2H: // DV_2H   X........X...... ......nnnnnddddd      Rd Vn      (fmov, fcvtXX - to general)
11259         case IF_DV_2I: // DV_2I   X........X...... ......nnnnnddddd      Vd Rn      (fmov, Xcvtf - from general)
11260         case IF_DV_2J: // DV_2J   ........SS.....D D.....nnnnnddddd      Vd Vn      (fcvt)
11261             dstsize = optGetDstsize(id->idInsOpt());
11262             srcsize = optGetSrcsize(id->idInsOpt());
11263
11264             emitDispReg(id->idReg1(), dstsize, true);
11265             emitDispReg(id->idReg2(), srcsize, false);
11266             break;
11267
11268         case IF_DV_3A: // DV_3A   .Q......XX.mmmmm ......nnnnnddddd      Vd Vn Vm  (vector)
11269         case IF_DV_3B: // DV_3B   .Q.........mmmmm ......nnnnnddddd      Vd Vn Vm  (vector)
11270             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11271             emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11272             emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11273             break;
11274
11275         case IF_DV_3C: // DV_3C   .Q.........mmmmm ......nnnnnddddd      Vd Vn Vm  (vector)
11276             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11277             if (ins != INS_mov)
11278             {
11279                 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11280             }
11281             emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11282             break;
11283
11284         case IF_DV_3AI: // DV_3AI  .Q......XXLMmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector by elem)
11285         case IF_DV_3BI: // DV_3BI  .Q........Lmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector by elem)
11286             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11287             emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11288             elemsize = optGetElemsize(id->idInsOpt());
11289             emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11290             break;
11291
11292         case IF_DV_3D: // DV_3D   .........X.mmmmm ......nnnnnddddd      Vd Vn Vm  (scalar)
11293         case IF_DV_3E: // DV_3E   ...........mmmmm ......nnnnnddddd      Vd Vn Vm  (scalar)
11294             emitDispReg(id->idReg1(), size, true);
11295             emitDispReg(id->idReg2(), size, true);
11296             emitDispReg(id->idReg3(), size, false);
11297             break;
11298
11299         case IF_DV_3DI: // DV_3DI  .........XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (scalar by elem)
11300             emitDispReg(id->idReg1(), size, true);
11301             emitDispReg(id->idReg2(), size, true);
11302             elemsize = size;
11303             emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11304             break;
11305
11306         case IF_DV_4A: // DV_4A   .........X.mmmmm .aaaaannnnnddddd      Vd Va Vn Vm (scalar)
11307             emitDispReg(id->idReg1(), size, true);
11308             emitDispReg(id->idReg2(), size, true);
11309             emitDispReg(id->idReg3(), size, true);
11310             emitDispReg(id->idReg4(), size, false);
11311             break;
11312
11313         case IF_SN_0A: // SN_0A   ................ ................
11314             break;
11315
11316         case IF_SI_0A: // SI_0A   ...........iiiii iiiiiiiiiii.....               imm16
11317             emitDispImm(emitGetInsSC(id), false);
11318             break;
11319
11320         case IF_SI_0B: // SI_0B   ................ ....bbbb........               imm4 - barrier
11321             emitDispBarrier((insBarrier)emitGetInsSC(id));
11322             break;
11323
11324         default:
11325             printf("unexpected format %s", emitIfName(id->idInsFmt()));
11326             assert(!"unexpectedFormat");
11327             break;
11328     }
11329
11330     if (id->idDebugOnlyInfo()->idVarRefOffs)
11331     {
11332         printf("\t// ");
11333         emitDispFrameRef(id->idAddr()->iiaLclVar.lvaVarNum(), id->idAddr()->iiaLclVar.lvaOffset(),
11334                          id->idDebugOnlyInfo()->idVarRefOffs, asmfm);
11335     }
11336
11337     printf("\n");
11338 }
11339
11340 /*****************************************************************************
11341  *
11342  *  Display a stack frame reference.
11343  */
11344
11345 void emitter::emitDispFrameRef(int varx, int disp, int offs, bool asmfm)
11346 {
11347     printf("[");
11348
11349     if (varx < 0)
11350         printf("TEMP_%02u", -varx);
11351     else
11352         emitComp->gtDispLclVar(+varx, false);
11353
11354     if (disp < 0)
11355         printf("-0x%02x", -disp);
11356     else if (disp > 0)
11357         printf("+0x%02x", +disp);
11358
11359     printf("]");
11360
11361     if (varx >= 0 && emitComp->opts.varNames)
11362     {
11363         LclVarDsc*  varDsc;
11364         const char* varName;
11365
11366         assert((unsigned)varx < emitComp->lvaCount);
11367         varDsc  = emitComp->lvaTable + varx;
11368         varName = emitComp->compLocalVarName(varx, offs);
11369
11370         if (varName)
11371         {
11372             printf("'%s", varName);
11373
11374             if (disp < 0)
11375                 printf("-%d", -disp);
11376             else if (disp > 0)
11377                 printf("+%d", +disp);
11378
11379             printf("'");
11380         }
11381     }
11382 }
11383
11384 #endif // DEBUG
11385
11386 // Generate code for a load or store operation with a potentially complex addressing mode
11387 // This method handles the case of a GT_IND with contained GT_LEA op1 of the x86 form [base + index*sccale + offset]
11388 // Since Arm64 does not directly support this complex of an addressing mode
11389 // we may generates up to three instructions for this for Arm64
11390 //
11391 void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataReg, GenTreeIndir* indir)
11392 {
11393     emitAttr ldstAttr = isVectorRegister(dataReg) ? attr : emitInsAdjustLoadStoreAttr(ins, attr);
11394
11395     GenTree* addr = indir->Addr();
11396
11397     if (addr->isContained())
11398     {
11399         assert(addr->OperGet() == GT_LCL_VAR_ADDR || addr->OperGet() == GT_LEA);
11400
11401         int   offset = 0;
11402         DWORD lsl    = 0;
11403
11404         if (addr->OperGet() == GT_LEA)
11405         {
11406             offset = addr->AsAddrMode()->Offset();
11407             if (addr->AsAddrMode()->gtScale > 0)
11408             {
11409                 assert(isPow2(addr->AsAddrMode()->gtScale));
11410                 BitScanForward(&lsl, addr->AsAddrMode()->gtScale);
11411             }
11412         }
11413
11414         GenTree* memBase = indir->Base();
11415
11416         if (indir->HasIndex())
11417         {
11418             GenTree* index = indir->Index();
11419
11420             if (offset != 0)
11421             {
11422                 regNumber tmpReg = indir->GetSingleTempReg();
11423
11424                 emitAttr addType = varTypeIsGC(memBase) ? EA_BYREF : EA_PTRSIZE;
11425
11426                 if (emitIns_valid_imm_for_add(offset, EA_8BYTE))
11427                 {
11428                     if (lsl > 0)
11429                     {
11430                         // Generate code to set tmpReg = base + index*scale
11431                         emitIns_R_R_R_I(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum, lsl,
11432                                         INS_OPTS_LSL);
11433                     }
11434                     else // no scale
11435                     {
11436                         // Generate code to set tmpReg = base + index
11437                         emitIns_R_R_R(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum);
11438                     }
11439
11440                     noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11441
11442                     // Then load/store dataReg from/to [tmpReg + offset]
11443                     emitIns_R_R_I(ins, ldstAttr, dataReg, tmpReg, offset);
11444                 }
11445                 else // large offset
11446                 {
11447                     // First load/store tmpReg with the large offset constant
11448                     codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11449                     // Then add the base register
11450                     //      rd = rd + base
11451                     emitIns_R_R_R(INS_add, addType, tmpReg, tmpReg, memBase->gtRegNum);
11452
11453                     noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11454                     noway_assert(tmpReg != index->gtRegNum);
11455
11456                     // Then load/store dataReg from/to [tmpReg + index*scale]
11457                     emitIns_R_R_R_I(ins, ldstAttr, dataReg, tmpReg, index->gtRegNum, lsl, INS_OPTS_LSL);
11458                 }
11459             }
11460             else // (offset == 0)
11461             {
11462                 if (lsl > 0)
11463                 {
11464                     // Then load/store dataReg from/to [memBase + index*scale]
11465                     emitIns_R_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum, lsl, INS_OPTS_LSL);
11466                 }
11467                 else // no scale
11468                 {
11469                     // Then load/store dataReg from/to [memBase + index]
11470                     emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum);
11471                 }
11472             }
11473         }
11474         else // no Index register
11475         {
11476             if (emitIns_valid_imm_for_ldst_offset(offset, EA_SIZE(attr)))
11477             {
11478                 // Then load/store dataReg from/to [memBase + offset]
11479                 emitIns_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, offset);
11480             }
11481             else
11482             {
11483                 // We require a tmpReg to hold the offset
11484                 regNumber tmpReg = indir->GetSingleTempReg();
11485
11486                 // First load/store tmpReg with the large offset constant
11487                 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11488
11489                 // Then load/store dataReg from/to [memBase + tmpReg]
11490                 emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, tmpReg);
11491             }
11492         }
11493     }
11494     else // addr is not contained, so we evaluate it into a register
11495     {
11496         // Then load/store dataReg from/to [addrReg]
11497         emitIns_R_R(ins, ldstAttr, dataReg, addr->gtRegNum);
11498     }
11499 }
11500
11501 // Generates an integer data section constant and returns a field handle representing
11502 // the data offset to access the constant via a load instruction.
11503 // This is called during ngen for any relocatable constants
11504 //
11505 CORINFO_FIELD_HANDLE emitter::emitLiteralConst(ssize_t cnsValIn, emitAttr attr /*=EA_8BYTE*/)
11506 {
11507     ssize_t constValue = cnsValIn;
11508     void*   cnsAddr    = &constValue;
11509     bool    dblAlign;
11510
11511     if (attr == EA_4BYTE)
11512     {
11513         dblAlign = false;
11514     }
11515     else
11516     {
11517         assert(attr == EA_8BYTE);
11518         dblAlign = true;
11519     }
11520
11521     // Access to inline data is 'abstracted' by a special type of static member
11522     // (produced by eeFindJitDataOffs) which the emitter recognizes as being a reference
11523     // to constant data, not a real static field.
11524
11525     UNATIVE_OFFSET cnsSize = (attr == EA_4BYTE) ? 4 : 8;
11526     UNATIVE_OFFSET cnum    = emitDataConst(cnsAddr, cnsSize, dblAlign);
11527     return emitComp->eeFindJitDataOffs(cnum);
11528 }
11529
11530 // Generates a float or double data section constant and returns field handle representing
11531 // the data offset to access the constant.  This is called by emitInsBinary() in case
11532 // of contained float of double constants.
11533 CORINFO_FIELD_HANDLE emitter::emitFltOrDblConst(GenTreeDblCon* tree, emitAttr attr /*=EA_UNKNOWN*/)
11534 {
11535     if (attr == EA_UNKNOWN)
11536     {
11537         attr = emitTypeSize(tree->TypeGet());
11538     }
11539     else
11540     {
11541         assert(emitTypeSize(tree->TypeGet()) == attr);
11542     }
11543
11544     double constValue = tree->gtDblCon.gtDconVal;
11545     void*  cnsAddr;
11546     float  f;
11547     bool   dblAlign;
11548
11549     if (attr == EA_4BYTE)
11550     {
11551         f        = forceCastToFloat(constValue);
11552         cnsAddr  = &f;
11553         dblAlign = false;
11554     }
11555     else
11556     {
11557         cnsAddr  = &constValue;
11558         dblAlign = true;
11559     }
11560
11561     // Access to inline data is 'abstracted' by a special type of static member
11562     // (produced by eeFindJitDataOffs) which the emitter recognizes as being a reference
11563     // to constant data, not a real static field.
11564
11565     UNATIVE_OFFSET cnsSize = (attr == EA_4BYTE) ? 4 : 8;
11566     UNATIVE_OFFSET cnum    = emitDataConst(cnsAddr, cnsSize, dblAlign);
11567     return emitComp->eeFindJitDataOffs(cnum);
11568 }
11569
11570 // The callee must call genConsumeReg() for any non-contained srcs
11571 // and genProduceReg() for any non-contained dsts.
11572
11573 regNumber emitter::emitInsBinary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src)
11574 {
11575     regNumber result = REG_NA;
11576
11577     // dst can only be a reg
11578     assert(!dst->isContained());
11579
11580     // src can be immed or reg
11581     assert(!src->isContained() || src->isContainedIntOrIImmed());
11582
11583     // find immed (if any) - it cannot be a dst
11584     GenTreeIntConCommon* intConst = nullptr;
11585     if (src->isContainedIntOrIImmed())
11586     {
11587         intConst = src->AsIntConCommon();
11588     }
11589
11590     if (intConst)
11591     {
11592         emitIns_R_I(ins, attr, dst->gtRegNum, intConst->IconValue());
11593         return dst->gtRegNum;
11594     }
11595     else
11596     {
11597         emitIns_R_R(ins, attr, dst->gtRegNum, src->gtRegNum);
11598         return dst->gtRegNum;
11599     }
11600 }
11601
11602 // The callee must call genConsumeReg() for any non-contained srcs
11603 // and genProduceReg() for any non-contained dsts.
11604
11605 regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src1, GenTree* src2)
11606 {
11607     regNumber result = REG_NA;
11608
11609     // dst can only be a reg
11610     assert(!dst->isContained());
11611
11612     // find immed (if any) - it cannot be a dst
11613     // Only one src can be an int.
11614     GenTreeIntConCommon* intConst  = nullptr;
11615     GenTree*             nonIntReg = nullptr;
11616
11617     if (varTypeIsFloating(dst))
11618     {
11619         // src1 can only be a reg
11620         assert(!src1->isContained());
11621         // src2 can only be a reg
11622         assert(!src2->isContained());
11623     }
11624     else // not floating point
11625     {
11626         // src2 can be immed or reg
11627         assert(!src2->isContained() || src2->isContainedIntOrIImmed());
11628
11629         // Check src2 first as we can always allow it to be a contained immediate
11630         if (src2->isContainedIntOrIImmed())
11631         {
11632             intConst  = src2->AsIntConCommon();
11633             nonIntReg = src1;
11634         }
11635         // Only for commutative operations do we check src1 and allow it to be a contained immediate
11636         else if (dst->OperIsCommutative())
11637         {
11638             // src1 can be immed or reg
11639             assert(!src1->isContained() || src1->isContainedIntOrIImmed());
11640
11641             // Check src1 and allow it to be a contained immediate
11642             if (src1->isContainedIntOrIImmed())
11643             {
11644                 assert(!src2->isContainedIntOrIImmed());
11645                 intConst  = src1->AsIntConCommon();
11646                 nonIntReg = src2;
11647             }
11648         }
11649         else
11650         {
11651             // src1 can only be a reg
11652             assert(!src1->isContained());
11653         }
11654     }
11655
11656     bool isMulOverflow = false;
11657     if (dst->gtOverflowEx())
11658     {
11659         if ((ins == INS_add) || (ins == INS_adds))
11660         {
11661             ins = INS_adds;
11662         }
11663         else if ((ins == INS_sub) || (ins == INS_subs))
11664         {
11665             ins = INS_subs;
11666         }
11667         else if (ins == INS_mul)
11668         {
11669             isMulOverflow = true;
11670             assert(intConst == nullptr); // overflow format doesn't support an int constant operand
11671         }
11672         else
11673         {
11674             assert(!"Invalid ins for overflow check");
11675         }
11676     }
11677     if (intConst != nullptr)
11678     {
11679         emitIns_R_R_I(ins, attr, dst->gtRegNum, nonIntReg->gtRegNum, intConst->IconValue());
11680     }
11681     else
11682     {
11683         if (isMulOverflow)
11684         {
11685             regNumber extraReg = dst->GetSingleTempReg();
11686             assert(extraReg != dst->gtRegNum);
11687
11688             if ((dst->gtFlags & GTF_UNSIGNED) != 0)
11689             {
11690                 if (attr == EA_4BYTE)
11691                 {
11692                     // Compute 8 byte results from 4 byte by 4 byte multiplication.
11693                     emitIns_R_R_R(INS_umull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11694
11695                     // Get the high result by shifting dst.
11696                     emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11697                 }
11698                 else
11699                 {
11700                     assert(attr == EA_8BYTE);
11701                     // Compute the high result.
11702                     emitIns_R_R_R(INS_umulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11703
11704                     // Now multiply without skewing the high result.
11705                     emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11706                 }
11707
11708                 // zero-sign bit comparison to detect overflow.
11709                 emitIns_R_I(INS_cmp, attr, extraReg, 0);
11710             }
11711             else
11712             {
11713                 int bitShift = 0;
11714                 if (attr == EA_4BYTE)
11715                 {
11716                     // Compute 8 byte results from 4 byte by 4 byte multiplication.
11717                     emitIns_R_R_R(INS_smull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11718
11719                     // Get the high result by shifting dst.
11720                     emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11721
11722                     bitShift = 31;
11723                 }
11724                 else
11725                 {
11726                     assert(attr == EA_8BYTE);
11727                     // Save the high result in a temporary register.
11728                     emitIns_R_R_R(INS_smulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11729
11730                     // Now multiply without skewing the high result.
11731                     emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11732
11733                     bitShift = 63;
11734                 }
11735
11736                 // Sign bit comparison to detect overflow.
11737                 emitIns_R_R_I(INS_cmp, attr, extraReg, dst->gtRegNum, bitShift, INS_OPTS_ASR);
11738             }
11739         }
11740         else
11741         {
11742             // We can just multiply.
11743             emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11744         }
11745     }
11746
11747     if (dst->gtOverflowEx())
11748     {
11749         assert(!varTypeIsFloating(dst));
11750         codeGen->genCheckOverflow(dst);
11751     }
11752
11753     return dst->gtRegNum;
11754 }
11755
11756 #endif // defined(_TARGET_ARM64_)