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