Merge pull request #14456 from fiigii/crc32
[platform/upstream/coreclr.git] / src / jit / emitarm64.cpp
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4
5 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
6 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
7 XX                                                                           XX
8 XX                             emitArm64.cpp                                 XX
9 XX                                                                           XX
10 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
11 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
12 */
13
14 #include "jitpch.h"
15 #ifdef _MSC_VER
16 #pragma hdrstop
17 #endif
18
19 #if defined(_TARGET_ARM64_)
20
21 /*****************************************************************************/
22 /*****************************************************************************/
23
24 #include "instr.h"
25 #include "emit.h"
26 #include "codegen.h"
27
28 /* static */ bool emitter::strictArmAsm = true;
29
30 /*****************************************************************************/
31
32 const instruction emitJumpKindInstructions[] = {
33     INS_nop,
34
35 #define JMP_SMALL(en, rev, ins) INS_##ins,
36 #include "emitjmps.h"
37 };
38
39 const emitJumpKind emitReverseJumpKinds[] = {
40     EJ_NONE,
41
42 #define JMP_SMALL(en, rev, ins) EJ_##rev,
43 #include "emitjmps.h"
44 };
45
46 /*****************************************************************************
47  * Look up the instruction for a jump kind
48  */
49
50 /*static*/ instruction emitter::emitJumpKindToIns(emitJumpKind jumpKind)
51 {
52     assert((unsigned)jumpKind < ArrLen(emitJumpKindInstructions));
53     return emitJumpKindInstructions[jumpKind];
54 }
55
56 /*****************************************************************************
57 * Look up the jump kind for an instruction. It better be a conditional
58 * branch instruction with a jump kind!
59 */
60
61 /*static*/ emitJumpKind emitter::emitInsToJumpKind(instruction ins)
62 {
63     for (unsigned i = 0; i < ArrLen(emitJumpKindInstructions); i++)
64     {
65         if (ins == emitJumpKindInstructions[i])
66         {
67             emitJumpKind ret = (emitJumpKind)i;
68             assert(EJ_NONE < ret && ret < EJ_COUNT);
69             return ret;
70         }
71     }
72     unreached();
73 }
74
75 /*****************************************************************************
76  * Reverse the conditional jump
77  */
78
79 /*static*/ emitJumpKind emitter::emitReverseJumpKind(emitJumpKind jumpKind)
80 {
81     assert(jumpKind < EJ_COUNT);
82     return emitReverseJumpKinds[jumpKind];
83 }
84
85 /*****************************************************************************
86  *
87  *  Return the allocated size (in bytes) of the given instruction descriptor.
88  */
89
90 size_t emitter::emitSizeOfInsDsc(instrDesc* id)
91 {
92     assert(!emitIsTinyInsDsc(id));
93
94     if (emitIsScnsInsDsc(id))
95         return SMALL_IDSC_SIZE;
96
97     assert((unsigned)id->idInsFmt() < emitFmtCount);
98
99     ID_OPS idOp      = (ID_OPS)emitFmtToOps[id->idInsFmt()];
100     bool   isCallIns = (id->idIns() == INS_bl) || (id->idIns() == INS_blr) || (id->idIns() == INS_b_tail) ||
101                      (id->idIns() == INS_br_tail);
102     bool maybeCallIns = (id->idIns() == INS_b) || (id->idIns() == INS_br);
103
104     switch (idOp)
105     {
106         case ID_OP_NONE:
107             break;
108
109         case ID_OP_JMP:
110             return sizeof(instrDescJmp);
111
112         case ID_OP_CALL:
113             assert(isCallIns || maybeCallIns);
114             if (id->idIsLargeCall())
115             {
116                 /* Must be a "fat" call descriptor */
117                 return sizeof(instrDescCGCA);
118             }
119             else
120             {
121                 assert(!id->idIsLargeDsp());
122                 assert(!id->idIsLargeCns());
123                 return sizeof(instrDesc);
124             }
125             break;
126
127         default:
128             NO_WAY("unexpected instruction descriptor format");
129             break;
130     }
131
132     if (id->idIsLargeCns())
133     {
134         if (id->idIsLargeDsp())
135             return sizeof(instrDescCnsDsp);
136         else
137             return sizeof(instrDescCns);
138     }
139     else
140     {
141         if (id->idIsLargeDsp())
142             return sizeof(instrDescDsp);
143         else
144             return sizeof(instrDesc);
145     }
146 }
147
148 #ifdef DEBUG
149 /*****************************************************************************
150  *
151  *  The following called for each recorded instruction -- use for debugging.
152  */
153 void emitter::emitInsSanityCheck(instrDesc* id)
154 {
155     /* What instruction format have we got? */
156
157     switch (id->idInsFmt())
158     {
159         instruction ins;
160         emitAttr    elemsize;
161         emitAttr    datasize;
162         emitAttr    dstsize;
163         emitAttr    srcsize;
164         ssize_t     imm;
165         unsigned    immShift;
166         ssize_t     index;
167         ssize_t     index2;
168
169         case IF_BI_0A: // BI_0A   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
170             break;
171
172         case IF_BI_0B: // BI_0B   ......iiiiiiiiii iiiiiiiiiiii....               simm19:00
173             break;
174
175         case IF_LARGEJMP:
176         case IF_LARGEADR:
177         case IF_LARGELDC:
178             break;
179
180         case IF_BI_0C: // BI_0C   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
181             break;
182
183         case IF_BI_1A: // BI_1A   ......iiiiiiiiii iiiiiiiiiiittttt      Rt       simm19:00
184             assert(isValidGeneralDatasize(id->idOpSize()));
185             assert(isGeneralRegister(id->idReg1()));
186             break;
187
188         case IF_BI_1B: // BI_1B   B.......bbbbbiii iiiiiiiiiiittttt      Rt imm6, simm14:00
189             assert(isValidGeneralDatasize(id->idOpSize()));
190             assert(isGeneralRegister(id->idReg1()));
191             assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
192             break;
193
194         case IF_BR_1A: // BR_1A   ................ ......nnnnn.....         Rn
195             assert(isGeneralRegister(id->idReg1()));
196             break;
197
198         case IF_BR_1B: // BR_1B   ................ ......nnnnn.....         Rn
199             assert(isGeneralRegister(id->idReg3()));
200             break;
201
202         case IF_LS_1A: // LS_1A   .X......iiiiiiii iiiiiiiiiiittttt      Rt    PC imm(1MB)
203             assert(isGeneralRegister(id->idReg1()) || isVectorRegister(id->idReg1()));
204             assert(insOptsNone(id->idInsOpt()));
205             break;
206
207         case IF_LS_2A:                                // LS_2A   .X.......X...... ......nnnnnttttt      Rt Rn
208             assert(isIntegerRegister(id->idReg1()) || // ZR
209                    isVectorRegister(id->idReg1()));
210             assert(isIntegerRegister(id->idReg2())); // SP
211             assert(emitGetInsSC(id) == 0);
212             assert(insOptsNone(id->idInsOpt()));
213             break;
214
215         case IF_LS_2B: // LS_2B   .X.......Xiiiiii iiiiiinnnnnttttt      Rt Rn    imm(0-4095)
216             assert(isIntegerRegister(id->idReg1()) || // ZR
217                    isVectorRegister(id->idReg1()));
218             assert(isIntegerRegister(id->idReg2())); // SP
219             assert(isValidUimm12(emitGetInsSC(id)));
220             assert(insOptsNone(id->idInsOpt()));
221             break;
222
223         case IF_LS_2C: // LS_2C   .X.......X.iiiii iiiiPPnnnnnttttt      Rt Rn    imm(-256..+255) no/pre/post inc
224             assert(isIntegerRegister(id->idReg1()) || // ZR
225                    isVectorRegister(id->idReg1()));
226             assert(isIntegerRegister(id->idReg2())); // SP
227             assert(emitGetInsSC(id) >= -0x100);
228             assert(emitGetInsSC(id) < 0x100);
229             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
230             break;
231
232         case IF_LS_3A: // LS_3A   .X.......X.mmmmm oooS..nnnnnttttt      Rt Rn Rm ext(Rm) LSL {}
233             assert(isIntegerRegister(id->idReg1()) || // ZR
234                    isVectorRegister(id->idReg1()));
235             assert(isIntegerRegister(id->idReg2())); // SP
236             if (id->idIsLclVar())
237             {
238                 assert(isGeneralRegister(codeGen->rsGetRsvdReg()));
239             }
240             else
241             {
242                 assert(isGeneralRegister(id->idReg3()));
243             }
244             assert(insOptsLSExtend(id->idInsOpt()));
245             break;
246
247         case IF_LS_3B: // LS_3B   X............... .aaaaannnnnttttt      Rt Ra Rn
248             assert((isValidGeneralDatasize(id->idOpSize()) && isIntegerRegister(id->idReg1())) ||
249                    (isValidVectorLSPDatasize(id->idOpSize()) && isVectorRegister(id->idReg1())));
250             assert(isIntegerRegister(id->idReg1()) || // ZR
251                    isVectorRegister(id->idReg1()));
252             assert(isIntegerRegister(id->idReg2()) || // ZR
253                    isVectorRegister(id->idReg2()));
254             assert(isIntegerRegister(id->idReg3())); // SP
255             assert(emitGetInsSC(id) == 0);
256             assert(insOptsNone(id->idInsOpt()));
257             break;
258
259         case IF_LS_3C: // LS_3C   X.........iiiiii iaaaaannnnnttttt      Rt Ra Rn imm(im7,sh)
260             assert((isValidGeneralDatasize(id->idOpSize()) && isIntegerRegister(id->idReg1())) ||
261                    (isValidVectorLSPDatasize(id->idOpSize()) && isVectorRegister(id->idReg1())));
262             assert(isIntegerRegister(id->idReg1()) || // ZR
263                    isVectorRegister(id->idReg1()));
264             assert(isIntegerRegister(id->idReg2()) || // ZR
265                    isVectorRegister(id->idReg2()));
266             assert(isIntegerRegister(id->idReg3())); // SP
267             assert(emitGetInsSC(id) >= -0x40);
268             assert(emitGetInsSC(id) < 0x40);
269             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
270             break;
271
272         case IF_LS_3D: // LS_3D   .X.......X.mmmmm ......nnnnnttttt      Wm Rt Rn
273             assert(isIntegerRegister(id->idReg1()));
274             assert(isIntegerRegister(id->idReg2()));
275             assert(isIntegerRegister(id->idReg3()));
276             assert(emitGetInsSC(id) == 0);
277             assert(!id->idIsLclVar());
278             assert(insOptsNone(id->idInsOpt()));
279             break;
280
281         case IF_DI_1A: // DI_1A   X.......shiiiiii iiiiiinnnnn.....         Rn    imm(i12,sh)
282             assert(isValidGeneralDatasize(id->idOpSize()));
283             assert(isGeneralRegister(id->idReg1()));
284             assert(isValidUimm12(emitGetInsSC(id)));
285             assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
286             break;
287
288         case IF_DI_1B: // DI_1B   X........hwiiiii iiiiiiiiiiiddddd      Rd       imm(i16,hw)
289             assert(isValidGeneralDatasize(id->idOpSize()));
290             assert(isGeneralRegister(id->idReg1()));
291             assert(isValidImmHWVal(emitGetInsSC(id), id->idOpSize()));
292             break;
293
294         case IF_DI_1C: // DI_1C   X........Nrrrrrr ssssssnnnnn.....         Rn    imm(N,r,s)
295             assert(isValidGeneralDatasize(id->idOpSize()));
296             assert(isGeneralRegister(id->idReg1()));
297             assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
298             break;
299
300         case IF_DI_1D: // DI_1D   X........Nrrrrrr ssssss.....ddddd      Rd       imm(N,r,s)
301             assert(isValidGeneralDatasize(id->idOpSize()));
302             assert(isIntegerRegister(id->idReg1())); // SP
303             assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
304             break;
305
306         case IF_DI_1E: // DI_1E   .ii.....iiiiiiii iiiiiiiiiiiddddd      Rd       simm21
307             assert(isGeneralRegister(id->idReg1()));
308             break;
309
310         case IF_DI_1F: // DI_1F   X..........iiiii cccc..nnnnn.nzcv      Rn imm5  nzcv cond
311             assert(isValidGeneralDatasize(id->idOpSize()));
312             assert(isGeneralRegister(id->idReg1()));
313             assert(isValidImmCondFlagsImm5(emitGetInsSC(id)));
314             break;
315
316         case IF_DI_2A: // DI_2A   X.......shiiiiii iiiiiinnnnnddddd      Rd Rn    imm(i12,sh)
317             assert(isValidGeneralDatasize(id->idOpSize()));
318             assert(isIntegerRegister(id->idReg1())); // SP
319             assert(isIntegerRegister(id->idReg2())); // SP
320             assert(isValidUimm12(emitGetInsSC(id)));
321             assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
322             break;
323
324         case IF_DI_2B: // DI_2B   X.........Xnnnnn ssssssnnnnnddddd      Rd Rn    imm(0-63)
325             assert(isValidGeneralDatasize(id->idOpSize()));
326             assert(isGeneralRegister(id->idReg1()));
327             assert(isGeneralRegister(id->idReg2()));
328             assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
329             break;
330
331         case IF_DI_2C: // DI_2C   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imm(N,r,s)
332             assert(isValidGeneralDatasize(id->idOpSize()));
333             assert(isIntegerRegister(id->idReg1())); // SP
334             assert(isGeneralRegister(id->idReg2()));
335             assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
336             break;
337
338         case IF_DI_2D: // DI_2D   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imr, imms   (N,r,s)
339             assert(isValidGeneralDatasize(id->idOpSize()));
340             assert(isGeneralRegister(id->idReg1()));
341             assert(isGeneralRegister(id->idReg2()));
342             assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
343             break;
344
345         case IF_DR_1D: // DR_1D   X............... cccc.......ddddd      Rd       cond
346             assert(isValidGeneralDatasize(id->idOpSize()));
347             assert(isGeneralRegister(id->idReg1()));
348             assert(isValidImmCond(emitGetInsSC(id)));
349             break;
350
351         case IF_DR_2A: // DR_2A   X..........mmmmm ......nnnnn.....         Rn Rm
352             assert(isValidGeneralDatasize(id->idOpSize()));
353             assert(isGeneralRegister(id->idReg1()));
354             assert(isGeneralRegister(id->idReg2()));
355             break;
356
357         case IF_DR_2B: // DR_2B   X.......sh.mmmmm ssssssnnnnn.....         Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
358             assert(isValidGeneralDatasize(id->idOpSize()));
359             assert(isIntegerRegister(id->idReg1())); // ZR
360             assert(isGeneralRegister(id->idReg2()));
361             assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
362             if (!insOptsNone(id->idInsOpt()))
363             {
364                 if (id->idIns() == INS_tst) // tst allows ROR, cmp/cmn don't
365                 {
366                     assert(insOptsAnyShift(id->idInsOpt()));
367                 }
368                 else
369                 {
370                     assert(insOptsAluShift(id->idInsOpt()));
371                 }
372             }
373             assert(insOptsNone(id->idInsOpt()) || (emitGetInsSC(id) > 0));
374             break;
375
376         case IF_DR_2C: // DR_2C   X..........mmmmm ooosssnnnnn.....         Rn Rm ext(Rm) LSL imm(0-4)
377             assert(isValidGeneralDatasize(id->idOpSize()));
378             assert(isIntegerRegister(id->idReg1())); // SP
379             assert(isGeneralRegister(id->idReg2()));
380             assert(insOptsNone(id->idInsOpt()) || insOptsLSL(id->idInsOpt()) || insOptsAnyExtend(id->idInsOpt()));
381             assert(emitGetInsSC(id) >= 0);
382             assert(emitGetInsSC(id) <= 4);
383             if (insOptsLSL(id->idInsOpt()))
384             {
385                 assert(emitGetInsSC(id) > 0);
386             }
387             break;
388
389         case IF_DR_2D: // DR_2D   X..........nnnnn cccc..nnnnnmmmmm      Rd Rn    cond
390             assert(isValidGeneralDatasize(id->idOpSize()));
391             assert(isGeneralRegister(id->idReg1()));
392             assert(isGeneralRegister(id->idReg2()));
393             assert(isValidImmCond(emitGetInsSC(id)));
394             break;
395
396         case IF_DR_2E: // DR_2E   X..........mmmmm ...........ddddd      Rd    Rm
397             assert(isValidGeneralDatasize(id->idOpSize()));
398             assert(isGeneralRegister(id->idReg1()));
399             assert(isIntegerRegister(id->idReg2())); // ZR
400             break;
401
402         case IF_DR_2F: // DR_2F   X.......sh.mmmmm ssssss.....ddddd      Rd    Rm {LSL,LSR,ASR} imm(0-63)
403             assert(isValidGeneralDatasize(id->idOpSize()));
404             assert(isGeneralRegister(id->idReg1()));
405             assert(isGeneralRegister(id->idReg2()));
406             assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
407             assert(insOptsNone(id->idInsOpt()) || insOptsAluShift(id->idInsOpt()));
408             assert(insOptsNone(id->idInsOpt()) || (emitGetInsSC(id) > 0));
409             break;
410
411         case IF_DR_2G: // DR_2G   X............... ......nnnnnddddd      Rd    Rm
412             assert(isValidGeneralDatasize(id->idOpSize()));
413             assert(isIntegerRegister(id->idReg1())); // SP
414             assert(isIntegerRegister(id->idReg2())); // SP
415             break;
416
417         case IF_DR_2H: // DR_2H   X........X...... ......nnnnnddddd      Rd Rn
418             assert(isValidGeneralDatasize(id->idOpSize()));
419             assert(isGeneralRegister(id->idReg1()));
420             assert(isGeneralRegister(id->idReg2()));
421             break;
422
423         case IF_DR_2I: // DR_2I   X..........mmmmm cccc..nnnnn.nzcv      Rn Rm    nzcv cond
424             assert(isValidGeneralDatasize(id->idOpSize()));
425             assert(isGeneralRegister(id->idReg1()));
426             assert(isGeneralRegister(id->idReg2()));
427             assert(isValidImmCondFlags(emitGetInsSC(id)));
428             break;
429
430         case IF_DR_3A: // DR_3A   X..........mmmmm ......nnnnnmmmmm      Rd Rn Rm
431             assert(isValidGeneralDatasize(id->idOpSize()));
432             assert(isIntegerRegister(id->idReg1())); // SP
433             assert(isIntegerRegister(id->idReg2())); // SP
434             if (id->idIsLclVar())
435             {
436                 assert(isGeneralRegister(codeGen->rsGetRsvdReg()));
437             }
438             else
439             {
440                 assert(isGeneralRegister(id->idReg3()));
441             }
442             assert(insOptsNone(id->idInsOpt()));
443             break;
444
445         case IF_DR_3B: // DR_3B   X.......sh.mmmmm ssssssnnnnnddddd      Rd Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
446             assert(isValidGeneralDatasize(id->idOpSize()));
447             assert(isGeneralRegister(id->idReg1()));
448             assert(isGeneralRegister(id->idReg2()));
449             assert(isGeneralRegister(id->idReg3()));
450             assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
451             assert(insOptsNone(id->idInsOpt()) || insOptsAnyShift(id->idInsOpt()));
452             assert(insOptsNone(id->idInsOpt()) || (emitGetInsSC(id) > 0));
453             break;
454
455         case IF_DR_3C: // DR_3C   X..........mmmmm ooosssnnnnnddddd      Rd Rn Rm ext(Rm) LSL imm(0-4)
456             assert(isValidGeneralDatasize(id->idOpSize()));
457             assert(isIntegerRegister(id->idReg1())); // SP
458             assert(isIntegerRegister(id->idReg2())); // SP
459             assert(isGeneralRegister(id->idReg3()));
460             assert(insOptsNone(id->idInsOpt()) || insOptsLSL(id->idInsOpt()) || insOptsAnyExtend(id->idInsOpt()));
461             assert(emitGetInsSC(id) >= 0);
462             assert(emitGetInsSC(id) <= 4);
463             if (insOptsLSL(id->idInsOpt()))
464             {
465                 assert((emitGetInsSC(id) > 0) ||
466                        (id->idReg2() == REG_ZR)); // REG_ZR encodes SP and we allow a shift of zero
467             }
468             break;
469
470         case IF_DR_3D: // DR_3D   X..........mmmmm cccc..nnnnnmmmmm      Rd Rn Rm cond
471             assert(isValidGeneralDatasize(id->idOpSize()));
472             assert(isGeneralRegister(id->idReg1()));
473             assert(isGeneralRegister(id->idReg2()));
474             assert(isGeneralRegister(id->idReg3()));
475             assert(isValidImmCond(emitGetInsSC(id)));
476             break;
477
478         case IF_DR_3E: // DR_3E   X........X.mmmmm ssssssnnnnnddddd      Rd Rn Rm imm(0-63)
479             assert(isValidGeneralDatasize(id->idOpSize()));
480             assert(isGeneralRegister(id->idReg1()));
481             assert(isGeneralRegister(id->idReg2()));
482             assert(isGeneralRegister(id->idReg3()));
483             assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
484             assert(insOptsNone(id->idInsOpt()));
485             break;
486
487         case IF_DR_4A: // DR_4A   X..........mmmmm .aaaaannnnnddddd      Rd Rn Rm Ra
488             assert(isValidGeneralDatasize(id->idOpSize()));
489             assert(isGeneralRegister(id->idReg1()));
490             assert(isGeneralRegister(id->idReg2()));
491             assert(isGeneralRegister(id->idReg3()));
492             assert(isGeneralRegister(id->idReg4()));
493             break;
494
495         case IF_DV_1A: // DV_1A   .........X.iiiii iii........ddddd      Vd imm8    (fmov - immediate scalar)
496             assert(insOptsNone(id->idInsOpt()));
497             elemsize = id->idOpSize();
498             assert(isValidVectorElemsizeFloat(elemsize));
499             assert(isVectorRegister(id->idReg1()));
500             assert(isValidUimm8(emitGetInsSC(id)));
501             break;
502
503         case IF_DV_1B: // DV_1B   .QX..........iii cmod..iiiiiddddd      Vd imm8    (immediate vector)
504             ins      = id->idIns();
505             imm      = emitGetInsSC(id) & 0x0ff;
506             immShift = (emitGetInsSC(id) & 0x700) >> 8;
507             assert(immShift >= 0);
508             datasize = id->idOpSize();
509             assert(isValidVectorDatasize(datasize));
510             assert(isValidArrangement(datasize, id->idInsOpt()));
511             elemsize = optGetElemsize(id->idInsOpt());
512             if (ins == INS_fmov)
513             {
514                 assert(isValidVectorElemsizeFloat(elemsize));
515                 assert(id->idInsOpt() != INS_OPTS_1D); // Reserved encoding
516                 assert(immShift == 0);
517             }
518             else
519             {
520                 assert(isValidVectorElemsize(elemsize));
521                 assert((immShift != 4) && (immShift != 7)); // always invalid values
522                 if (ins != INS_movi)                        // INS_mvni, INS_orr, INS_bic
523                 {
524                     assert((elemsize != EA_1BYTE) && (elemsize != EA_8BYTE)); // only H or S
525                     if (elemsize == EA_2BYTE)
526                     {
527                         assert(immShift < 2);
528                     }
529                     else // (elemsize == EA_4BYTE)
530                     {
531                         if (ins != INS_mvni)
532                         {
533                             assert(immShift < 4);
534                         }
535                     }
536                 }
537             }
538             assert(isVectorRegister(id->idReg1()));
539             assert(isValidUimm8(imm));
540             break;
541
542         case IF_DV_1C: // DV_1C   .........X...... ......nnnnn.....      Vn #0.0    (fcmp - with zero)
543             assert(insOptsNone(id->idInsOpt()));
544             elemsize = id->idOpSize();
545             assert(isValidVectorElemsizeFloat(elemsize));
546             assert(isVectorRegister(id->idReg1()));
547             break;
548
549         case IF_DV_2A: // DV_2A   .Q.......X...... ......nnnnnddddd      Vd Vn      (fabs, fcvt - vector)
550         case IF_DV_2M: // DV_2M   .Q......XX...... ......nnnnnddddd      Vd Vn      (abs, neg   - vector)
551             assert(isValidVectorDatasize(id->idOpSize()));
552             assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
553             assert(isVectorRegister(id->idReg1()));
554             assert(isVectorRegister(id->idReg2()));
555             break;
556
557         case IF_DV_2N: // DV_2N   .........iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - scalar)
558             assert(id->idOpSize() == EA_8BYTE);
559             assert(insOptsNone(id->idInsOpt()));
560             assert(isVectorRegister(id->idReg1()));
561             assert(isVectorRegister(id->idReg2()));
562             assert(isValidImmShift(emitGetInsSC(id), EA_8BYTE));
563             break;
564
565         case IF_DV_2O: // DV_2O   .Q.......iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - vector)
566             assert(isValidVectorDatasize(id->idOpSize()));
567             assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
568             assert(isVectorRegister(id->idReg1()));
569             assert(isVectorRegister(id->idReg2()));
570             elemsize = optGetElemsize(id->idInsOpt());
571             assert(isValidImmShift(emitGetInsSC(id), elemsize));
572             break;
573
574         case IF_DV_2B: // DV_2B   .Q.........iiiii ......nnnnnddddd      Rd Vn[]  (umov/smov    - to general)
575             elemsize = id->idOpSize();
576             index    = emitGetInsSC(id);
577             assert(insOptsNone(id->idInsOpt()));
578             assert(isValidVectorIndex(EA_16BYTE, elemsize, index));
579             assert(isValidVectorElemsize(elemsize));
580             assert(isGeneralRegister(id->idReg1()));
581             assert(isVectorRegister(id->idReg2()));
582             break;
583
584         case IF_DV_2C: // DV_2C   .Q.........iiiii ......nnnnnddddd      Vd Rn    (dup/ins - vector from general)
585             if (id->idIns() == INS_dup)
586             {
587                 datasize = id->idOpSize();
588                 assert(isValidVectorDatasize(datasize));
589                 assert(isValidArrangement(datasize, id->idInsOpt()));
590                 elemsize = optGetElemsize(id->idInsOpt());
591             }
592             else // INS_ins
593             {
594                 datasize = EA_16BYTE;
595                 elemsize = id->idOpSize();
596                 assert(isValidVectorElemsize(elemsize));
597             }
598             assert(isVectorRegister(id->idReg1()));
599             assert(isGeneralRegisterOrZR(id->idReg2()));
600             break;
601
602         case IF_DV_2D: // DV_2D   .Q.........iiiii ......nnnnnddddd      Vd Vn[]  (dup - vector)
603             datasize = id->idOpSize();
604             assert(isValidVectorDatasize(datasize));
605             assert(isValidArrangement(datasize, id->idInsOpt()));
606             elemsize = optGetElemsize(id->idInsOpt());
607             index    = emitGetInsSC(id);
608             assert(isValidVectorIndex(datasize, elemsize, index));
609             assert(isVectorRegister(id->idReg1()));
610             assert(isVectorRegister(id->idReg2()));
611             break;
612
613         case IF_DV_2E: // DV_2E   ...........iiiii ......nnnnnddddd      Vd Vn[]  (dup - scalar)
614             elemsize = id->idOpSize();
615             index    = emitGetInsSC(id);
616             assert(isValidVectorIndex(EA_16BYTE, elemsize, index));
617             assert(isValidVectorElemsize(elemsize));
618             assert(isVectorRegister(id->idReg1()));
619             assert(isVectorRegister(id->idReg2()));
620             break;
621
622         case IF_DV_2F: // DV_2F   ...........iiiii .jjjj.nnnnnddddd      Vd[] Vn[] (ins - element)
623             imm      = emitGetInsSC(id);
624             index    = (imm >> 4) & 0xf;
625             index2   = imm & 0xf;
626             elemsize = id->idOpSize();
627             assert(isValidVectorElemsize(elemsize));
628             assert(isValidVectorIndex(EA_16BYTE, elemsize, index));
629             assert(isValidVectorIndex(EA_16BYTE, elemsize, index2));
630             assert(isVectorRegister(id->idReg1()));
631             assert(isVectorRegister(id->idReg2()));
632             break;
633
634         case IF_DV_2L: // DV_2L   ........XX...... ......nnnnnddddd      Vd Vn      (abs, neg - scalar)
635             assert(id->idOpSize() == EA_8BYTE); // only type D is supported
636             __fallthrough;
637
638         case IF_DV_2G: // DV_2G   .........X...... ......nnnnnddddd      Vd Vn      (fmov, fcvtXX - register)
639         case IF_DV_2K: // DV_2K   .........X.mmmmm ......nnnnn.....      Vn Vm      (fcmp)
640             assert(insOptsNone(id->idInsOpt()));
641             assert(isValidVectorElemsizeFloat(id->idOpSize()));
642             assert(isVectorRegister(id->idReg1()));
643             assert(isVectorRegister(id->idReg2()));
644             break;
645
646         case IF_DV_2H: // DV_2H   X........X...... ......nnnnnddddd      Rd Vn      (fmov/fcvtXX - to general)
647             assert(insOptsConvertFloatToInt(id->idInsOpt()));
648             dstsize = optGetDstsize(id->idInsOpt());
649             srcsize = optGetSrcsize(id->idInsOpt());
650             assert(isValidGeneralDatasize(dstsize));
651             assert(isValidVectorElemsizeFloat(srcsize));
652             assert(dstsize == id->idOpSize());
653             assert(isGeneralRegister(id->idReg1()));
654             assert(isVectorRegister(id->idReg2()));
655             break;
656
657         case IF_DV_2I: // DV_2I   X........X...... ......nnnnnddddd      Vd Rn      (fmov/Xcvtf - from general)
658             assert(insOptsConvertIntToFloat(id->idInsOpt()));
659             dstsize = optGetDstsize(id->idInsOpt());
660             srcsize = optGetSrcsize(id->idInsOpt());
661             assert(isValidGeneralDatasize(srcsize));
662             assert(isValidVectorElemsizeFloat(dstsize));
663             assert(dstsize == id->idOpSize());
664             assert(isVectorRegister(id->idReg1()));
665             assert(isGeneralRegister(id->idReg2()));
666             break;
667
668         case IF_DV_2J: // DV_2J   ........SS.....D D.....nnnnnddddd      Vd Vn      (fcvt)
669             assert(insOptsConvertFloatToFloat(id->idInsOpt()));
670             dstsize = optGetDstsize(id->idInsOpt());
671             srcsize = optGetSrcsize(id->idInsOpt());
672             assert(isValidVectorFcvtsize(srcsize));
673             assert(isValidVectorFcvtsize(dstsize));
674             assert(dstsize == id->idOpSize());
675             assert(isVectorRegister(id->idReg1()));
676             assert(isVectorRegister(id->idReg2()));
677             break;
678
679         case IF_DV_3A: // DV_3A   .Q......XX.mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
680             assert(isValidVectorDatasize(id->idOpSize()));
681             assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
682             assert(isVectorRegister(id->idReg1()));
683             assert(isVectorRegister(id->idReg2()));
684             assert(isVectorRegister(id->idReg3()));
685             elemsize = optGetElemsize(id->idInsOpt());
686             ins      = id->idIns();
687             if (ins == INS_mul)
688             {
689                 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
690             }
691             else if (ins == INS_pmul)
692             {
693                 assert(elemsize == EA_1BYTE); // only supports 8B or 16B
694             }
695             break;
696
697         case IF_DV_3AI: // DV_3AI  .Q......XXLMmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector by elem)
698             assert(isValidVectorDatasize(id->idOpSize()));
699             assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
700             assert(isVectorRegister(id->idReg1()));
701             assert(isVectorRegister(id->idReg2()));
702             assert(isVectorRegister(id->idReg3()));
703             elemsize = optGetElemsize(id->idInsOpt());
704             assert(isValidVectorIndex(EA_16BYTE, elemsize, emitGetInsSC(id)));
705             // Only has encodings for H or S elemsize
706             assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE));
707             break;
708
709         case IF_DV_3B: // DV_3B   .Q.......X.mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
710             assert(isValidVectorDatasize(id->idOpSize()));
711             assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
712             assert(isVectorRegister(id->idReg1()));
713             assert(isVectorRegister(id->idReg2()));
714             assert(isVectorRegister(id->idReg3()));
715             break;
716
717         case IF_DV_3BI: // DV_3BI  .Q.......XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector by elem)
718             assert(isValidVectorDatasize(id->idOpSize()));
719             assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
720             assert(isVectorRegister(id->idReg1()));
721             assert(isVectorRegister(id->idReg2()));
722             assert(isVectorRegister(id->idReg3()));
723             elemsize = optGetElemsize(id->idInsOpt());
724             assert(isValidVectorIndex(id->idOpSize(), elemsize, emitGetInsSC(id)));
725             break;
726
727         case IF_DV_3C: // DV_3C   .Q.........mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
728             assert(isValidVectorDatasize(id->idOpSize()));
729             assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
730             assert(isVectorRegister(id->idReg1()));
731             assert(isVectorRegister(id->idReg2()));
732             assert(isVectorRegister(id->idReg3()));
733             break;
734
735         case IF_DV_3D: // DV_3D   .........X.mmmmm ......nnnnnddddd      Vd Vn Vm   (scalar)
736             assert(isValidScalarDatasize(id->idOpSize()));
737             assert(insOptsNone(id->idInsOpt()));
738             assert(isVectorRegister(id->idReg1()));
739             assert(isVectorRegister(id->idReg2()));
740             assert(isVectorRegister(id->idReg3()));
741             break;
742
743         case IF_DV_3DI: // DV_3DI  .........XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (scalar by elem)
744             assert(isValidScalarDatasize(id->idOpSize()));
745             assert(insOptsNone(id->idInsOpt()));
746             assert(isVectorRegister(id->idReg1()));
747             assert(isVectorRegister(id->idReg2()));
748             assert(isVectorRegister(id->idReg3()));
749             elemsize = id->idOpSize();
750             assert(isValidVectorIndex(EA_16BYTE, elemsize, emitGetInsSC(id)));
751             break;
752
753         case IF_DV_3E: // DV_3E   ...........mmmmm ......nnnnnddddd      Vd Vn Vm  (scalar)
754             assert(insOptsNone(id->idInsOpt()));
755             assert(id->idOpSize() == EA_8BYTE);
756             assert(isVectorRegister(id->idReg1()));
757             assert(isVectorRegister(id->idReg2()));
758             assert(isVectorRegister(id->idReg3()));
759             break;
760
761         case IF_DV_4A: // DR_4A   .........X.mmmmm .aaaaannnnnddddd      Rd Rn Rm Ra (scalar)
762             assert(isValidGeneralDatasize(id->idOpSize()));
763             assert(isVectorRegister(id->idReg1()));
764             assert(isVectorRegister(id->idReg2()));
765             assert(isVectorRegister(id->idReg3()));
766             assert(isVectorRegister(id->idReg4()));
767             break;
768
769         case IF_SN_0A: // SN_0A   ................ ................
770         case IF_SI_0A: // SI_0A   ...........iiiii iiiiiiiiiii.....               imm16
771         case IF_SI_0B: // SI_0B   ................ ....bbbb........               imm4 - barrier
772             break;
773
774         default:
775             printf("unexpected format %s\n", emitIfName(id->idInsFmt()));
776             assert(!"Unexpected format");
777             break;
778     }
779 }
780 #endif // DEBUG
781
782 bool emitter::emitInsMayWriteToGCReg(instrDesc* id)
783 {
784     instruction ins = id->idIns();
785     insFormat   fmt = id->idInsFmt();
786
787     switch (fmt)
788     {
789
790         // These are the formats with "destination" registers:
791
792         case IF_DI_1B: // DI_1B   X........hwiiiii iiiiiiiiiiiddddd      Rd       imm(i16,hw)
793         case IF_DI_1D: // DI_1D   X........Nrrrrrr ssssss.....ddddd      Rd       imm(N,r,s)
794         case IF_DI_1E: // DI_1E   .ii.....iiiiiiii iiiiiiiiiiiddddd      Rd       simm21
795
796         case IF_DI_2A: // DI_2A   X.......shiiiiii iiiiiinnnnnddddd      Rd Rn    imm(i12,sh)
797         case IF_DI_2B: // DI_2B   X.........Xnnnnn ssssssnnnnnddddd      Rd Rn    imm(0-63)
798         case IF_DI_2C: // DI_2C   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imm(N,r,s)
799         case IF_DI_2D: // DI_2D   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imr, imms   (N,r,s)
800
801         case IF_DR_1D: // DR_1D   X............... cccc.......ddddd      Rd       cond
802
803         case IF_DR_2D: // DR_2D   X..........nnnnn cccc..nnnnnddddd      Rd Rn    cond
804         case IF_DR_2E: // DR_2E   X..........mmmmm ...........ddddd      Rd    Rm
805         case IF_DR_2F: // DR_2F   X.......sh.mmmmm ssssss.....ddddd      Rd    Rm {LSL,LSR,ASR} imm(0-63)
806         case IF_DR_2G: // DR_2G   X............... ......nnnnnddddd      Rd Rn
807         case IF_DR_2H: // DR_2H   X........X...... ......nnnnnddddd      Rd Rn
808
809         case IF_DR_3A: // DR_3A   X..........mmmmm ......nnnnnddddd      Rd Rn Rm
810         case IF_DR_3B: // DR_3B   X.......sh.mmmmm ssssssnnnnnddddd      Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
811         case IF_DR_3C: // DR_3C   X..........mmmmm xxxsssnnnnnddddd      Rd Rn Rm ext(Rm) LSL imm(0-4)
812         case IF_DR_3D: // DR_3D   X..........mmmmm cccc..nnnnnddddd      Rd Rn Rm cond
813         case IF_DR_3E: // DR_3E   X........X.mmmmm ssssssnnnnnddddd      Rd Rn Rm imm(0-63)
814
815         case IF_DR_4A: // DR_4A   X..........mmmmm .aaaaannnnnddddd      Rd Rn Rm Ra
816
817         case IF_DV_2B: // DV_2B   .Q.........iiiii ......nnnnnddddd      Rd Vn[]    (umov - to general)
818         case IF_DV_2H: // DV_2H   X........X...... ......nnnnnddddd      Rd Vn      (fmov - to general)
819
820             return true;
821
822         case IF_DV_2C:  // DV_2C   .Q.........iiiii ......nnnnnddddd      Vd Rn      (dup/ins - vector from general)
823         case IF_DV_2D:  // DV_2D   .Q.........iiiii ......nnnnnddddd      Vd Vn[]    (dup - vector)
824         case IF_DV_2E:  // DV_2E   ...........iiiii ......nnnnnddddd      Vd Vn[]    (dup - scalar)
825         case IF_DV_2F:  // DV_2F   ...........iiiii .jjjj.nnnnnddddd      Vd[] Vn[]  (ins - element)
826         case IF_DV_2G:  // DV_2G   .........X...... ......nnnnnddddd      Vd Vn      (fmov, fcvtXX - register)
827         case IF_DV_2I:  // DV_2I   X........X...... ......nnnnnddddd      Vd Rn      (fmov - from general)
828         case IF_DV_2J:  // DV_2J   ........SS.....D D.....nnnnnddddd      Vd Vn      (fcvt)
829         case IF_DV_2K:  // DV_2K   .........X.mmmmm ......nnnnn.....      Vn Vm      (fcmp)
830         case IF_DV_2L:  // DV_2L   ........XX...... ......nnnnnddddd      Vd Vn      (abs, neg - scalar)
831         case IF_DV_2M:  // DV_2M   .Q......XX...... ......nnnnnddddd      Vd Vn      (abs, neg - vector)
832         case IF_DV_3A:  // DV_3A   .Q......XX.mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
833         case IF_DV_3AI: // DV_3AI  .Q......XXLMmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector)
834         case IF_DV_3B:  // DV_3B   .Q.......X.mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
835         case IF_DV_3BI: // DV_3BI  .Q.......XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector by elem)
836         case IF_DV_3C:  // DV_3C   .Q.........mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
837         case IF_DV_3D:  // DV_3D   .........X.mmmmm ......nnnnnddddd      Vd Vn Vm   (scalar)
838         case IF_DV_3DI: // DV_3DI  .........XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (scalar by elem)
839         case IF_DV_3E:  // DV_3E   ...........mmmmm ......nnnnnddddd      Vd Vn Vm   (scalar)
840         case IF_DV_4A:  // DV_4A   .........X.mmmmm .aaaaannnnnddddd      Vd Va Vn Vm (scalar)
841             // Tracked GC pointers cannot be placed into the SIMD registers.
842             return false;
843
844         // These are the load/store formats with "target" registers:
845
846         case IF_LS_1A: // LS_1A   XX...V..iiiiiiii iiiiiiiiiiittttt      Rt    PC imm(1MB)
847         case IF_LS_2A: // LS_2A   .X.......X...... ......nnnnnttttt      Rt Rn
848         case IF_LS_2B: // LS_2B   .X.......Xiiiiii iiiiiinnnnnttttt      Rt Rn    imm(0-4095)
849         case IF_LS_2C: // LS_2C   .X.......X.iiiii iiiiP.nnnnnttttt      Rt Rn    imm(-256..+255) pre/post inc
850         case IF_LS_3A: // LS_3A   .X.......X.mmmmm xxxS..nnnnnttttt      Rt Rn Rm ext(Rm) LSL {}
851         case IF_LS_3B: // LS_3B   X............... .aaaaannnnnttttt      Rt Ra Rn
852         case IF_LS_3C: // LS_3C   X.........iiiiii iaaaaannnnnttttt      Rt Ra Rn imm(im7,sh)
853         case IF_LS_3D: // LS_3D   .X.......X.mmmmm ......nnnnnttttt      Wm Rt Rn
854
855             // For the Store instructions the "target" register is actually a "source" value
856
857             if (emitInsIsStore(ins))
858             {
859                 return false;
860             }
861             else
862             {
863                 assert(emitInsIsLoad(ins));
864                 return true;
865             }
866
867         default:
868             return false;
869     }
870 }
871
872 bool emitter::emitInsWritesToLclVarStackLoc(instrDesc* id)
873 {
874     if (!id->idIsLclVar())
875         return false;
876
877     instruction ins = id->idIns();
878
879     // This list is related to the list of instructions used to store local vars in emitIns_S_R().
880     // We don't accept writing to float local vars.
881
882     switch (ins)
883     {
884         case INS_strb:
885         case INS_strh:
886         case INS_str:
887         case INS_stur:
888         case INS_sturb:
889         case INS_sturh:
890             return true;
891         default:
892             return false;
893     }
894 }
895
896 bool emitter::emitInsWritesToLclVarStackLocPair(instrDesc* id)
897 {
898     if (!id->idIsLclVar())
899         return false;
900
901     instruction ins = id->idIns();
902
903     // This list is related to the list of instructions used to store local vars in emitIns_S_S_R_R().
904     // We don't accept writing to float local vars.
905
906     switch (ins)
907     {
908         case INS_stnp:
909         case INS_stp:
910             return true;
911         default:
912             return false;
913     }
914 }
915
916 bool emitter::emitInsMayWriteMultipleRegs(instrDesc* id)
917 {
918     instruction ins = id->idIns();
919
920     switch (ins)
921     {
922         case INS_ldp:
923         case INS_ldpsw:
924         case INS_ldnp:
925             return true;
926         default:
927             return false;
928     }
929 }
930
931 // For the small loads/store instruction we adjust the size 'attr'
932 // depending upon whether we have a load or a store
933 //
934 emitAttr emitter::emitInsAdjustLoadStoreAttr(instruction ins, emitAttr attr)
935 {
936     if (EA_SIZE(attr) <= EA_4BYTE)
937     {
938         if (emitInsIsLoad(ins))
939         {
940             // The value of 'ins' encodes the size to load
941             // we use EA_8BYTE here because it is the size we will write (into dataReg)
942             // it is also required when ins is INS_ldrsw
943             //
944             attr = EA_8BYTE;
945         }
946         else
947         {
948             assert(emitInsIsStore(ins));
949
950             // The value of 'ins' encodes the size to store
951             // we use EA_4BYTE here because it is the size of the register
952             // that we want to display when storing small values
953             //
954             attr = EA_4BYTE;
955         }
956     }
957     return attr;
958 }
959
960 // Takes an instrDesc 'id' and uses the instruction 'ins' to determine the
961 // size of the target register that is written or read by the instruction.
962 // Note that even if EA_4BYTE is returned a load instruction will still
963 // always zero the upper 4 bytes of the target register.
964 // This method is required so that we can distinguish between loads that are
965 // sign-extending as they can have two different sizes for their target register.
966 // Additionally for instructions like 'ldr' and 'str' these can load/store
967 // either 4 byte or 8 bytes to/from the target register.
968 // By convention the small unsigned load instructions are considered to write
969 // a 4 byte sized target register, though since these also zero the upper 4 bytes
970 // they could equally be considered to write the unsigned value to full 8 byte register.
971 //
972 emitAttr emitter::emitInsTargetRegSize(instrDesc* id)
973 {
974     instruction ins    = id->idIns();
975     emitAttr    result = EA_UNKNOWN;
976
977     // This is used to determine the size of the target registers for a load/store instruction
978
979     switch (ins)
980     {
981         case INS_ldxrb:
982         case INS_ldarb:
983         case INS_ldaxrb:
984         case INS_stxrb:
985         case INS_stlrb:
986         case INS_stlxrb:
987         case INS_ldrb:
988         case INS_strb:
989         case INS_ldurb:
990         case INS_sturb:
991             result = EA_4BYTE;
992             break;
993
994         case INS_ldxrh:
995         case INS_ldarh:
996         case INS_ldaxrh:
997         case INS_stxrh:
998         case INS_stlrh:
999         case INS_stlxrh:
1000         case INS_ldrh:
1001         case INS_strh:
1002         case INS_ldurh:
1003         case INS_sturh:
1004             result = EA_4BYTE;
1005             break;
1006
1007         case INS_ldrsb:
1008         case INS_ldursb:
1009         case INS_ldrsh:
1010         case INS_ldursh:
1011             if (id->idOpSize() == EA_8BYTE)
1012                 result = EA_8BYTE;
1013             else
1014                 result = EA_4BYTE;
1015             break;
1016
1017         case INS_ldrsw:
1018         case INS_ldursw:
1019         case INS_ldpsw:
1020             result = EA_8BYTE;
1021             break;
1022
1023         case INS_ldp:
1024         case INS_stp:
1025         case INS_ldnp:
1026         case INS_stnp:
1027             result = id->idOpSize();
1028             break;
1029
1030         case INS_ldxr:
1031         case INS_ldar:
1032         case INS_ldaxr:
1033         case INS_stxr:
1034         case INS_stlr:
1035         case INS_stlxr:
1036         case INS_ldr:
1037         case INS_str:
1038         case INS_ldur:
1039         case INS_stur:
1040             result = id->idOpSize();
1041             break;
1042
1043         default:
1044             NO_WAY("unexpected instruction");
1045             break;
1046     }
1047     return result;
1048 }
1049
1050 // Takes an instrDesc and uses the instruction to determine the 'size' of the
1051 // data that is loaded from memory.
1052 //
1053 emitAttr emitter::emitInsLoadStoreSize(instrDesc* id)
1054 {
1055     instruction ins    = id->idIns();
1056     emitAttr    result = EA_UNKNOWN;
1057
1058     // The 'result' returned is the 'size' of the data that is loaded from memory.
1059
1060     switch (ins)
1061     {
1062         case INS_ldarb:
1063         case INS_stlrb:
1064         case INS_ldrb:
1065         case INS_strb:
1066         case INS_ldurb:
1067         case INS_sturb:
1068         case INS_ldrsb:
1069         case INS_ldursb:
1070             result = EA_1BYTE;
1071             break;
1072
1073         case INS_ldarh:
1074         case INS_stlrh:
1075         case INS_ldrh:
1076         case INS_strh:
1077         case INS_ldurh:
1078         case INS_sturh:
1079         case INS_ldrsh:
1080         case INS_ldursh:
1081             result = EA_2BYTE;
1082             break;
1083
1084         case INS_ldrsw:
1085         case INS_ldursw:
1086         case INS_ldpsw:
1087             result = EA_4BYTE;
1088             break;
1089
1090         case INS_ldp:
1091         case INS_stp:
1092         case INS_ldnp:
1093         case INS_stnp:
1094             result = id->idOpSize();
1095             break;
1096
1097         case INS_ldar:
1098         case INS_stlr:
1099         case INS_ldr:
1100         case INS_str:
1101         case INS_ldur:
1102         case INS_stur:
1103             result = id->idOpSize();
1104             break;
1105
1106         default:
1107             NO_WAY("unexpected instruction");
1108             break;
1109     }
1110     return result;
1111 }
1112
1113 /*****************************************************************************/
1114 #ifdef DEBUG
1115
1116 // clang-format off
1117 static const char * const  xRegNames[] =
1118 {
1119     #define REGDEF(name, rnum, mask, xname, wname) xname,
1120     #include "register.h"
1121 };
1122
1123 static const char * const  wRegNames[] =
1124 {
1125     #define REGDEF(name, rnum, mask, xname, wname) wname,
1126     #include "register.h"
1127 };
1128
1129 static const char * const  vRegNames[] =
1130 {
1131     "v0",  "v1",  "v2",  "v3",  "v4", 
1132     "v5",  "v6",  "v7",  "v8",  "v9", 
1133     "v10", "v11", "v12", "v13", "v14", 
1134     "v15", "v16", "v17", "v18", "v19", 
1135     "v20", "v21", "v22", "v23", "v24", 
1136     "v25", "v26", "v27", "v28", "v29",
1137     "v30", "v31"
1138 };
1139
1140 static const char * const  qRegNames[] =
1141 {
1142     "q0",  "q1",  "q2",  "q3",  "q4", 
1143     "q5",  "q6",  "q7",  "q8",  "q9", 
1144     "q10", "q11", "q12", "q13", "q14", 
1145     "q15", "q16", "q17", "q18", "q19", 
1146     "q20", "q21", "q22", "q23", "q24", 
1147     "q25", "q26", "q27", "q28", "q29",
1148     "q30", "q31"
1149 };
1150
1151 static const char * const  hRegNames[] =
1152 {
1153     "h0",  "h1",  "h2",  "h3",  "h4", 
1154     "h5",  "h6",  "h7",  "h8",  "h9", 
1155     "h10", "h11", "h12", "h13", "h14", 
1156     "h15", "h16", "h17", "h18", "h19", 
1157     "h20", "h21", "h22", "h23", "h24", 
1158     "h25", "h26", "h27", "h28", "h29",
1159     "h30", "h31"
1160 };
1161 static const char * const  bRegNames[] =
1162 {
1163     "b0",  "b1",  "b2",  "b3",  "b4", 
1164     "b5",  "b6",  "b7",  "b8",  "b9", 
1165     "b10", "b11", "b12", "b13", "b14", 
1166     "b15", "b16", "b17", "b18", "b19", 
1167     "b20", "b21", "b22", "b23", "b24", 
1168     "b25", "b26", "b27", "b28", "b29",
1169     "b30", "b31"
1170 };
1171 // clang-format on
1172
1173 /*****************************************************************************
1174  *
1175  *  Return a string that represents the given register.
1176  */
1177
1178 const char* emitter::emitRegName(regNumber reg, emitAttr size, bool varName)
1179 {
1180     assert(reg < REG_COUNT);
1181
1182     const char* rn = nullptr;
1183
1184     if (size == EA_8BYTE)
1185     {
1186         rn = xRegNames[reg];
1187     }
1188     else if (size == EA_4BYTE)
1189     {
1190         rn = wRegNames[reg];
1191     }
1192     else if (isVectorRegister(reg))
1193     {
1194         if (size == EA_16BYTE)
1195         {
1196             rn = qRegNames[reg - REG_V0];
1197         }
1198         else if (size == EA_2BYTE)
1199         {
1200             rn = hRegNames[reg - REG_V0];
1201         }
1202         else if (size == EA_1BYTE)
1203         {
1204             rn = bRegNames[reg - REG_V0];
1205         }
1206     }
1207
1208     assert(rn != nullptr);
1209
1210     return rn;
1211 }
1212
1213 /*****************************************************************************
1214  *
1215  *  Return a string that represents the given register.
1216  */
1217
1218 const char* emitter::emitVectorRegName(regNumber reg)
1219 {
1220     assert((reg >= REG_V0) && (reg <= REG_V31));
1221
1222     int index = (int)reg - (int)REG_V0;
1223
1224     return vRegNames[index];
1225 }
1226 #endif // DEBUG
1227
1228 /*****************************************************************************
1229  *
1230  *  Returns the base encoding of the given CPU instruction.
1231  */
1232
1233 emitter::insFormat emitter::emitInsFormat(instruction ins)
1234 {
1235     // clang-format off
1236     const static insFormat insFormats[] =
1237     {
1238         #define INST1(id, nm, fp, ldst, fmt, e1                                ) fmt,
1239         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            ) fmt,
1240         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        ) fmt,
1241         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    ) fmt,
1242         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                ) fmt,
1243         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            ) fmt,
1244         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) fmt,
1245         #include "instrs.h"
1246     };
1247     // clang-format on
1248
1249     assert(ins < ArrLen(insFormats));
1250     assert((insFormats[ins] != IF_NONE));
1251
1252     return insFormats[ins];
1253 }
1254
1255 // INST_FP is 1
1256 #define LD 2
1257 #define ST 4
1258 #define CMP 8
1259
1260 // clang-format off
1261 /*static*/ const BYTE CodeGenInterface::instInfo[] =
1262 {
1263     #define INST1(id, nm, fp, ldst, fmt, e1                                ) ldst | INST_FP*fp,
1264     #define INST2(id, nm, fp, ldst, fmt, e1, e2                            ) ldst | INST_FP*fp,
1265     #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        ) ldst | INST_FP*fp,
1266     #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    ) ldst | INST_FP*fp,
1267     #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                ) ldst | INST_FP*fp,
1268     #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            ) ldst | INST_FP*fp,
1269     #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) ldst | INST_FP*fp,
1270     #include "instrs.h"
1271 };
1272 // clang-format on
1273
1274 /*****************************************************************************
1275  *
1276  *  Returns true if the instruction is some kind of compare or test instruction
1277  */
1278
1279 bool emitter::emitInsIsCompare(instruction ins)
1280 {
1281     // We have pseudo ins like lea which are not included in emitInsLdStTab.
1282     if (ins < ArrLen(CodeGenInterface::instInfo))
1283         return (CodeGenInterface::instInfo[ins] & CMP) ? true : false;
1284     else
1285         return false;
1286 }
1287
1288 /*****************************************************************************
1289  *
1290  *  Returns true if the instruction is some kind of load instruction
1291  */
1292
1293 bool emitter::emitInsIsLoad(instruction ins)
1294 {
1295     // We have pseudo ins like lea which are not included in emitInsLdStTab.
1296     if (ins < ArrLen(CodeGenInterface::instInfo))
1297         return (CodeGenInterface::instInfo[ins] & LD) ? true : false;
1298     else
1299         return false;
1300 }
1301 /*****************************************************************************
1302  *
1303  *  Returns true if the instruction is some kind of store instruction
1304  */
1305
1306 bool emitter::emitInsIsStore(instruction ins)
1307 {
1308     // We have pseudo ins like lea which are not included in emitInsLdStTab.
1309     if (ins < ArrLen(CodeGenInterface::instInfo))
1310         return (CodeGenInterface::instInfo[ins] & ST) ? true : false;
1311     else
1312         return false;
1313 }
1314
1315 /*****************************************************************************
1316  *
1317  *  Returns true if the instruction is some kind of load/store instruction
1318  */
1319
1320 bool emitter::emitInsIsLoadOrStore(instruction ins)
1321 {
1322     // We have pseudo ins like lea which are not included in emitInsLdStTab.
1323     if (ins < ArrLen(CodeGenInterface::instInfo))
1324         return (CodeGenInterface::instInfo[ins] & (LD | ST)) ? true : false;
1325     else
1326         return false;
1327 }
1328
1329 #undef LD
1330 #undef ST
1331 #undef CMP
1332
1333 /*****************************************************************************
1334  *
1335  *  Returns the specific encoding of the given CPU instruction and format
1336  */
1337
1338 emitter::code_t emitter::emitInsCode(instruction ins, insFormat fmt)
1339 {
1340     // clang-format off
1341     const static code_t insCodes1[] =
1342     {
1343         #define INST1(id, nm, fp, ldst, fmt, e1                                ) e1,
1344         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            ) e1,
1345         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        ) e1,
1346         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    ) e1,
1347         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                ) e1,
1348         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            ) e1,
1349         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e1,
1350         #include "instrs.h"
1351     };
1352     const static code_t insCodes2[] =
1353     {
1354         #define INST1(id, nm, fp, ldst, fmt, e1                                )
1355         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            ) e2,
1356         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        ) e2,
1357         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    ) e2,
1358         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                ) e2,
1359         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            ) e2,
1360         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e2,
1361         #include "instrs.h"
1362     };
1363     const static code_t insCodes3[] =
1364     {
1365         #define INST1(id, nm, fp, ldst, fmt, e1                                )
1366         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            )
1367         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        ) e3,
1368         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    ) e3,
1369         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                ) e3,
1370         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            ) e3,
1371         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e3,
1372         #include "instrs.h"
1373     };
1374     const static code_t insCodes4[] =
1375     {
1376         #define INST1(id, nm, fp, ldst, fmt, e1                                )
1377         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            )
1378         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        )
1379         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    ) e4,
1380         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                ) e4,
1381         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            ) e4,
1382         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e4,
1383         #include "instrs.h"
1384     };
1385     const static code_t insCodes5[] =
1386     {
1387         #define INST1(id, nm, fp, ldst, fmt, e1                                )
1388         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            )
1389         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        )
1390         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    )
1391         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                ) e5,
1392         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            ) e5,
1393         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e5,
1394         #include "instrs.h"
1395     };
1396     const static code_t insCodes6[] =
1397     {
1398         #define INST1(id, nm, fp, ldst, fmt, e1                                )
1399         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            )
1400         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        )
1401         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    )
1402         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                )
1403         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            ) e6,
1404         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e6,
1405         #include "instrs.h"
1406     };
1407     const static code_t insCodes7[] =
1408     {
1409         #define INST1(id, nm, fp, ldst, fmt, e1                                )
1410         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            )
1411         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        )
1412         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    )
1413         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                )
1414         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            )
1415         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e7,
1416         #include "instrs.h"
1417     };
1418     const static code_t insCodes8[] =
1419     {
1420         #define INST1(id, nm, fp, ldst, fmt, e1                                )
1421         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            )
1422         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        )
1423         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    )
1424         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                )
1425         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            )
1426         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e8,
1427         #include "instrs.h"
1428     };
1429     const static code_t insCodes9[] =
1430     {
1431         #define INST1(id, nm, fp, ldst, fmt, e1                                )
1432         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            )
1433         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        )
1434         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    )
1435         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                )
1436         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            )
1437         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e9,
1438         #include "instrs.h"
1439     };
1440     // clang-format on
1441
1442     const static insFormat formatEncode9[9] = {IF_DR_2E, IF_DR_2G, IF_DI_1B, IF_DI_1D, IF_DV_3C,
1443                                                IF_DV_2B, IF_DV_2C, IF_DV_2E, IF_DV_2F};
1444     const static insFormat formatEncode6A[6] = {IF_DR_3A, IF_DR_3B, IF_DR_3C, IF_DI_2A, IF_DV_3A, IF_DV_3E};
1445     const static insFormat formatEncode5A[5] = {IF_LS_2A, IF_LS_2B, IF_LS_2C, IF_LS_3A, IF_LS_1A};
1446     const static insFormat formatEncode5B[5] = {IF_DV_2G, IF_DV_2H, IF_DV_2I, IF_DV_1A, IF_DV_1B};
1447     const static insFormat formatEncode5C[5] = {IF_DR_3A, IF_DR_3B, IF_DI_2C, IF_DV_3C, IF_DV_1B};
1448     const static insFormat formatEncode4A[4] = {IF_LS_2A, IF_LS_2B, IF_LS_2C, IF_LS_3A};
1449     const static insFormat formatEncode4B[4] = {IF_DR_3A, IF_DR_3B, IF_DR_3C, IF_DI_2A};
1450     const static insFormat formatEncode4C[4] = {IF_DR_2A, IF_DR_2B, IF_DR_2C, IF_DI_1A};
1451     const static insFormat formatEncode4D[4] = {IF_DV_3B, IF_DV_3D, IF_DV_3BI, IF_DV_3DI};
1452     const static insFormat formatEncode4E[4] = {IF_DR_3A, IF_DR_3B, IF_DI_2C, IF_DV_3C};
1453     const static insFormat formatEncode4F[4] = {IF_DR_3A, IF_DR_3B, IF_DV_3C, IF_DV_1B};
1454     const static insFormat formatEncode4G[4] = {IF_DR_2E, IF_DR_2F, IF_DV_2M, IF_DV_2L};
1455     const static insFormat formatEncode4H[4] = {IF_DV_3E, IF_DV_3A, IF_DV_2L, IF_DV_2M};
1456     const static insFormat formatEncode4I[4] = {IF_DV_3D, IF_DV_3B, IF_DV_2G, IF_DV_2A};
1457     const static insFormat formatEncode3A[3] = {IF_DR_3A, IF_DR_3B, IF_DI_2C};
1458     const static insFormat formatEncode3B[3] = {IF_DR_2A, IF_DR_2B, IF_DI_1C};
1459     const static insFormat formatEncode3C[3] = {IF_DR_3A, IF_DR_3B, IF_DV_3C};
1460     const static insFormat formatEncode3D[3] = {IF_DV_2C, IF_DV_2D, IF_DV_2E};
1461     const static insFormat formatEncode3E[3] = {IF_DV_3B, IF_DV_3BI, IF_DV_3DI};
1462     const static insFormat formatEncode3F[3] = {IF_DV_2A, IF_DV_2G, IF_DV_2H};
1463     const static insFormat formatEncode3G[3] = {IF_DV_2A, IF_DV_2G, IF_DV_2I};
1464     const static insFormat formatEncode3H[3] = {IF_DR_3A, IF_DV_3A, IF_DV_3AI};
1465     const static insFormat formatEncode3I[3] = {IF_DR_2E, IF_DR_2F, IF_DV_2M};
1466     const static insFormat formatEncode2A[2] = {IF_DR_2E, IF_DR_2F};
1467     const static insFormat formatEncode2B[2] = {IF_DR_3A, IF_DR_3B};
1468     const static insFormat formatEncode2C[2] = {IF_DR_3A, IF_DI_2D};
1469     const static insFormat formatEncode2D[2] = {IF_DR_3A, IF_DI_2B};
1470     const static insFormat formatEncode2E[2] = {IF_LS_3B, IF_LS_3C};
1471     const static insFormat formatEncode2F[2] = {IF_DR_2I, IF_DI_1F};
1472     const static insFormat formatEncode2G[2] = {IF_DV_3B, IF_DV_3D};
1473     const static insFormat formatEncode2H[2] = {IF_DV_2C, IF_DV_2F};
1474     const static insFormat formatEncode2I[2] = {IF_DV_2K, IF_DV_1C};
1475     const static insFormat formatEncode2J[2] = {IF_DV_2A, IF_DV_2G};
1476     const static insFormat formatEncode2K[2] = {IF_DV_2M, IF_DV_2L};
1477     const static insFormat formatEncode2L[2] = {IF_DV_2G, IF_DV_2M};
1478     const static insFormat formatEncode2M[2] = {IF_DV_3A, IF_DV_3AI};
1479     const static insFormat formatEncode2N[2] = {IF_DV_2N, IF_DV_2O};
1480     const static insFormat formatEncode2O[2] = {IF_DV_3E, IF_DV_3A};
1481     const static insFormat formatEncode2P[2] = {IF_DV_2G, IF_DV_3B};
1482
1483     code_t    code           = BAD_CODE;
1484     insFormat insFmt         = emitInsFormat(ins);
1485     bool      encoding_found = false;
1486     int       index          = -1;
1487
1488     switch (insFmt)
1489     {
1490         case IF_EN9:
1491             for (index = 0; index < 9; index++)
1492             {
1493                 if (fmt == formatEncode9[index])
1494                 {
1495                     encoding_found = true;
1496                     break;
1497                 }
1498             }
1499             break;
1500
1501         case IF_EN6A:
1502             for (index = 0; index < 6; index++)
1503             {
1504                 if (fmt == formatEncode6A[index])
1505                 {
1506                     encoding_found = true;
1507                     break;
1508                 }
1509             }
1510             break;
1511
1512         case IF_EN5A:
1513             for (index = 0; index < 5; index++)
1514             {
1515                 if (fmt == formatEncode5A[index])
1516                 {
1517                     encoding_found = true;
1518                     break;
1519                 }
1520             }
1521             break;
1522
1523         case IF_EN5B:
1524             for (index = 0; index < 5; index++)
1525             {
1526                 if (fmt == formatEncode5B[index])
1527                 {
1528                     encoding_found = true;
1529                     break;
1530                 }
1531             }
1532             break;
1533
1534         case IF_EN5C:
1535             for (index = 0; index < 5; index++)
1536             {
1537                 if (fmt == formatEncode5C[index])
1538                 {
1539                     encoding_found = true;
1540                     break;
1541                 }
1542             }
1543             break;
1544
1545         case IF_EN4A:
1546             for (index = 0; index < 4; index++)
1547             {
1548                 if (fmt == formatEncode4A[index])
1549                 {
1550                     encoding_found = true;
1551                     break;
1552                 }
1553             }
1554             break;
1555
1556         case IF_EN4B:
1557             for (index = 0; index < 4; index++)
1558             {
1559                 if (fmt == formatEncode4B[index])
1560                 {
1561                     encoding_found = true;
1562                     break;
1563                 }
1564             }
1565             break;
1566
1567         case IF_EN4C:
1568             for (index = 0; index < 4; index++)
1569             {
1570                 if (fmt == formatEncode4C[index])
1571                 {
1572                     encoding_found = true;
1573                     break;
1574                 }
1575             }
1576             break;
1577
1578         case IF_EN4D:
1579             for (index = 0; index < 4; index++)
1580             {
1581                 if (fmt == formatEncode4D[index])
1582                 {
1583                     encoding_found = true;
1584                     break;
1585                 }
1586             }
1587             break;
1588
1589         case IF_EN4E:
1590             for (index = 0; index < 4; index++)
1591             {
1592                 if (fmt == formatEncode4E[index])
1593                 {
1594                     encoding_found = true;
1595                     break;
1596                 }
1597             }
1598             break;
1599
1600         case IF_EN4F:
1601             for (index = 0; index < 4; index++)
1602             {
1603                 if (fmt == formatEncode4F[index])
1604                 {
1605                     encoding_found = true;
1606                     break;
1607                 }
1608             }
1609             break;
1610
1611         case IF_EN4G:
1612             for (index = 0; index < 4; index++)
1613             {
1614                 if (fmt == formatEncode4G[index])
1615                 {
1616                     encoding_found = true;
1617                     break;
1618                 }
1619             }
1620             break;
1621
1622         case IF_EN4H:
1623             for (index = 0; index < 4; index++)
1624             {
1625                 if (fmt == formatEncode4H[index])
1626                 {
1627                     encoding_found = true;
1628                     break;
1629                 }
1630             }
1631             break;
1632
1633         case IF_EN4I:
1634             for (index = 0; index < 4; index++)
1635             {
1636                 if (fmt == formatEncode4I[index])
1637                 {
1638                     encoding_found = true;
1639                     break;
1640                 }
1641             }
1642             break;
1643
1644         case IF_EN3A:
1645             for (index = 0; index < 3; index++)
1646             {
1647                 if (fmt == formatEncode3A[index])
1648                 {
1649                     encoding_found = true;
1650                     break;
1651                 }
1652             }
1653             break;
1654
1655         case IF_EN3B:
1656             for (index = 0; index < 3; index++)
1657             {
1658                 if (fmt == formatEncode3B[index])
1659                 {
1660                     encoding_found = true;
1661                     break;
1662                 }
1663             }
1664             break;
1665
1666         case IF_EN3C:
1667             for (index = 0; index < 3; index++)
1668             {
1669                 if (fmt == formatEncode3C[index])
1670                 {
1671                     encoding_found = true;
1672                     break;
1673                 }
1674             }
1675             break;
1676
1677         case IF_EN3D:
1678             for (index = 0; index < 3; index++)
1679             {
1680                 if (fmt == formatEncode3D[index])
1681                 {
1682                     encoding_found = true;
1683                     break;
1684                 }
1685             }
1686             break;
1687
1688         case IF_EN3E:
1689             for (index = 0; index < 3; index++)
1690             {
1691                 if (fmt == formatEncode3E[index])
1692                 {
1693                     encoding_found = true;
1694                     break;
1695                 }
1696             }
1697             break;
1698
1699         case IF_EN3F:
1700             for (index = 0; index < 3; index++)
1701             {
1702                 if (fmt == formatEncode3F[index])
1703                 {
1704                     encoding_found = true;
1705                     break;
1706                 }
1707             }
1708             break;
1709
1710         case IF_EN3G:
1711             for (index = 0; index < 3; index++)
1712             {
1713                 if (fmt == formatEncode3G[index])
1714                 {
1715                     encoding_found = true;
1716                     break;
1717                 }
1718             }
1719             break;
1720
1721         case IF_EN3H:
1722             for (index = 0; index < 3; index++)
1723             {
1724                 if (fmt == formatEncode3H[index])
1725                 {
1726                     encoding_found = true;
1727                     break;
1728                 }
1729             }
1730             break;
1731
1732         case IF_EN3I:
1733             for (index = 0; index < 3; index++)
1734             {
1735                 if (fmt == formatEncode3I[index])
1736                 {
1737                     encoding_found = true;
1738                     break;
1739                 }
1740             }
1741             break;
1742
1743         case IF_EN2A:
1744             for (index = 0; index < 2; index++)
1745             {
1746                 if (fmt == formatEncode2A[index])
1747                 {
1748                     encoding_found = true;
1749                     break;
1750                 }
1751             }
1752             break;
1753
1754         case IF_EN2B:
1755             for (index = 0; index < 2; index++)
1756             {
1757                 if (fmt == formatEncode2B[index])
1758                 {
1759                     encoding_found = true;
1760                     break;
1761                 }
1762             }
1763             break;
1764
1765         case IF_EN2C:
1766             for (index = 0; index < 2; index++)
1767             {
1768                 if (fmt == formatEncode2C[index])
1769                 {
1770                     encoding_found = true;
1771                     break;
1772                 }
1773             }
1774             break;
1775
1776         case IF_EN2D:
1777             for (index = 0; index < 2; index++)
1778             {
1779                 if (fmt == formatEncode2D[index])
1780                 {
1781                     encoding_found = true;
1782                     break;
1783                 }
1784             }
1785             break;
1786
1787         case IF_EN2E:
1788             for (index = 0; index < 2; index++)
1789             {
1790                 if (fmt == formatEncode2E[index])
1791                 {
1792                     encoding_found = true;
1793                     break;
1794                 }
1795             }
1796             break;
1797
1798         case IF_EN2F:
1799             for (index = 0; index < 2; index++)
1800             {
1801                 if (fmt == formatEncode2F[index])
1802                 {
1803                     encoding_found = true;
1804                     break;
1805                 }
1806             }
1807             break;
1808
1809         case IF_EN2G:
1810             for (index = 0; index < 2; index++)
1811             {
1812                 if (fmt == formatEncode2G[index])
1813                 {
1814                     encoding_found = true;
1815                     break;
1816                 }
1817             }
1818             break;
1819
1820         case IF_EN2H:
1821             for (index = 0; index < 2; index++)
1822             {
1823                 if (fmt == formatEncode2H[index])
1824                 {
1825                     encoding_found = true;
1826                     break;
1827                 }
1828             }
1829             break;
1830
1831         case IF_EN2I:
1832             for (index = 0; index < 2; index++)
1833             {
1834                 if (fmt == formatEncode2I[index])
1835                 {
1836                     encoding_found = true;
1837                     break;
1838                 }
1839             }
1840             break;
1841
1842         case IF_EN2J:
1843             for (index = 0; index < 2; index++)
1844             {
1845                 if (fmt == formatEncode2J[index])
1846                 {
1847                     encoding_found = true;
1848                     break;
1849                 }
1850             }
1851             break;
1852
1853         case IF_EN2K:
1854             for (index = 0; index < 2; index++)
1855             {
1856                 if (fmt == formatEncode2K[index])
1857                 {
1858                     encoding_found = true;
1859                     break;
1860                 }
1861             }
1862             break;
1863
1864         case IF_EN2L:
1865             for (index = 0; index < 2; index++)
1866             {
1867                 if (fmt == formatEncode2L[index])
1868                 {
1869                     encoding_found = true;
1870                     break;
1871                 }
1872             }
1873             break;
1874
1875         case IF_EN2M:
1876             for (index = 0; index < 2; index++)
1877             {
1878                 if (fmt == formatEncode2M[index])
1879                 {
1880                     encoding_found = true;
1881                     break;
1882                 }
1883             }
1884             break;
1885
1886         case IF_EN2N:
1887             for (index = 0; index < 2; index++)
1888             {
1889                 if (fmt == formatEncode2N[index])
1890                 {
1891                     encoding_found = true;
1892                     break;
1893                 }
1894             }
1895             break;
1896
1897         case IF_EN2O:
1898             for (index = 0; index < 2; index++)
1899             {
1900                 if (fmt == formatEncode2O[index])
1901                 {
1902                     encoding_found = true;
1903                     break;
1904                 }
1905             }
1906             break;
1907
1908         case IF_EN2P:
1909             for (index = 0; index < 2; index++)
1910             {
1911                 if (fmt == formatEncode2P[index])
1912                 {
1913                     encoding_found = true;
1914                     break;
1915                 }
1916             }
1917             break;
1918
1919         case IF_BI_0A:
1920         case IF_BI_0B:
1921         case IF_BI_0C:
1922         case IF_BI_1A:
1923         case IF_BI_1B:
1924         case IF_BR_1A:
1925         case IF_BR_1B:
1926         case IF_LS_1A:
1927         case IF_LS_2A:
1928         case IF_LS_2B:
1929         case IF_LS_2C:
1930         case IF_LS_3A:
1931         case IF_LS_3B:
1932         case IF_LS_3C:
1933         case IF_LS_3D:
1934         case IF_DI_1A:
1935         case IF_DI_1B:
1936         case IF_DI_1C:
1937         case IF_DI_1D:
1938         case IF_DI_1E:
1939         case IF_DI_1F:
1940         case IF_DI_2A:
1941         case IF_DI_2B:
1942         case IF_DI_2C:
1943         case IF_DI_2D:
1944         case IF_DR_1D:
1945         case IF_DR_2A:
1946         case IF_DR_2B:
1947         case IF_DR_2C:
1948         case IF_DR_2D:
1949         case IF_DR_2E:
1950         case IF_DR_2F:
1951         case IF_DR_2G:
1952         case IF_DR_2H:
1953         case IF_DR_2I:
1954         case IF_DR_3A:
1955         case IF_DR_3B:
1956         case IF_DR_3C:
1957         case IF_DR_3D:
1958         case IF_DR_3E:
1959         case IF_DR_4A:
1960         case IF_DV_1A:
1961         case IF_DV_1B:
1962         case IF_DV_1C:
1963         case IF_DV_2A:
1964         case IF_DV_2B:
1965         case IF_DV_2C:
1966         case IF_DV_2D:
1967         case IF_DV_2E:
1968         case IF_DV_2F:
1969         case IF_DV_2G:
1970         case IF_DV_2H:
1971         case IF_DV_2I:
1972         case IF_DV_2J:
1973         case IF_DV_2K:
1974         case IF_DV_2L:
1975         case IF_DV_2M:
1976         case IF_DV_2N:
1977         case IF_DV_2O:
1978         case IF_DV_3A:
1979         case IF_DV_3AI:
1980         case IF_DV_3B:
1981         case IF_DV_3BI:
1982         case IF_DV_3C:
1983         case IF_DV_3D:
1984         case IF_DV_3DI:
1985         case IF_DV_3E:
1986         case IF_DV_4A:
1987         case IF_SN_0A:
1988         case IF_SI_0A:
1989         case IF_SI_0B:
1990
1991             index          = 0;
1992             encoding_found = true;
1993             break;
1994
1995         default:
1996
1997             encoding_found = false;
1998             break;
1999     }
2000
2001     assert(encoding_found);
2002
2003     switch (index)
2004     {
2005         case 0:
2006             assert(ins < ArrLen(insCodes1));
2007             code = insCodes1[ins];
2008             break;
2009         case 1:
2010             assert(ins < ArrLen(insCodes2));
2011             code = insCodes2[ins];
2012             break;
2013         case 2:
2014             assert(ins < ArrLen(insCodes3));
2015             code = insCodes3[ins];
2016             break;
2017         case 3:
2018             assert(ins < ArrLen(insCodes4));
2019             code = insCodes4[ins];
2020             break;
2021         case 4:
2022             assert(ins < ArrLen(insCodes5));
2023             code = insCodes5[ins];
2024             break;
2025         case 5:
2026             assert(ins < ArrLen(insCodes6));
2027             code = insCodes6[ins];
2028             break;
2029         case 6:
2030             assert(ins < ArrLen(insCodes7));
2031             code = insCodes7[ins];
2032             break;
2033         case 7:
2034             assert(ins < ArrLen(insCodes8));
2035             code = insCodes8[ins];
2036             break;
2037         case 8:
2038             assert(ins < ArrLen(insCodes9));
2039             code = insCodes9[ins];
2040             break;
2041     }
2042
2043     assert((code != BAD_CODE));
2044
2045     return code;
2046 }
2047
2048 // true if this 'imm' can be encoded as a input operand to a mov instruction
2049 /*static*/ bool emitter::emitIns_valid_imm_for_mov(INT64 imm, emitAttr size)
2050 {
2051     // Check for "MOV (wide immediate)".
2052     if (canEncodeHalfwordImm(imm, size))
2053         return true;
2054
2055     // Next try the ones-complement form of 'halfword immediate' imm(i16,hw),
2056     // namely "MOV (inverted wide immediate)".
2057     ssize_t notOfImm = NOT_helper(imm, getBitWidth(size));
2058     if (canEncodeHalfwordImm(notOfImm, size))
2059         return true;
2060
2061     // Finally try "MOV (bitmask immediate)" imm(N,r,s)
2062     if (canEncodeBitMaskImm(imm, size))
2063         return true;
2064
2065     return false;
2066 }
2067
2068 // true if this 'imm' can be encoded as a input operand to a vector movi instruction
2069 /*static*/ bool emitter::emitIns_valid_imm_for_movi(INT64 imm, emitAttr elemsize)
2070 {
2071     if (elemsize == EA_8BYTE)
2072     {
2073         UINT64 uimm = imm;
2074         while (uimm != 0)
2075         {
2076             INT64 loByte = uimm & 0xFF;
2077             if ((loByte == 0) || (loByte == 0xFF))
2078             {
2079                 uimm >>= 8;
2080             }
2081             else
2082             {
2083                 return false;
2084             }
2085         }
2086         assert(uimm == 0);
2087         return true;
2088     }
2089     else
2090     {
2091         // First try the standard 'byteShifted immediate' imm(i8,bySh)
2092         if (canEncodeByteShiftedImm(imm, elemsize, true))
2093             return true;
2094
2095         // Next try the ones-complement form of the 'immediate' imm(i8,bySh)
2096         ssize_t notOfImm = NOT_helper(imm, getBitWidth(elemsize));
2097         if (canEncodeByteShiftedImm(notOfImm, elemsize, true))
2098             return true;
2099     }
2100     return false;
2101 }
2102
2103 // true if this 'imm' can be encoded as a input operand to a fmov instruction
2104 /*static*/ bool emitter::emitIns_valid_imm_for_fmov(double immDbl)
2105 {
2106     if (canEncodeFloatImm8(immDbl))
2107         return true;
2108
2109     return false;
2110 }
2111
2112 // true if this 'imm' can be encoded as a input operand to an add instruction
2113 /*static*/ bool emitter::emitIns_valid_imm_for_add(INT64 imm, emitAttr size)
2114 {
2115     if (unsigned_abs(imm) <= 0x0fff)
2116         return true;
2117     else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
2118         return true;
2119
2120     return false;
2121 }
2122
2123 // true if this 'imm' can be encoded as a input operand to an non-add/sub alu instruction
2124 /*static*/ bool emitter::emitIns_valid_imm_for_cmp(INT64 imm, emitAttr size)
2125 {
2126     return emitIns_valid_imm_for_add(imm, size);
2127 }
2128
2129 // true if this 'imm' can be encoded as a input operand to an non-add/sub alu instruction
2130 /*static*/ bool emitter::emitIns_valid_imm_for_alu(INT64 imm, emitAttr size)
2131 {
2132     if (canEncodeBitMaskImm(imm, size))
2133         return true;
2134
2135     return false;
2136 }
2137
2138 // true if this 'imm' can be encoded as the offset in a ldr/str instruction
2139 /*static*/ bool emitter::emitIns_valid_imm_for_ldst_offset(INT64 imm, emitAttr attr)
2140 {
2141     if (imm == 0)
2142         return true; // Encodable using IF_LS_2A
2143
2144     if ((imm >= -256) && (imm <= 255))
2145         return true; // Encodable using IF_LS_2C (or possibly IF_LS_2B)
2146
2147     if (imm < 0)
2148         return false; // not encodable
2149
2150     emitAttr size  = EA_SIZE(attr);
2151     unsigned scale = NaturalScale_helper(size);
2152     ssize_t  mask  = size - 1; // the mask of low bits that must be zero to encode the immediate
2153
2154     if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
2155         return true; // Encodable using IF_LS_2B
2156
2157     return false; // not encodable
2158 }
2159
2160 /************************************************************************
2161  *
2162  *   A helper method to return the natural scale for an EA 'size'
2163  */
2164
2165 /*static*/ unsigned emitter::NaturalScale_helper(emitAttr size)
2166 {
2167     assert(size == EA_1BYTE || size == EA_2BYTE || size == EA_4BYTE || size == EA_8BYTE || size == EA_16BYTE);
2168
2169     unsigned result = 0;
2170     unsigned utemp  = (unsigned)size;
2171
2172     // Compute log base 2 of utemp (aka 'size')
2173     while (utemp > 1)
2174     {
2175         result++;
2176         utemp >>= 1;
2177     }
2178
2179     return result;
2180 }
2181
2182 /************************************************************************
2183  *
2184  *  A helper method to perform a Rotate-Right shift operation
2185  *  the source is 'value' and it is rotated right by 'sh' bits
2186  *  'value' is considered to be a fixed size 'width' set of bits.
2187  *
2188  *  Example
2189  *      value is '00001111', sh is 2 and width is 8
2190  *     result is '11000011'
2191  */
2192
2193 /*static*/ UINT64 emitter::ROR_helper(UINT64 value, unsigned sh, unsigned width)
2194 {
2195     assert(width <= 64);
2196     // Check that 'value' fits in 'width' bits
2197     assert((width == 64) || (value < (1ULL << width)));
2198     // We don't support shifts >= width
2199     assert(sh < width);
2200
2201     UINT64 result;
2202
2203     unsigned rsh = sh;
2204     unsigned lsh = width - rsh;
2205
2206     result = (value >> rsh);
2207     result |= (value << lsh);
2208
2209     if (width < 64)
2210     {
2211         // mask off any extra bits that we got from the left shift
2212         result &= ((1ULL << width) - 1);
2213     }
2214     return result;
2215 }
2216 /************************************************************************
2217  *
2218  *  A helper method to perform a 'NOT' bitwise complement operation.
2219  *  'value' is considered to be a fixed size 'width' set of bits.
2220  *
2221  *  Example
2222  *      value is '01001011', and width is 8
2223  *     result is '10110100'
2224  */
2225
2226 /*static*/ UINT64 emitter::NOT_helper(UINT64 value, unsigned width)
2227 {
2228     assert(width <= 64);
2229
2230     UINT64 result = ~value;
2231
2232     if (width < 64)
2233     {
2234         // Check that 'value' fits in 'width' bits. Don't consider "sign" bits above width.
2235         UINT64 maxVal       = 1ULL << width;
2236         UINT64 lowBitsMask  = maxVal - 1;
2237         UINT64 signBitsMask = ~lowBitsMask | (1ULL << (width - 1)); // The high bits must be set, and the top bit
2238                                                                     // (sign bit) must be set.
2239         assert((value < maxVal) || ((value & signBitsMask) == signBitsMask));
2240
2241         // mask off any extra bits that we got from the complement operation
2242         result &= lowBitsMask;
2243     }
2244
2245     return result;
2246 }
2247
2248 /************************************************************************
2249  *
2250  *  A helper method to perform a bit Replicate operation
2251  *  the source is 'value' with a fixed size 'width' set of bits.
2252  *  value is replicated to fill out 32 or 64 bits as determined by 'size'.
2253  *
2254  *  Example
2255  *      value is '11000011' (0xE3), width is 8 and size is EA_8BYTE
2256  *     result is '11000011 11000011 11000011 11000011 11000011 11000011 11000011 11000011'
2257  *               0xE3E3E3E3E3E3E3E3
2258  */
2259
2260 /*static*/ UINT64 emitter::Replicate_helper(UINT64 value, unsigned width, emitAttr size)
2261 {
2262     assert(emitter::isValidGeneralDatasize(size));
2263
2264     unsigned immWidth = (size == EA_8BYTE) ? 64 : 32;
2265     assert(width <= immWidth);
2266
2267     UINT64   result     = value;
2268     unsigned filledBits = width;
2269
2270     while (filledBits < immWidth)
2271     {
2272         value <<= width;
2273         result |= value;
2274         filledBits += width;
2275     }
2276     return result;
2277 }
2278
2279 /************************************************************************
2280  *
2281  *  Convert an imm(N,r,s) into a 64-bit immediate
2282  *  inputs 'bmImm' a bitMaskImm struct
2283  *         'size' specifies the size of the result (64 or 32 bits)
2284  */
2285
2286 /*static*/ INT64 emitter::emitDecodeBitMaskImm(const emitter::bitMaskImm bmImm, emitAttr size)
2287 {
2288     assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2289
2290     unsigned N = bmImm.immN; // read the N,R and S values from the 'bitMaskImm' encoding
2291     unsigned R = bmImm.immR;
2292     unsigned S = bmImm.immS;
2293
2294     unsigned elemWidth = 64; // used when immN == 1
2295
2296     if (bmImm.immN == 0) // find the smaller elemWidth when immN == 0
2297     {
2298         // Scan S for the highest bit not set
2299         elemWidth = 32;
2300         for (unsigned bitNum = 5; bitNum > 0; bitNum--)
2301         {
2302             unsigned oneBit = elemWidth;
2303             if ((S & oneBit) == 0)
2304                 break;
2305             elemWidth /= 2;
2306         }
2307     }
2308     else
2309     {
2310         assert(size == EA_8BYTE);
2311     }
2312
2313     unsigned maskSR = elemWidth - 1;
2314
2315     S &= maskSR;
2316     R &= maskSR;
2317
2318     // encoding for S is one less than the number of consecutive one bits
2319     S++; // Number of consecutive ones to generate in 'welem'
2320
2321     // At this point:
2322     //
2323     //    'elemWidth' is the number of bits that we will use for the ROR and Replicate operations
2324     //    'S'         is the number of consecutive 1 bits for the immediate
2325     //    'R'         is the number of bits that we will Rotate Right the immediate
2326     //    'size'      selects the final size of the immedate that we return (64 or 32 bits)
2327
2328     assert(S < elemWidth); // 'elemWidth' consecutive one's is a reserved encoding
2329
2330     UINT64 welem;
2331     UINT64 wmask;
2332
2333     welem = (1ULL << S) - 1;
2334
2335     wmask = ROR_helper(welem, R, elemWidth);
2336     wmask = Replicate_helper(wmask, elemWidth, size);
2337
2338     return wmask;
2339 }
2340
2341 /*****************************************************************************
2342  *
2343  *  Check if an immediate can use the left shifted by 12 bits encoding
2344  */
2345
2346 /*static*/ bool emitter::canEncodeWithShiftImmBy12(INT64 imm)
2347 {
2348     if (imm < 0)
2349     {
2350         imm = -imm; // convert to unsigned
2351     }
2352
2353     if (imm < 0)
2354     {
2355         return false; // Must be MIN_INT64
2356     }
2357
2358     if ((imm & 0xfff) != 0) // Now the low 12 bits all have to be zero
2359     {
2360         return false;
2361     }
2362
2363     imm >>= 12; // shift right by 12 bits
2364
2365     return (imm <= 0x0fff); // Does it fit in 12 bits
2366 }
2367
2368 /*****************************************************************************
2369  *
2370  *  Normalize the 'imm' so that the upper bits, as defined by 'size' are zero
2371  */
2372
2373 /*static*/ INT64 emitter::normalizeImm64(INT64 imm, emitAttr size)
2374 {
2375     unsigned immWidth = getBitWidth(size);
2376     INT64    result   = imm;
2377
2378     if (immWidth < 64)
2379     {
2380         // Check that 'imm' fits in 'immWidth' bits. Don't consider "sign" bits above width.
2381         INT64 maxVal      = 1LL << immWidth;
2382         INT64 lowBitsMask = maxVal - 1;
2383         INT64 hiBitsMask  = ~lowBitsMask;
2384         INT64 signBitsMask =
2385             hiBitsMask | (1LL << (immWidth - 1)); // The high bits must be set, and the top bit (sign bit) must be set.
2386         assert((imm < maxVal) || ((imm & signBitsMask) == signBitsMask));
2387
2388         // mask off the hiBits
2389         result &= lowBitsMask;
2390     }
2391     return result;
2392 }
2393
2394 /*****************************************************************************
2395  *
2396  *  Normalize the 'imm' so that the upper bits, as defined by 'size' are zero
2397  */
2398
2399 /*static*/ INT32 emitter::normalizeImm32(INT32 imm, emitAttr size)
2400 {
2401     unsigned immWidth = getBitWidth(size);
2402     INT32    result   = imm;
2403
2404     if (immWidth < 32)
2405     {
2406         // Check that 'imm' fits in 'immWidth' bits. Don't consider "sign" bits above width.
2407         INT32 maxVal       = 1 << immWidth;
2408         INT32 lowBitsMask  = maxVal - 1;
2409         INT32 hiBitsMask   = ~lowBitsMask;
2410         INT32 signBitsMask = hiBitsMask | (1 << (immWidth - 1)); // The high bits must be set, and the top bit
2411                                                                  // (sign bit) must be set.
2412         assert((imm < maxVal) || ((imm & signBitsMask) == signBitsMask));
2413
2414         // mask off the hiBits
2415         result &= lowBitsMask;
2416     }
2417     return result;
2418 }
2419
2420 /************************************************************************
2421  *
2422  *  returns true if 'imm' of 'size bits (32/64) can be encoded
2423  *  using the ARM64 'bitmask immediate' form.
2424  *  When a non-null value is passed for 'wbBMI' then this method
2425  *  writes back the 'N','S' and 'R' values use to encode this immediate
2426  *
2427  */
2428
2429 /*static*/ bool emitter::canEncodeBitMaskImm(INT64 imm, emitAttr size, emitter::bitMaskImm* wbBMI)
2430 {
2431     assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2432
2433     unsigned immWidth = (size == EA_8BYTE) ? 64 : 32;
2434     unsigned maxLen   = (size == EA_8BYTE) ? 6 : 5;
2435
2436     imm = normalizeImm64(imm, size);
2437
2438     // Starting with len=1, elemWidth is 2 bits
2439     //               len=2, elemWidth is 4 bits
2440     //               len=3, elemWidth is 8 bits
2441     //               len=4, elemWidth is 16 bits
2442     //               len=5, elemWidth is 32 bits
2443     // (optionally)  len=6, elemWidth is 64 bits
2444     //
2445     for (unsigned len = 1; (len <= maxLen); len++)
2446     {
2447         unsigned elemWidth = 1 << len;
2448         UINT64   elemMask  = ((UINT64)-1) >> (64 - elemWidth);
2449         UINT64   tempImm   = (UINT64)imm;        // A working copy of 'imm' that we can mutate
2450         UINT64   elemVal   = tempImm & elemMask; // The low 'elemWidth' bits of 'imm'
2451
2452         // Check for all 1's or 0's as these can't be encoded
2453         if ((elemVal == 0) || (elemVal == elemMask))
2454             continue;
2455
2456         // 'checkedBits' is the count of bits that are known to match 'elemVal' when replicated
2457         unsigned checkedBits = elemWidth; // by definition the first 'elemWidth' bits match
2458
2459         // Now check to see if each of the next bits match...
2460         //
2461         while (checkedBits < immWidth)
2462         {
2463             tempImm >>= elemWidth;
2464
2465             UINT64 nextElem = tempImm & elemMask;
2466             if (nextElem != elemVal)
2467             {
2468                 // Not matching, exit this loop and checkedBits will not be equal to immWidth
2469                 break;
2470             }
2471
2472             // The 'nextElem' is matching, so increment 'checkedBits'
2473             checkedBits += elemWidth;
2474         }
2475
2476         // Did the full immediate contain bits that can be formed by repeating 'elemVal'?
2477         if (checkedBits == immWidth)
2478         {
2479             // We are not quite done, since the only values that we can encode as a
2480             // 'bitmask immediate' are those that can be formed by starting with a
2481             // bit string of 0*1* that is rotated by some number of bits.
2482             //
2483             // We check to see if 'elemVal' can be formed using these restrictions.
2484             //
2485             // Observation:
2486             // Rotating by one bit any value that passes these restrictions
2487             // can be xor-ed with the original value and will result it a string
2488             // of bits that have exactly two 1 bits: 'elemRorXor'
2489             // Further the distance between the two one bits tells us the value
2490             // of S and the location of the 1 bits tells us the value of R
2491             //
2492             // Some examples:   (immWidth is 8)
2493             //
2494             // S=4,R=0   S=5,R=3   S=3,R=6
2495             // elemVal:        00001111  11100011  00011100
2496             // elemRor:        10000111  11110001  00001110
2497             // elemRorXor:     10001000  00010010  00010010
2498             //      compute S  45678---  ---5678-  ---3210-
2499             //      compute R  01234567  ---34567  ------67
2500
2501             UINT64 elemRor    = ROR_helper(elemVal, 1, elemWidth); // Rotate 'elemVal' Right by one bit
2502             UINT64 elemRorXor = elemVal ^ elemRor;                 // Xor elemVal and elemRor
2503
2504             // If we only have a two-bit change in elemROR then we can form a mask for this value
2505             unsigned bitCount = 0;
2506             UINT64   oneBit   = 0x1;
2507             unsigned R        = elemWidth; // R is shift count for ROR (rotate right shift)
2508             unsigned S        = 0;         // S is number of consecutive one bits
2509             int      incr     = -1;
2510
2511             // Loop over the 'elemWidth' bits in 'elemRorXor'
2512             //
2513             for (unsigned bitNum = 0; bitNum < elemWidth; bitNum++)
2514             {
2515                 if (incr == -1)
2516                 {
2517                     R--; // We decrement R by one whenever incr is -1
2518                 }
2519                 if (bitCount == 1)
2520                 {
2521                     S += incr; // We incr/decr S, after we find the first one bit in 'elemRorXor'
2522                 }
2523
2524                 // Is this bit position a 1 bit in 'elemRorXor'?
2525                 //
2526                 if (oneBit & elemRorXor)
2527                 {
2528                     bitCount++;
2529                     // Is this the first 1 bit that we found in 'elemRorXor'?
2530                     if (bitCount == 1)
2531                     {
2532                         // Does this 1 bit represent a transition to zero bits?
2533                         bool toZeros = ((oneBit & elemVal) != 0);
2534                         if (toZeros)
2535                         {
2536                             // S :: Count down from elemWidth
2537                             S    = elemWidth;
2538                             incr = -1;
2539                         }
2540                         else // this 1 bit represent a transition to one bits.
2541                         {
2542                             // S :: Count up from zero
2543                             S    = 0;
2544                             incr = +1;
2545                         }
2546                     }
2547                     else // bitCount > 1
2548                     {
2549                         // We found the second (or third...) 1 bit in 'elemRorXor'
2550                         incr = 0; // stop decrementing 'R'
2551
2552                         if (bitCount > 2)
2553                         {
2554                             // More than 2 transitions from 0/1 in 'elemVal'
2555                             // This means that 'elemVal' can't be encoded
2556                             // using a 'bitmask immediate'.
2557                             //
2558                             // Furthermore, it will continue to fail
2559                             // with any larger 'len' that we try.
2560                             // so just return false.
2561                             //
2562                             return false;
2563                         }
2564                     }
2565                 }
2566
2567                 // shift oneBit left by one bit to test the next position
2568                 oneBit <<= 1;
2569             }
2570
2571             // We expect that bitCount will always be two at this point
2572             // but just in case return false for any bad cases.
2573             //
2574             assert(bitCount == 2);
2575             if (bitCount != 2)
2576                 return false;
2577
2578             // Perform some sanity checks on the values of 'S' and 'R'
2579             assert(S > 0);
2580             assert(S < elemWidth);
2581             assert(R < elemWidth);
2582
2583             // Does the caller want us to return the N,R,S encoding values?
2584             //
2585             if (wbBMI != nullptr)
2586             {
2587
2588                 // The encoding used for S is one less than the
2589                 //  number of consecutive one bits
2590                 S--;
2591
2592                 if (len == 6)
2593                 {
2594                     wbBMI->immN = 1;
2595                 }
2596                 else
2597                 {
2598                     wbBMI->immN = 0;
2599                     // The encoding used for 'S' here is a bit peculiar.
2600                     //
2601                     // The upper bits need to be complemented, followed by a zero bit
2602                     // then the value of 'S-1'
2603                     //
2604                     unsigned upperBitsOfS = 64 - (1 << (len + 1));
2605                     S |= upperBitsOfS;
2606                 }
2607                 wbBMI->immR = R;
2608                 wbBMI->immS = S;
2609
2610                 // Verify that what we are returning is correct.
2611                 assert(imm == emitDecodeBitMaskImm(*wbBMI, size));
2612             }
2613             // Tell the caller that we can successfully encode this immediate
2614             // using a 'bitmask immediate'.
2615             //
2616             return true;
2617         }
2618     }
2619     return false;
2620 }
2621
2622 /************************************************************************
2623  *
2624  *  Convert a 64-bit immediate into its 'bitmask immediate' representation imm(N,r,s)
2625  */
2626
2627 /*static*/ emitter::bitMaskImm emitter::emitEncodeBitMaskImm(INT64 imm, emitAttr size)
2628 {
2629     emitter::bitMaskImm result;
2630     result.immNRS = 0;
2631
2632     bool canEncode = canEncodeBitMaskImm(imm, size, &result);
2633     assert(canEncode);
2634
2635     return result;
2636 }
2637
2638 /************************************************************************
2639  *
2640  *  Convert an imm(i16,hw) into a 32/64-bit immediate
2641  *  inputs 'hwImm' a halfwordImm struct
2642  *         'size' specifies the size of the result (64 or 32 bits)
2643  */
2644
2645 /*static*/ INT64 emitter::emitDecodeHalfwordImm(const emitter::halfwordImm hwImm, emitAttr size)
2646 {
2647     assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2648
2649     unsigned hw  = hwImm.immHW;
2650     INT64    val = (INT64)hwImm.immVal;
2651
2652     assert((hw <= 1) || (size == EA_8BYTE));
2653
2654     INT64 result = val << (16 * hw);
2655     return result;
2656 }
2657
2658 /************************************************************************
2659  *
2660  *  returns true if 'imm' of 'size' bits (32/64) can be encoded
2661  *  using the ARM64 'halfword immediate' form.
2662  *  When a non-null value is passed for 'wbHWI' then this method
2663  *  writes back the 'immHW' and 'immVal' values use to encode this immediate
2664  *
2665  */
2666
2667 /*static*/ bool emitter::canEncodeHalfwordImm(INT64 imm, emitAttr size, emitter::halfwordImm* wbHWI)
2668 {
2669     assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2670
2671     unsigned immWidth = (size == EA_8BYTE) ? 64 : 32;
2672     unsigned maxHW    = (size == EA_8BYTE) ? 4 : 2;
2673
2674     // setup immMask to a (EA_4BYTE) 0x00000000_FFFFFFFF or (EA_8BYTE) 0xFFFFFFFF_FFFFFFFF
2675     const UINT64 immMask = ((UINT64)-1) >> (64 - immWidth);
2676     const INT64  mask16  = (INT64)0xFFFF;
2677
2678     imm = normalizeImm64(imm, size);
2679
2680     // Try each of the valid hw shift sizes
2681     for (unsigned hw = 0; (hw < maxHW); hw++)
2682     {
2683         INT64 curMask   = mask16 << (hw * 16); // Represents the mask of the bits in the current halfword
2684         INT64 checkBits = immMask & ~curMask;
2685
2686         // Excluding the current halfword (using ~curMask)
2687         //  does the immediate have zero bits in every other bit that we care about?
2688         //  note we care about all 64-bits for EA_8BYTE
2689         //  and we care about the lowest 32 bits for EA_4BYTE
2690         //
2691         if ((imm & checkBits) == 0)
2692         {
2693             // Does the caller want us to return the imm(i16,hw) encoding values?
2694             //
2695             if (wbHWI != nullptr)
2696             {
2697                 INT64 val     = ((imm & curMask) >> (hw * 16)) & mask16;
2698                 wbHWI->immHW  = hw;
2699                 wbHWI->immVal = val;
2700
2701                 // Verify that what we are returning is correct.
2702                 assert(imm == emitDecodeHalfwordImm(*wbHWI, size));
2703             }
2704             // Tell the caller that we can successfully encode this immediate
2705             // using a 'halfword immediate'.
2706             //
2707             return true;
2708         }
2709     }
2710     return false;
2711 }
2712
2713 /************************************************************************
2714  *
2715  *  Convert a 64-bit immediate into its 'halfword immediate' representation imm(i16,hw)
2716  */
2717
2718 /*static*/ emitter::halfwordImm emitter::emitEncodeHalfwordImm(INT64 imm, emitAttr size)
2719 {
2720     emitter::halfwordImm result;
2721     result.immHWVal = 0;
2722
2723     bool canEncode = canEncodeHalfwordImm(imm, size, &result);
2724     assert(canEncode);
2725
2726     return result;
2727 }
2728
2729 /************************************************************************
2730  *
2731  *  Convert an imm(i8,sh) into a 16/32-bit immediate
2732  *  inputs 'bsImm' a byteShiftedImm struct
2733  *         'size' specifies the size of the result (16 or 32 bits)
2734  */
2735
2736 /*static*/ INT32 emitter::emitDecodeByteShiftedImm(const emitter::byteShiftedImm bsImm, emitAttr size)
2737 {
2738     bool     onesShift = (bsImm.immOnes == 1);
2739     unsigned bySh      = bsImm.immBY;         // Num Bytes to shift 0,1,2,3
2740     INT32    val       = (INT32)bsImm.immVal; // 8-bit immediate
2741     INT32    result    = val;
2742
2743     if (bySh > 0)
2744     {
2745         assert((size == EA_2BYTE) || (size == EA_4BYTE)); // Only EA_2BYTE or EA_4BYTE forms
2746         if (size == EA_2BYTE)
2747         {
2748             assert(bySh < 2);
2749         }
2750         else
2751         {
2752             assert(bySh < 4);
2753         }
2754
2755         result <<= (8 * bySh);
2756
2757         if (onesShift)
2758         {
2759             result |= ((1 << (8 * bySh)) - 1);
2760         }
2761     }
2762     return result;
2763 }
2764
2765 /************************************************************************
2766  *
2767  *  returns true if 'imm' of 'size' bits (16/32) can be encoded
2768  *  using the ARM64 'byteShifted immediate' form.
2769  *  When a non-null value is passed for 'wbBSI' then this method
2770  *  writes back the 'immBY' and 'immVal' values use to encode this immediate
2771  *
2772  */
2773
2774 /*static*/ bool emitter::canEncodeByteShiftedImm(INT64                    imm,
2775                                                  emitAttr                 size,
2776                                                  bool                     allow_MSL,
2777                                                  emitter::byteShiftedImm* wbBSI)
2778 {
2779     bool     canEncode = false;
2780     bool     onesShift = false; // true if we use the shifting ones variant
2781     unsigned bySh      = 0;     // number of bytes to shift: 0, 1, 2, 3
2782     unsigned imm8      = 0;     // immediate to use in the encoding
2783
2784     imm = normalizeImm64(imm, size);
2785
2786     if (size == EA_1BYTE)
2787     {
2788         imm8 = (unsigned)imm;
2789         assert(imm8 < 0x100);
2790         canEncode = true;
2791     }
2792     else if (size == EA_8BYTE)
2793     {
2794         imm8 = (unsigned)imm;
2795         assert(imm8 < 0x100);
2796         canEncode = true;
2797     }
2798     else
2799     {
2800         assert((size == EA_2BYTE) || (size == EA_4BYTE)); // Only EA_2BYTE or EA_4BYTE forms
2801
2802         unsigned immWidth = (size == EA_4BYTE) ? 32 : 16;
2803         unsigned maxBY    = (size == EA_4BYTE) ? 4 : 2;
2804
2805         // setup immMask to a (EA_2BYTE) 0x0000FFFF or (EA_4BYTE) 0xFFFFFFFF
2806         const UINT32 immMask = ((UINT32)-1) >> (32 - immWidth);
2807         const INT32  mask8   = (INT32)0xFF;
2808
2809         // Try each of the valid by shift sizes
2810         for (bySh = 0; (bySh < maxBY); bySh++)
2811         {
2812             INT32 curMask   = mask8 << (bySh * 8); // Represents the mask of the bits in the current byteShifted
2813             INT32 checkBits = immMask & ~curMask;
2814             INT32 immCheck  = (imm & checkBits);
2815
2816             // Excluding the current byte (using ~curMask)
2817             //  does the immediate have zero bits in every other bit that we care about?
2818             //  or can be use the shifted one variant?
2819             //  note we care about all 32-bits for EA_4BYTE
2820             //  and we care about the lowest 16 bits for EA_2BYTE
2821             //
2822             if (immCheck == 0)
2823             {
2824                 canEncode = true;
2825             }
2826             if (allow_MSL)
2827             {
2828                 if ((bySh == 1) && (immCheck == 0xFF))
2829                 {
2830                     canEncode = true;
2831                     onesShift = true;
2832                 }
2833                 else if ((bySh == 2) && (immCheck == 0xFFFF))
2834                 {
2835                     canEncode = true;
2836                     onesShift = true;
2837                 }
2838             }
2839             if (canEncode)
2840             {
2841                 imm8 = (unsigned)(((imm & curMask) >> (bySh * 8)) & mask8);
2842                 break;
2843             }
2844         }
2845     }
2846
2847     if (canEncode)
2848     {
2849         // Does the caller want us to return the imm(i8,bySh) encoding values?
2850         //
2851         if (wbBSI != nullptr)
2852         {
2853             wbBSI->immOnes = onesShift;
2854             wbBSI->immBY   = bySh;
2855             wbBSI->immVal  = imm8;
2856
2857             // Verify that what we are returning is correct.
2858             assert(imm == emitDecodeByteShiftedImm(*wbBSI, size));
2859         }
2860         // Tell the caller that we can successfully encode this immediate
2861         // using a 'byteShifted immediate'.
2862         //
2863         return true;
2864     }
2865     return false;
2866 }
2867
2868 /************************************************************************
2869  *
2870  *  Convert a 32-bit immediate into its 'byteShifted immediate' representation imm(i8,by)
2871  */
2872
2873 /*static*/ emitter::byteShiftedImm emitter::emitEncodeByteShiftedImm(INT64 imm, emitAttr size, bool allow_MSL)
2874 {
2875     emitter::byteShiftedImm result;
2876     result.immBSVal = 0;
2877
2878     bool canEncode = canEncodeByteShiftedImm(imm, size, allow_MSL, &result);
2879     assert(canEncode);
2880
2881     return result;
2882 }
2883
2884 /************************************************************************
2885  *
2886  *  Convert a 'float 8-bit immediate' into a double.
2887  *  inputs 'fpImm' a floatImm8 struct
2888  */
2889
2890 /*static*/ double emitter::emitDecodeFloatImm8(const emitter::floatImm8 fpImm)
2891 {
2892     unsigned sign  = fpImm.immSign;
2893     unsigned exp   = fpImm.immExp ^ 0x4;
2894     unsigned mant  = fpImm.immMant + 16;
2895     unsigned scale = 16 * 8;
2896
2897     while (exp > 0)
2898     {
2899         scale /= 2;
2900         exp--;
2901     }
2902
2903     double result = ((double)mant) / ((double)scale);
2904     if (sign == 1)
2905     {
2906         result = -result;
2907     }
2908
2909     return result;
2910 }
2911
2912 /************************************************************************
2913  *
2914  *  returns true if the 'immDbl' can be encoded using the 'float 8-bit immediate' form.
2915  *  also returns the encoding if wbFPI is non-null
2916  *
2917  */
2918
2919 /*static*/ bool emitter::canEncodeFloatImm8(double immDbl, emitter::floatImm8* wbFPI)
2920 {
2921     bool   canEncode = false;
2922     double val       = immDbl;
2923
2924     int sign = 0;
2925     if (val < 0.0)
2926     {
2927         val  = -val;
2928         sign = 1;
2929     }
2930
2931     int exp = 0;
2932     while ((val < 1.0) && (exp >= -4))
2933     {
2934         val *= 2.0;
2935         exp--;
2936     }
2937     while ((val >= 2.0) && (exp <= 5))
2938     {
2939         val *= 0.5;
2940         exp++;
2941     }
2942     exp += 3;
2943     val *= 16.0;
2944     int ival = (int)val;
2945
2946     if ((exp >= 0) && (exp <= 7))
2947     {
2948         if (val == (double)ival)
2949         {
2950             canEncode = true;
2951
2952             if (wbFPI != nullptr)
2953             {
2954                 ival -= 16;
2955                 assert((ival >= 0) && (ival <= 15));
2956
2957                 wbFPI->immSign = sign;
2958                 wbFPI->immExp  = exp ^ 0x4;
2959                 wbFPI->immMant = ival;
2960                 unsigned imm8  = wbFPI->immFPIVal;
2961                 assert((imm8 >= 0) && (imm8 <= 0xff));
2962             }
2963         }
2964     }
2965
2966     return canEncode;
2967 }
2968
2969 /************************************************************************
2970  *
2971  *  Convert a double into its 'float 8-bit immediate' representation
2972  */
2973
2974 /*static*/ emitter::floatImm8 emitter::emitEncodeFloatImm8(double immDbl)
2975 {
2976     emitter::floatImm8 result;
2977     result.immFPIVal = 0;
2978
2979     bool canEncode = canEncodeFloatImm8(immDbl, &result);
2980     assert(canEncode);
2981
2982     return result;
2983 }
2984
2985 /*****************************************************************************
2986  *
2987  *  For the given 'ins' returns the reverse instruction
2988  *  if one exists, otherwise returns INS_INVALID
2989  */
2990
2991 /*static*/ instruction emitter::insReverse(instruction ins)
2992 {
2993     switch (ins)
2994     {
2995         case INS_add:
2996             return INS_sub;
2997         case INS_adds:
2998             return INS_subs;
2999
3000         case INS_sub:
3001             return INS_add;
3002         case INS_subs:
3003             return INS_adds;
3004
3005         case INS_cmp:
3006             return INS_cmn;
3007         case INS_cmn:
3008             return INS_cmp;
3009
3010         case INS_ccmp:
3011             return INS_ccmn;
3012         case INS_ccmn:
3013             return INS_ccmp;
3014
3015         default:
3016             return INS_invalid;
3017     }
3018 }
3019
3020 /*****************************************************************************
3021  *
3022  *  For the given 'datasize' and 'elemsize', make the proper arrangement option
3023  *  returns the insOpts that specifies the vector register arrangement
3024  *  if one does not exist returns INS_OPTS_NONE
3025  */
3026
3027 /*static*/ insOpts emitter::optMakeArrangement(emitAttr datasize, emitAttr elemsize)
3028 {
3029     insOpts result = INS_OPTS_NONE;
3030
3031     if (datasize == EA_8BYTE)
3032     {
3033         switch (elemsize)
3034         {
3035             case EA_1BYTE:
3036                 result = INS_OPTS_8B;
3037                 break;
3038             case EA_2BYTE:
3039                 result = INS_OPTS_4H;
3040                 break;
3041             case EA_4BYTE:
3042                 result = INS_OPTS_2S;
3043                 break;
3044             case EA_8BYTE:
3045                 result = INS_OPTS_1D;
3046                 break;
3047             default:
3048                 unreached();
3049                 break;
3050         }
3051     }
3052     else if (datasize == EA_16BYTE)
3053     {
3054         switch (elemsize)
3055         {
3056             case EA_1BYTE:
3057                 result = INS_OPTS_16B;
3058                 break;
3059             case EA_2BYTE:
3060                 result = INS_OPTS_8H;
3061                 break;
3062             case EA_4BYTE:
3063                 result = INS_OPTS_4S;
3064                 break;
3065             case EA_8BYTE:
3066                 result = INS_OPTS_2D;
3067                 break;
3068             default:
3069                 unreached();
3070                 break;
3071         }
3072     }
3073     return result;
3074 }
3075
3076 /*****************************************************************************
3077  *
3078  *  For the given 'datasize' and arrangement 'opts'
3079  *  returns true is the pair spcifies a valid arrangement
3080  */
3081 /*static*/ bool emitter::isValidArrangement(emitAttr datasize, insOpts opt)
3082 {
3083     if (datasize == EA_8BYTE)
3084     {
3085         if ((opt == INS_OPTS_8B) || (opt == INS_OPTS_4H) || (opt == INS_OPTS_2S) || (opt == INS_OPTS_1D))
3086         {
3087             return true;
3088         }
3089     }
3090     else if (datasize == EA_16BYTE)
3091     {
3092         if ((opt == INS_OPTS_16B) || (opt == INS_OPTS_8H) || (opt == INS_OPTS_4S) || (opt == INS_OPTS_2D))
3093         {
3094             return true;
3095         }
3096     }
3097     return false;
3098 }
3099
3100 //  For the given 'arrangement' returns the 'datasize' specified by the vector register arrangement
3101 //  asserts and returns EA_UNKNOWN if an invalid 'arrangement' value is passed
3102 //
3103 /*static*/ emitAttr emitter::optGetDatasize(insOpts arrangement)
3104 {
3105     if ((arrangement == INS_OPTS_8B) || (arrangement == INS_OPTS_4H) || (arrangement == INS_OPTS_2S) ||
3106         (arrangement == INS_OPTS_1D))
3107     {
3108         return EA_8BYTE;
3109     }
3110     else if ((arrangement == INS_OPTS_16B) || (arrangement == INS_OPTS_8H) || (arrangement == INS_OPTS_4S) ||
3111              (arrangement == INS_OPTS_2D))
3112     {
3113         return EA_16BYTE;
3114     }
3115     else
3116     {
3117         assert(!" invalid 'arrangement' value");
3118         return EA_UNKNOWN;
3119     }
3120 }
3121
3122 //  For the given 'arrangement' returns the 'elemsize' specified by the vector register arrangement
3123 //  asserts and returns EA_UNKNOWN if an invalid 'arrangement' value is passed
3124 //
3125 /*static*/ emitAttr emitter::optGetElemsize(insOpts arrangement)
3126 {
3127     if ((arrangement == INS_OPTS_8B) || (arrangement == INS_OPTS_16B))
3128     {
3129         return EA_1BYTE;
3130     }
3131     else if ((arrangement == INS_OPTS_4H) || (arrangement == INS_OPTS_8H))
3132     {
3133         return EA_2BYTE;
3134     }
3135     else if ((arrangement == INS_OPTS_2S) || (arrangement == INS_OPTS_4S))
3136     {
3137         return EA_4BYTE;
3138     }
3139     else if ((arrangement == INS_OPTS_1D) || (arrangement == INS_OPTS_2D))
3140     {
3141         return EA_8BYTE;
3142     }
3143     else
3144     {
3145         assert(!" invalid 'arrangement' value");
3146         return EA_UNKNOWN;
3147     }
3148 }
3149
3150 //  For the given 'arrangement' returns the 'widen-arrangement' specified by the vector register arrangement
3151 //  asserts and returns INS_OPTS_NONE if an invalid 'arrangement' value is passed
3152 //
3153 /*static*/ insOpts emitter::optWidenElemsize(insOpts arrangement)
3154 {
3155     if ((arrangement == INS_OPTS_8B) || (arrangement == INS_OPTS_16B))
3156     {
3157         return INS_OPTS_8H;
3158     }
3159     else if ((arrangement == INS_OPTS_4H) || (arrangement == INS_OPTS_8H))
3160     {
3161         return INS_OPTS_4S;
3162     }
3163     else if ((arrangement == INS_OPTS_2S) || (arrangement == INS_OPTS_4S))
3164     {
3165         return INS_OPTS_2D;
3166     }
3167     else
3168     {
3169         assert(!" invalid 'arrangement' value");
3170         return INS_OPTS_NONE;
3171     }
3172 }
3173
3174 //  For the given 'conversion' returns the 'dstsize' specified by the conversion option
3175 /*static*/ emitAttr emitter::optGetDstsize(insOpts conversion)
3176 {
3177     switch (conversion)
3178     {
3179         case INS_OPTS_S_TO_8BYTE:
3180         case INS_OPTS_D_TO_8BYTE:
3181         case INS_OPTS_4BYTE_TO_D:
3182         case INS_OPTS_8BYTE_TO_D:
3183         case INS_OPTS_S_TO_D:
3184         case INS_OPTS_H_TO_D:
3185
3186             return EA_8BYTE;
3187
3188         case INS_OPTS_S_TO_4BYTE:
3189         case INS_OPTS_D_TO_4BYTE:
3190         case INS_OPTS_4BYTE_TO_S:
3191         case INS_OPTS_8BYTE_TO_S:
3192         case INS_OPTS_D_TO_S:
3193         case INS_OPTS_H_TO_S:
3194
3195             return EA_4BYTE;
3196
3197         case INS_OPTS_S_TO_H:
3198         case INS_OPTS_D_TO_H:
3199
3200             return EA_2BYTE;
3201
3202         default:
3203             assert(!" invalid 'conversion' value");
3204             return EA_UNKNOWN;
3205     }
3206 }
3207
3208 //  For the given 'conversion' returns the 'srcsize' specified by the conversion option
3209 /*static*/ emitAttr emitter::optGetSrcsize(insOpts conversion)
3210 {
3211     switch (conversion)
3212     {
3213         case INS_OPTS_D_TO_8BYTE:
3214         case INS_OPTS_D_TO_4BYTE:
3215         case INS_OPTS_8BYTE_TO_D:
3216         case INS_OPTS_8BYTE_TO_S:
3217         case INS_OPTS_D_TO_S:
3218         case INS_OPTS_D_TO_H:
3219
3220             return EA_8BYTE;
3221
3222         case INS_OPTS_S_TO_8BYTE:
3223         case INS_OPTS_S_TO_4BYTE:
3224         case INS_OPTS_4BYTE_TO_S:
3225         case INS_OPTS_4BYTE_TO_D:
3226         case INS_OPTS_S_TO_D:
3227         case INS_OPTS_S_TO_H:
3228
3229             return EA_4BYTE;
3230
3231         case INS_OPTS_H_TO_S:
3232         case INS_OPTS_H_TO_D:
3233
3234             return EA_2BYTE;
3235
3236         default:
3237             assert(!" invalid 'conversion' value");
3238             return EA_UNKNOWN;
3239     }
3240 }
3241
3242 //    For the given 'size' and 'index' returns true if it specifies a valid index for a vector register of 'size'
3243 /*static*/ bool emitter::isValidVectorIndex(emitAttr datasize, emitAttr elemsize, ssize_t index)
3244 {
3245     assert(isValidVectorDatasize(datasize));
3246     assert(isValidVectorElemsize(elemsize));
3247
3248     bool result = false;
3249     if (index >= 0)
3250     {
3251         if (datasize == EA_8BYTE)
3252         {
3253             switch (elemsize)
3254             {
3255                 case EA_1BYTE:
3256                     result = (index < 8);
3257                     break;
3258                 case EA_2BYTE:
3259                     result = (index < 4);
3260                     break;
3261                 case EA_4BYTE:
3262                     result = (index < 2);
3263                     break;
3264                 case EA_8BYTE:
3265                     result = (index < 1);
3266                     break;
3267                 default:
3268                     unreached();
3269                     break;
3270             }
3271         }
3272         else if (datasize == EA_16BYTE)
3273         {
3274             switch (elemsize)
3275             {
3276                 case EA_1BYTE:
3277                     result = (index < 16);
3278                     break;
3279                 case EA_2BYTE:
3280                     result = (index < 8);
3281                     break;
3282                 case EA_4BYTE:
3283                     result = (index < 4);
3284                     break;
3285                 case EA_8BYTE:
3286                     result = (index < 2);
3287                     break;
3288                 default:
3289                     unreached();
3290                     break;
3291             }
3292         }
3293     }
3294     return result;
3295 }
3296
3297 /*****************************************************************************
3298  *
3299  *  Add an instruction with no operands.
3300  */
3301
3302 void emitter::emitIns(instruction ins)
3303 {
3304     instrDesc* id  = emitNewInstrSmall(EA_8BYTE);
3305     insFormat  fmt = emitInsFormat(ins);
3306
3307     assert(fmt == IF_SN_0A);
3308
3309     id->idIns(ins);
3310     id->idInsFmt(fmt);
3311
3312     dispIns(id);
3313     appendToCurIG(id);
3314 }
3315
3316 /*****************************************************************************
3317  *
3318  *  Add an instruction with a single immediate value.
3319  */
3320
3321 void emitter::emitIns_I(instruction ins, emitAttr attr, ssize_t imm)
3322 {
3323     insFormat fmt = IF_NONE;
3324
3325     /* Figure out the encoding format of the instruction */
3326     switch (ins)
3327     {
3328         case INS_brk:
3329             if ((imm & 0x0000ffff) == imm)
3330             {
3331                 fmt = IF_SI_0A;
3332             }
3333             else
3334             {
3335                 assert(!"Instruction cannot be encoded: IF_SI_0A");
3336             }
3337             break;
3338         default:
3339             unreached();
3340             break;
3341     }
3342     assert(fmt != IF_NONE);
3343
3344     instrDesc* id = emitNewInstrSC(attr, imm);
3345
3346     id->idIns(ins);
3347     id->idInsFmt(fmt);
3348
3349     dispIns(id);
3350     appendToCurIG(id);
3351 }
3352
3353 /*****************************************************************************
3354  *
3355  *  Add an instruction referencing a single register.
3356  */
3357
3358 void emitter::emitIns_R(instruction ins, emitAttr attr, regNumber reg)
3359 {
3360     emitAttr   size = EA_SIZE(attr);
3361     insFormat  fmt  = IF_NONE;
3362     instrDesc* id   = nullptr;
3363
3364     /* Figure out the encoding format of the instruction */
3365     switch (ins)
3366     {
3367         case INS_br:
3368         case INS_ret:
3369             assert(isGeneralRegister(reg));
3370             id = emitNewInstrSmall(attr);
3371             id->idReg1(reg);
3372             fmt = IF_BR_1A;
3373             break;
3374
3375         default:
3376             unreached();
3377     }
3378
3379     assert(fmt != IF_NONE);
3380
3381     id->idIns(ins);
3382     id->idInsFmt(fmt);
3383
3384     dispIns(id);
3385     appendToCurIG(id);
3386 }
3387
3388 /*****************************************************************************
3389  *
3390  *  Add an instruction referencing a register and a constant.
3391  */
3392
3393 void emitter::emitIns_R_I(instruction ins, emitAttr attr, regNumber reg, ssize_t imm, insOpts opt /* = INS_OPTS_NONE */)
3394 {
3395     emitAttr  size      = EA_SIZE(attr);
3396     emitAttr  elemsize  = EA_UNKNOWN;
3397     insFormat fmt       = IF_NONE;
3398     bool      canEncode = false;
3399
3400     /* Figure out the encoding format of the instruction */
3401     switch (ins)
3402     {
3403         bitMaskImm     bmi;
3404         halfwordImm    hwi;
3405         byteShiftedImm bsi;
3406         ssize_t        notOfImm;
3407
3408         case INS_tst:
3409             assert(insOptsNone(opt));
3410             assert(isGeneralRegister(reg));
3411             bmi.immNRS = 0;
3412             canEncode  = canEncodeBitMaskImm(imm, size, &bmi);
3413             if (canEncode)
3414             {
3415                 imm = bmi.immNRS;
3416                 assert(isValidImmNRS(imm, size));
3417                 fmt = IF_DI_1C;
3418             }
3419             break;
3420
3421         case INS_movk:
3422         case INS_movn:
3423         case INS_movz:
3424             assert(isValidGeneralDatasize(size));
3425             assert(insOptsNone(opt)); // No LSL here (you must use emitIns_R_I_I if a shift is needed)
3426             assert(isGeneralRegister(reg));
3427             assert(isValidUimm16(imm));
3428
3429             hwi.immHW  = 0;
3430             hwi.immVal = imm;
3431             assert(imm == emitDecodeHalfwordImm(hwi, size));
3432
3433             imm       = hwi.immHWVal;
3434             canEncode = true;
3435             fmt       = IF_DI_1B;
3436             break;
3437
3438         case INS_mov:
3439             assert(isValidGeneralDatasize(size));
3440             assert(insOptsNone(opt)); // No explicit LSL here
3441             // We will automatically determine the shift based upon the imm
3442
3443             // First try the standard 'halfword immediate' imm(i16,hw)
3444             hwi.immHWVal = 0;
3445             canEncode    = canEncodeHalfwordImm(imm, size, &hwi);
3446             if (canEncode)
3447             {
3448                 // uses a movz encoding
3449                 assert(isGeneralRegister(reg));
3450                 imm = hwi.immHWVal;
3451                 assert(isValidImmHWVal(imm, size));
3452                 fmt = IF_DI_1B;
3453                 break;
3454             }
3455
3456             // Next try the ones-complement form of 'halfword immediate' imm(i16,hw)
3457             notOfImm  = NOT_helper(imm, getBitWidth(size));
3458             canEncode = canEncodeHalfwordImm(notOfImm, size, &hwi);
3459             if (canEncode)
3460             {
3461                 assert(isGeneralRegister(reg));
3462                 imm = hwi.immHWVal;
3463                 ins = INS_movn; // uses a movn encoding
3464                 assert(isValidImmHWVal(imm, size));
3465                 fmt = IF_DI_1B;
3466                 break;
3467             }
3468
3469             // Finally try the 'bitmask immediate' imm(N,r,s)
3470             bmi.immNRS = 0;
3471             canEncode  = canEncodeBitMaskImm(imm, size, &bmi);
3472             if (canEncode)
3473             {
3474                 assert(isGeneralRegisterOrSP(reg));
3475                 reg = encodingSPtoZR(reg);
3476                 imm = bmi.immNRS;
3477                 assert(isValidImmNRS(imm, size));
3478                 fmt = IF_DI_1D;
3479                 break;
3480             }
3481             else
3482             {
3483                 assert(!"Instruction cannot be encoded: mov imm");
3484             }
3485
3486             break;
3487
3488         case INS_movi:
3489             assert(isValidVectorDatasize(size));
3490             assert(isVectorRegister(reg));
3491             if (insOptsNone(opt) && (size == EA_8BYTE))
3492             {
3493                 opt = INS_OPTS_1D;
3494             }
3495             assert(isValidArrangement(size, opt));
3496             elemsize = optGetElemsize(opt);
3497
3498             if (elemsize == EA_8BYTE)
3499             {
3500                 size_t   uimm = imm;
3501                 ssize_t  imm8 = 0;
3502                 unsigned pos  = 0;
3503                 canEncode     = true;
3504                 bool failed   = false;
3505                 while (uimm != 0)
3506                 {
3507                     INT64 loByte = uimm & 0xFF;
3508                     if (((loByte == 0) || (loByte == 0xFF)) && (pos < 8))
3509                     {
3510                         if (loByte == 0xFF)
3511                         {
3512                             imm8 |= (1 << pos);
3513                         }
3514                         uimm >>= 8;
3515                         pos++;
3516                     }
3517                     else
3518                     {
3519                         canEncode = false;
3520                         break;
3521                     }
3522                 }
3523                 imm = imm8;
3524                 assert(isValidUimm8(imm));
3525                 fmt = IF_DV_1B;
3526                 break;
3527             }
3528             else
3529             {
3530                 // Vector operation
3531
3532                 // No explicit LSL/MSL is used for the immediate
3533                 // We will automatically determine the shift based upon the value of imm
3534
3535                 // First try the standard 'byteShifted immediate' imm(i8,bySh)
3536                 bsi.immBSVal = 0;
3537                 canEncode    = canEncodeByteShiftedImm(imm, elemsize, true, &bsi);
3538                 if (canEncode)
3539                 {
3540                     imm = bsi.immBSVal;
3541                     assert(isValidImmBSVal(imm, size));
3542                     fmt = IF_DV_1B;
3543                     break;
3544                 }
3545
3546                 // Next try the ones-complement form of the 'immediate' imm(i8,bySh)
3547                 if ((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE)) // Only EA_2BYTE or EA_4BYTE forms
3548                 {
3549                     notOfImm  = NOT_helper(imm, getBitWidth(elemsize));
3550                     canEncode = canEncodeByteShiftedImm(notOfImm, elemsize, true, &bsi);
3551                     if (canEncode)
3552                     {
3553                         imm = bsi.immBSVal;
3554                         ins = INS_mvni; // uses a mvni encoding
3555                         assert(isValidImmBSVal(imm, size));
3556                         fmt = IF_DV_1B;
3557                         break;
3558                     }
3559                 }
3560             }
3561             break;
3562
3563         case INS_orr:
3564         case INS_bic:
3565         case INS_mvni:
3566             assert(isValidVectorDatasize(size));
3567             assert(isVectorRegister(reg));
3568             assert(isValidArrangement(size, opt));
3569             elemsize = optGetElemsize(opt);
3570             assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE)); // Only EA_2BYTE or EA_4BYTE forms
3571
3572             // Vector operation
3573
3574             // No explicit LSL/MSL is used for the immediate
3575             // We will automatically determine the shift based upon the value of imm
3576
3577             // First try the standard 'byteShifted immediate' imm(i8,bySh)
3578             bsi.immBSVal = 0;
3579             canEncode    = canEncodeByteShiftedImm(imm, elemsize,
3580                                                 (ins == INS_mvni), // mvni supports the ones shifting variant (aka MSL)
3581                                                 &bsi);
3582             if (canEncode)
3583             {
3584                 imm = bsi.immBSVal;
3585                 assert(isValidImmBSVal(imm, size));
3586                 fmt = IF_DV_1B;
3587                 break;
3588             }
3589             break;
3590
3591         case INS_cmp:
3592         case INS_cmn:
3593             assert(insOptsNone(opt));
3594             assert(isGeneralRegister(reg));
3595
3596             if (unsigned_abs(imm) <= 0x0fff)
3597             {
3598                 if (imm < 0)
3599                 {
3600                     ins = insReverse(ins);
3601                     imm = -imm;
3602                 }
3603                 assert(isValidUimm12(imm));
3604                 canEncode = true;
3605                 fmt       = IF_DI_1A;
3606             }
3607             else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
3608             {
3609                 // Encoding will use a 12-bit left shift of the immediate
3610                 opt = INS_OPTS_LSL12;
3611                 if (imm < 0)
3612                 {
3613                     ins = insReverse(ins);
3614                     imm = -imm;
3615                 }
3616                 assert((imm & 0xfff) == 0);
3617                 imm >>= 12;
3618                 assert(isValidUimm12(imm));
3619                 canEncode = true;
3620                 fmt       = IF_DI_1A;
3621             }
3622             else
3623             {
3624                 assert(!"Instruction cannot be encoded: IF_DI_1A");
3625             }
3626             break;
3627
3628         default:
3629             unreached();
3630             break;
3631
3632     } // end switch (ins)
3633
3634     assert(canEncode);
3635     assert(fmt != IF_NONE);
3636
3637     instrDesc* id = emitNewInstrSC(attr, imm);
3638
3639     id->idIns(ins);
3640     id->idInsFmt(fmt);
3641     id->idInsOpt(opt);
3642
3643     id->idReg1(reg);
3644
3645     dispIns(id);
3646     appendToCurIG(id);
3647 }
3648
3649 /*****************************************************************************
3650  *
3651  *  Add an instruction referencing a register and a floating point constant.
3652  */
3653
3654 void emitter::emitIns_R_F(
3655     instruction ins, emitAttr attr, regNumber reg, double immDbl, insOpts opt /* = INS_OPTS_NONE */)
3656
3657 {
3658     emitAttr  size      = EA_SIZE(attr);
3659     emitAttr  elemsize  = EA_UNKNOWN;
3660     insFormat fmt       = IF_NONE;
3661     ssize_t   imm       = 0;
3662     bool      canEncode = false;
3663
3664     /* Figure out the encoding format of the instruction */
3665     switch (ins)
3666     {
3667         floatImm8 fpi;
3668
3669         case INS_fcmp:
3670         case INS_fcmpe:
3671             assert(insOptsNone(opt));
3672             assert(isValidVectorElemsizeFloat(size));
3673             assert(isVectorRegister(reg));
3674             if (immDbl == 0.0)
3675             {
3676                 canEncode = true;
3677                 fmt       = IF_DV_1C;
3678             }
3679             break;
3680
3681         case INS_fmov:
3682             assert(isVectorRegister(reg));
3683             fpi.immFPIVal = 0;
3684             canEncode     = canEncodeFloatImm8(immDbl, &fpi);
3685
3686             if (insOptsAnyArrangement(opt))
3687             {
3688                 // Vector operation
3689                 assert(isValidVectorDatasize(size));
3690                 assert(isValidArrangement(size, opt));
3691                 elemsize = optGetElemsize(opt);
3692                 assert(isValidVectorElemsizeFloat(elemsize));
3693                 assert(opt != INS_OPTS_1D); // Reserved encoding
3694
3695                 if (canEncode)
3696                 {
3697                     imm = fpi.immFPIVal;
3698                     assert((imm >= 0) && (imm <= 0xff));
3699                     fmt = IF_DV_1B;
3700                 }
3701             }
3702             else
3703             {
3704                 // Scalar operation
3705                 assert(insOptsNone(opt));
3706                 assert(isValidVectorElemsizeFloat(size));
3707
3708                 if (canEncode)
3709                 {
3710                     imm = fpi.immFPIVal;
3711                     assert((imm >= 0) && (imm <= 0xff));
3712                     fmt = IF_DV_1A;
3713                 }
3714             }
3715             break;
3716
3717         default:
3718             unreached();
3719             break;
3720
3721     } // end switch (ins)
3722
3723     assert(canEncode);
3724     assert(fmt != IF_NONE);
3725
3726     instrDesc* id = emitNewInstrSC(attr, imm);
3727
3728     id->idIns(ins);
3729     id->idInsFmt(fmt);
3730     id->idInsOpt(opt);
3731
3732     id->idReg1(reg);
3733
3734     dispIns(id);
3735     appendToCurIG(id);
3736 }
3737
3738 /*****************************************************************************
3739  *
3740  *  Add an instruction referencing two registers
3741  */
3742
3743 void emitter::emitIns_R_R(
3744     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insOpts opt /* = INS_OPTS_NONE */)
3745 {
3746     emitAttr  size     = EA_SIZE(attr);
3747     emitAttr  elemsize = EA_UNKNOWN;
3748     insFormat fmt      = IF_NONE;
3749
3750     /* Figure out the encoding format of the instruction */
3751     switch (ins)
3752     {
3753         case INS_mov:
3754             assert(insOptsNone(opt));
3755             // Is the mov even necessary?
3756             if (reg1 == reg2)
3757             {
3758                 // A mov with a EA_4BYTE has the side-effect of clearing the upper bits
3759                 // So only eliminate mov instructions that are not clearing the upper bits
3760                 //
3761                 if (isGeneralRegisterOrSP(reg1) && (size == EA_8BYTE))
3762                 {
3763                     return;
3764                 }
3765                 else if (isVectorRegister(reg1) && (size == EA_16BYTE))
3766                 {
3767                     return;
3768                 }
3769             }
3770
3771             // Check for the 'mov' aliases for the vector registers
3772             if (isVectorRegister(reg1))
3773             {
3774                 if (isVectorRegister(reg2) && isValidVectorDatasize(size))
3775                 {
3776                     return emitIns_R_R_R(INS_mov, size, reg1, reg2, reg2);
3777                 }
3778                 else
3779                 {
3780                     return emitIns_R_R_I(INS_mov, size, reg1, reg2, 0);
3781                 }
3782             }
3783             else
3784             {
3785                 if (isVectorRegister(reg2))
3786                 {
3787                     assert(isGeneralRegister(reg1));
3788                     return emitIns_R_R_I(INS_mov, size, reg1, reg2, 0);
3789                 }
3790             }
3791
3792             // Is this a MOV to/from SP instruction?
3793             if ((reg1 == REG_SP) || (reg2 == REG_SP))
3794             {
3795                 assert(isGeneralRegisterOrSP(reg1));
3796                 assert(isGeneralRegisterOrSP(reg2));
3797                 reg1 = encodingSPtoZR(reg1);
3798                 reg2 = encodingSPtoZR(reg2);
3799                 fmt  = IF_DR_2G;
3800             }
3801             else
3802             {
3803                 assert(insOptsNone(opt));
3804                 assert(isGeneralRegister(reg1));
3805                 assert(isGeneralRegisterOrZR(reg2));
3806                 fmt = IF_DR_2E;
3807             }
3808             break;
3809
3810         case INS_dup:
3811             // Vector operation
3812             assert(insOptsAnyArrangement(opt));
3813             assert(isVectorRegister(reg1));
3814             assert(isGeneralRegisterOrZR(reg2));
3815             assert(isValidVectorDatasize(size));
3816             assert(isValidArrangement(size, opt));
3817             fmt = IF_DV_2C;
3818             break;
3819
3820         case INS_abs:
3821         case INS_not:
3822             assert(isVectorRegister(reg1));
3823             assert(isVectorRegister(reg2));
3824             // for 'NOT' we can construct the arrangement: 8B or 16B
3825             if ((ins == INS_not) && insOptsNone(opt))
3826             {
3827                 assert(isValidVectorDatasize(size));
3828                 elemsize = EA_1BYTE;
3829                 opt      = optMakeArrangement(size, elemsize);
3830             }
3831             if (insOptsNone(opt))
3832             {
3833                 // Scalar operation
3834                 assert(size == EA_8BYTE); // Only type D is supported
3835                 fmt = IF_DV_2L;
3836             }
3837             else
3838             {
3839                 // Vector operation
3840                 assert(insOptsAnyArrangement(opt));
3841                 assert(isValidVectorDatasize(size));
3842                 assert(isValidArrangement(size, opt));
3843                 elemsize = optGetElemsize(opt);
3844                 if (ins == INS_not)
3845                 {
3846                     assert(elemsize == EA_1BYTE);
3847                 }
3848                 fmt = IF_DV_2M;
3849             }
3850             break;
3851
3852         case INS_mvn:
3853         case INS_neg:
3854             if (isVectorRegister(reg1))
3855             {
3856                 assert(isVectorRegister(reg2));
3857                 // for 'mvn' we can construct the arrangement: 8B or 16b
3858                 if ((ins == INS_mvn) && insOptsNone(opt))
3859                 {
3860                     assert(isValidVectorDatasize(size));
3861                     elemsize = EA_1BYTE;
3862                     opt      = optMakeArrangement(size, elemsize);
3863                 }
3864                 if (insOptsNone(opt))
3865                 {
3866                     // Scalar operation
3867                     assert(size == EA_8BYTE); // Only type D is supported
3868                     fmt = IF_DV_2L;
3869                 }
3870                 else
3871                 {
3872                     // Vector operation
3873                     assert(isValidVectorDatasize(size));
3874                     assert(isValidArrangement(size, opt));
3875                     elemsize = optGetElemsize(opt);
3876                     if (ins == INS_mvn)
3877                     {
3878                         assert(elemsize == EA_1BYTE); // Only supports 8B or 16B
3879                     }
3880                     fmt = IF_DV_2M;
3881                 }
3882                 break;
3883             }
3884             __fallthrough;
3885
3886         case INS_negs:
3887             assert(insOptsNone(opt));
3888             assert(isGeneralRegister(reg1));
3889             assert(isGeneralRegisterOrZR(reg2));
3890             fmt = IF_DR_2E;
3891             break;
3892
3893         case INS_sxtw:
3894             assert(size == EA_8BYTE);
3895             __fallthrough;
3896
3897         case INS_sxtb:
3898         case INS_sxth:
3899         case INS_uxtb:
3900         case INS_uxth:
3901             assert(insOptsNone(opt));
3902             assert(isValidGeneralDatasize(size));
3903             assert(isGeneralRegister(reg1));
3904             assert(isGeneralRegister(reg2));
3905             fmt = IF_DR_2H;
3906             break;
3907
3908         case INS_sxtl:
3909         case INS_sxtl2:
3910         case INS_uxtl:
3911         case INS_uxtl2:
3912             return emitIns_R_R_I(ins, size, reg1, reg2, 0, opt);
3913
3914         case INS_cls:
3915         case INS_clz:
3916         case INS_rbit:
3917         case INS_rev16:
3918         case INS_rev32:
3919         case INS_cnt:
3920             if (isVectorRegister(reg1))
3921             {
3922                 assert(isVectorRegister(reg2));
3923                 assert(isValidVectorDatasize(size));
3924                 assert(isValidArrangement(size, opt));
3925                 elemsize = optGetElemsize(opt);
3926                 if ((ins == INS_cls) || (ins == INS_clz))
3927                 {
3928                     assert(elemsize != EA_8BYTE); // No encoding for type D
3929                 }
3930                 else if (ins == INS_rev32)
3931                 {
3932                     assert((elemsize == EA_2BYTE) || (elemsize == EA_1BYTE));
3933                 }
3934                 else
3935                 {
3936                     assert(elemsize == EA_1BYTE); // Only supports 8B or 16B
3937                 }
3938                 fmt = IF_DV_2M;
3939                 break;
3940             }
3941             if (ins == INS_cnt)
3942             {
3943                 // Doesn't have general register version(s)
3944                 break;
3945             }
3946
3947             __fallthrough;
3948
3949         case INS_rev:
3950             assert(insOptsNone(opt));
3951             assert(isGeneralRegister(reg1));
3952             assert(isGeneralRegister(reg2));
3953             if (ins == INS_rev32)
3954             {
3955                 assert(size == EA_8BYTE);
3956             }
3957             else
3958             {
3959                 assert(isValidGeneralDatasize(size));
3960             }
3961             fmt = IF_DR_2G;
3962             break;
3963
3964         case INS_addv:
3965         case INS_saddlv:
3966         case INS_smaxv:
3967         case INS_sminv:
3968         case INS_uaddlv:
3969         case INS_umaxv:
3970         case INS_uminv:
3971         case INS_rev64:
3972             assert(isVectorRegister(reg1));
3973             assert(isVectorRegister(reg2));
3974             assert(isValidVectorDatasize(size));
3975             assert(isValidArrangement(size, opt));
3976             elemsize = optGetElemsize(opt);
3977             assert(elemsize != EA_8BYTE); // No encoding for type D
3978             fmt = IF_DV_2M;
3979             break;
3980
3981         case INS_xtn:
3982         case INS_xtn2:
3983             assert(isVectorRegister(reg1));
3984             assert(isVectorRegister(reg2));
3985             assert(isValidVectorDatasize(size));
3986             assert(isValidArrangement(size, opt));
3987             elemsize = optGetElemsize(opt);
3988             assert(size != EA_16BYTE);    // Narrowing must start with wide format
3989             assert(elemsize != EA_1BYTE); // Narrowing must start with more than one byte src
3990             fmt = IF_DV_2M;
3991             break;
3992
3993         case INS_ldar:
3994         case INS_ldaxr:
3995         case INS_ldxr:
3996         case INS_stlr:
3997             assert(isValidGeneralDatasize(size));
3998
3999             __fallthrough;
4000
4001         case INS_ldarb:
4002         case INS_ldaxrb:
4003         case INS_ldxrb:
4004         case INS_ldarh:
4005         case INS_ldaxrh:
4006         case INS_ldxrh:
4007         case INS_stlrb:
4008         case INS_stlrh:
4009             assert(isValidGeneralLSDatasize(size));
4010             assert(isGeneralRegisterOrZR(reg1));
4011             assert(isGeneralRegisterOrSP(reg2));
4012             assert(insOptsNone(opt));
4013
4014             reg2 = encodingSPtoZR(reg2);
4015
4016             fmt = IF_LS_2A;
4017             break;
4018
4019         case INS_ldr:
4020         case INS_ldrb:
4021         case INS_ldrh:
4022         case INS_ldrsb:
4023         case INS_ldrsh:
4024         case INS_ldrsw:
4025         case INS_str:
4026         case INS_strb:
4027         case INS_strh:
4028
4029         case INS_cmp:
4030         case INS_cmn:
4031         case INS_tst:
4032             assert(insOptsNone(opt));
4033             emitIns_R_R_I(ins, attr, reg1, reg2, 0, INS_OPTS_NONE);
4034             return;
4035
4036         case INS_fmov:
4037             assert(isValidVectorElemsizeFloat(size));
4038
4039             // Is the mov even necessary?
4040             if (reg1 == reg2)
4041             {
4042                 return;
4043             }
4044
4045             if (isVectorRegister(reg1))
4046             {
4047                 if (isVectorRegister(reg2))
4048                 {
4049                     assert(insOptsNone(opt));
4050                     fmt = IF_DV_2G;
4051                 }
4052                 else
4053                 {
4054                     assert(isGeneralRegister(reg2));
4055
4056                     // if the optional conversion specifier is not present we calculate it
4057                     if (opt == INS_OPTS_NONE)
4058                     {
4059                         opt = (size == EA_4BYTE) ? INS_OPTS_4BYTE_TO_S : INS_OPTS_8BYTE_TO_D;
4060                     }
4061                     assert(insOptsConvertIntToFloat(opt));
4062
4063                     fmt = IF_DV_2I;
4064                 }
4065             }
4066             else
4067             {
4068                 assert(isGeneralRegister(reg1));
4069                 assert(isVectorRegister(reg2));
4070
4071                 // if the optional conversion specifier is not present we calculate it
4072                 if (opt == INS_OPTS_NONE)
4073                 {
4074                     opt = (size == EA_4BYTE) ? INS_OPTS_S_TO_4BYTE : INS_OPTS_D_TO_8BYTE;
4075                 }
4076                 assert(insOptsConvertFloatToInt(opt));
4077
4078                 fmt = IF_DV_2H;
4079             }
4080             break;
4081
4082         case INS_fcmp:
4083         case INS_fcmpe:
4084             assert(insOptsNone(opt));
4085             assert(isValidVectorElemsizeFloat(size));
4086             assert(isVectorRegister(reg1));
4087             assert(isVectorRegister(reg2));
4088             fmt = IF_DV_2K;
4089             break;
4090
4091         case INS_fcvtns:
4092         case INS_fcvtnu:
4093         case INS_fcvtas:
4094         case INS_fcvtau:
4095         case INS_fcvtps:
4096         case INS_fcvtpu:
4097         case INS_fcvtms:
4098         case INS_fcvtmu:
4099         case INS_fcvtzs:
4100         case INS_fcvtzu:
4101             if (insOptsAnyArrangement(opt))
4102             {
4103                 // Vector operation
4104                 assert(isVectorRegister(reg1));
4105                 assert(isVectorRegister(reg2));
4106                 assert(isValidVectorDatasize(size));
4107                 assert(isValidArrangement(size, opt));
4108                 elemsize = optGetElemsize(opt);
4109                 assert(isValidVectorElemsizeFloat(elemsize));
4110                 assert(opt != INS_OPTS_1D); // Reserved encoding
4111                 fmt = IF_DV_2A;
4112             }
4113             else
4114             {
4115                 // Scalar operation
4116                 assert(isVectorRegister(reg2));
4117                 if (isVectorRegister(reg1))
4118                 {
4119                     assert(insOptsNone(opt));
4120                     assert(isValidVectorElemsizeFloat(size));
4121                     fmt = IF_DV_2G;
4122                 }
4123                 else
4124                 {
4125                     assert(isGeneralRegister(reg1));
4126                     assert(insOptsConvertFloatToInt(opt));
4127                     assert(isValidVectorElemsizeFloat(size));
4128                     fmt = IF_DV_2H;
4129                 }
4130             }
4131             break;
4132
4133         case INS_fcvtl:
4134         case INS_fcvtl2:
4135             assert(isVectorRegister(reg1));
4136             assert(isVectorRegister(reg2));
4137             assert(isValidVectorDatasize(size));
4138             assert(isValidArrangement(size, opt));
4139             elemsize = optGetElemsize(opt);
4140             assert(elemsize == EA_4BYTE); // Widening from Float to Double, opt should correspond to src layout
4141             fmt = IF_DV_2G;
4142             break;
4143
4144         case INS_fcvtn:
4145         case INS_fcvtn2:
4146             assert(isVectorRegister(reg1));
4147             assert(isVectorRegister(reg2));
4148             assert(isValidVectorDatasize(size));
4149             assert(isValidArrangement(size, opt));
4150             elemsize = optGetElemsize(opt);
4151             assert(elemsize == EA_8BYTE); // Narrowing from Double to Float, opt should correspond to src layout
4152             fmt = IF_DV_2G;
4153             break;
4154
4155         case INS_scvtf:
4156         case INS_ucvtf:
4157             if (insOptsAnyArrangement(opt))
4158             {
4159                 // Vector operation
4160                 assert(isVectorRegister(reg1));
4161                 assert(isVectorRegister(reg2));
4162                 assert(isValidVectorDatasize(size));
4163                 assert(isValidArrangement(size, opt));
4164                 elemsize = optGetElemsize(opt);
4165                 assert(isValidVectorElemsizeFloat(elemsize));
4166                 assert(opt != INS_OPTS_1D); // Reserved encoding
4167                 fmt = IF_DV_2A;
4168             }
4169             else
4170             {
4171                 // Scalar operation
4172                 assert(isVectorRegister(reg1));
4173                 if (isVectorRegister(reg2))
4174                 {
4175                     assert(insOptsNone(opt));
4176                     assert(isValidVectorElemsizeFloat(size));
4177                     fmt = IF_DV_2G;
4178                 }
4179                 else
4180                 {
4181                     assert(isGeneralRegister(reg2));
4182                     assert(insOptsConvertIntToFloat(opt));
4183                     assert(isValidVectorElemsizeFloat(size));
4184                     fmt = IF_DV_2I;
4185                 }
4186             }
4187             break;
4188
4189         case INS_fabs:
4190         case INS_fneg:
4191         case INS_fsqrt:
4192         case INS_frinta:
4193         case INS_frinti:
4194         case INS_frintm:
4195         case INS_frintn:
4196         case INS_frintp:
4197         case INS_frintx:
4198         case INS_frintz:
4199             if (insOptsAnyArrangement(opt))
4200             {
4201                 // Vector operation
4202                 assert(isVectorRegister(reg1));
4203                 assert(isVectorRegister(reg2));
4204                 assert(isValidVectorDatasize(size));
4205                 assert(isValidArrangement(size, opt));
4206                 elemsize = optGetElemsize(opt);
4207                 assert(isValidVectorElemsizeFloat(elemsize));
4208                 assert(opt != INS_OPTS_1D); // Reserved encoding
4209                 fmt = IF_DV_2A;
4210             }
4211             else
4212             {
4213                 // Scalar operation
4214                 assert(insOptsNone(opt));
4215                 assert(isValidVectorElemsizeFloat(size));
4216                 assert(isVectorRegister(reg1));
4217                 assert(isVectorRegister(reg2));
4218                 fmt = IF_DV_2G;
4219             }
4220             break;
4221
4222         case INS_faddp:
4223             // Scalar operation
4224             assert(insOptsNone(opt));
4225             assert(isValidVectorElemsizeFloat(size));
4226             assert(isVectorRegister(reg1));
4227             assert(isVectorRegister(reg2));
4228             fmt = IF_DV_2G;
4229             break;
4230
4231         case INS_fcvt:
4232             assert(insOptsConvertFloatToFloat(opt));
4233             assert(isValidVectorFcvtsize(size));
4234             assert(isVectorRegister(reg1));
4235             assert(isVectorRegister(reg2));
4236             fmt = IF_DV_2J;
4237             break;
4238
4239         default:
4240             unreached();
4241             break;
4242
4243     } // end switch (ins)
4244
4245     assert(fmt != IF_NONE);
4246
4247     instrDesc* id = emitNewInstrSmall(attr);
4248
4249     id->idIns(ins);
4250     id->idInsFmt(fmt);
4251     id->idInsOpt(opt);
4252
4253     id->idReg1(reg1);
4254     id->idReg2(reg2);
4255
4256     dispIns(id);
4257     appendToCurIG(id);
4258 }
4259
4260 /*****************************************************************************
4261  *
4262  *  Add an instruction referencing a register and two constants.
4263  */
4264
4265 void emitter::emitIns_R_I_I(
4266     instruction ins, emitAttr attr, regNumber reg, ssize_t imm1, ssize_t imm2, insOpts opt /* = INS_OPTS_NONE */)
4267 {
4268     emitAttr  size   = EA_SIZE(attr);
4269     insFormat fmt    = IF_NONE;
4270     size_t    immOut = 0; // composed from imm1 and imm2 and stored in the instrDesc
4271
4272     /* Figure out the encoding format of the instruction */
4273     switch (ins)
4274     {
4275         bool        canEncode;
4276         halfwordImm hwi;
4277
4278         case INS_mov:
4279             ins = INS_movz; // INS_mov with LSL is an alias for INS_movz LSL
4280             __fallthrough;
4281
4282         case INS_movk:
4283         case INS_movn:
4284         case INS_movz:
4285             assert(isValidGeneralDatasize(size));
4286             assert(isGeneralRegister(reg));
4287             assert(isValidUimm16(imm1));
4288             assert(insOptsLSL(opt)); // Must be INS_OPTS_LSL
4289
4290             if (size == EA_8BYTE)
4291             {
4292                 assert((imm2 == 0) || (imm2 == 16) || // shift amount: 0, 16, 32 or 48
4293                        (imm2 == 32) || (imm2 == 48));
4294             }
4295             else // EA_4BYTE
4296             {
4297                 assert((imm2 == 0) || (imm2 == 16)); // shift amount: 0 or 16
4298             }
4299
4300             hwi.immHWVal = 0;
4301
4302             switch (imm2)
4303             {
4304                 case 0:
4305                     hwi.immHW = 0;
4306                     canEncode = true;
4307                     break;
4308
4309                 case 16:
4310                     hwi.immHW = 1;
4311                     canEncode = true;
4312                     break;
4313
4314                 case 32:
4315                     hwi.immHW = 2;
4316                     canEncode = true;
4317                     break;
4318
4319                 case 48:
4320                     hwi.immHW = 3;
4321                     canEncode = true;
4322                     break;
4323
4324                 default:
4325                     canEncode = false;
4326             }
4327
4328             if (canEncode)
4329             {
4330                 hwi.immVal = imm1;
4331
4332                 immOut = hwi.immHWVal;
4333                 assert(isValidImmHWVal(immOut, size));
4334                 fmt = IF_DI_1B;
4335             }
4336             break;
4337
4338         default:
4339             unreached();
4340             break;
4341
4342     } // end switch (ins)
4343
4344     assert(fmt != IF_NONE);
4345
4346     instrDesc* id = emitNewInstrSC(attr, immOut);
4347
4348     id->idIns(ins);
4349     id->idInsFmt(fmt);
4350
4351     id->idReg1(reg);
4352
4353     dispIns(id);
4354     appendToCurIG(id);
4355 }
4356
4357 /*****************************************************************************
4358  *
4359  *  Add an instruction referencing two registers and a constant.
4360  */
4361
4362 void emitter::emitIns_R_R_I(
4363     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm, insOpts opt /* = INS_OPTS_NONE */)
4364 {
4365     emitAttr  size       = EA_SIZE(attr);
4366     emitAttr  elemsize   = EA_UNKNOWN;
4367     insFormat fmt        = IF_NONE;
4368     bool      isLdSt     = false;
4369     bool      isSIMD     = false;
4370     bool      isAddSub   = false;
4371     bool      setFlags   = false;
4372     unsigned  scale      = 0;
4373     bool      unscaledOp = false;
4374
4375     /* Figure out the encoding format of the instruction */
4376     switch (ins)
4377     {
4378         bool       canEncode;
4379         bitMaskImm bmi;
4380
4381         case INS_mov:
4382             // Check for the 'mov' aliases for the vector registers
4383             assert(insOptsNone(opt));
4384             assert(isValidVectorElemsize(size));
4385             elemsize = size;
4386             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4387
4388             if (isVectorRegister(reg1))
4389             {
4390                 if (isGeneralRegisterOrZR(reg2))
4391                 {
4392                     fmt = IF_DV_2C; // Alias for 'ins'
4393                     break;
4394                 }
4395                 else if (isVectorRegister(reg2))
4396                 {
4397                     fmt = IF_DV_2E; // Alias for 'dup'
4398                     break;
4399                 }
4400             }
4401             else // isGeneralRegister(reg1)
4402             {
4403                 assert(isGeneralRegister(reg1));
4404                 if (isVectorRegister(reg2))
4405                 {
4406                     fmt = IF_DV_2B; // Alias for 'umov'
4407                     break;
4408                 }
4409             }
4410             assert(!" invalid INS_mov operands");
4411             break;
4412
4413         case INS_lsl:
4414         case INS_lsr:
4415         case INS_asr:
4416             assert(insOptsNone(opt));
4417             assert(isValidGeneralDatasize(size));
4418             assert(isGeneralRegister(reg1));
4419             assert(isGeneralRegister(reg2));
4420             assert(isValidImmShift(imm, size));
4421             fmt = IF_DI_2D;
4422             break;
4423
4424         case INS_ror:
4425             assert(insOptsNone(opt));
4426             assert(isValidGeneralDatasize(size));
4427             assert(isGeneralRegister(reg1));
4428             assert(isGeneralRegister(reg2));
4429             assert(isValidImmShift(imm, size));
4430             fmt = IF_DI_2B;
4431             break;
4432
4433         case INS_sshr:
4434         case INS_ssra:
4435         case INS_srshr:
4436         case INS_srsra:
4437         case INS_shl:
4438         case INS_ushr:
4439         case INS_usra:
4440         case INS_urshr:
4441         case INS_ursra:
4442         case INS_sri:
4443         case INS_sli:
4444             assert(isVectorRegister(reg1));
4445             assert(isVectorRegister(reg2));
4446             if (insOptsAnyArrangement(opt))
4447             {
4448                 // Vector operation
4449                 assert(isValidVectorDatasize(size));
4450                 assert(isValidArrangement(size, opt));
4451                 elemsize = optGetElemsize(opt);
4452                 assert(isValidVectorElemsize(elemsize));
4453                 assert(isValidImmShift(imm, elemsize));
4454                 assert(opt != INS_OPTS_1D); // Reserved encoding
4455                 fmt = IF_DV_2O;
4456                 break;
4457             }
4458             else
4459             {
4460                 // Scalar operation
4461                 assert(insOptsNone(opt));
4462                 assert(size == EA_8BYTE); // only supported size
4463                 assert(isValidImmShift(imm, size));
4464                 fmt = IF_DV_2N;
4465             }
4466             break;
4467
4468         case INS_sxtl:
4469         case INS_uxtl:
4470             assert(imm == 0);
4471             __fallthrough;
4472
4473         case INS_shrn:
4474         case INS_rshrn:
4475         case INS_sshll:
4476         case INS_ushll:
4477             assert(isVectorRegister(reg1));
4478             assert(isVectorRegister(reg2));
4479             // Vector operation
4480             assert(size == EA_8BYTE);
4481             assert(isValidArrangement(size, opt));
4482             elemsize = optGetElemsize(opt);
4483             assert(elemsize != EA_8BYTE); // Reserved encodings
4484             assert(isValidVectorElemsize(elemsize));
4485             assert(isValidImmShift(imm, elemsize));
4486             fmt = IF_DV_2O;
4487             break;
4488
4489         case INS_sxtl2:
4490         case INS_uxtl2:
4491             assert(imm == 0);
4492             __fallthrough;
4493
4494         case INS_shrn2:
4495         case INS_rshrn2:
4496         case INS_sshll2:
4497         case INS_ushll2:
4498             assert(isVectorRegister(reg1));
4499             assert(isVectorRegister(reg2));
4500             // Vector operation
4501             assert(size == EA_16BYTE);
4502             assert(isValidArrangement(size, opt));
4503             elemsize = optGetElemsize(opt);
4504             assert(elemsize != EA_8BYTE); // Reserved encodings
4505             assert(isValidVectorElemsize(elemsize));
4506             assert(isValidImmShift(imm, elemsize));
4507             fmt = IF_DV_2O;
4508             break;
4509
4510         case INS_mvn:
4511         case INS_neg:
4512         case INS_negs:
4513             assert(isValidGeneralDatasize(size));
4514             assert(isGeneralRegister(reg1));
4515             assert(isGeneralRegisterOrZR(reg2));
4516
4517             if (imm == 0)
4518             {
4519                 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4520
4521                 fmt = IF_DR_2E;
4522             }
4523             else
4524             {
4525                 if (ins == INS_mvn)
4526                 {
4527                     assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
4528                 }
4529                 else // neg or negs
4530                 {
4531                     assert(insOptsAluShift(opt)); // a non-zero imm, must select shift kind, can't use ROR
4532                 }
4533                 assert(isValidImmShift(imm, size));
4534                 fmt = IF_DR_2F;
4535             }
4536             break;
4537
4538         case INS_tst:
4539             assert(isValidGeneralDatasize(size));
4540             assert(isGeneralRegisterOrZR(reg1));
4541             assert(isGeneralRegister(reg2));
4542
4543             if (insOptsAnyShift(opt))
4544             {
4545                 assert(isValidImmShift(imm, size) && (imm != 0));
4546                 fmt = IF_DR_2B;
4547             }
4548             else
4549             {
4550                 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4551                 assert(imm == 0);
4552                 fmt = IF_DR_2A;
4553             }
4554             break;
4555
4556         case INS_cmp:
4557         case INS_cmn:
4558             assert(isValidGeneralDatasize(size));
4559             assert(isGeneralRegisterOrSP(reg1));
4560             assert(isGeneralRegister(reg2));
4561
4562             reg1 = encodingSPtoZR(reg1);
4563             if (insOptsAnyExtend(opt))
4564             {
4565                 assert((imm >= 0) && (imm <= 4));
4566
4567                 fmt = IF_DR_2C;
4568             }
4569             else if (imm == 0)
4570             {
4571                 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4572
4573                 fmt = IF_DR_2A;
4574             }
4575             else
4576             {
4577                 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
4578                 assert(isValidImmShift(imm, size));
4579                 fmt = IF_DR_2B;
4580             }
4581             break;
4582
4583         case INS_ands:
4584         case INS_and:
4585         case INS_eor:
4586         case INS_orr:
4587             assert(insOptsNone(opt));
4588             assert(isGeneralRegister(reg2));
4589             if (ins == INS_ands)
4590             {
4591                 assert(isGeneralRegister(reg1));
4592             }
4593             else
4594             {
4595                 assert(isGeneralRegisterOrSP(reg1));
4596                 reg1 = encodingSPtoZR(reg1);
4597             }
4598
4599             bmi.immNRS = 0;
4600             canEncode  = canEncodeBitMaskImm(imm, size, &bmi);
4601             if (canEncode)
4602             {
4603                 imm = bmi.immNRS;
4604                 assert(isValidImmNRS(imm, size));
4605                 fmt = IF_DI_2C;
4606             }
4607             break;
4608
4609         case INS_dup: // by element, imm selects the element of reg2
4610             assert(isVectorRegister(reg1));
4611             if (isVectorRegister(reg2))
4612             {
4613                 if (insOptsAnyArrangement(opt))
4614                 {
4615                     // Vector operation
4616                     assert(isValidVectorDatasize(size));
4617                     assert(isValidArrangement(size, opt));
4618                     elemsize = optGetElemsize(opt);
4619                     assert(isValidVectorElemsize(elemsize));
4620                     assert(isValidVectorIndex(size, elemsize, imm));
4621                     assert(opt != INS_OPTS_1D); // Reserved encoding
4622                     fmt = IF_DV_2D;
4623                     break;
4624                 }
4625                 else
4626                 {
4627                     // Scalar operation
4628                     assert(insOptsNone(opt));
4629                     elemsize = size;
4630                     assert(isValidVectorElemsize(elemsize));
4631                     assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4632                     fmt = IF_DV_2E;
4633                     break;
4634                 }
4635             }
4636             __fallthrough;
4637
4638         case INS_ins: // (MOV from general)
4639             assert(insOptsNone(opt));
4640             assert(isValidVectorElemsize(size));
4641             assert(isVectorRegister(reg1));
4642             assert(isGeneralRegisterOrZR(reg2));
4643             elemsize = size;
4644             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4645             fmt = IF_DV_2C;
4646             break;
4647
4648         case INS_umov: // (MOV to general)
4649             assert(insOptsNone(opt));
4650             assert(isValidVectorElemsize(size));
4651             assert(isGeneralRegister(reg1));
4652             assert(isVectorRegister(reg2));
4653             elemsize = size;
4654             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4655             fmt = IF_DV_2B;
4656             break;
4657
4658         case INS_smov:
4659             assert(insOptsNone(opt));
4660             assert(isValidVectorElemsize(size));
4661             assert(size != EA_8BYTE); // no encoding, use INS_umov
4662             assert(isGeneralRegister(reg1));
4663             assert(isVectorRegister(reg2));
4664             elemsize = size;
4665             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4666             fmt = IF_DV_2B;
4667             break;
4668
4669         case INS_add:
4670         case INS_sub:
4671             setFlags = false;
4672             isAddSub = true;
4673             break;
4674
4675         case INS_adds:
4676         case INS_subs:
4677             setFlags = true;
4678             isAddSub = true;
4679             break;
4680
4681         case INS_ldrsb:
4682         case INS_ldursb:
4683             // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4684             assert(isValidGeneralDatasize(size));
4685             unscaledOp = (ins == INS_ldursb);
4686             scale      = 0;
4687             isLdSt     = true;
4688             break;
4689
4690         case INS_ldrsh:
4691         case INS_ldursh:
4692             // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4693             assert(isValidGeneralDatasize(size));
4694             unscaledOp = (ins == INS_ldursh);
4695             scale      = 1;
4696             isLdSt     = true;
4697             break;
4698
4699         case INS_ldrsw:
4700         case INS_ldursw:
4701             // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4702             assert(size == EA_8BYTE);
4703             unscaledOp = (ins == INS_ldursw);
4704             scale      = 2;
4705             isLdSt     = true;
4706             break;
4707
4708         case INS_ldrb:
4709         case INS_strb:
4710             // size is ignored
4711             unscaledOp = false;
4712             scale      = 0;
4713             isLdSt     = true;
4714             break;
4715
4716         case INS_ldurb:
4717         case INS_sturb:
4718             // size is ignored
4719             unscaledOp = true;
4720             scale      = 0;
4721             isLdSt     = true;
4722             break;
4723
4724         case INS_ldrh:
4725         case INS_strh:
4726             // size is ignored
4727             unscaledOp = false;
4728             scale      = 1;
4729             isLdSt     = true;
4730             break;
4731
4732         case INS_ldurh:
4733         case INS_sturh:
4734             // size is ignored
4735             unscaledOp = true;
4736             scale      = 0;
4737             isLdSt     = true;
4738             break;
4739
4740         case INS_ldr:
4741         case INS_str:
4742             // Is the target a vector register?
4743             if (isVectorRegister(reg1))
4744             {
4745                 assert(isValidVectorLSDatasize(size));
4746                 assert(isGeneralRegisterOrSP(reg2));
4747                 isSIMD = true;
4748             }
4749             else
4750             {
4751                 assert(isValidGeneralDatasize(size));
4752             }
4753             unscaledOp = false;
4754             scale      = NaturalScale_helper(size);
4755             isLdSt     = true;
4756             break;
4757
4758         case INS_ldur:
4759         case INS_stur:
4760             // Is the target a vector register?
4761             if (isVectorRegister(reg1))
4762             {
4763                 assert(isValidVectorLSDatasize(size));
4764                 assert(isGeneralRegisterOrSP(reg2));
4765                 isSIMD = true;
4766             }
4767             else
4768             {
4769                 assert(isValidGeneralDatasize(size));
4770             }
4771             unscaledOp = true;
4772             scale      = 0;
4773             isLdSt     = true;
4774             break;
4775
4776         default:
4777             unreached();
4778             break;
4779
4780     } // end switch (ins)
4781
4782     if (isLdSt)
4783     {
4784         assert(!isAddSub);
4785
4786         if (isSIMD)
4787         {
4788             assert(isValidVectorLSDatasize(size));
4789             assert(isVectorRegister(reg1));
4790             assert((scale >= 0) && (scale <= 4));
4791         }
4792         else
4793         {
4794             assert(isValidGeneralLSDatasize(size));
4795             assert(isGeneralRegisterOrZR(reg1));
4796             assert((scale >= 0) && (scale <= 3));
4797         }
4798
4799         assert(isGeneralRegisterOrSP(reg2));
4800
4801         // Load/Store reserved encodings:
4802         if (insOptsIndexed(opt))
4803         {
4804             assert(reg1 != reg2);
4805         }
4806
4807         reg2 = encodingSPtoZR(reg2);
4808
4809         ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
4810         if (imm == 0)
4811         {
4812             assert(insOptsNone(opt)); // PRE/POST Index doesn't make sense with an immediate of zero
4813
4814             fmt = IF_LS_2A;
4815         }
4816         else if (insOptsIndexed(opt) || unscaledOp || (imm < 0) || ((imm & mask) != 0))
4817         {
4818             if ((imm >= -256) && (imm <= 255))
4819             {
4820                 fmt = IF_LS_2C;
4821             }
4822             else
4823             {
4824                 assert(!"Instruction cannot be encoded: IF_LS_2C");
4825             }
4826         }
4827         else if (imm > 0)
4828         {
4829             assert(insOptsNone(opt));
4830             assert(!unscaledOp);
4831
4832             if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
4833             {
4834                 imm >>= scale; // The immediate is scaled by the size of the ld/st
4835
4836                 fmt = IF_LS_2B;
4837             }
4838             else
4839             {
4840                 assert(!"Instruction cannot be encoded: IF_LS_2B");
4841             }
4842         }
4843     }
4844     else if (isAddSub)
4845     {
4846         assert(!isLdSt);
4847         assert(insOptsNone(opt));
4848
4849         if (setFlags) // Can't encode SP with setFlags
4850         {
4851             assert(isGeneralRegister(reg1));
4852             assert(isGeneralRegister(reg2));
4853         }
4854         else
4855         {
4856             assert(isGeneralRegisterOrSP(reg1));
4857             assert(isGeneralRegisterOrSP(reg2));
4858
4859             // Is it just a mov?
4860             if (imm == 0)
4861             {
4862                 // Is the mov even necessary?
4863                 if (reg1 != reg2)
4864                 {
4865                     emitIns_R_R(INS_mov, attr, reg1, reg2);
4866                 }
4867                 return;
4868             }
4869
4870             reg1 = encodingSPtoZR(reg1);
4871             reg2 = encodingSPtoZR(reg2);
4872         }
4873
4874         if (unsigned_abs(imm) <= 0x0fff)
4875         {
4876             if (imm < 0)
4877             {
4878                 ins = insReverse(ins);
4879                 imm = -imm;
4880             }
4881             assert(isValidUimm12(imm));
4882             fmt = IF_DI_2A;
4883         }
4884         else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
4885         {
4886             // Encoding will use a 12-bit left shift of the immediate
4887             opt = INS_OPTS_LSL12;
4888             if (imm < 0)
4889             {
4890                 ins = insReverse(ins);
4891                 imm = -imm;
4892             }
4893             assert((imm & 0xfff) == 0);
4894             imm >>= 12;
4895             assert(isValidUimm12(imm));
4896             fmt = IF_DI_2A;
4897         }
4898         else
4899         {
4900             assert(!"Instruction cannot be encoded: IF_DI_2A");
4901         }
4902     }
4903
4904     assert(fmt != IF_NONE);
4905
4906     instrDesc* id = emitNewInstrSC(attr, imm);
4907
4908     id->idIns(ins);
4909     id->idInsFmt(fmt);
4910     id->idInsOpt(opt);
4911
4912     id->idReg1(reg1);
4913     id->idReg2(reg2);
4914
4915     dispIns(id);
4916     appendToCurIG(id);
4917 }
4918
4919 /*****************************************************************************
4920 *
4921 *  Add an instruction referencing two registers and a constant.
4922 *  Also checks for a large immediate that needs a second instruction
4923 *  and will load it in reg1
4924 *
4925 *  - Supports instructions: add, adds, sub, subs, and, ands, eor and orr
4926 *  - Requires that reg1 is a general register and not SP or ZR
4927 *  - Requires that reg1 != reg2
4928 */
4929 void emitter::emitIns_R_R_Imm(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm)
4930 {
4931     assert(isGeneralRegister(reg1));
4932     assert(reg1 != reg2);
4933
4934     bool immFits = true;
4935
4936     switch (ins)
4937     {
4938         case INS_add:
4939         case INS_adds:
4940         case INS_sub:
4941         case INS_subs:
4942             immFits = emitter::emitIns_valid_imm_for_add(imm, attr);
4943             break;
4944
4945         case INS_ands:
4946         case INS_and:
4947         case INS_eor:
4948         case INS_orr:
4949             immFits = emitter::emitIns_valid_imm_for_alu(imm, attr);
4950             break;
4951
4952         default:
4953             assert(!"Unsupported instruction in emitIns_R_R_Imm");
4954     }
4955
4956     if (immFits)
4957     {
4958         emitIns_R_R_I(ins, attr, reg1, reg2, imm);
4959     }
4960     else
4961     {
4962         // Load 'imm' into the reg1 register
4963         // then issue:   'ins'  reg1, reg2, reg1
4964         //
4965         codeGen->instGen_Set_Reg_To_Imm(attr, reg1, imm);
4966         emitIns_R_R_R(ins, attr, reg1, reg2, reg1);
4967     }
4968 }
4969
4970 /*****************************************************************************
4971  *
4972  *  Add an instruction referencing three registers.
4973  */
4974
4975 void emitter::emitIns_R_R_R(
4976     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insOpts opt) /* = INS_OPTS_NONE */
4977 {
4978     emitAttr  size     = EA_SIZE(attr);
4979     emitAttr  elemsize = EA_UNKNOWN;
4980     insFormat fmt      = IF_NONE;
4981
4982     /* Figure out the encoding format of the instruction */
4983     switch (ins)
4984     {
4985         case INS_lsl:
4986         case INS_lsr:
4987         case INS_asr:
4988         case INS_ror:
4989         case INS_adc:
4990         case INS_adcs:
4991         case INS_sbc:
4992         case INS_sbcs:
4993         case INS_udiv:
4994         case INS_sdiv:
4995         case INS_mneg:
4996         case INS_smull:
4997         case INS_smnegl:
4998         case INS_smulh:
4999         case INS_umull:
5000         case INS_umnegl:
5001         case INS_umulh:
5002         case INS_lslv:
5003         case INS_lsrv:
5004         case INS_asrv:
5005         case INS_rorv:
5006             assert(insOptsNone(opt));
5007             assert(isValidGeneralDatasize(size));
5008             assert(isGeneralRegister(reg1));
5009             assert(isGeneralRegister(reg2));
5010             assert(isGeneralRegister(reg3));
5011             fmt = IF_DR_3A;
5012             break;
5013
5014         case INS_mul:
5015             if (insOptsNone(opt))
5016             {
5017                 // general register
5018                 assert(isValidGeneralDatasize(size));
5019                 assert(isGeneralRegister(reg1));
5020                 assert(isGeneralRegister(reg2));
5021                 assert(isGeneralRegister(reg3));
5022                 fmt = IF_DR_3A;
5023                 break;
5024             }
5025             __fallthrough;
5026
5027         case INS_mla:
5028         case INS_mls:
5029         case INS_pmul:
5030             assert(insOptsAnyArrangement(opt));
5031             assert(isVectorRegister(reg1));
5032             assert(isVectorRegister(reg2));
5033             assert(isVectorRegister(reg3));
5034             assert(isValidVectorDatasize(size));
5035             assert(isValidArrangement(size, opt));
5036             elemsize = optGetElemsize(opt);
5037             if (ins == INS_pmul)
5038             {
5039                 assert(elemsize == EA_1BYTE); // only supports 8B or 16B
5040             }
5041             else // INS_mul, INS_mla, INS_mls
5042             {
5043                 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
5044             }
5045             fmt = IF_DV_3A;
5046             break;
5047
5048         case INS_add:
5049         case INS_sub:
5050             if (isVectorRegister(reg1))
5051             {
5052                 assert(isVectorRegister(reg2));
5053                 assert(isVectorRegister(reg3));
5054
5055                 if (insOptsAnyArrangement(opt))
5056                 {
5057                     // Vector operation
5058                     assert(opt != INS_OPTS_1D); // Reserved encoding
5059                     assert(isValidVectorDatasize(size));
5060                     assert(isValidArrangement(size, opt));
5061                     fmt = IF_DV_3A;
5062                 }
5063                 else
5064                 {
5065                     // Scalar operation
5066                     assert(insOptsNone(opt));
5067                     assert(size == EA_8BYTE);
5068                     fmt = IF_DV_3E;
5069                 }
5070                 break;
5071             }
5072             __fallthrough;
5073
5074         case INS_adds:
5075         case INS_subs:
5076             emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, INS_OPTS_NONE);
5077             return;
5078
5079         case INS_cmeq:
5080         case INS_cmge:
5081         case INS_cmgt:
5082         case INS_cmhi:
5083         case INS_cmhs:
5084         case INS_ctst:
5085             assert(isVectorRegister(reg1));
5086             assert(isVectorRegister(reg2));
5087             assert(isVectorRegister(reg3));
5088
5089             if (isValidVectorDatasize(size))
5090             {
5091                 // Vector operation
5092                 assert(insOptsAnyArrangement(opt));
5093                 assert(isValidArrangement(size, opt));
5094                 elemsize = optGetElemsize(opt);
5095                 fmt      = IF_DV_3A;
5096             }
5097             else
5098             {
5099                 NYI("Untested");
5100                 // Scalar operation
5101                 assert(size == EA_8BYTE); // Only Double supported
5102                 fmt = IF_DV_3E;
5103             }
5104             break;
5105
5106         case INS_fcmeq:
5107         case INS_fcmge:
5108         case INS_fcmgt:
5109             assert(isVectorRegister(reg1));
5110             assert(isVectorRegister(reg2));
5111             assert(isVectorRegister(reg3));
5112
5113             if (isValidVectorDatasize(size))
5114             {
5115                 // Vector operation
5116                 assert(insOptsAnyArrangement(opt));
5117                 assert(isValidArrangement(size, opt));
5118                 elemsize = optGetElemsize(opt);
5119                 assert((elemsize == EA_8BYTE) || (elemsize == EA_4BYTE)); // Only Double/Float supported
5120                 assert(opt != INS_OPTS_1D);                               // Reserved encoding
5121                 fmt = IF_DV_3B;
5122             }
5123             else
5124             {
5125                 NYI("Untested");
5126                 // Scalar operation
5127                 assert((size == EA_8BYTE) || (size == EA_4BYTE)); // Only Double/Float supported
5128                 fmt = IF_DV_3D;
5129             }
5130             break;
5131
5132         case INS_saba:
5133         case INS_sabd:
5134         case INS_smax:
5135         case INS_smin:
5136         case INS_uaba:
5137         case INS_uabd:
5138         case INS_umax:
5139         case INS_umin:
5140             assert(isVectorRegister(reg1));
5141             assert(isVectorRegister(reg2));
5142             assert(isVectorRegister(reg3));
5143             assert(insOptsAnyArrangement(opt));
5144
5145             // Vector operation
5146             assert(isValidVectorDatasize(size));
5147             assert(isValidArrangement(size, opt));
5148             elemsize = optGetElemsize(opt);
5149             assert(elemsize != EA_8BYTE); // can't use 2D or 1D
5150
5151             fmt = IF_DV_3A;
5152             break;
5153
5154         case INS_mov:
5155             assert(isVectorRegister(reg1));
5156             assert(isVectorRegister(reg2));
5157             assert(reg2 == reg3);
5158             assert(isValidVectorDatasize(size));
5159             // INS_mov is an alias for INS_orr (vector register)
5160             if (opt == INS_OPTS_NONE)
5161             {
5162                 elemsize = EA_1BYTE;
5163                 opt      = optMakeArrangement(size, elemsize);
5164             }
5165             assert(isValidArrangement(size, opt));
5166             fmt = IF_DV_3C;
5167             break;
5168
5169         case INS_and:
5170         case INS_bic:
5171         case INS_eor:
5172         case INS_orr:
5173         case INS_orn:
5174             if (isVectorRegister(reg1))
5175             {
5176                 assert(isValidVectorDatasize(size));
5177                 assert(isVectorRegister(reg2));
5178                 assert(isVectorRegister(reg3));
5179                 if (opt == INS_OPTS_NONE)
5180                 {
5181                     elemsize = EA_1BYTE;
5182                     opt      = optMakeArrangement(size, elemsize);
5183                 }
5184                 assert(isValidArrangement(size, opt));
5185                 fmt = IF_DV_3C;
5186                 break;
5187             }
5188             __fallthrough;
5189
5190         case INS_ands:
5191         case INS_bics:
5192         case INS_eon:
5193             emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, INS_OPTS_NONE);
5194             return;
5195
5196         case INS_bsl:
5197         case INS_bit:
5198         case INS_bif:
5199             assert(isValidVectorDatasize(size));
5200             assert(isVectorRegister(reg1));
5201             assert(isVectorRegister(reg2));
5202             assert(isVectorRegister(reg3));
5203             if (opt == INS_OPTS_NONE)
5204             {
5205                 elemsize = EA_1BYTE;
5206                 opt      = optMakeArrangement(size, elemsize);
5207             }
5208             assert(isValidArrangement(size, opt));
5209             fmt = IF_DV_3C;
5210             break;
5211
5212         case INS_fadd:
5213         case INS_fsub:
5214         case INS_fdiv:
5215         case INS_fmax:
5216         case INS_fmin:
5217         case INS_fabd:
5218         case INS_fmul:
5219         case INS_fmulx:
5220             assert(isVectorRegister(reg1));
5221             assert(isVectorRegister(reg2));
5222             assert(isVectorRegister(reg3));
5223             if (insOptsAnyArrangement(opt))
5224             {
5225                 // Vector operation
5226                 assert(isValidVectorDatasize(size));
5227                 assert(isValidArrangement(size, opt));
5228                 elemsize = optGetElemsize(opt);
5229                 assert(isValidVectorElemsizeFloat(elemsize));
5230                 assert(opt != INS_OPTS_1D); // Reserved encoding
5231                 fmt = IF_DV_3B;
5232             }
5233             else
5234             {
5235                 // Scalar operation
5236                 assert(insOptsNone(opt));
5237                 assert(isValidScalarDatasize(size));
5238                 fmt = IF_DV_3D;
5239             }
5240             break;
5241
5242         case INS_fnmul:
5243             // Scalar operation
5244             assert(insOptsNone(opt));
5245             assert(isVectorRegister(reg1));
5246             assert(isVectorRegister(reg2));
5247             assert(isVectorRegister(reg3));
5248             assert(isValidScalarDatasize(size));
5249             fmt = IF_DV_3D;
5250             break;
5251
5252         case INS_faddp:
5253         case INS_fmla:
5254         case INS_fmls:
5255             assert(isVectorRegister(reg1));
5256             assert(isVectorRegister(reg2));
5257             assert(isVectorRegister(reg3));
5258             assert(insOptsAnyArrangement(opt)); // no scalar encoding, use 4-operand 'fmadd' or 'fmsub'
5259
5260             // Vector operation
5261             assert(isValidVectorDatasize(size));
5262             assert(isValidArrangement(size, opt));
5263             elemsize = optGetElemsize(opt);
5264             assert(isValidVectorElemsizeFloat(elemsize));
5265             assert(opt != INS_OPTS_1D); // Reserved encoding
5266             fmt = IF_DV_3B;
5267             break;
5268
5269         case INS_ldr:
5270         case INS_ldrb:
5271         case INS_ldrh:
5272         case INS_ldrsb:
5273         case INS_ldrsh:
5274         case INS_ldrsw:
5275         case INS_str:
5276         case INS_strb:
5277         case INS_strh:
5278             emitIns_R_R_R_Ext(ins, attr, reg1, reg2, reg3, opt);
5279             return;
5280
5281         case INS_ldp:
5282         case INS_ldpsw:
5283         case INS_ldnp:
5284         case INS_stp:
5285         case INS_stnp:
5286             emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0);
5287             return;
5288
5289         case INS_stxr:
5290         case INS_stxrb:
5291         case INS_stxrh:
5292         case INS_stlxr:
5293         case INS_stlxrb:
5294         case INS_stlxrh:
5295             assert(isGeneralRegisterOrZR(reg1));
5296             assert(isGeneralRegisterOrZR(reg2));
5297             assert(isGeneralRegisterOrSP(reg3));
5298             fmt = IF_LS_3D;
5299             break;
5300
5301         default:
5302             unreached();
5303             break;
5304
5305     } // end switch (ins)
5306
5307     assert(fmt != IF_NONE);
5308
5309     instrDesc* id = emitNewInstr(attr);
5310
5311     id->idIns(ins);
5312     id->idInsFmt(fmt);
5313     id->idInsOpt(opt);
5314
5315     id->idReg1(reg1);
5316     id->idReg2(reg2);
5317     id->idReg3(reg3);
5318
5319     dispIns(id);
5320     appendToCurIG(id);
5321 }
5322
5323 /*****************************************************************************
5324  *
5325  *  Add an instruction referencing three registers and a constant.
5326  */
5327
5328 void emitter::emitIns_R_R_R_I(instruction ins,
5329                               emitAttr    attr,
5330                               regNumber   reg1,
5331                               regNumber   reg2,
5332                               regNumber   reg3,
5333                               ssize_t     imm,
5334                               insOpts     opt /* = INS_OPTS_NONE */,
5335                               emitAttr    attrReg2 /* = EA_UNKNOWN */)
5336 {
5337     emitAttr  size     = EA_SIZE(attr);
5338     emitAttr  elemsize = EA_UNKNOWN;
5339     insFormat fmt      = IF_NONE;
5340     bool      isLdSt   = false;
5341     bool      isSIMD   = false;
5342     bool      isAddSub = false;
5343     bool      setFlags = false;
5344     unsigned  scale    = 0;
5345
5346     /* Figure out the encoding format of the instruction */
5347     switch (ins)
5348     {
5349         case INS_extr:
5350             assert(insOptsNone(opt));
5351             assert(isValidGeneralDatasize(size));
5352             assert(isGeneralRegister(reg1));
5353             assert(isGeneralRegister(reg2));
5354             assert(isGeneralRegister(reg3));
5355             assert(isValidImmShift(imm, size));
5356             fmt = IF_DR_3E;
5357             break;
5358
5359         case INS_and:
5360         case INS_ands:
5361         case INS_eor:
5362         case INS_orr:
5363         case INS_bic:
5364         case INS_bics:
5365         case INS_eon:
5366         case INS_orn:
5367             assert(isValidGeneralDatasize(size));
5368             assert(isGeneralRegister(reg1));
5369             assert(isGeneralRegister(reg2));
5370             assert(isGeneralRegister(reg3));
5371             assert(isValidImmShift(imm, size));
5372             if (imm == 0)
5373             {
5374                 assert(insOptsNone(opt)); // a zero imm, means no shift kind
5375                 fmt = IF_DR_3A;
5376             }
5377             else
5378             {
5379                 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
5380                 fmt = IF_DR_3B;
5381             }
5382             break;
5383
5384         case INS_fmul: // by element, imm[0..3] selects the element of reg3
5385         case INS_fmla:
5386         case INS_fmls:
5387         case INS_fmulx:
5388             assert(isVectorRegister(reg1));
5389             assert(isVectorRegister(reg2));
5390             assert(isVectorRegister(reg3));
5391             if (insOptsAnyArrangement(opt))
5392             {
5393                 // Vector operation
5394                 assert(isValidVectorDatasize(size));
5395                 assert(isValidArrangement(size, opt));
5396                 elemsize = optGetElemsize(opt);
5397                 assert(isValidVectorElemsizeFloat(elemsize));
5398                 assert(isValidVectorIndex(size, elemsize, imm));
5399                 assert(opt != INS_OPTS_1D); // Reserved encoding
5400                 fmt = IF_DV_3BI;
5401             }
5402             else
5403             {
5404                 // Scalar operation
5405                 assert(insOptsNone(opt));
5406                 assert(isValidScalarDatasize(size));
5407                 elemsize = size;
5408                 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
5409                 fmt = IF_DV_3DI;
5410             }
5411             break;
5412
5413         case INS_mul: // by element, imm[0..7] selects the element of reg3
5414         case INS_mla:
5415         case INS_mls:
5416             assert(isVectorRegister(reg1));
5417             assert(isVectorRegister(reg2));
5418             assert(isVectorRegister(reg3));
5419             // Vector operation
5420             assert(insOptsAnyArrangement(opt));
5421             assert(isValidVectorDatasize(size));
5422             assert(isValidArrangement(size, opt));
5423             elemsize = optGetElemsize(opt);
5424             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
5425             // Only has encodings for H or S elemsize
5426             assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE));
5427             // Only has encodings for V0..V15
5428             if ((elemsize == EA_2BYTE) && (reg3 >= REG_V16))
5429             {
5430                 noway_assert(!"Invalid reg3");
5431             }
5432             fmt = IF_DV_3AI;
5433             break;
5434
5435         case INS_add:
5436         case INS_sub:
5437             setFlags = false;
5438             isAddSub = true;
5439             break;
5440
5441         case INS_adds:
5442         case INS_subs:
5443             setFlags = true;
5444             isAddSub = true;
5445             break;
5446
5447         case INS_ldpsw:
5448             scale  = 2;
5449             isLdSt = true;
5450             break;
5451
5452         case INS_ldnp:
5453         case INS_stnp:
5454             assert(insOptsNone(opt)); // Can't use Pre/Post index on these two instructions
5455             __fallthrough;
5456
5457         case INS_ldp:
5458         case INS_stp:
5459             // Is the target a vector register?
5460             if (isVectorRegister(reg1))
5461             {
5462                 scale  = NaturalScale_helper(size);
5463                 isSIMD = true;
5464             }
5465             else
5466             {
5467                 scale = (size == EA_8BYTE) ? 3 : 2;
5468             }
5469             isLdSt = true;
5470             break;
5471
5472         default:
5473             unreached();
5474             break;
5475
5476     } // end switch (ins)
5477
5478     if (isLdSt)
5479     {
5480         assert(!isAddSub);
5481         assert(isGeneralRegisterOrSP(reg3));
5482         assert(insOptsNone(opt) || insOptsIndexed(opt));
5483
5484         if (isSIMD)
5485         {
5486             assert(isValidVectorLSPDatasize(size));
5487             assert(isVectorRegister(reg1));
5488             assert(isVectorRegister(reg2));
5489             assert((scale >= 2) && (scale <= 4));
5490         }
5491         else
5492         {
5493             assert(isValidGeneralDatasize(size));
5494             assert(isGeneralRegisterOrZR(reg1));
5495             assert(isGeneralRegisterOrZR(reg2));
5496             assert((scale == 2) || (scale == 3));
5497         }
5498
5499         // Load/Store Pair reserved encodings:
5500         if (emitInsIsLoad(ins))
5501         {
5502             assert(reg1 != reg2);
5503         }
5504         if (insOptsIndexed(opt))
5505         {
5506             assert(reg1 != reg3);
5507             assert(reg2 != reg3);
5508         }
5509
5510         reg3 = encodingSPtoZR(reg3);
5511
5512         ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
5513         if (imm == 0)
5514         {
5515             assert(insOptsNone(opt)); // PRE/POST Index doesn't make sense with an immediate of zero
5516
5517             fmt = IF_LS_3B;
5518         }
5519         else
5520         {
5521             if ((imm & mask) == 0)
5522             {
5523                 imm >>= scale; // The immediate is scaled by the size of the ld/st
5524
5525                 if ((imm >= -64) && (imm <= 63))
5526                 {
5527                     fmt = IF_LS_3C;
5528                 }
5529             }
5530 #ifdef DEBUG
5531             if (fmt != IF_LS_3C)
5532             {
5533                 assert(!"Instruction cannot be encoded: IF_LS_3C");
5534             }
5535 #endif
5536         }
5537     }
5538     else if (isAddSub)
5539     {
5540         bool reg2IsSP = (reg2 == REG_SP);
5541         assert(!isLdSt);
5542         assert(isValidGeneralDatasize(size));
5543         assert(isGeneralRegister(reg3));
5544
5545         if (setFlags || insOptsAluShift(opt)) // Can't encode SP in reg1 with setFlags or AluShift option
5546         {
5547             assert(isGeneralRegisterOrZR(reg1));
5548         }
5549         else
5550         {
5551             assert(isGeneralRegisterOrSP(reg1));
5552             reg1 = encodingSPtoZR(reg1);
5553         }
5554
5555         if (insOptsAluShift(opt)) // Can't encode SP in reg2 with AluShift option
5556         {
5557             assert(isGeneralRegister(reg2));
5558         }
5559         else
5560         {
5561             assert(isGeneralRegisterOrSP(reg2));
5562             reg2 = encodingSPtoZR(reg2);
5563         }
5564
5565         if (insOptsAnyExtend(opt))
5566         {
5567             assert((imm >= 0) && (imm <= 4));
5568
5569             fmt = IF_DR_3C;
5570         }
5571         else if (insOptsAluShift(opt))
5572         {
5573             // imm should be non-zero and in [1..63]
5574             assert(isValidImmShift(imm, size) && (imm != 0));
5575             fmt = IF_DR_3B;
5576         }
5577         else if (imm == 0)
5578         {
5579             assert(insOptsNone(opt));
5580
5581             if (reg2IsSP)
5582             {
5583                 // To encode the SP register as reg2 we must use the IF_DR_3C encoding
5584                 // and also specify a LSL of zero (imm == 0)
5585                 opt = INS_OPTS_LSL;
5586                 fmt = IF_DR_3C;
5587             }
5588             else
5589             {
5590                 fmt = IF_DR_3A;
5591             }
5592         }
5593         else
5594         {
5595             assert(!"Instruction cannot be encoded: Add/Sub IF_DR_3A");
5596         }
5597     }
5598     assert(fmt != IF_NONE);
5599
5600     instrDesc* id = emitNewInstrCns(attr, imm);
5601
5602     id->idIns(ins);
5603     id->idInsFmt(fmt);
5604     id->idInsOpt(opt);
5605
5606     id->idReg1(reg1);
5607     id->idReg2(reg2);
5608     id->idReg3(reg3);
5609
5610     // Record the attribute for the second register in the pair
5611     id->idGCrefReg2(GCT_NONE);
5612     if (attrReg2 != EA_UNKNOWN)
5613     {
5614         // Record the attribute for the second register in the pair
5615         assert((fmt == IF_LS_3B) || (fmt == IF_LS_3C));
5616         if (EA_IS_GCREF(attrReg2))
5617         {
5618             id->idGCrefReg2(GCT_GCREF);
5619         }
5620         else if (EA_IS_BYREF(attrReg2))
5621         {
5622             id->idGCrefReg2(GCT_BYREF);
5623         }
5624     }
5625
5626     dispIns(id);
5627     appendToCurIG(id);
5628 }
5629
5630 /*****************************************************************************
5631  *
5632  *  Add an instruction referencing three registers, with an extend option
5633  */
5634
5635 void emitter::emitIns_R_R_R_Ext(instruction ins,
5636                                 emitAttr    attr,
5637                                 regNumber   reg1,
5638                                 regNumber   reg2,
5639                                 regNumber   reg3,
5640                                 insOpts     opt,         /* = INS_OPTS_NONE */
5641                                 int         shiftAmount) /* = -1 -- unset   */
5642 {
5643     emitAttr  size   = EA_SIZE(attr);
5644     insFormat fmt    = IF_NONE;
5645     bool      isSIMD = false;
5646     int       scale  = -1;
5647
5648     /* Figure out the encoding format of the instruction */
5649     switch (ins)
5650     {
5651         case INS_ldrb:
5652         case INS_ldrsb:
5653         case INS_strb:
5654             scale = 0;
5655             break;
5656
5657         case INS_ldrh:
5658         case INS_ldrsh:
5659         case INS_strh:
5660             scale = 1;
5661             break;
5662
5663         case INS_ldrsw:
5664             scale = 2;
5665             break;
5666
5667         case INS_ldr:
5668         case INS_str:
5669             // Is the target a vector register?
5670             if (isVectorRegister(reg1))
5671             {
5672                 assert(isValidVectorLSDatasize(size));
5673                 scale  = NaturalScale_helper(size);
5674                 isSIMD = true;
5675             }
5676             else
5677             {
5678                 assert(isValidGeneralDatasize(size));
5679                 scale = (size == EA_8BYTE) ? 3 : 2;
5680             }
5681
5682             break;
5683
5684         default:
5685             unreached();
5686             break;
5687
5688     } // end switch (ins)
5689
5690     assert(scale != -1);
5691     assert(insOptsLSExtend(opt));
5692
5693     if (isSIMD)
5694     {
5695         assert(isValidVectorLSDatasize(size));
5696         assert(isVectorRegister(reg1));
5697     }
5698     else
5699     {
5700         assert(isValidGeneralLSDatasize(size));
5701         assert(isGeneralRegisterOrZR(reg1));
5702     }
5703
5704     assert(isGeneralRegisterOrSP(reg2));
5705     assert(isGeneralRegister(reg3));
5706
5707     // Load/Store reserved encodings:
5708     if (insOptsIndexed(opt))
5709     {
5710         assert(reg1 != reg2);
5711     }
5712
5713     if (shiftAmount == -1)
5714     {
5715         shiftAmount = insOptsLSL(opt) ? scale : 0;
5716     }
5717     assert((shiftAmount == scale) || (shiftAmount == 0));
5718
5719     reg2 = encodingSPtoZR(reg2);
5720     fmt  = IF_LS_3A;
5721
5722     instrDesc* id = emitNewInstr(attr);
5723
5724     id->idIns(ins);
5725     id->idInsFmt(fmt);
5726     id->idInsOpt(opt);
5727
5728     id->idReg1(reg1);
5729     id->idReg2(reg2);
5730     id->idReg3(reg3);
5731     id->idReg3Scaled(shiftAmount == scale);
5732
5733     dispIns(id);
5734     appendToCurIG(id);
5735 }
5736
5737 /*****************************************************************************
5738  *
5739  *  Add an instruction referencing two registers and two constants.
5740  */
5741
5742 void emitter::emitIns_R_R_I_I(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, int imm1, int imm2)
5743 {
5744     emitAttr  size     = EA_SIZE(attr);
5745     emitAttr  elemsize = EA_UNKNOWN;
5746     insFormat fmt      = IF_NONE;
5747     size_t    immOut   = 0; // composed from imm1 and imm2 and stored in the instrDesc
5748
5749     /* Figure out the encoding format of the instruction */
5750     switch (ins)
5751     {
5752         int        lsb;
5753         int        width;
5754         bitMaskImm bmi;
5755
5756         case INS_bfm:
5757         case INS_sbfm:
5758         case INS_ubfm:
5759             assert(isGeneralRegister(reg1));
5760             assert(isGeneralRegister(reg2));
5761             assert(isValidImmShift(imm1, size));
5762             assert(isValidImmShift(imm2, size));
5763             bmi.immNRS = 0;
5764             bmi.immN   = (size == EA_8BYTE);
5765             bmi.immR   = imm1;
5766             bmi.immS   = imm2;
5767             immOut     = bmi.immNRS;
5768             fmt        = IF_DI_2D;
5769             break;
5770
5771         case INS_bfi:
5772         case INS_sbfiz:
5773         case INS_ubfiz:
5774             assert(isGeneralRegister(reg1));
5775             assert(isGeneralRegister(reg2));
5776             lsb   = getBitWidth(size) - imm1;
5777             width = imm2 - 1;
5778             assert(isValidImmShift(lsb, size));
5779             assert(isValidImmShift(width, size));
5780             bmi.immNRS = 0;
5781             bmi.immN   = (size == EA_8BYTE);
5782             bmi.immR   = lsb;
5783             bmi.immS   = width;
5784             immOut     = bmi.immNRS;
5785             fmt        = IF_DI_2D;
5786             break;
5787
5788         case INS_bfxil:
5789         case INS_sbfx:
5790         case INS_ubfx:
5791             assert(isGeneralRegister(reg1));
5792             assert(isGeneralRegister(reg2));
5793             lsb   = imm1;
5794             width = imm2 + imm1 - 1;
5795             assert(isValidImmShift(lsb, size));
5796             assert(isValidImmShift(width, size));
5797             bmi.immNRS = 0;
5798             bmi.immN   = (size == EA_8BYTE);
5799             bmi.immR   = imm1;
5800             bmi.immS   = imm2 + imm1 - 1;
5801             immOut     = bmi.immNRS;
5802             fmt        = IF_DI_2D;
5803             break;
5804
5805         case INS_mov:
5806         case INS_ins:
5807             assert(isVectorRegister(reg1));
5808             assert(isVectorRegister(reg2));
5809             elemsize = size;
5810             assert(isValidVectorElemsize(elemsize));
5811             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm1));
5812             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm2));
5813             immOut = (imm1 << 4) + imm2;
5814             fmt    = IF_DV_2F;
5815             break;
5816
5817         default:
5818             unreached();
5819             break;
5820     }
5821     assert(fmt != IF_NONE);
5822
5823     instrDesc* id = emitNewInstrSC(attr, immOut);
5824
5825     id->idIns(ins);
5826     id->idInsFmt(fmt);
5827
5828     id->idReg1(reg1);
5829     id->idReg2(reg2);
5830
5831     dispIns(id);
5832     appendToCurIG(id);
5833 }
5834
5835 /*****************************************************************************
5836  *
5837  *  Add an instruction referencing four registers.
5838  */
5839
5840 void emitter::emitIns_R_R_R_R(
5841     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, regNumber reg4)
5842 {
5843     emitAttr  size = EA_SIZE(attr);
5844     insFormat fmt  = IF_NONE;
5845
5846     /* Figure out the encoding format of the instruction */
5847     switch (ins)
5848     {
5849         case INS_madd:
5850         case INS_msub:
5851         case INS_smaddl:
5852         case INS_smsubl:
5853         case INS_umaddl:
5854         case INS_umsubl:
5855             assert(isValidGeneralDatasize(size));
5856             assert(isGeneralRegister(reg1));
5857             assert(isGeneralRegister(reg2));
5858             assert(isGeneralRegister(reg3));
5859             assert(isGeneralRegister(reg4));
5860             fmt = IF_DR_4A;
5861             break;
5862
5863         case INS_fmadd:
5864         case INS_fmsub:
5865         case INS_fnmadd:
5866         case INS_fnmsub:
5867             // Scalar operation
5868             assert(isValidScalarDatasize(size));
5869             assert(isVectorRegister(reg1));
5870             assert(isVectorRegister(reg2));
5871             assert(isVectorRegister(reg3));
5872             assert(isVectorRegister(reg4));
5873             fmt = IF_DV_4A;
5874             break;
5875
5876         case INS_invalid:
5877             fmt = IF_NONE;
5878             break;
5879
5880         default:
5881             unreached();
5882             break;
5883     }
5884     assert(fmt != IF_NONE);
5885
5886     instrDesc* id = emitNewInstr(attr);
5887
5888     id->idIns(ins);
5889     id->idInsFmt(fmt);
5890
5891     id->idReg1(reg1);
5892     id->idReg2(reg2);
5893     id->idReg3(reg3);
5894     id->idReg4(reg4);
5895
5896     dispIns(id);
5897     appendToCurIG(id);
5898 }
5899
5900 /*****************************************************************************
5901  *
5902  *  Add an instruction referencing a register and a condition code
5903  */
5904
5905 void emitter::emitIns_R_COND(instruction ins, emitAttr attr, regNumber reg, insCond cond)
5906 {
5907     emitAttr     size = EA_SIZE(attr);
5908     insFormat    fmt  = IF_NONE;
5909     condFlagsImm cfi;
5910     cfi.immCFVal = 0;
5911
5912     /* Figure out the encoding format of the instruction */
5913     switch (ins)
5914     {
5915         case INS_cset:
5916         case INS_csetm:
5917             assert(isGeneralRegister(reg));
5918             cfi.cond = cond;
5919             fmt      = IF_DR_1D;
5920             break;
5921
5922         default:
5923             unreached();
5924             break;
5925
5926     } // end switch (ins)
5927
5928     assert(fmt != IF_NONE);
5929     assert(isValidImmCond(cfi.immCFVal));
5930
5931     instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
5932
5933     id->idIns(ins);
5934     id->idInsFmt(fmt);
5935     id->idInsOpt(INS_OPTS_NONE);
5936
5937     id->idReg1(reg);
5938
5939     dispIns(id);
5940     appendToCurIG(id);
5941 }
5942
5943 /*****************************************************************************
5944  *
5945  *  Add an instruction referencing two registers and a condition code
5946  */
5947
5948 void emitter::emitIns_R_R_COND(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insCond cond)
5949 {
5950     emitAttr     size = EA_SIZE(attr);
5951     insFormat    fmt  = IF_NONE;
5952     condFlagsImm cfi;
5953     cfi.immCFVal = 0;
5954
5955     /* Figure out the encoding format of the instruction */
5956     switch (ins)
5957     {
5958         case INS_cinc:
5959         case INS_cinv:
5960         case INS_cneg:
5961             assert(isGeneralRegister(reg1));
5962             assert(isGeneralRegister(reg2));
5963             cfi.cond = cond;
5964             fmt      = IF_DR_2D;
5965             break;
5966         default:
5967             unreached();
5968             break;
5969
5970     } // end switch (ins)
5971
5972     assert(fmt != IF_NONE);
5973     assert(isValidImmCond(cfi.immCFVal));
5974
5975     instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
5976
5977     id->idIns(ins);
5978     id->idInsFmt(fmt);
5979     id->idInsOpt(INS_OPTS_NONE);
5980
5981     id->idReg1(reg1);
5982     id->idReg2(reg2);
5983
5984     dispIns(id);
5985     appendToCurIG(id);
5986 }
5987
5988 /*****************************************************************************
5989  *
5990  *  Add an instruction referencing two registers and a condition code
5991  */
5992
5993 void emitter::emitIns_R_R_R_COND(
5994     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insCond cond)
5995 {
5996     emitAttr     size = EA_SIZE(attr);
5997     insFormat    fmt  = IF_NONE;
5998     condFlagsImm cfi;
5999     cfi.immCFVal = 0;
6000
6001     /* Figure out the encoding format of the instruction */
6002     switch (ins)
6003     {
6004         case INS_csel:
6005         case INS_csinc:
6006         case INS_csinv:
6007         case INS_csneg:
6008             assert(isGeneralRegister(reg1));
6009             assert(isGeneralRegister(reg2));
6010             assert(isGeneralRegister(reg3));
6011             cfi.cond = cond;
6012             fmt      = IF_DR_3D;
6013             break;
6014
6015         default:
6016             unreached();
6017             break;
6018
6019     } // end switch (ins)
6020
6021     assert(fmt != IF_NONE);
6022     assert(isValidImmCond(cfi.immCFVal));
6023
6024     instrDesc* id = emitNewInstr(attr);
6025
6026     id->idIns(ins);
6027     id->idInsFmt(fmt);
6028     id->idInsOpt(INS_OPTS_NONE);
6029
6030     id->idReg1(reg1);
6031     id->idReg2(reg2);
6032     id->idReg3(reg3);
6033     id->idSmallCns(cfi.immCFVal);
6034
6035     dispIns(id);
6036     appendToCurIG(id);
6037 }
6038
6039 /*****************************************************************************
6040  *
6041  *  Add an instruction referencing two registers the flags and a condition code
6042  */
6043
6044 void emitter::emitIns_R_R_FLAGS_COND(
6045     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insCflags flags, insCond cond)
6046 {
6047     emitAttr     size = EA_SIZE(attr);
6048     insFormat    fmt  = IF_NONE;
6049     condFlagsImm cfi;
6050     cfi.immCFVal = 0;
6051
6052     /* Figure out the encoding format of the instruction */
6053     switch (ins)
6054     {
6055         case INS_ccmp:
6056         case INS_ccmn:
6057             assert(isGeneralRegister(reg1));
6058             assert(isGeneralRegister(reg2));
6059             cfi.flags = flags;
6060             cfi.cond  = cond;
6061             fmt       = IF_DR_2I;
6062             break;
6063         default:
6064             unreached();
6065             break;
6066     } // end switch (ins)
6067
6068     assert(fmt != IF_NONE);
6069     assert(isValidImmCondFlags(cfi.immCFVal));
6070
6071     instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6072
6073     id->idIns(ins);
6074     id->idInsFmt(fmt);
6075     id->idInsOpt(INS_OPTS_NONE);
6076
6077     id->idReg1(reg1);
6078     id->idReg2(reg2);
6079
6080     dispIns(id);
6081     appendToCurIG(id);
6082 }
6083
6084 /*****************************************************************************
6085  *
6086  *  Add an instruction referencing a register, an immediate, the flags and a condition code
6087  */
6088
6089 void emitter::emitIns_R_I_FLAGS_COND(
6090     instruction ins, emitAttr attr, regNumber reg, int imm, insCflags flags, insCond cond)
6091 {
6092     emitAttr     size = EA_SIZE(attr);
6093     insFormat    fmt  = IF_NONE;
6094     condFlagsImm cfi;
6095     cfi.immCFVal = 0;
6096
6097     /* Figure out the encoding format of the instruction */
6098     switch (ins)
6099     {
6100         case INS_ccmp:
6101         case INS_ccmn:
6102             assert(isGeneralRegister(reg));
6103             if (imm < 0)
6104             {
6105                 ins = insReverse(ins);
6106                 imm = -imm;
6107             }
6108             if ((imm >= 0) && (imm <= 31))
6109             {
6110                 cfi.imm5  = imm;
6111                 cfi.flags = flags;
6112                 cfi.cond  = cond;
6113                 fmt       = IF_DI_1F;
6114             }
6115             else
6116             {
6117                 assert(!"Instruction cannot be encoded: ccmp/ccmn imm5");
6118             }
6119             break;
6120         default:
6121             unreached();
6122             break;
6123     } // end switch (ins)
6124
6125     assert(fmt != IF_NONE);
6126     assert(isValidImmCondFlagsImm5(cfi.immCFVal));
6127
6128     instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6129
6130     id->idIns(ins);
6131     id->idInsFmt(fmt);
6132     id->idInsOpt(INS_OPTS_NONE);
6133
6134     id->idReg1(reg);
6135
6136     dispIns(id);
6137     appendToCurIG(id);
6138 }
6139
6140 /*****************************************************************************
6141  *
6142  *  Add a memory barrier instruction with a 'barrier' immediate
6143  */
6144
6145 void emitter::emitIns_BARR(instruction ins, insBarrier barrier)
6146 {
6147     insFormat fmt = IF_NONE;
6148     ssize_t   imm = 0;
6149
6150     /* Figure out the encoding format of the instruction */
6151     switch (ins)
6152     {
6153         case INS_dsb:
6154         case INS_dmb:
6155         case INS_isb:
6156
6157             fmt = IF_SI_0B;
6158             imm = (ssize_t)barrier;
6159             break;
6160         default:
6161             unreached();
6162             break;
6163     } // end switch (ins)
6164
6165     assert(fmt != IF_NONE);
6166
6167     instrDesc* id = emitNewInstrSC(EA_8BYTE, imm);
6168
6169     id->idIns(ins);
6170     id->idInsFmt(fmt);
6171     id->idInsOpt(INS_OPTS_NONE);
6172
6173     dispIns(id);
6174     appendToCurIG(id);
6175 }
6176
6177 /*****************************************************************************
6178  *
6179  *  Add an instruction with a static data member operand. If 'size' is 0, the
6180  *  instruction operates on the address of the static member instead of its
6181  *  value (e.g. "push offset clsvar", rather than "push dword ptr [clsvar]").
6182  */
6183
6184 void emitter::emitIns_C(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, int offs)
6185 {
6186     NYI("emitIns_C");
6187 }
6188
6189 /*****************************************************************************
6190  *
6191  *  Add an instruction referencing stack-based local variable.
6192  */
6193
6194 void emitter::emitIns_S(instruction ins, emitAttr attr, int varx, int offs)
6195 {
6196     NYI("emitIns_S");
6197 }
6198
6199 /*****************************************************************************
6200  *
6201  *  Add an instruction referencing a register and a stack-based local variable.
6202  */
6203 void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
6204 {
6205     emitAttr  size  = EA_SIZE(attr);
6206     insFormat fmt   = IF_NONE;
6207     int       disp  = 0;
6208     unsigned  scale = 0;
6209
6210     assert(offs >= 0);
6211
6212     // TODO-ARM64-CQ: use unscaled loads?
6213     /* Figure out the encoding format of the instruction */
6214     switch (ins)
6215     {
6216         case INS_strb:
6217         case INS_ldrb:
6218         case INS_ldrsb:
6219             scale = 0;
6220             break;
6221
6222         case INS_strh:
6223         case INS_ldrh:
6224         case INS_ldrsh:
6225             scale = 1;
6226             break;
6227
6228         case INS_ldrsw:
6229             scale = 2;
6230             break;
6231
6232         case INS_str:
6233         case INS_ldr:
6234             assert(isValidGeneralDatasize(size) || isValidVectorDatasize(size));
6235             scale = genLog2(EA_SIZE_IN_BYTES(size));
6236             break;
6237
6238         case INS_lea:
6239             assert(size == EA_8BYTE);
6240             scale = 0;
6241             break;
6242
6243         default:
6244             NYI("emitIns_R_S"); // FP locals?
6245             return;
6246
6247     } // end switch (ins)
6248
6249     /* Figure out the variable's frame position */
6250     ssize_t imm;
6251     int     base;
6252     bool    FPbased;
6253
6254     base = emitComp->lvaFrameAddress(varx, &FPbased);
6255     disp = base + offs;
6256     assert((scale >= 0) && (scale <= 4));
6257
6258     regNumber reg2 = FPbased ? REG_FPBASE : REG_SPBASE;
6259     reg2           = encodingSPtoZR(reg2);
6260
6261     if (ins == INS_lea)
6262     {
6263         if (disp >= 0)
6264         {
6265             ins = INS_add;
6266             imm = disp;
6267         }
6268         else
6269         {
6270             ins = INS_sub;
6271             imm = -disp;
6272         }
6273
6274         if (imm <= 0x0fff)
6275         {
6276             fmt = IF_DI_2A; // add reg1,reg2,#disp
6277         }
6278         else
6279         {
6280             regNumber rsvdReg = codeGen->rsGetRsvdReg();
6281             codeGen->instGen_Set_Reg_To_Imm(size, rsvdReg, imm);
6282             fmt = IF_DR_3A; // add reg1,reg2,rsvdReg
6283         }
6284     }
6285     else
6286     {
6287         bool    useRegForImm = false;
6288         ssize_t mask         = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6289
6290         imm = disp;
6291         if (imm == 0)
6292         {
6293             fmt = IF_LS_2A;
6294         }
6295         else if ((imm < 0) || ((imm & mask) != 0))
6296         {
6297             if ((imm >= -256) && (imm <= 255))
6298             {
6299                 fmt = IF_LS_2C;
6300             }
6301             else
6302             {
6303                 useRegForImm = true;
6304             }
6305         }
6306         else if (imm > 0)
6307         {
6308             if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
6309             {
6310                 imm >>= scale; // The immediate is scaled by the size of the ld/st
6311
6312                 fmt = IF_LS_2B;
6313             }
6314             else
6315             {
6316                 useRegForImm = true;
6317             }
6318         }
6319
6320         if (useRegForImm)
6321         {
6322             regNumber rsvdReg = codeGen->rsGetRsvdReg();
6323             codeGen->instGen_Set_Reg_To_Imm(size, rsvdReg, imm);
6324             fmt = IF_LS_3A;
6325         }
6326     }
6327
6328     assert(fmt != IF_NONE);
6329
6330     instrDesc* id = emitNewInstrCns(attr, imm);
6331
6332     id->idIns(ins);
6333     id->idInsFmt(fmt);
6334     id->idInsOpt(INS_OPTS_NONE);
6335
6336     id->idReg1(reg1);
6337     id->idReg2(reg2);
6338     id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6339     id->idSetIsLclVar();
6340
6341 #ifdef DEBUG
6342     id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6343 #endif
6344
6345     dispIns(id);
6346     appendToCurIG(id);
6347 }
6348
6349 /*****************************************************************************
6350  *
6351  *  Add an instruction referencing two register and consectutive stack-based local variable slots.
6352  */
6353 void emitter::emitIns_R_R_S_S(
6354     instruction ins, emitAttr attr1, emitAttr attr2, regNumber reg1, regNumber reg2, int varx, int offs)
6355 {
6356     assert((ins == INS_ldp) || (ins == INS_ldnp));
6357     assert(EA_8BYTE == EA_SIZE(attr1));
6358     assert(EA_8BYTE == EA_SIZE(attr2));
6359     assert(isGeneralRegisterOrZR(reg1));
6360     assert(isGeneralRegisterOrZR(reg2));
6361     assert(offs >= 0);
6362
6363     emitAttr       size  = EA_SIZE(attr1);
6364     insFormat      fmt   = IF_LS_3B;
6365     int            disp  = 0;
6366     const unsigned scale = 3;
6367
6368     /* Figure out the variable's frame position */
6369     int  base;
6370     bool FPbased;
6371
6372     base = emitComp->lvaFrameAddress(varx, &FPbased);
6373     disp = base + offs;
6374
6375     // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6376     regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE;
6377     reg3           = encodingSPtoZR(reg3);
6378
6379     bool    useRegForAdr = true;
6380     ssize_t imm          = disp;
6381     ssize_t mask         = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6382     if (imm == 0)
6383     {
6384         useRegForAdr = false;
6385     }
6386     else
6387     {
6388         if ((imm & mask) == 0)
6389         {
6390             ssize_t immShift = imm >> scale; // The immediate is scaled by the size of the ld/st
6391
6392             if ((immShift >= -64) && (immShift <= 63))
6393             {
6394                 fmt          = IF_LS_3C;
6395                 useRegForAdr = false;
6396                 imm          = immShift;
6397             }
6398         }
6399     }
6400
6401     if (useRegForAdr)
6402     {
6403         regNumber rsvd = codeGen->rsGetRsvdReg();
6404         emitIns_R_R_Imm(INS_add, EA_8BYTE, rsvd, reg3, imm);
6405         reg3 = rsvd;
6406         imm  = 0;
6407     }
6408
6409     assert(fmt != IF_NONE);
6410
6411     instrDesc* id = emitNewInstrCns(attr1, imm);
6412
6413     id->idIns(ins);
6414     id->idInsFmt(fmt);
6415     id->idInsOpt(INS_OPTS_NONE);
6416
6417     // Record the attribute for the second register in the pair
6418     if (EA_IS_GCREF(attr2))
6419     {
6420         id->idGCrefReg2(GCT_GCREF);
6421     }
6422     else if (EA_IS_BYREF(attr2))
6423     {
6424         id->idGCrefReg2(GCT_BYREF);
6425     }
6426     else
6427     {
6428         id->idGCrefReg2(GCT_NONE);
6429     }
6430
6431     id->idReg1(reg1);
6432     id->idReg2(reg2);
6433     id->idReg3(reg3);
6434     id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6435     id->idSetIsLclVar();
6436
6437 #ifdef DEBUG
6438     id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6439 #endif
6440
6441     dispIns(id);
6442     appendToCurIG(id);
6443 }
6444
6445 /*****************************************************************************
6446  *
6447  *  Add an instruction referencing a stack-based local variable and a register
6448  */
6449 void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
6450 {
6451     assert(offs >= 0);
6452     emitAttr  size          = EA_SIZE(attr);
6453     insFormat fmt           = IF_NONE;
6454     int       disp          = 0;
6455     unsigned  scale         = 0;
6456     bool      isVectorStore = false;
6457
6458     // TODO-ARM64-CQ: use unscaled loads?
6459     /* Figure out the encoding format of the instruction */
6460     switch (ins)
6461     {
6462         case INS_strb:
6463             scale = 0;
6464             assert(isGeneralRegisterOrZR(reg1));
6465             break;
6466
6467         case INS_strh:
6468             scale = 1;
6469             assert(isGeneralRegisterOrZR(reg1));
6470             break;
6471
6472         case INS_str:
6473             if (isGeneralRegisterOrZR(reg1))
6474             {
6475                 assert(isValidGeneralDatasize(size));
6476                 scale = (size == EA_8BYTE) ? 3 : 2;
6477             }
6478             else
6479             {
6480                 assert(isVectorRegister(reg1));
6481                 assert(isValidVectorLSDatasize(size));
6482                 scale         = NaturalScale_helper(size);
6483                 isVectorStore = true;
6484             }
6485             break;
6486
6487         default:
6488             NYI("emitIns_S_R"); // FP locals?
6489             return;
6490
6491     } // end switch (ins)
6492
6493     /* Figure out the variable's frame position */
6494     int  base;
6495     bool FPbased;
6496
6497     base = emitComp->lvaFrameAddress(varx, &FPbased);
6498     disp = base + offs;
6499     assert(scale >= 0);
6500     if (isVectorStore)
6501     {
6502         assert(scale <= 4);
6503     }
6504     else
6505     {
6506         assert(scale <= 3);
6507     }
6508
6509     // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6510     regNumber reg2 = FPbased ? REG_FPBASE : REG_SPBASE;
6511     reg2           = encodingSPtoZR(reg2);
6512
6513     bool    useRegForImm = false;
6514     ssize_t imm          = disp;
6515     ssize_t mask         = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6516     if (imm == 0)
6517     {
6518         fmt = IF_LS_2A;
6519     }
6520     else if ((imm < 0) || ((imm & mask) != 0))
6521     {
6522         if ((imm >= -256) && (imm <= 255))
6523         {
6524             fmt = IF_LS_2C;
6525         }
6526         else
6527         {
6528             useRegForImm = true;
6529         }
6530     }
6531     else if (imm > 0)
6532     {
6533         if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
6534         {
6535             imm >>= scale; // The immediate is scaled by the size of the ld/st
6536
6537             fmt = IF_LS_2B;
6538         }
6539         else
6540         {
6541             useRegForImm = true;
6542         }
6543     }
6544
6545     if (useRegForImm)
6546     {
6547         // The reserved register is not stored in idReg3() since that field overlaps with iiaLclVar.
6548         // It is instead implicit when idSetIsLclVar() is set, with this encoding format.
6549         regNumber rsvdReg = codeGen->rsGetRsvdReg();
6550         codeGen->instGen_Set_Reg_To_Imm(size, rsvdReg, imm);
6551         fmt = IF_LS_3A;
6552     }
6553
6554     assert(fmt != IF_NONE);
6555
6556     instrDesc* id = emitNewInstrCns(attr, imm);
6557
6558     id->idIns(ins);
6559     id->idInsFmt(fmt);
6560     id->idInsOpt(INS_OPTS_NONE);
6561
6562     id->idReg1(reg1);
6563     id->idReg2(reg2);
6564     id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6565     id->idSetIsLclVar();
6566
6567 #ifdef DEBUG
6568     id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6569 #endif
6570
6571     dispIns(id);
6572     appendToCurIG(id);
6573 }
6574
6575 /*****************************************************************************
6576  *
6577  *  Add an instruction referencing consecutive stack-based local variable slots and two registers
6578  */
6579 void emitter::emitIns_S_S_R_R(
6580     instruction ins, emitAttr attr1, emitAttr attr2, regNumber reg1, regNumber reg2, int varx, int offs)
6581 {
6582     assert((ins == INS_stp) || (ins == INS_stnp));
6583     assert(EA_8BYTE == EA_SIZE(attr1));
6584     assert(EA_8BYTE == EA_SIZE(attr2));
6585     assert(isGeneralRegisterOrZR(reg1));
6586     assert(isGeneralRegisterOrZR(reg2));
6587     assert(offs >= 0);
6588
6589     emitAttr       size  = EA_SIZE(attr1);
6590     insFormat      fmt   = IF_LS_3B;
6591     int            disp  = 0;
6592     const unsigned scale = 3;
6593
6594     /* Figure out the variable's frame position */
6595     int  base;
6596     bool FPbased;
6597
6598     base = emitComp->lvaFrameAddress(varx, &FPbased);
6599     disp = base + offs;
6600
6601     // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6602     regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE;
6603     reg3           = encodingSPtoZR(reg3);
6604
6605     bool    useRegForAdr = true;
6606     ssize_t imm          = disp;
6607     ssize_t mask         = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6608     if (imm == 0)
6609     {
6610         useRegForAdr = false;
6611     }
6612     else
6613     {
6614         if ((imm & mask) == 0)
6615         {
6616             ssize_t immShift = imm >> scale; // The immediate is scaled by the size of the ld/st
6617
6618             if ((immShift >= -64) && (immShift <= 63))
6619             {
6620                 fmt          = IF_LS_3C;
6621                 useRegForAdr = false;
6622                 imm          = immShift;
6623             }
6624         }
6625     }
6626
6627     if (useRegForAdr)
6628     {
6629         regNumber rsvd = codeGen->rsGetRsvdReg();
6630         emitIns_R_R_Imm(INS_add, EA_8BYTE, rsvd, reg3, imm);
6631         reg3 = rsvd;
6632         imm  = 0;
6633     }
6634
6635     assert(fmt != IF_NONE);
6636
6637     instrDesc* id = emitNewInstrCns(attr1, imm);
6638
6639     id->idIns(ins);
6640     id->idInsFmt(fmt);
6641     id->idInsOpt(INS_OPTS_NONE);
6642
6643     // Record the attribute for the second register in the pair
6644     if (EA_IS_GCREF(attr2))
6645     {
6646         id->idGCrefReg2(GCT_GCREF);
6647     }
6648     else if (EA_IS_BYREF(attr2))
6649     {
6650         id->idGCrefReg2(GCT_BYREF);
6651     }
6652     else
6653     {
6654         id->idGCrefReg2(GCT_NONE);
6655     }
6656
6657     id->idReg1(reg1);
6658     id->idReg2(reg2);
6659     id->idReg3(reg3);
6660     id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6661     id->idSetIsLclVar();
6662
6663 #ifdef DEBUG
6664     id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6665 #endif
6666
6667     dispIns(id);
6668     appendToCurIG(id);
6669 }
6670
6671 /*****************************************************************************
6672  *
6673  *  Add an instruction referencing stack-based local variable and an immediate
6674  */
6675 void emitter::emitIns_S_I(instruction ins, emitAttr attr, int varx, int offs, int val)
6676 {
6677     NYI("emitIns_S_I");
6678 }
6679
6680 /*****************************************************************************
6681  *
6682  *  Add an instruction with a register + static member operands.
6683  *  Constant is stored into JIT data which is adjacent to code.
6684  *  No relocation is needed. PC-relative offset will be encoded directly into instruction.
6685  *
6686  */
6687 void emitter::emitIns_R_C(
6688     instruction ins, emitAttr attr, regNumber reg, regNumber addrReg, CORINFO_FIELD_HANDLE fldHnd, int offs)
6689 {
6690     assert(offs >= 0);
6691     assert(instrDesc::fitsInSmallCns(offs));
6692
6693     emitAttr      size = EA_SIZE(attr);
6694     insFormat     fmt  = IF_NONE;
6695     int           disp = 0;
6696     instrDescJmp* id   = emitNewInstrJmp();
6697
6698     switch (ins)
6699     {
6700         case INS_adr:
6701             // This is case to get address to the constant data.
6702             fmt = IF_LARGEADR;
6703             assert(isGeneralRegister(reg));
6704             assert(isValidGeneralDatasize(size));
6705             break;
6706
6707         case INS_ldr:
6708             fmt = IF_LARGELDC;
6709             if (isVectorRegister(reg))
6710             {
6711                 assert(isValidScalarDatasize(size));
6712                 // For vector (float/double) register, we should have an integer address reg to
6713                 // compute long address which consists of page address and page offset.
6714                 // For integer constant, this is not needed since the dest reg can be used to
6715                 // compute address as well as contain the final contents.
6716                 assert(isGeneralRegister(reg) || (addrReg != REG_NA));
6717             }
6718             else
6719             {
6720                 assert(isGeneralRegister(reg));
6721                 assert(isValidGeneralDatasize(size));
6722             }
6723             break;
6724         default:
6725             unreached();
6726     }
6727
6728     assert(fmt != IF_NONE);
6729
6730     id->idIns(ins);
6731     id->idInsFmt(fmt);
6732     id->idInsOpt(INS_OPTS_NONE);
6733     id->idSmallCns(offs);
6734     id->idOpSize(size);
6735     id->idAddr()->iiaFieldHnd = fldHnd;
6736     id->idSetIsBound(); // We won't patch address since we will know the exact distance once JIT code and data are
6737                         // allocated together.
6738
6739     id->idReg1(reg); // destination register that will get the constant value.
6740     if (addrReg != REG_NA)
6741     {
6742         id->idReg2(addrReg); // integer register to compute long address (used for vector dest when we end up with long
6743                              // address)
6744     }
6745     id->idjShort = false; // Assume loading constant from long address
6746
6747     // Keep it long if it's in cold code.
6748     id->idjKeepLong = emitComp->fgIsBlockCold(emitComp->compCurBB);
6749
6750 #ifdef DEBUG
6751     if (emitComp->opts.compLongAddress)
6752         id->idjKeepLong = 1;
6753 #endif // DEBUG
6754
6755     // If it's possible to be shortened, then put it in jump list
6756     // to be revisited by emitJumpDistBind.
6757     if (!id->idjKeepLong)
6758     {
6759         /* Record the jump's IG and offset within it */
6760         id->idjIG   = emitCurIG;
6761         id->idjOffs = emitCurIGsize;
6762
6763         /* Append this jump to this IG's jump list */
6764         id->idjNext      = emitCurIGjmpList;
6765         emitCurIGjmpList = id;
6766
6767 #if EMITTER_STATS
6768         emitTotalIGjmps++;
6769 #endif
6770     }
6771
6772     dispIns(id);
6773     appendToCurIG(id);
6774 }
6775
6776 /*****************************************************************************
6777  *
6778  *  Add an instruction with a static member + constant.
6779  */
6780
6781 void emitter::emitIns_C_I(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, ssize_t offs, ssize_t val)
6782 {
6783     NYI("emitIns_C_I");
6784 }
6785
6786 /*****************************************************************************
6787  *
6788  *  Add an instruction with a static member + register operands.
6789  */
6790
6791 void emitter::emitIns_C_R(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, regNumber reg, int offs)
6792 {
6793     assert(!"emitIns_C_R not supported for RyuJIT backend");
6794 }
6795
6796 void emitter::emitIns_R_AR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
6797 {
6798     NYI("emitIns_R_AR");
6799 }
6800
6801 // This computes address from the immediate which is relocatable.
6802 void emitter::emitIns_R_AI(instruction ins, emitAttr attr, regNumber ireg, ssize_t addr)
6803 {
6804     assert(EA_IS_RELOC(attr));
6805     emitAttr      size    = EA_SIZE(attr);
6806     insFormat     fmt     = IF_DI_1E;
6807     bool          needAdd = false;
6808     instrDescJmp* id      = emitNewInstrJmp();
6809
6810     switch (ins)
6811     {
6812         case INS_adrp:
6813             // This computes page address.
6814             // page offset is needed using add.
6815             needAdd = true;
6816             break;
6817         case INS_adr:
6818             break;
6819         default:
6820             unreached();
6821     }
6822
6823     id->idIns(ins);
6824     id->idInsFmt(fmt);
6825     id->idInsOpt(INS_OPTS_NONE);
6826     id->idOpSize(size);
6827     id->idAddr()->iiaAddr = (BYTE*)addr;
6828     id->idReg1(ireg);
6829     id->idSetIsDspReloc();
6830
6831     dispIns(id);
6832     appendToCurIG(id);
6833
6834     if (needAdd)
6835     {
6836         // add reg, reg, imm
6837         ins           = INS_add;
6838         fmt           = IF_DI_2A;
6839         instrDesc* id = emitAllocInstr(attr);
6840         assert(id->idIsReloc());
6841
6842         id->idIns(ins);
6843         id->idInsFmt(fmt);
6844         id->idInsOpt(INS_OPTS_NONE);
6845         id->idOpSize(size);
6846         id->idAddr()->iiaAddr = (BYTE*)addr;
6847         id->idReg1(ireg);
6848         id->idReg2(ireg);
6849
6850         dispIns(id);
6851         appendToCurIG(id);
6852     }
6853 }
6854
6855 void emitter::emitIns_AR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
6856 {
6857     NYI("emitIns_AR_R");
6858 }
6859
6860 void emitter::emitIns_R_ARR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
6861 {
6862     NYI("emitIns_R_ARR");
6863 }
6864
6865 void emitter::emitIns_ARR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
6866 {
6867     NYI("emitIns_R_ARR");
6868 }
6869
6870 void emitter::emitIns_R_ARX(
6871     instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, unsigned mul, int disp)
6872 {
6873     NYI("emitIns_R_ARR");
6874 }
6875
6876 /*****************************************************************************
6877  *
6878  *  Record that a jump instruction uses the short encoding
6879  *
6880  */
6881 void emitter::emitSetShortJump(instrDescJmp* id)
6882 {
6883     if (id->idjKeepLong)
6884         return;
6885
6886     insFormat fmt = IF_NONE;
6887     if (emitIsCondJump(id))
6888     {
6889         switch (id->idIns())
6890         {
6891             case INS_cbz:
6892             case INS_cbnz:
6893                 fmt = IF_BI_1A;
6894                 break;
6895             case INS_tbz:
6896             case INS_tbnz:
6897                 fmt = IF_BI_1B;
6898                 break;
6899             default:
6900                 fmt = IF_BI_0B;
6901                 break;
6902         }
6903     }
6904     else if (emitIsLoadLabel(id))
6905     {
6906         fmt = IF_DI_1E;
6907     }
6908     else if (emitIsLoadConstant(id))
6909     {
6910         fmt = IF_LS_1A;
6911     }
6912     else
6913     {
6914         unreached();
6915     }
6916
6917     id->idInsFmt(fmt);
6918     id->idjShort = true;
6919 }
6920
6921 /*****************************************************************************
6922  *
6923  *  Add a label instruction.
6924  */
6925
6926 void emitter::emitIns_R_L(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
6927 {
6928     assert(dst->bbFlags & BBF_JMP_TARGET);
6929
6930     insFormat fmt = IF_NONE;
6931
6932     switch (ins)
6933     {
6934         case INS_adr:
6935             fmt = IF_LARGEADR;
6936             break;
6937         default:
6938             unreached();
6939     }
6940
6941     instrDescJmp* id = emitNewInstrJmp();
6942
6943     id->idIns(ins);
6944     id->idInsFmt(fmt);
6945     id->idjShort             = false;
6946     id->idAddr()->iiaBBlabel = dst;
6947     id->idReg1(reg);
6948     id->idOpSize(EA_PTRSIZE);
6949
6950 #ifdef DEBUG
6951     // Mark the catch return
6952     if (emitComp->compCurBB->bbJumpKind == BBJ_EHCATCHRET)
6953     {
6954         id->idDebugOnlyInfo()->idCatchRet = true;
6955     }
6956 #endif // DEBUG
6957
6958     id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
6959
6960 #ifdef DEBUG
6961     if (emitComp->opts.compLongAddress)
6962         id->idjKeepLong = 1;
6963 #endif // DEBUG
6964
6965     /* Record the jump's IG and offset within it */
6966
6967     id->idjIG   = emitCurIG;
6968     id->idjOffs = emitCurIGsize;
6969
6970     /* Append this jump to this IG's jump list */
6971
6972     id->idjNext      = emitCurIGjmpList;
6973     emitCurIGjmpList = id;
6974
6975 #if EMITTER_STATS
6976     emitTotalIGjmps++;
6977 #endif
6978
6979     dispIns(id);
6980     appendToCurIG(id);
6981 }
6982
6983 /*****************************************************************************
6984  *
6985  *  Add a data label instruction.
6986  */
6987
6988 void emitter::emitIns_R_D(instruction ins, emitAttr attr, unsigned offs, regNumber reg)
6989 {
6990     NYI("emitIns_R_D");
6991 }
6992
6993 void emitter::emitIns_J_R(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
6994 {
6995     assert((ins == INS_cbz) || (ins == INS_cbnz));
6996
6997     assert(dst != nullptr);
6998     assert((dst->bbFlags & BBF_JMP_TARGET) != 0);
6999
7000     insFormat fmt = IF_LARGEJMP;
7001
7002     instrDescJmp* id = emitNewInstrJmp();
7003
7004     id->idIns(ins);
7005     id->idInsFmt(fmt);
7006     id->idReg1(reg);
7007     id->idjShort = false;
7008     id->idOpSize(EA_SIZE(attr));
7009
7010     id->idAddr()->iiaBBlabel = dst;
7011     id->idjKeepLong          = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7012
7013     /* Record the jump's IG and offset within it */
7014
7015     id->idjIG   = emitCurIG;
7016     id->idjOffs = emitCurIGsize;
7017
7018     /* Append this jump to this IG's jump list */
7019
7020     id->idjNext      = emitCurIGjmpList;
7021     emitCurIGjmpList = id;
7022
7023 #if EMITTER_STATS
7024     emitTotalIGjmps++;
7025 #endif
7026
7027     dispIns(id);
7028     appendToCurIG(id);
7029 }
7030
7031 void emitter::emitIns_J_R_I(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg, int imm)
7032 {
7033     assert((ins == INS_tbz) || (ins == INS_tbnz));
7034
7035     assert(dst != nullptr);
7036     assert((dst->bbFlags & BBF_JMP_TARGET) != 0);
7037     assert((EA_SIZE(attr) == EA_4BYTE) || (EA_SIZE(attr) == EA_8BYTE));
7038     assert(imm < ((EA_SIZE(attr) == EA_4BYTE) ? 32 : 64));
7039
7040     insFormat fmt = IF_LARGEJMP;
7041
7042     instrDescJmp* id = emitNewInstrJmp();
7043
7044     id->idIns(ins);
7045     id->idInsFmt(fmt);
7046     id->idReg1(reg);
7047     id->idjShort = false;
7048     id->idSmallCns(imm);
7049     id->idOpSize(EA_SIZE(attr));
7050
7051     id->idAddr()->iiaBBlabel = dst;
7052     id->idjKeepLong          = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7053
7054     /* Record the jump's IG and offset within it */
7055
7056     id->idjIG   = emitCurIG;
7057     id->idjOffs = emitCurIGsize;
7058
7059     /* Append this jump to this IG's jump list */
7060
7061     id->idjNext      = emitCurIGjmpList;
7062     emitCurIGjmpList = id;
7063
7064 #if EMITTER_STATS
7065     emitTotalIGjmps++;
7066 #endif
7067
7068     dispIns(id);
7069     appendToCurIG(id);
7070 }
7071
7072 void emitter::emitIns_J(instruction ins, BasicBlock* dst, int instrCount)
7073 {
7074     insFormat fmt = IF_NONE;
7075
7076     if (dst != nullptr)
7077     {
7078         assert(dst->bbFlags & BBF_JMP_TARGET);
7079     }
7080     else
7081     {
7082         assert(instrCount != 0);
7083     }
7084
7085     /* Figure out the encoding format of the instruction */
7086
7087     bool idjShort = false;
7088     switch (ins)
7089     {
7090         case INS_bl_local:
7091         case INS_b:
7092             // Unconditional jump is a single form.
7093             idjShort = true;
7094             fmt      = IF_BI_0A;
7095             break;
7096
7097         case INS_beq:
7098         case INS_bne:
7099         case INS_bhs:
7100         case INS_blo:
7101         case INS_bmi:
7102         case INS_bpl:
7103         case INS_bvs:
7104         case INS_bvc:
7105         case INS_bhi:
7106         case INS_bls:
7107         case INS_bge:
7108         case INS_blt:
7109         case INS_bgt:
7110         case INS_ble:
7111             // Assume conditional jump is long.
7112             fmt = IF_LARGEJMP;
7113             break;
7114
7115         default:
7116             unreached();
7117             break;
7118     }
7119
7120     instrDescJmp* id = emitNewInstrJmp();
7121
7122     id->idIns(ins);
7123     id->idInsFmt(fmt);
7124     id->idjShort = idjShort;
7125
7126 #ifdef DEBUG
7127     // Mark the finally call
7128     if (ins == INS_bl_local && emitComp->compCurBB->bbJumpKind == BBJ_CALLFINALLY)
7129     {
7130         id->idDebugOnlyInfo()->idFinallyCall = true;
7131     }
7132 #endif // DEBUG
7133
7134     if (dst != nullptr)
7135     {
7136         id->idAddr()->iiaBBlabel = dst;
7137
7138         // Skip unconditional jump that has a single form.
7139         // TODO-ARM64-NYI: enable hot/cold splittingNYI.
7140         // The target needs to be relocated.
7141         if (!idjShort)
7142         {
7143             id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7144
7145 #ifdef DEBUG
7146             if (emitComp->opts.compLongAddress) // Force long branches
7147                 id->idjKeepLong = 1;
7148 #endif // DEBUG
7149         }
7150     }
7151     else
7152     {
7153         id->idAddr()->iiaSetInstrCount(instrCount);
7154         id->idjKeepLong = false;
7155         /* This jump must be short */
7156         emitSetShortJump(id);
7157         id->idSetIsBound();
7158     }
7159
7160     /* Record the jump's IG and offset within it */
7161
7162     id->idjIG   = emitCurIG;
7163     id->idjOffs = emitCurIGsize;
7164
7165     /* Append this jump to this IG's jump list */
7166
7167     id->idjNext      = emitCurIGjmpList;
7168     emitCurIGjmpList = id;
7169
7170 #if EMITTER_STATS
7171     emitTotalIGjmps++;
7172 #endif
7173
7174     dispIns(id);
7175     appendToCurIG(id);
7176 }
7177
7178 /*****************************************************************************
7179  *
7180  *  Add a call instruction (direct or indirect).
7181  *      argSize<0 means that the caller will pop the arguments
7182  *
7183  * The other arguments are interpreted depending on callType as shown:
7184  * Unless otherwise specified, ireg,xreg,xmul,disp should have default values.
7185  *
7186  * EC_FUNC_TOKEN       : addr is the method address
7187  * EC_FUNC_ADDR        : addr is the absolute address of the function
7188  *
7189  * If callType is one of these emitCallTypes, addr has to be NULL.
7190  * EC_INDIR_R          : "call ireg".
7191  *
7192  * For ARM xreg, xmul and disp are never used and should always be 0/REG_NA.
7193  *
7194  *  Please consult the "debugger team notification" comment in genFnProlog().
7195  */
7196
7197 void emitter::emitIns_Call(EmitCallType          callType,
7198                            CORINFO_METHOD_HANDLE methHnd,
7199                            INDEBUG_LDISASM_COMMA(CORINFO_SIG_INFO* sigInfo) // used to report call sites to the EE
7200                            void*            addr,
7201                            ssize_t          argSize,
7202                            emitAttr         retSize,
7203                            emitAttr         secondRetSize,
7204                            VARSET_VALARG_TP ptrVars,
7205                            regMaskTP        gcrefRegs,
7206                            regMaskTP        byrefRegs,
7207                            IL_OFFSETX       ilOffset /* = BAD_IL_OFFSET */,
7208                            regNumber        ireg /* = REG_NA */,
7209                            regNumber        xreg /* = REG_NA */,
7210                            unsigned         xmul /* = 0     */,
7211                            ssize_t          disp /* = 0     */,
7212                            bool             isJump /* = false */,
7213                            bool             isNoGC /* = false */,
7214                            bool             isProfLeaveCB /* = false */)
7215 {
7216     /* Sanity check the arguments depending on callType */
7217
7218     assert(callType < EC_COUNT);
7219     assert((callType != EC_FUNC_TOKEN && callType != EC_FUNC_ADDR) ||
7220            (ireg == REG_NA && xreg == REG_NA && xmul == 0 && disp == 0));
7221     assert(callType < EC_INDIR_R || addr == NULL);
7222     assert(callType != EC_INDIR_R || (ireg < REG_COUNT && xreg == REG_NA && xmul == 0 && disp == 0));
7223
7224     // ARM never uses these
7225     assert(xreg == REG_NA && xmul == 0 && disp == 0);
7226
7227     // Our stack level should be always greater than the bytes of arguments we push. Just
7228     // a sanity test.
7229     assert((unsigned)abs(argSize) <= codeGen->genStackLevel);
7230
7231     int        argCnt;
7232     instrDesc* id;
7233
7234     /* This is the saved set of registers after a normal call */
7235     regMaskTP savedSet = RBM_CALLEE_SAVED;
7236
7237     /* some special helper calls have a different saved set registers */
7238
7239     if (isNoGC)
7240     {
7241         assert(emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
7242
7243         // Get the set of registers that this call kills and remove it from the saved set.
7244         savedSet = RBM_ALLINT & ~emitComp->compNoGCHelperCallKillSet(Compiler::eeGetHelperNum(methHnd));
7245
7246         // In case of Leave profiler callback, we need to preserve liveness of REG_PROFILER_RET_SCRATCH
7247         if (isProfLeaveCB)
7248         {
7249             savedSet |= RBM_PROFILER_RET_SCRATCH;
7250         }
7251     }
7252     else
7253     {
7254         assert(!emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
7255     }
7256
7257     /* Trim out any callee-trashed registers from the live set */
7258
7259     gcrefRegs &= savedSet;
7260     byrefRegs &= savedSet;
7261
7262 #ifdef DEBUG
7263     if (EMIT_GC_VERBOSE)
7264     {
7265         printf("Call: GCvars=%s ", VarSetOps::ToString(emitComp, ptrVars));
7266         dumpConvertedVarSet(emitComp, ptrVars);
7267         printf(", gcrefRegs=");
7268         printRegMaskInt(gcrefRegs);
7269         emitDispRegSet(gcrefRegs);
7270         printf(", byrefRegs=");
7271         printRegMaskInt(byrefRegs);
7272         emitDispRegSet(byrefRegs);
7273         printf("\n");
7274     }
7275 #endif
7276
7277     assert(argSize % REGSIZE_BYTES == 0);
7278     argCnt = (int)(argSize / (int)sizeof(void*));
7279
7280     /* Managed RetVal: emit sequence point for the call */
7281     if (emitComp->opts.compDbgInfo && ilOffset != BAD_IL_OFFSET)
7282     {
7283         codeGen->genIPmappingAdd(ilOffset, false);
7284     }
7285
7286     /*
7287         We need to allocate the appropriate instruction descriptor based
7288         on whether this is a direct/indirect call, and whether we need to
7289         record an updated set of live GC variables.
7290      */
7291
7292     if (callType >= EC_INDIR_R)
7293     {
7294         /* Indirect call, virtual calls */
7295
7296         assert(callType == EC_INDIR_R);
7297
7298         id = emitNewInstrCallInd(argCnt, disp, ptrVars, gcrefRegs, byrefRegs, retSize, secondRetSize);
7299     }
7300     else
7301     {
7302         /* Helper/static/nonvirtual/function calls (direct or through handle),
7303            and calls to an absolute addr. */
7304
7305         assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
7306
7307         id = emitNewInstrCallDir(argCnt, ptrVars, gcrefRegs, byrefRegs, retSize, secondRetSize);
7308     }
7309
7310     /* Update the emitter's live GC ref sets */
7311
7312     VarSetOps::Assign(emitComp, emitThisGCrefVars, ptrVars);
7313     emitThisGCrefRegs = gcrefRegs;
7314     emitThisByrefRegs = byrefRegs;
7315
7316     /* Set the instruction - special case jumping a function */
7317     instruction ins;
7318     insFormat   fmt = IF_NONE;
7319
7320     id->idSetIsNoGC(isNoGC);
7321
7322     /* Record the address: method, indirection, or funcptr */
7323
7324     if (callType > EC_FUNC_ADDR)
7325     {
7326         /* This is an indirect call (either a virtual call or func ptr call) */
7327
7328         switch (callType)
7329         {
7330             case EC_INDIR_R: // the address is in a register
7331
7332                 id->idSetIsCallRegPtr();
7333
7334                 if (isJump)
7335                 {
7336                     ins = INS_br_tail; // INS_br_tail  Reg
7337                 }
7338                 else
7339                 {
7340                     ins = INS_blr; // INS_blr Reg
7341                 }
7342                 fmt = IF_BR_1B;
7343
7344                 id->idIns(ins);
7345                 id->idInsFmt(fmt);
7346
7347                 id->idReg3(ireg);
7348                 assert(xreg == REG_NA);
7349                 break;
7350
7351             default:
7352                 NO_WAY("unexpected instruction");
7353                 break;
7354         }
7355     }
7356     else
7357     {
7358         /* This is a simple direct call: "call helper/method/addr" */
7359
7360         assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
7361
7362         assert(addr != NULL);
7363
7364         if (isJump)
7365         {
7366             ins = INS_b_tail; // INS_b_tail imm28
7367         }
7368         else
7369         {
7370             ins = INS_bl; // INS_bl imm28
7371         }
7372         fmt = IF_BI_0C;
7373
7374         id->idIns(ins);
7375         id->idInsFmt(fmt);
7376
7377         id->idAddr()->iiaAddr = (BYTE*)addr;
7378
7379         if (callType == EC_FUNC_ADDR)
7380         {
7381             id->idSetIsCallAddr();
7382         }
7383
7384         if (emitComp->opts.compReloc)
7385         {
7386             id->idSetIsDspReloc();
7387         }
7388     }
7389
7390 #ifdef DEBUG
7391     if (EMIT_GC_VERBOSE)
7392     {
7393         if (id->idIsLargeCall())
7394         {
7395             printf("[%02u] Rec call GC vars = %s\n", id->idDebugOnlyInfo()->idNum,
7396                    VarSetOps::ToString(emitComp, ((instrDescCGCA*)id)->idcGCvars));
7397         }
7398     }
7399
7400     id->idDebugOnlyInfo()->idMemCookie = (size_t)methHnd; // method token
7401     id->idDebugOnlyInfo()->idCallSig   = sigInfo;
7402 #endif // DEBUG
7403
7404 #ifdef LATE_DISASM
7405     if (addr != nullptr)
7406     {
7407         codeGen->getDisAssembler().disSetMethod((size_t)addr, methHnd);
7408     }
7409 #endif // LATE_DISASM
7410
7411     dispIns(id);
7412     appendToCurIG(id);
7413 }
7414
7415 /*****************************************************************************
7416  *
7417  *  Returns true if 'imm' is valid Cond encoding
7418  */
7419
7420 /*static*/ bool emitter::isValidImmCond(ssize_t imm)
7421 {
7422     // range check the ssize_t value, to make sure it is a small unsigned value
7423     // and that only the bits in the cfi.cond are set
7424     if ((imm < 0) || (imm > 0xF))
7425         return false;
7426
7427     condFlagsImm cfi;
7428     cfi.immCFVal = (unsigned)imm;
7429
7430     return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7431 }
7432
7433 /*****************************************************************************
7434  *
7435  *  Returns true if 'imm' is valid Cond/Flags encoding
7436  */
7437
7438 /*static*/ bool emitter::isValidImmCondFlags(ssize_t imm)
7439 {
7440     // range check the ssize_t value, to make sure it is a small unsigned value
7441     // and that only the bits in the cfi.cond or cfi.flags are set
7442     if ((imm < 0) || (imm > 0xFF))
7443         return false;
7444
7445     condFlagsImm cfi;
7446     cfi.immCFVal = (unsigned)imm;
7447
7448     return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7449 }
7450
7451 /*****************************************************************************
7452  *
7453  *  Returns true if 'imm' is valid Cond/Flags/Imm5 encoding
7454  */
7455
7456 /*static*/ bool emitter::isValidImmCondFlagsImm5(ssize_t imm)
7457 {
7458     // range check the ssize_t value, to make sure it is a small unsigned value
7459     // and that only the bits in the cfi.cond, cfi.flags or cfi.imm5 are set
7460     if ((imm < 0) || (imm > 0x1FFF))
7461         return false;
7462
7463     condFlagsImm cfi;
7464     cfi.immCFVal = (unsigned)imm;
7465
7466     return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7467 }
7468
7469 /*****************************************************************************
7470  *
7471  *  Returns an encoding for the specified register used in the 'Rd' position
7472  */
7473
7474 /*static*/ emitter::code_t emitter::insEncodeReg_Rd(regNumber reg)
7475 {
7476     assert(isIntegerRegister(reg));
7477     emitter::code_t ureg = (emitter::code_t)reg;
7478     assert((ureg >= 0) && (ureg <= 31));
7479     return ureg;
7480 }
7481
7482 /*****************************************************************************
7483  *
7484  *  Returns an encoding for the specified register used in the 'Rt' position
7485  */
7486
7487 /*static*/ emitter::code_t emitter::insEncodeReg_Rt(regNumber reg)
7488 {
7489     assert(isIntegerRegister(reg));
7490     emitter::code_t ureg = (emitter::code_t)reg;
7491     assert((ureg >= 0) && (ureg <= 31));
7492     return ureg;
7493 }
7494
7495 /*****************************************************************************
7496  *
7497  *  Returns an encoding for the specified register used in the 'Rn' position
7498  */
7499
7500 /*static*/ emitter::code_t emitter::insEncodeReg_Rn(regNumber reg)
7501 {
7502     assert(isIntegerRegister(reg));
7503     emitter::code_t ureg = (emitter::code_t)reg;
7504     assert((ureg >= 0) && (ureg <= 31));
7505     return ureg << 5;
7506 }
7507
7508 /*****************************************************************************
7509  *
7510  *  Returns an encoding for the specified register used in the 'Rm' position
7511  */
7512
7513 /*static*/ emitter::code_t emitter::insEncodeReg_Rm(regNumber reg)
7514 {
7515     assert(isIntegerRegister(reg));
7516     emitter::code_t ureg = (emitter::code_t)reg;
7517     assert((ureg >= 0) && (ureg <= 31));
7518     return ureg << 16;
7519 }
7520
7521 /*****************************************************************************
7522  *
7523  *  Returns an encoding for the specified register used in the 'Ra' position
7524  */
7525
7526 /*static*/ emitter::code_t emitter::insEncodeReg_Ra(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 << 10;
7532 }
7533
7534 /*****************************************************************************
7535  *
7536  *  Returns an encoding for the specified register used in the 'Vd' position
7537  */
7538
7539 /*static*/ emitter::code_t emitter::insEncodeReg_Vd(regNumber reg)
7540 {
7541     assert(emitter::isVectorRegister(reg));
7542     emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7543     assert((ureg >= 0) && (ureg <= 31));
7544     return ureg;
7545 }
7546
7547 /*****************************************************************************
7548  *
7549  *  Returns an encoding for the specified register used in the 'Vt' position
7550  */
7551
7552 /*static*/ emitter::code_t emitter::insEncodeReg_Vt(regNumber reg)
7553 {
7554     assert(emitter::isVectorRegister(reg));
7555     emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7556     assert((ureg >= 0) && (ureg <= 31));
7557     return ureg;
7558 }
7559
7560 /*****************************************************************************
7561  *
7562  *  Returns an encoding for the specified register used in the 'Vn' position
7563  */
7564
7565 /*static*/ emitter::code_t emitter::insEncodeReg_Vn(regNumber reg)
7566 {
7567     assert(emitter::isVectorRegister(reg));
7568     emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7569     assert((ureg >= 0) && (ureg <= 31));
7570     return ureg << 5;
7571 }
7572
7573 /*****************************************************************************
7574  *
7575  *  Returns an encoding for the specified register used in the 'Vm' position
7576  */
7577
7578 /*static*/ emitter::code_t emitter::insEncodeReg_Vm(regNumber reg)
7579 {
7580     assert(emitter::isVectorRegister(reg));
7581     emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7582     assert((ureg >= 0) && (ureg <= 31));
7583     return ureg << 16;
7584 }
7585
7586 /*****************************************************************************
7587  *
7588  *  Returns an encoding for the specified register used in the 'Va' position
7589  */
7590
7591 /*static*/ emitter::code_t emitter::insEncodeReg_Va(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 << 10;
7597 }
7598
7599 /*****************************************************************************
7600  *
7601  *  Returns an encoding for the specified condition code.
7602  */
7603
7604 /*static*/ emitter::code_t emitter::insEncodeCond(insCond cond)
7605 {
7606     emitter::code_t uimm = (emitter::code_t)cond;
7607     return uimm << 12;
7608 }
7609
7610 /*****************************************************************************
7611  *
7612  *  Returns an encoding for the condition code with the lowest bit inverted (marked by invert(<cond>) in the
7613  *  architecture manual).
7614  */
7615
7616 /*static*/ emitter::code_t emitter::insEncodeInvertedCond(insCond cond)
7617 {
7618     emitter::code_t uimm = (emitter::code_t)cond;
7619     uimm ^= 1; // invert the lowest bit
7620     return uimm << 12;
7621 }
7622
7623 /*****************************************************************************
7624  *
7625  *  Returns an encoding for the specified flags.
7626  */
7627
7628 /*static*/ emitter::code_t emitter::insEncodeFlags(insCflags flags)
7629 {
7630     emitter::code_t uimm = (emitter::code_t)flags;
7631     return uimm;
7632 }
7633
7634 /*****************************************************************************
7635  *
7636  *  Returns the encoding for the Shift Count bits to be used for Arm64 encodings
7637  */
7638
7639 /*static*/ emitter::code_t emitter::insEncodeShiftCount(ssize_t imm, emitAttr size)
7640 {
7641     assert((imm & 0x003F) == imm);
7642     assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
7643
7644     return (emitter::code_t)imm << 10;
7645 }
7646
7647 /*****************************************************************************
7648  *
7649  *  Returns the encoding to select a 64-bit datasize for an Arm64 instruction
7650  */
7651
7652 /*static*/ emitter::code_t emitter::insEncodeDatasize(emitAttr size)
7653 {
7654     if (size == EA_8BYTE)
7655     {
7656         return 0x80000000; // set the bit at location 31
7657     }
7658     else
7659     {
7660         assert(size == EA_4BYTE);
7661         return 0;
7662     }
7663 }
7664
7665 /*****************************************************************************
7666  *
7667  *  Returns the encoding to select the datasize for the general load/store Arm64 instructions
7668  *
7669  */
7670
7671 /*static*/ emitter::code_t emitter::insEncodeDatasizeLS(emitter::code_t code, emitAttr size)
7672 {
7673     bool exclusive = ((code & 0x35000000) == 0);
7674
7675     if ((code & 0x00800000) && !exclusive) // Is this a sign-extending opcode? (i.e. ldrsw, ldrsh, ldrsb)
7676     {
7677         assert((size == EA_4BYTE) || (size == EA_8BYTE));
7678         if ((code & 0x80000000) == 0) // Is it a ldrsh or ldrsb and not ldrsw ?
7679         {
7680             if (size == EA_4BYTE) // Do we need to encode the 32-bit Rt size bit?
7681             {
7682                 return 0x00400000; // set the bit at location 22
7683             }
7684         }
7685     }
7686     else if (code & 0x80000000) // Is this a ldr/str/ldur/stur opcode?
7687     {
7688         assert((size == EA_4BYTE) || (size == EA_8BYTE));
7689         if (size == EA_8BYTE) // Do we need to encode the 64-bit size bit?
7690         {
7691             return 0x40000000; // set the bit at location 30
7692         }
7693     }
7694     return 0;
7695 }
7696
7697 /*****************************************************************************
7698  *
7699  *  Returns the encoding to select the datasize for the vector load/store Arm64 instructions
7700  *
7701  */
7702
7703 /*static*/ emitter::code_t emitter::insEncodeDatasizeVLS(emitter::code_t code, emitAttr size)
7704 {
7705     code_t result = 0;
7706
7707     // Check bit 29
7708     if ((code & 0x20000000) == 0)
7709     {
7710         // LDR literal
7711
7712         if (size == EA_16BYTE)
7713         {
7714             // set the operation size in bit 31
7715             result = 0x80000000;
7716         }
7717         else if (size == EA_8BYTE)
7718         {
7719             // set the operation size in bit 30
7720             result = 0x40000000;
7721         }
7722         else
7723         {
7724             assert(size == EA_4BYTE);
7725             // no bits are set
7726             result = 0x00000000;
7727         }
7728     }
7729     else
7730     {
7731         // LDR non-literal
7732
7733         if (size == EA_16BYTE)
7734         {
7735             // The operation size in bits 31 and 30 are zero
7736             // Bit 23 specifies a 128-bit Load/Store
7737             result = 0x00800000;
7738         }
7739         else if (size == EA_8BYTE)
7740         {
7741             // set the operation size in bits 31 and 30
7742             result = 0xC0000000;
7743         }
7744         else if (size == EA_4BYTE)
7745         {
7746             // set the operation size in bit 31
7747             result = 0x80000000;
7748         }
7749         else if (size == EA_2BYTE)
7750         {
7751             // set the operation size in bit 30
7752             result = 0x40000000;
7753         }
7754         else
7755         {
7756             assert(size == EA_1BYTE);
7757             // The operation size in bits 31 and 30 are zero
7758             result = 0x00000000;
7759         }
7760     }
7761
7762     // Or in bit 26 to indicate a Vector register is used as 'target'
7763     result |= 0x04000000;
7764
7765     return result;
7766 }
7767
7768 /*****************************************************************************
7769  *
7770  *  Returns the encoding to select the datasize for the vector load/store Arm64 instructions
7771  *
7772  */
7773
7774 /*static*/ emitter::code_t emitter::insEncodeDatasizeVPLS(emitter::code_t code, emitAttr size)
7775 {
7776     code_t result = 0;
7777
7778     if (size == EA_16BYTE)
7779     {
7780         // The operation size in bits 31 and 30 are zero
7781         // Bit 23 specifies a 128-bit Load/Store
7782         result = 0x80000000;
7783     }
7784     else if (size == EA_8BYTE)
7785     {
7786         // set the operation size in bits 31 and 30
7787         result = 0x40000000;
7788     }
7789     else if (size == EA_4BYTE)
7790     {
7791         // set the operation size in bit 31
7792         result = 0x00000000;
7793     }
7794
7795     // Or in bit 26 to indicate a Vector register is used as 'target'
7796     result |= 0x04000000;
7797
7798     return result;
7799 }
7800
7801 /*****************************************************************************
7802  *
7803  *  Returns the encoding to set the size bit and the N bits for a 'bitfield' instruction
7804  *
7805  */
7806
7807 /*static*/ emitter::code_t emitter::insEncodeDatasizeBF(emitter::code_t code, emitAttr size)
7808 {
7809     // is bit 30 equal to 0?
7810     if ((code & 0x40000000) == 0) // is the opcode one of extr, sxtb, sxth or sxtw
7811     {
7812         if (size == EA_8BYTE) // Do we need to set the sf and N bits?
7813         {
7814             return 0x80400000; // set the sf-bit at location 31 and the N-bit at location 22
7815         }
7816     }
7817     return 0; // don't set any bits
7818 }
7819
7820 /*****************************************************************************
7821  *
7822  *  Returns the encoding to select the 64/128-bit datasize for an Arm64 vector instruction
7823  */
7824
7825 /*static*/ emitter::code_t emitter::insEncodeVectorsize(emitAttr size)
7826 {
7827     if (size == EA_16BYTE)
7828     {
7829         return 0x40000000; // set the bit at location 30
7830     }
7831     else
7832     {
7833         assert(size == EA_8BYTE);
7834         return 0;
7835     }
7836 }
7837
7838 /*****************************************************************************
7839  *
7840  *  Returns the encoding to select 'index' for an Arm64 vector elem instruction
7841  */
7842 /*static*/ emitter::code_t emitter::insEncodeVectorIndex(emitAttr elemsize, ssize_t index)
7843 {
7844     code_t bits = (code_t)index;
7845     if (elemsize == EA_1BYTE)
7846     {
7847         bits <<= 1;
7848         bits |= 1;
7849     }
7850     else if (elemsize == EA_2BYTE)
7851     {
7852         bits <<= 2;
7853         bits |= 2;
7854     }
7855     else if (elemsize == EA_4BYTE)
7856     {
7857         bits <<= 3;
7858         bits |= 4;
7859     }
7860     else
7861     {
7862         assert(elemsize == EA_8BYTE);
7863         bits <<= 4;
7864         bits |= 8;
7865     }
7866     assert((bits >= 1) && (bits <= 0x1f));
7867
7868     return (bits << 16); // bits at locations [20,19,18,17,16]
7869 }
7870
7871 /*****************************************************************************
7872  *
7873  *  Returns the encoding to select 'index2' for an Arm64 'ins' elem instruction
7874  */
7875 /*static*/ emitter::code_t emitter::insEncodeVectorIndex2(emitAttr elemsize, ssize_t index2)
7876 {
7877     code_t bits = (code_t)index2;
7878     if (elemsize == EA_1BYTE)
7879     {
7880         // bits are correct
7881     }
7882     else if (elemsize == EA_2BYTE)
7883     {
7884         bits <<= 1;
7885     }
7886     else if (elemsize == EA_4BYTE)
7887     {
7888         bits <<= 2;
7889     }
7890     else
7891     {
7892         assert(elemsize == EA_8BYTE);
7893         bits <<= 3;
7894     }
7895     assert((bits >= 0) && (bits <= 0xf));
7896
7897     return (bits << 11); // bits at locations [14,13,12,11]
7898 }
7899
7900 /*****************************************************************************
7901  *
7902  *  Returns the encoding to select the 'index' for an Arm64 'mul' by elem instruction
7903  */
7904 /*static*/ emitter::code_t emitter::insEncodeVectorIndexLMH(emitAttr elemsize, ssize_t index)
7905 {
7906     code_t bits = 0;
7907
7908     if (elemsize == EA_2BYTE)
7909     {
7910         assert((index >= 0) && (index <= 7));
7911         if (index & 0x4)
7912         {
7913             bits |= (1 << 11); // set bit 11 'H'
7914         }
7915         if (index & 0x2)
7916         {
7917             bits |= (1 << 21); // set bit 21 'L'
7918         }
7919         if (index & 0x1)
7920         {
7921             bits |= (1 << 20); // set bit 20 'M'
7922         }
7923     }
7924     else if (elemsize == EA_4BYTE)
7925     {
7926         assert((index >= 0) && (index <= 3));
7927         if (index & 0x2)
7928         {
7929             bits |= (1 << 11); // set bit 11 'H'
7930         }
7931         if (index & 0x1)
7932         {
7933             bits |= (1 << 21); // set bit 21 'L'
7934         }
7935     }
7936     else
7937     {
7938         assert(!"Invalid 'elemsize' value");
7939     }
7940
7941     return bits;
7942 }
7943
7944 /*****************************************************************************
7945  *
7946  *   Returns the encoding to shift by 'shift' for an Arm64 vector or scalar instruction
7947  */
7948
7949 /*static*/ emitter::code_t emitter::insEncodeVectorShift(emitAttr size, ssize_t shift)
7950 {
7951     assert(shift < getBitWidth(size));
7952
7953     code_t imm = (code_t)(getBitWidth(size) + shift);
7954
7955     return imm << 16;
7956 }
7957
7958 /*****************************************************************************
7959  *
7960  *  Returns the encoding to select the 1/2/4/8 byte elemsize for an Arm64 vector instruction
7961  */
7962
7963 /*static*/ emitter::code_t emitter::insEncodeElemsize(emitAttr size)
7964 {
7965     if (size == EA_8BYTE)
7966     {
7967         return 0x00C00000; // set the bit at location 23 and 22
7968     }
7969     else if (size == EA_4BYTE)
7970     {
7971         return 0x00800000; // set the bit at location 23
7972     }
7973     else if (size == EA_2BYTE)
7974     {
7975         return 0x00400000; // set the bit at location 22
7976     }
7977     assert(size == EA_1BYTE);
7978     return 0x00000000;
7979 }
7980
7981 /*****************************************************************************
7982  *
7983  *  Returns the encoding to select the 4/8 byte elemsize for an Arm64 float vector instruction
7984  */
7985
7986 /*static*/ emitter::code_t emitter::insEncodeFloatElemsize(emitAttr size)
7987 {
7988     if (size == EA_8BYTE)
7989     {
7990         return 0x00400000; // set the bit at location 22
7991     }
7992     assert(size == EA_4BYTE);
7993     return 0x00000000;
7994 }
7995
7996 // Returns the encoding to select the index for an Arm64 float vector by elem instruction
7997 /*static*/ emitter::code_t emitter::insEncodeFloatIndex(emitAttr elemsize, ssize_t index)
7998 {
7999     code_t result = 0x00000000;
8000     if (elemsize == EA_8BYTE)
8001     {
8002         assert((index >= 0) && (index <= 1));
8003         if (index == 1)
8004         {
8005             result |= 0x00000800; // 'H' - set the bit at location 11
8006         }
8007     }
8008     else
8009     {
8010         assert(elemsize == EA_4BYTE);
8011         assert((index >= 0) && (index <= 3));
8012         if (index & 2)
8013         {
8014             result |= 0x00000800; // 'H' - set the bit at location 11
8015         }
8016         if (index & 1)
8017         {
8018             result |= 0x00200000; // 'L' - set the bit at location 21
8019         }
8020     }
8021     return result;
8022 }
8023
8024 /*****************************************************************************
8025  *
8026  *  Returns the encoding to select the fcvt operation for Arm64 instructions
8027  */
8028 /*static*/ emitter::code_t emitter::insEncodeConvertOpt(insFormat fmt, insOpts conversion)
8029 {
8030     code_t result = 0;
8031     switch (conversion)
8032     {
8033         case INS_OPTS_S_TO_D: // Single to Double
8034             assert(fmt == IF_DV_2J);
8035             result = 0x00008000; // type=00, opc=01
8036             break;
8037
8038         case INS_OPTS_D_TO_S: // Double to Single
8039             assert(fmt == IF_DV_2J);
8040             result = 0x00400000; // type=01, opc=00
8041             break;
8042
8043         case INS_OPTS_H_TO_S: // Half to Single
8044             assert(fmt == IF_DV_2J);
8045             result = 0x00C00000; // type=11, opc=00
8046             break;
8047
8048         case INS_OPTS_H_TO_D: // Half to Double
8049             assert(fmt == IF_DV_2J);
8050             result = 0x00C08000; // type=11, opc=01
8051             break;
8052
8053         case INS_OPTS_S_TO_H: // Single to Half
8054             assert(fmt == IF_DV_2J);
8055             result = 0x00018000; // type=00, opc=11
8056             break;
8057
8058         case INS_OPTS_D_TO_H: // Double to Half
8059             assert(fmt == IF_DV_2J);
8060             result = 0x00418000; // type=01, opc=11
8061             break;
8062
8063         case INS_OPTS_S_TO_4BYTE: // Single to INT32
8064             assert(fmt == IF_DV_2H);
8065             result = 0x00000000; // sf=0, type=00
8066             break;
8067
8068         case INS_OPTS_D_TO_4BYTE: // Double to INT32
8069             assert(fmt == IF_DV_2H);
8070             result = 0x00400000; // sf=0, type=01
8071             break;
8072
8073         case INS_OPTS_S_TO_8BYTE: // Single to INT64
8074             assert(fmt == IF_DV_2H);
8075             result = 0x80000000; // sf=1, type=00
8076             break;
8077
8078         case INS_OPTS_D_TO_8BYTE: // Double to INT64
8079             assert(fmt == IF_DV_2H);
8080             result = 0x80400000; // sf=1, type=01
8081             break;
8082
8083         case INS_OPTS_4BYTE_TO_S: // INT32 to Single
8084             assert(fmt == IF_DV_2I);
8085             result = 0x00000000; // sf=0, type=00
8086             break;
8087
8088         case INS_OPTS_4BYTE_TO_D: // INT32 to Double
8089             assert(fmt == IF_DV_2I);
8090             result = 0x00400000; // sf=0, type=01
8091             break;
8092
8093         case INS_OPTS_8BYTE_TO_S: // INT64 to Single
8094             assert(fmt == IF_DV_2I);
8095             result = 0x80000000; // sf=1, type=00
8096             break;
8097
8098         case INS_OPTS_8BYTE_TO_D: // INT64 to Double
8099             assert(fmt == IF_DV_2I);
8100             result = 0x80400000; // sf=1, type=01
8101             break;
8102
8103         default:
8104             assert(!"Invalid 'conversion' value");
8105             break;
8106     }
8107     return result;
8108 }
8109
8110 /*****************************************************************************
8111  *
8112  *  Returns the encoding to have the Rn register be updated Pre/Post indexed
8113  *  or not updated
8114  */
8115
8116 /*static*/ emitter::code_t emitter::insEncodeIndexedOpt(insOpts opt)
8117 {
8118     assert(emitter::insOptsNone(opt) || emitter::insOptsIndexed(opt));
8119
8120     if (emitter::insOptsIndexed(opt))
8121     {
8122         if (emitter::insOptsPostIndex(opt))
8123         {
8124             return 0x00000400; // set the bit at location 10
8125         }
8126         else
8127         {
8128             assert(emitter::insOptsPreIndex(opt));
8129             return 0x00000C00; // set the bit at location 10 and 11
8130         }
8131     }
8132     else
8133     {
8134         assert(emitter::insOptsNone(opt));
8135         return 0; // bits 10 and 11 are zero
8136     }
8137 }
8138
8139 /*****************************************************************************
8140  *
8141  *  Returns the encoding for a ldp/stp instruction to have the Rn register
8142  *  be updated Pre/Post indexed or not updated
8143  */
8144
8145 /*static*/ emitter::code_t emitter::insEncodePairIndexedOpt(instruction ins, insOpts opt)
8146 {
8147     assert(emitter::insOptsNone(opt) || emitter::insOptsIndexed(opt));
8148
8149     if ((ins == INS_ldnp) || (ins == INS_stnp))
8150     {
8151         assert(emitter::insOptsNone(opt));
8152         return 0; // bits 23 and 24 are zero
8153     }
8154     else
8155     {
8156         if (emitter::insOptsIndexed(opt))
8157         {
8158             if (emitter::insOptsPostIndex(opt))
8159             {
8160                 return 0x00800000; // set the bit at location 23
8161             }
8162             else
8163             {
8164                 assert(emitter::insOptsPreIndex(opt));
8165                 return 0x01800000; // set the bit at location 24 and 23
8166             }
8167         }
8168         else
8169         {
8170             assert(emitter::insOptsNone(opt));
8171             return 0x01000000; // set the bit at location 24
8172         }
8173     }
8174 }
8175
8176 /*****************************************************************************
8177  *
8178  *  Returns the encoding to apply a Shift Type on the Rm register
8179  */
8180
8181 /*static*/ emitter::code_t emitter::insEncodeShiftType(insOpts opt)
8182 {
8183     if (emitter::insOptsNone(opt))
8184     {
8185         // None implies the we encode LSL (with a zero immediate)
8186         opt = INS_OPTS_LSL;
8187     }
8188     assert(emitter::insOptsAnyShift(opt));
8189
8190     emitter::code_t option = (emitter::code_t)opt - (emitter::code_t)INS_OPTS_LSL;
8191     assert(option <= 3);
8192
8193     return option << 22; // bits 23, 22
8194 }
8195
8196 /*****************************************************************************
8197  *
8198  *  Returns the encoding to apply a 12 bit left shift to the immediate
8199  */
8200
8201 /*static*/ emitter::code_t emitter::insEncodeShiftImm12(insOpts opt)
8202 {
8203     if (emitter::insOptsLSL12(opt))
8204     {
8205         return 0x00400000; // set the bit at location 22
8206     }
8207     return 0;
8208 }
8209
8210 /*****************************************************************************
8211  *
8212  *  Returns the encoding to have the Rm register use an extend operation
8213  */
8214
8215 /*static*/ emitter::code_t emitter::insEncodeExtend(insOpts opt)
8216 {
8217     if (emitter::insOptsNone(opt) || (opt == INS_OPTS_LSL))
8218     {
8219         // None or LSL implies the we encode UXTX
8220         opt = INS_OPTS_UXTX;
8221     }
8222     assert(emitter::insOptsAnyExtend(opt));
8223
8224     emitter::code_t option = (emitter::code_t)opt - (emitter::code_t)INS_OPTS_UXTB;
8225     assert(option <= 7);
8226
8227     return option << 13; // bits 15,14,13
8228 }
8229
8230 /*****************************************************************************
8231  *
8232  *  Returns the encoding to scale the Rm register by {0,1,2,3,4}
8233  *  when using an extend operation
8234  */
8235
8236 /*static*/ emitter::code_t emitter::insEncodeExtendScale(ssize_t imm)
8237 {
8238     assert((imm >= 0) && (imm <= 4));
8239
8240     return (emitter::code_t)imm << 10; // bits 12,11,10
8241 }
8242
8243 /*****************************************************************************
8244  *
8245  *  Returns the encoding to have the Rm register be auto scaled by the ld/st size
8246  */
8247
8248 /*static*/ emitter::code_t emitter::insEncodeReg3Scale(bool isScaled)
8249 {
8250     if (isScaled)
8251     {
8252         return 0x00001000; // set the bit at location 12
8253     }
8254     else
8255     {
8256         return 0;
8257     }
8258 }
8259
8260 BYTE* emitter::emitOutputLoadLabel(BYTE* dst, BYTE* srcAddr, BYTE* dstAddr, instrDescJmp* id)
8261 {
8262     instruction ins    = id->idIns();
8263     insFormat   fmt    = id->idInsFmt();
8264     regNumber   dstReg = id->idReg1();
8265     if (id->idjShort)
8266     {
8267         // adr x, [rel addr] --  compute address: current addr(ip) + rel addr.
8268         assert(ins == INS_adr);
8269         assert(fmt == IF_DI_1E);
8270         ssize_t distVal = (ssize_t)(dstAddr - srcAddr);
8271         dst             = emitOutputShortAddress(dst, ins, fmt, distVal, dstReg);
8272     }
8273     else
8274     {
8275         // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8276         assert(fmt == IF_LARGEADR);
8277         ssize_t relPageAddr =
8278             (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8279         dst = emitOutputShortAddress(dst, INS_adrp, IF_DI_1E, relPageAddr, dstReg);
8280
8281         // add x, x, page offs -- compute address = page addr + page offs
8282         ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8283         assert(isValidUimm12(imm12));
8284         code_t code =
8285             emitInsCode(INS_add, IF_DI_2A);  // DI_2A  X0010001shiiiiii iiiiiinnnnnddddd   1100 0000   imm(i12, sh)
8286         code |= insEncodeDatasize(EA_8BYTE); // X
8287         code |= ((code_t)imm12 << 10);       // iiiiiiiiiiii
8288         code |= insEncodeReg_Rd(dstReg);     // ddddd
8289         code |= insEncodeReg_Rn(dstReg);     // nnnnn
8290         dst += emitOutput_Instr(dst, code);
8291     }
8292     return dst;
8293 }
8294
8295 /*****************************************************************************
8296  *
8297  *  Output a local jump or other instruction with a pc-relative immediate.
8298  *  Note that this may be invoked to overwrite an existing jump instruction at 'dst'
8299  *  to handle forward branch patching.
8300  */
8301
8302 BYTE* emitter::emitOutputLJ(insGroup* ig, BYTE* dst, instrDesc* i)
8303 {
8304     instrDescJmp* id = (instrDescJmp*)i;
8305
8306     unsigned srcOffs;
8307     unsigned dstOffs;
8308     BYTE*    srcAddr;
8309     BYTE*    dstAddr;
8310     ssize_t  distVal;
8311     ssize_t  loBits;
8312
8313     // Set default ins/fmt from id.
8314     instruction ins = id->idIns();
8315     insFormat   fmt = id->idInsFmt();
8316
8317     bool loadLabel    = false;
8318     bool isJump       = false;
8319     bool loadConstant = false;
8320
8321     switch (ins)
8322     {
8323         default:
8324             isJump = true;
8325             break;
8326
8327         case INS_tbz:
8328         case INS_tbnz:
8329         case INS_cbz:
8330         case INS_cbnz:
8331             isJump = true;
8332             break;
8333
8334         case INS_ldr:
8335         case INS_ldrsw:
8336             loadConstant = true;
8337             break;
8338
8339         case INS_adr:
8340         case INS_adrp:
8341             loadLabel = true;
8342             break;
8343     }
8344
8345     /* Figure out the distance to the target */
8346
8347     srcOffs = emitCurCodeOffs(dst);
8348     srcAddr = emitOffsetToPtr(srcOffs);
8349
8350     if (id->idAddr()->iiaIsJitDataOffset())
8351     {
8352         assert(loadConstant || loadLabel);
8353         int doff = id->idAddr()->iiaGetJitDataOffset();
8354         assert(doff >= 0);
8355         ssize_t imm = emitGetInsSC(id);
8356         assert((imm >= 0) && (imm < 0x1000)); // 0x1000 is arbitrary, currently 'imm' is always 0
8357
8358         unsigned dataOffs = (unsigned)(doff + imm);
8359         assert(dataOffs < emitDataSize());
8360         dstAddr = emitDataOffsetToPtr(dataOffs);
8361
8362         regNumber dstReg  = id->idReg1();
8363         regNumber addrReg = dstReg; // an integer register to compute long address.
8364         emitAttr  opSize  = id->idOpSize();
8365
8366         if (loadConstant)
8367         {
8368             if (id->idjShort)
8369             {
8370                 // ldr x/v, [rel addr] -- load constant from current addr(ip) + rel addr.
8371                 assert(ins == INS_ldr);
8372                 assert(fmt == IF_LS_1A);
8373                 distVal = (ssize_t)(dstAddr - srcAddr);
8374                 dst     = emitOutputShortConstant(dst, ins, fmt, distVal, dstReg, opSize);
8375             }
8376             else
8377             {
8378                 // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8379                 assert(fmt == IF_LARGELDC);
8380                 ssize_t relPageAddr =
8381                     (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8382                 if (isVectorRegister(dstReg))
8383                 {
8384                     // Update addrReg with the reserved integer register
8385                     // since we cannot use dstReg (vector) to load constant directly from memory.
8386                     addrReg = id->idReg2();
8387                     assert(isGeneralRegister(addrReg));
8388                 }
8389                 ins = INS_adrp;
8390                 fmt = IF_DI_1E;
8391                 dst = emitOutputShortAddress(dst, ins, fmt, relPageAddr, addrReg);
8392
8393                 // ldr x, [x, page offs] -- load constant from page address + page offset into integer register.
8394                 ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8395                 assert(isValidUimm12(imm12));
8396                 ins = INS_ldr;
8397                 fmt = IF_LS_2B;
8398                 dst = emitOutputShortConstant(dst, ins, fmt, imm12, addrReg, opSize);
8399
8400                 // fmov v, d -- copy constant in integer register to vector register.
8401                 // This is needed only for vector constant.
8402                 if (addrReg != dstReg)
8403                 {
8404                     //  fmov    Vd,Rn                DV_2I  X00111100X100111 000000nnnnnddddd   1E27 0000   Vd,Rn
8405                     //  (scalar, from general)
8406                     assert(isVectorRegister(dstReg) && isGeneralRegister(addrReg));
8407                     ins         = INS_fmov;
8408                     fmt         = IF_DV_2I;
8409                     code_t code = emitInsCode(ins, fmt);
8410
8411                     code |= insEncodeReg_Vd(dstReg);  // ddddd
8412                     code |= insEncodeReg_Rn(addrReg); // nnnnn
8413                     if (id->idOpSize() == EA_8BYTE)
8414                     {
8415                         code |= 0x80400000; // X ... X
8416                     }
8417                     dst += emitOutput_Instr(dst, code);
8418                 }
8419             }
8420         }
8421         else
8422         {
8423             assert(loadLabel);
8424             dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8425         }
8426
8427         return dst;
8428     }
8429
8430     assert(loadLabel || isJump);
8431
8432     if (id->idAddr()->iiaHasInstrCount())
8433     {
8434         assert(ig != NULL);
8435         int      instrCount = id->idAddr()->iiaGetInstrCount();
8436         unsigned insNum     = emitFindInsNum(ig, id);
8437         if (instrCount < 0)
8438         {
8439             // Backward branches using instruction count must be within the same instruction group.
8440             assert(insNum + 1 >= (unsigned)(-instrCount));
8441         }
8442         dstOffs = ig->igOffs + emitFindOffset(ig, (insNum + 1 + instrCount));
8443         dstAddr = emitOffsetToPtr(dstOffs);
8444     }
8445     else
8446     {
8447         dstOffs = id->idAddr()->iiaIGlabel->igOffs;
8448         dstAddr = emitOffsetToPtr(dstOffs);
8449     }
8450
8451     distVal = (ssize_t)(dstAddr - srcAddr);
8452
8453     if (dstOffs <= srcOffs)
8454     {
8455 #if DEBUG_EMIT
8456         /* This is a backward jump - distance is known at this point */
8457
8458         if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8459         {
8460             size_t blkOffs = id->idjIG->igOffs;
8461
8462             if (INTERESTING_JUMP_NUM == 0)
8463                 printf("[3] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8464             printf("[3] Jump  block is at %08X - %02X = %08X\n", blkOffs, emitOffsAdj, blkOffs - emitOffsAdj);
8465             printf("[3] Jump        is at %08X - %02X = %08X\n", srcOffs, emitOffsAdj, srcOffs - emitOffsAdj);
8466             printf("[3] Label block is at %08X - %02X = %08X\n", dstOffs, emitOffsAdj, dstOffs - emitOffsAdj);
8467         }
8468 #endif
8469     }
8470     else
8471     {
8472         /* This is a  forward jump - distance will be an upper limit */
8473
8474         emitFwdJumps = true;
8475
8476         /* The target offset will be closer by at least 'emitOffsAdj', but only if this
8477            jump doesn't cross the hot-cold boundary. */
8478
8479         if (!emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8480         {
8481             dstOffs -= emitOffsAdj;
8482             distVal -= emitOffsAdj;
8483         }
8484
8485         /* Record the location of the jump for later patching */
8486
8487         id->idjOffs = dstOffs;
8488
8489         /* Are we overflowing the id->idjOffs bitfield? */
8490         if (id->idjOffs != dstOffs)
8491             IMPL_LIMITATION("Method is too large");
8492
8493 #if DEBUG_EMIT
8494         if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8495         {
8496             size_t blkOffs = id->idjIG->igOffs;
8497
8498             if (INTERESTING_JUMP_NUM == 0)
8499                 printf("[4] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8500             printf("[4] Jump  block is at %08X\n", blkOffs);
8501             printf("[4] Jump        is at %08X\n", srcOffs);
8502             printf("[4] Label block is at %08X - %02X = %08X\n", dstOffs + emitOffsAdj, emitOffsAdj, dstOffs);
8503         }
8504 #endif
8505     }
8506
8507 #ifdef DEBUG
8508     if (0 && emitComp->verbose)
8509     {
8510         size_t sz          = 4;
8511         int    distValSize = id->idjShort ? 4 : 8;
8512         printf("; %s jump [%08X/%03u] from %0*X to %0*X: dist = %08XH\n", (dstOffs <= srcOffs) ? "Fwd" : "Bwd",
8513                dspPtr(id), id->idDebugOnlyInfo()->idNum, distValSize, srcOffs + sz, distValSize, dstOffs, distVal);
8514     }
8515 #endif
8516
8517     /* For forward jumps, record the address of the distance value */
8518     id->idjTemp.idjAddr = (distVal > 0) ? dst : NULL;
8519
8520     if (emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8521     {
8522         assert(!id->idjShort);
8523         NYI_ARM64("Relocation Support for long address");
8524     }
8525
8526     assert(insOptsNone(id->idInsOpt()));
8527
8528     if (isJump)
8529     {
8530         if (id->idjShort)
8531         {
8532             // Short conditional/unconditional jump
8533             assert(!id->idjKeepLong);
8534             assert(emitJumpCrossHotColdBoundary(srcOffs, dstOffs) == false);
8535             assert((fmt == IF_BI_0A) || (fmt == IF_BI_0B) || (fmt == IF_BI_1A) || (fmt == IF_BI_1B));
8536         }
8537         else
8538         {
8539             // Long conditional jump
8540             assert(fmt == IF_LARGEJMP);
8541             // This is a pseudo-instruction format representing a large conditional branch, to allow
8542             // us to get a greater branch target range than we can get by using a straightforward conditional
8543             // branch. It is encoded as a short conditional branch that branches around a long unconditional
8544             // branch.
8545             //
8546             // Conceptually, we have:
8547             //
8548             //      b<cond> L_target
8549             //
8550             // The code we emit is:
8551             //
8552             //      b<!cond> L_not  // 4 bytes. Note that we reverse the condition.
8553             //      b L_target      // 4 bytes
8554             //   L_not:
8555             //
8556             // Note that we don't actually insert any blocks: we simply encode "b <!cond> L_not" as a branch with
8557             // the correct offset. Note also that this works for both integer and floating-point conditions, because
8558             // the condition inversion takes ordered/unordered into account, preserving NaN behavior. For example,
8559             // "GT" (greater than) is inverted to "LE" (less than, equal, or unordered).
8560
8561             instruction reverseIns;
8562             insFormat   reverseFmt;
8563
8564             switch (ins)
8565             {
8566                 case INS_cbz:
8567                     reverseIns = INS_cbnz;
8568                     reverseFmt = IF_BI_1A;
8569                     break;
8570                 case INS_cbnz:
8571                     reverseIns = INS_cbz;
8572                     reverseFmt = IF_BI_1A;
8573                     break;
8574                 case INS_tbz:
8575                     reverseIns = INS_tbnz;
8576                     reverseFmt = IF_BI_1B;
8577                     break;
8578                 case INS_tbnz:
8579                     reverseIns = INS_tbz;
8580                     reverseFmt = IF_BI_1B;
8581                     break;
8582                 default:
8583                     reverseIns = emitJumpKindToIns(emitReverseJumpKind(emitInsToJumpKind(ins)));
8584                     reverseFmt = IF_BI_0B;
8585             }
8586
8587             dst =
8588                 emitOutputShortBranch(dst,
8589                                       reverseIns, // reverse the conditional instruction
8590                                       reverseFmt,
8591                                       8, /* 8 bytes from start of this large conditional pseudo-instruction to L_not. */
8592                                       id);
8593
8594             // Now, pretend we've got a normal unconditional branch, and fall through to the code to emit that.
8595             ins = INS_b;
8596             fmt = IF_BI_0A;
8597
8598             // The distVal was computed based on the beginning of the pseudo-instruction,
8599             // So subtract the size of the conditional branch so that it is relative to the
8600             // unconditional branch.
8601             distVal -= 4;
8602         }
8603
8604         dst = emitOutputShortBranch(dst, ins, fmt, distVal, id);
8605     }
8606     else if (loadLabel)
8607     {
8608         dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8609     }
8610
8611     return dst;
8612 }
8613
8614 /*****************************************************************************
8615 *
8616 *  Output a short branch instruction.
8617 */
8618 BYTE* emitter::emitOutputShortBranch(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, instrDescJmp* id)
8619 {
8620     code_t code = emitInsCode(ins, fmt);
8621
8622     ssize_t loBits = (distVal & 3);
8623     noway_assert(loBits == 0);
8624     distVal >>= 2; // branch offset encodings are scaled by 4.
8625
8626     if (fmt == IF_BI_0A)
8627     {
8628         // INS_b or INS_bl_local
8629         noway_assert(isValidSimm26(distVal));
8630         distVal &= 0x3FFFFFFLL;
8631         code |= distVal;
8632     }
8633     else if (fmt == IF_BI_0B) // BI_0B   01010100iiiiiiii iiiiiiiiiiiXXXXX      simm19:00
8634     {
8635         // INS_beq, INS_bne, etc...
8636         noway_assert(isValidSimm19(distVal));
8637         distVal &= 0x7FFFFLL;
8638         code |= distVal << 5;
8639     }
8640     else if (fmt == IF_BI_1A) // BI_1A   X.......iiiiiiii iiiiiiiiiiittttt      Rt simm19:00
8641     {
8642         // INS_cbz or INS_cbnz
8643         assert(id != nullptr);
8644         code |= insEncodeDatasize(id->idOpSize()); // X
8645         code |= insEncodeReg_Rt(id->idReg1());     // ttttt
8646
8647         noway_assert(isValidSimm19(distVal));
8648         distVal &= 0x7FFFFLL; // 19 bits
8649         code |= distVal << 5;
8650     }
8651     else if (fmt == IF_BI_1B) // BI_1B   B.......bbbbbiii iiiiiiiiiiittttt      Rt imm6, simm14:00
8652     {
8653         // INS_tbz or INS_tbnz
8654         assert(id != nullptr);
8655         ssize_t imm = emitGetInsSC(id);
8656         assert(isValidImmShift(imm, id->idOpSize()));
8657
8658         if (imm & 0x20) // test bit 32-63 ?
8659         {
8660             code |= 0x80000000; // B
8661         }
8662         code |= ((imm & 0x1F) << 19);          // bbbbb
8663         code |= insEncodeReg_Rt(id->idReg1()); // ttttt
8664
8665         noway_assert(isValidSimm14(distVal));
8666         distVal &= 0x3FFFLL; // 14 bits
8667         code |= distVal << 5;
8668     }
8669     else
8670     {
8671         assert(!"Unknown fmt for emitOutputShortBranch");
8672     }
8673
8674     dst += emitOutput_Instr(dst, code);
8675
8676     return dst;
8677 }
8678
8679 /*****************************************************************************
8680 *
8681 *  Output a short address instruction.
8682 */
8683 BYTE* emitter::emitOutputShortAddress(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, regNumber reg)
8684 {
8685     ssize_t loBits = (distVal & 3);
8686     distVal >>= 2;
8687
8688     code_t code = emitInsCode(ins, fmt);
8689     if (fmt == IF_DI_1E) // DI_1E   .ii.....iiiiiiii iiiiiiiiiiiddddd      Rd simm21
8690     {
8691         // INS_adr or INS_adrp
8692         code |= insEncodeReg_Rd(reg); // ddddd
8693
8694         noway_assert(isValidSimm19(distVal));
8695         distVal &= 0x7FFFFLL; // 19 bits
8696         code |= distVal << 5;
8697         code |= loBits << 29; //  2 bits
8698     }
8699     else
8700     {
8701         assert(!"Unknown fmt for emitOutputShortAddress");
8702     }
8703
8704     dst += emitOutput_Instr(dst, code);
8705
8706     return dst;
8707 }
8708
8709 /*****************************************************************************
8710 *
8711 *  Output a short constant instruction.
8712 */
8713 BYTE* emitter::emitOutputShortConstant(
8714     BYTE* dst, instruction ins, insFormat fmt, ssize_t imm, regNumber reg, emitAttr opSize)
8715 {
8716     code_t code = emitInsCode(ins, fmt);
8717
8718     if (fmt == IF_LS_1A)
8719     {
8720         // LS_1A   XX...V..iiiiiiii iiiiiiiiiiittttt      Rt simm21
8721         // INS_ldr or INS_ldrsw (PC-Relative)
8722
8723         ssize_t loBits = (imm & 3);
8724         noway_assert(loBits == 0);
8725         ssize_t distVal = imm >>= 2; // load offset encodings are scaled by 4.
8726
8727         noway_assert(isValidSimm19(distVal));
8728
8729         // Is the target a vector register?
8730         if (isVectorRegister(reg))
8731         {
8732             code |= insEncodeDatasizeVLS(code, opSize); // XX V
8733             code |= insEncodeReg_Vt(reg);               // ttttt
8734         }
8735         else
8736         {
8737             assert(isGeneralRegister(reg));
8738             // insEncodeDatasizeLS is not quite right for this case.
8739             // So just specialize it.
8740             if ((ins == INS_ldr) && (opSize == EA_8BYTE))
8741             {
8742                 // set the operation size in bit 30
8743                 code |= 0x40000000;
8744             }
8745
8746             code |= insEncodeReg_Rt(reg); // ttttt
8747         }
8748
8749         distVal &= 0x7FFFFLL; // 19 bits
8750         code |= distVal << 5;
8751     }
8752     else if (fmt == IF_LS_2B)
8753     {
8754         //  ldr     Rt,[Xn+pimm12]       LS_2B  1X11100101iiiiii iiiiiinnnnnttttt   B940 0000   imm(0-4095<<{2,3})
8755         // INS_ldr or INS_ldrsw (PC-Relative)
8756         noway_assert(isValidUimm12(imm));
8757         assert(isGeneralRegister(reg));
8758
8759         if (opSize == EA_8BYTE)
8760         {
8761             // insEncodeDatasizeLS is not quite right for this case.
8762             // So just specialize it.
8763             if (ins == INS_ldr)
8764             {
8765                 // set the operation size in bit 30
8766                 code |= 0x40000000;
8767             }
8768             // Low 3 bits should be 0 -- 8 byte JIT data should be aligned on 8 byte.
8769             assert((imm & 7) == 0);
8770             imm >>= 3;
8771         }
8772         else
8773         {
8774             assert(opSize == EA_4BYTE);
8775             // Low 2 bits should be 0 -- 4 byte aligned data.
8776             assert((imm & 3) == 0);
8777             imm >>= 2;
8778         }
8779
8780         code |= insEncodeReg_Rt(reg); // ttttt
8781         code |= insEncodeReg_Rn(reg); // nnnnn
8782         code |= imm << 10;
8783     }
8784     else
8785     {
8786         assert(!"Unknown fmt for emitOutputShortConstant");
8787     }
8788
8789     dst += emitOutput_Instr(dst, code);
8790
8791     return dst;
8792 }
8793 /*****************************************************************************
8794  *
8795  *  Output a call instruction.
8796  */
8797
8798 unsigned emitter::emitOutputCall(insGroup* ig, BYTE* dst, instrDesc* id, code_t code)
8799 {
8800     const unsigned char callInstrSize = sizeof(code_t); // 4 bytes
8801     regMaskTP           gcrefRegs;
8802     regMaskTP           byrefRegs;
8803
8804     VARSET_TP GCvars(VarSetOps::UninitVal());
8805
8806     // Is this a "fat" call descriptor?
8807     if (id->idIsLargeCall())
8808     {
8809         instrDescCGCA* idCall = (instrDescCGCA*)id;
8810         gcrefRegs             = idCall->idcGcrefRegs;
8811         byrefRegs             = idCall->idcByrefRegs;
8812         VarSetOps::Assign(emitComp, GCvars, idCall->idcGCvars);
8813     }
8814     else
8815     {
8816         assert(!id->idIsLargeDsp());
8817         assert(!id->idIsLargeCns());
8818
8819         gcrefRegs = emitDecodeCallGCregs(id);
8820         byrefRegs = 0;
8821         VarSetOps::AssignNoCopy(emitComp, GCvars, VarSetOps::MakeEmpty(emitComp));
8822     }
8823
8824     /* We update the GC info before the call as the variables cannot be
8825         used by the call. Killing variables before the call helps with
8826         boundary conditions if the call is CORINFO_HELP_THROW - see bug 50029.
8827         If we ever track aliased variables (which could be used by the
8828         call), we would have to keep them alive past the call. */
8829
8830     emitUpdateLiveGCvars(GCvars, dst);
8831
8832     // Now output the call instruction and update the 'dst' pointer
8833     //
8834     unsigned outputInstrSize = emitOutput_Instr(dst, code);
8835     dst += outputInstrSize;
8836
8837     // All call instructions are 4-byte in size on ARM64
8838     //
8839     assert(outputInstrSize == callInstrSize);
8840
8841     // If the method returns a GC ref, mark INTRET (R0) appropriately.
8842     if (id->idGCref() == GCT_GCREF)
8843     {
8844         gcrefRegs |= RBM_INTRET;
8845     }
8846     else if (id->idGCref() == GCT_BYREF)
8847     {
8848         byrefRegs |= RBM_INTRET;
8849     }
8850
8851     // If is a multi-register return method is called, mark INTRET_1 (X1) appropriately
8852     if (id->idIsLargeCall())
8853     {
8854         instrDescCGCA* idCall = (instrDescCGCA*)id;
8855         if (idCall->idSecondGCref() == GCT_GCREF)
8856         {
8857             gcrefRegs |= RBM_INTRET_1;
8858         }
8859         else if (idCall->idSecondGCref() == GCT_BYREF)
8860         {
8861             byrefRegs |= RBM_INTRET_1;
8862         }
8863     }
8864
8865     // If the GC register set has changed, report the new set.
8866     if (gcrefRegs != emitThisGCrefRegs)
8867     {
8868         emitUpdateLiveGCregs(GCT_GCREF, gcrefRegs, dst);
8869     }
8870     // If the Byref register set has changed, report the new set.
8871     if (byrefRegs != emitThisByrefRegs)
8872     {
8873         emitUpdateLiveGCregs(GCT_BYREF, byrefRegs, dst);
8874     }
8875
8876     // Some helper calls may be marked as not requiring GC info to be recorded.
8877     if ((!id->idIsNoGC()))
8878     {
8879         // On ARM64, as on AMD64, we don't change the stack pointer to push/pop args.
8880         // So we're not really doing a "stack pop" here (note that "args" is 0), but we use this mechanism
8881         // to record the call for GC info purposes.  (It might be best to use an alternate call,
8882         // and protect "emitStackPop" under the EMIT_TRACK_STACK_DEPTH preprocessor variable.)
8883         emitStackPop(dst, /*isCall*/ true, callInstrSize, /*args*/ 0);
8884
8885         // Do we need to record a call location for GC purposes?
8886         //
8887         if (!emitFullGCinfo)
8888         {
8889             emitRecordGCcall(dst, callInstrSize);
8890         }
8891     }
8892     return callInstrSize;
8893 }
8894
8895 /*****************************************************************************
8896  *
8897  *  Emit a 32-bit Arm64 instruction
8898  */
8899
8900 /*static*/ unsigned emitter::emitOutput_Instr(BYTE* dst, code_t code)
8901 {
8902     assert(sizeof(code_t) == 4);
8903     *((code_t*)dst) = code;
8904
8905     return sizeof(code_t);
8906 }
8907
8908 /*****************************************************************************
8909 *
8910  *  Append the machine code corresponding to the given instruction descriptor
8911  *  to the code block at '*dp'; the base of the code block is 'bp', and 'ig'
8912  *  is the instruction group that contains the instruction. Updates '*dp' to
8913  *  point past the generated code, and returns the size of the instruction
8914  *  descriptor in bytes.
8915  */
8916
8917 size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
8918 {
8919     BYTE*         dst  = *dp;
8920     BYTE*         odst = dst;
8921     code_t        code = 0;
8922     size_t        sz   = emitGetInstrDescSize(id); // TODO-ARM64-Cleanup: on ARM, this is set in each case. why?
8923     instruction   ins  = id->idIns();
8924     insFormat     fmt  = id->idInsFmt();
8925     emitAttr      size = id->idOpSize();
8926     unsigned char callInstrSize = 0;
8927     unsigned      condcode;
8928
8929 #ifdef DEBUG
8930 #if DUMP_GC_TABLES
8931     bool dspOffs = emitComp->opts.dspGCtbls;
8932 #else
8933     bool dspOffs = !emitComp->opts.disDiffable;
8934 #endif
8935 #endif // DEBUG
8936
8937     assert(REG_NA == (int)REG_NA);
8938
8939     VARSET_TP GCvars(VarSetOps::UninitVal());
8940
8941     /* What instruction format have we got? */
8942
8943     switch (fmt)
8944     {
8945         ssize_t  imm;
8946         ssize_t  index;
8947         ssize_t  index2;
8948         unsigned scale;
8949         unsigned cmode;
8950         unsigned immShift;
8951         bool     hasShift;
8952         emitAttr extSize;
8953         emitAttr elemsize;
8954         emitAttr datasize;
8955
8956         case IF_BI_0A: // BI_0A   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
8957         case IF_BI_0B: // BI_0B   ......iiiiiiiiii iiiiiiiiiii.....               simm19:00
8958         case IF_LARGEJMP:
8959             assert(id->idGCref() == GCT_NONE);
8960             assert(id->idIsBound());
8961             dst = emitOutputLJ(ig, dst, id);
8962             sz  = sizeof(instrDescJmp);
8963             break;
8964
8965         case IF_BI_0C: // BI_0C   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
8966             code = emitInsCode(ins, fmt);
8967             sz   = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
8968             dst += emitOutputCall(ig, dst, id, code);
8969             // Always call RecordRelocation so that we wire in a JumpStub when we don't reach
8970             emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_BRANCH26);
8971             break;
8972
8973         case IF_BI_1A: // BI_1A   ......iiiiiiiiii iiiiiiiiiiittttt      Rt       simm19:00
8974             assert(insOptsNone(id->idInsOpt()));
8975             assert(id->idIsBound());
8976
8977             dst = emitOutputLJ(ig, dst, id);
8978             sz  = sizeof(instrDescJmp);
8979             break;
8980
8981         case IF_BI_1B: // BI_1B   B.......bbbbbiii iiiiiiiiiiittttt      Rt imm6, simm14:00
8982             assert(insOptsNone(id->idInsOpt()));
8983             assert(id->idIsBound());
8984
8985             dst = emitOutputLJ(ig, dst, id);
8986             sz  = sizeof(instrDescJmp);
8987             break;
8988
8989         case IF_BR_1A: // BR_1A   ................ ......nnnnn.....         Rn
8990             assert(insOptsNone(id->idInsOpt()));
8991             assert((ins == INS_ret) || (ins == INS_br));
8992             code = emitInsCode(ins, fmt);
8993             code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
8994
8995             dst += emitOutput_Instr(dst, code);
8996             break;
8997
8998         case IF_BR_1B: // BR_1B   ................ ......nnnnn.....         Rn
8999             assert(insOptsNone(id->idInsOpt()));
9000             assert((ins == INS_br_tail) || (ins == INS_blr));
9001             code = emitInsCode(ins, fmt);
9002             code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9003
9004             sz = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
9005             dst += emitOutputCall(ig, dst, id, code);
9006             break;
9007
9008         case IF_LS_1A: // LS_1A   XX...V..iiiiiiii iiiiiiiiiiittttt      Rt    PC imm(1MB)
9009         case IF_LARGELDC:
9010             assert(insOptsNone(id->idInsOpt()));
9011             assert(id->idIsBound());
9012
9013             dst = emitOutputLJ(ig, dst, id);
9014             sz  = sizeof(instrDescJmp);
9015             break;
9016
9017         case IF_LS_2A: // LS_2A   .X.......X...... ......nnnnnttttt      Rt Rn
9018             assert(insOptsNone(id->idInsOpt()));
9019             code = emitInsCode(ins, fmt);
9020             // Is the target a vector register?
9021             if (isVectorRegister(id->idReg1()))
9022             {
9023                 code &= 0x3FFFFFFF;                                 // clear the size bits
9024                 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9025                 code |= insEncodeReg_Vt(id->idReg1());              // ttttt
9026             }
9027             else
9028             {
9029                 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9030                 code |= insEncodeReg_Rt(id->idReg1());             // ttttt
9031             }
9032             code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9033             dst += emitOutput_Instr(dst, code);
9034             break;
9035
9036         case IF_LS_2B: // LS_2B   .X.......Xiiiiii iiiiiinnnnnttttt      Rt Rn    imm(0-4095)
9037             assert(insOptsNone(id->idInsOpt()));
9038             imm = emitGetInsSC(id);
9039             assert(isValidUimm12(imm));
9040             code = emitInsCode(ins, fmt);
9041             // Is the target a vector register?
9042             if (isVectorRegister(id->idReg1()))
9043             {
9044                 code &= 0x3FFFFFFF;                                 // clear the size bits
9045                 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9046                 code |= insEncodeReg_Vt(id->idReg1());              // ttttt
9047             }
9048             else
9049             {
9050                 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9051                 code |= insEncodeReg_Rt(id->idReg1());             // ttttt
9052             }
9053             code |= ((code_t)imm << 10);           // iiiiiiiiiiii
9054             code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9055             dst += emitOutput_Instr(dst, code);
9056             break;
9057
9058         case IF_LS_2C: // LS_2C   .X.......X.iiiii iiiiPPnnnnnttttt      Rt Rn    imm(-256..+255) no/pre/post inc
9059             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9060             imm = emitGetInsSC(id);
9061             assert((imm >= -256) && (imm <= 255)); // signed 9 bits
9062             imm &= 0x1ff;                          // force into unsigned 9 bit representation
9063             code = emitInsCode(ins, fmt);
9064             // Is the target a vector register?
9065             if (isVectorRegister(id->idReg1()))
9066             {
9067                 code &= 0x3FFFFFFF;                                 // clear the size bits
9068                 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9069                 code |= insEncodeReg_Vt(id->idReg1());              // ttttt
9070             }
9071             else
9072             {
9073                 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9074                 code |= insEncodeReg_Rt(id->idReg1());             // ttttt
9075             }
9076             code |= insEncodeIndexedOpt(id->idInsOpt()); // PP
9077             code |= ((code_t)imm << 12);                 // iiiiiiiii
9078             code |= insEncodeReg_Rn(id->idReg2());       // nnnnn
9079             dst += emitOutput_Instr(dst, code);
9080             break;
9081
9082         case IF_LS_3A: // LS_3A   .X.......X.mmmmm oooS..nnnnnttttt      Rt Rn Rm ext(Rm) LSL {}
9083             assert(insOptsLSExtend(id->idInsOpt()));
9084             code = emitInsCode(ins, fmt);
9085             // Is the target a vector register?
9086             if (isVectorRegister(id->idReg1()))
9087             {
9088                 code &= 0x3FFFFFFF;                                 // clear the size bits
9089                 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9090                 code |= insEncodeReg_Vt(id->idReg1());              // ttttt
9091             }
9092             else
9093             {
9094                 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9095                 code |= insEncodeReg_Rt(id->idReg1());             // ttttt
9096             }
9097             code |= insEncodeExtend(id->idInsOpt()); // ooo
9098             code |= insEncodeReg_Rn(id->idReg2());   // nnnnn
9099             if (id->idIsLclVar())
9100             {
9101                 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9102             }
9103             else
9104             {
9105                 code |= insEncodeReg3Scale(id->idReg3Scaled()); // S
9106                 code |= insEncodeReg_Rm(id->idReg3());          // mmmmm
9107             }
9108             dst += emitOutput_Instr(dst, code);
9109             break;
9110
9111         case IF_LS_3B: // LS_3B   X............... .aaaaannnnnddddd      Rd Ra Rn
9112             assert(insOptsNone(id->idInsOpt()));
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 |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9119                 code |= insEncodeReg_Vt(id->idReg1());               // ttttt
9120                 code |= insEncodeReg_Va(id->idReg2());               // aaaaa
9121             }
9122             else
9123             {
9124                 code |= insEncodeDatasize(id->idOpSize()); // X
9125                 code |= insEncodeReg_Rt(id->idReg1());     // ttttt
9126                 code |= insEncodeReg_Ra(id->idReg2());     // aaaaa
9127             }
9128             code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9129             dst += emitOutput_Instr(dst, code);
9130             break;
9131
9132         case IF_LS_3C: // LS_3C   X......PP.iiiiii iaaaaannnnnddddd      Rd Ra Rn imm(im7,sh)
9133             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9134             imm = emitGetInsSC(id);
9135             assert((imm >= -64) && (imm <= 63)); // signed 7 bits
9136             imm &= 0x7f;                         // force into unsigned 7 bit representation
9137             code = emitInsCode(ins, fmt);
9138             // Is the target a vector register?
9139             if (isVectorRegister(id->idReg1()))
9140             {
9141                 code &= 0x3FFFFFFF;                                  // clear the size bits
9142                 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9143                 code |= insEncodeReg_Vt(id->idReg1());               // ttttt
9144                 code |= insEncodeReg_Va(id->idReg2());               // aaaaa
9145             }
9146             else
9147             {
9148                 code |= insEncodeDatasize(id->idOpSize()); // X
9149                 code |= insEncodeReg_Rt(id->idReg1());     // ttttt
9150                 code |= insEncodeReg_Ra(id->idReg2());     // aaaaa
9151             }
9152             code |= insEncodePairIndexedOpt(ins, id->idInsOpt()); // PP
9153             code |= ((code_t)imm << 15);                          // iiiiiiiii
9154             code |= insEncodeReg_Rn(id->idReg3());                // nnnnn
9155             dst += emitOutput_Instr(dst, code);
9156             break;
9157
9158         case IF_LS_3D: // LS_3D   .X.......X.mmmmm ......nnnnnttttt      Wm Rt Rn
9159             code = emitInsCode(ins, fmt);
9160             // Arm64 store exclusive unpredictable cases
9161             assert(id->idReg1() != id->idReg2());
9162             assert(id->idReg1() != id->idReg3());
9163             code |= insEncodeDatasizeLS(code, id->idOpSize()); // X
9164             code |= insEncodeReg_Rm(id->idReg1());             // mmmmm
9165             code |= insEncodeReg_Rt(id->idReg2());             // ttttt
9166             code |= insEncodeReg_Rn(id->idReg3());             // nnnnn
9167             dst += emitOutput_Instr(dst, code);
9168             break;
9169
9170         case IF_DI_1A: // DI_1A   X.......shiiiiii iiiiiinnnnn.....         Rn    imm(i12,sh)
9171             assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9172             imm = emitGetInsSC(id);
9173             assert(isValidUimm12(imm));
9174             code = emitInsCode(ins, fmt);
9175             code |= insEncodeDatasize(id->idOpSize());   // X
9176             code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9177             code |= ((code_t)imm << 10);                 // iiiiiiiiiiii
9178             code |= insEncodeReg_Rn(id->idReg1());       // nnnnn
9179             dst += emitOutput_Instr(dst, code);
9180             break;
9181
9182         case IF_DI_1B: // DI_1B   X........hwiiiii iiiiiiiiiiiddddd      Rd       imm(i16,hw)
9183             imm = emitGetInsSC(id);
9184             assert(isValidImmHWVal(imm, id->idOpSize()));
9185             code = emitInsCode(ins, fmt);
9186             code |= insEncodeDatasize(id->idOpSize()); // X
9187             code |= ((code_t)imm << 5);                // hwiiiii iiiiiiiiiii
9188             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9189             dst += emitOutput_Instr(dst, code);
9190             break;
9191
9192         case IF_DI_1C: // DI_1C   X........Nrrrrrr ssssssnnnnn.....         Rn    imm(N,r,s)
9193             imm = emitGetInsSC(id);
9194             assert(isValidImmNRS(imm, id->idOpSize()));
9195             code = emitInsCode(ins, fmt);
9196             code |= ((code_t)imm << 10);               // Nrrrrrrssssss
9197             code |= insEncodeDatasize(id->idOpSize()); // X
9198             code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9199             dst += emitOutput_Instr(dst, code);
9200             break;
9201
9202         case IF_DI_1D: // DI_1D   X........Nrrrrrr ssssss.....ddddd      Rd       imm(N,r,s)
9203             imm = emitGetInsSC(id);
9204             assert(isValidImmNRS(imm, id->idOpSize()));
9205             code = emitInsCode(ins, fmt);
9206             code |= ((code_t)imm << 10);               // Nrrrrrrssssss
9207             code |= insEncodeDatasize(id->idOpSize()); // X
9208             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9209             dst += emitOutput_Instr(dst, code);
9210             break;
9211
9212         case IF_DI_1E: // DI_1E   .ii.....iiiiiiii iiiiiiiiiiiddddd      Rd       simm21
9213         case IF_LARGEADR:
9214             assert(insOptsNone(id->idInsOpt()));
9215             if (id->idIsReloc())
9216             {
9217                 code = emitInsCode(ins, fmt);
9218                 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9219                 dst += emitOutput_Instr(dst, code);
9220                 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEBASE_REL21);
9221             }
9222             else
9223             {
9224                 // Local jmp/load case which does not need a relocation.
9225                 assert(id->idIsBound());
9226                 dst = emitOutputLJ(ig, dst, id);
9227             }
9228             sz = sizeof(instrDescJmp);
9229             break;
9230
9231         case IF_DI_1F: // DI_1F   X..........iiiii cccc..nnnnn.nzcv      Rn imm5  nzcv cond
9232             imm = emitGetInsSC(id);
9233             assert(isValidImmCondFlagsImm5(imm));
9234             {
9235                 condFlagsImm cfi;
9236                 cfi.immCFVal = (unsigned)imm;
9237                 code         = emitInsCode(ins, fmt);
9238                 code |= insEncodeDatasize(id->idOpSize()); // X
9239                 code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9240                 code |= ((code_t)cfi.imm5 << 16);          // iiiii
9241                 code |= insEncodeFlags(cfi.flags);         // nzcv
9242                 code |= insEncodeCond(cfi.cond);           // cccc
9243                 dst += emitOutput_Instr(dst, code);
9244             }
9245             break;
9246
9247         case IF_DI_2A: // DI_2A   X.......shiiiiii iiiiiinnnnnddddd      Rd Rn    imm(i12,sh)
9248             assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9249             imm = emitGetInsSC(id);
9250             assert(isValidUimm12(imm));
9251             code = emitInsCode(ins, fmt);
9252             code |= insEncodeDatasize(id->idOpSize());   // X
9253             code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9254             code |= ((code_t)imm << 10);                 // iiiiiiiiiiii
9255             code |= insEncodeReg_Rd(id->idReg1());       // ddddd
9256             code |= insEncodeReg_Rn(id->idReg2());       // nnnnn
9257             dst += emitOutput_Instr(dst, code);
9258
9259             if (id->idIsReloc())
9260             {
9261                 assert(sz == sizeof(instrDesc));
9262                 assert(id->idAddr()->iiaAddr != nullptr);
9263                 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEOFFSET_12A);
9264             }
9265             break;
9266
9267         case IF_DI_2B: // DI_2B   X.........Xnnnnn ssssssnnnnnddddd      Rd Rn    imm(0-63)
9268             code = emitInsCode(ins, fmt);
9269             imm  = emitGetInsSC(id);
9270             assert(isValidImmShift(imm, id->idOpSize()));
9271             code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9272             code |= insEncodeReg_Rd(id->idReg1());             // ddddd
9273             code |= insEncodeReg_Rn(id->idReg2());             // nnnnn
9274             code |= insEncodeReg_Rm(id->idReg2());             // Reg2 also in mmmmm
9275             code |= insEncodeShiftCount(imm, id->idOpSize());  // ssssss
9276             dst += emitOutput_Instr(dst, code);
9277             break;
9278
9279         case IF_DI_2C: // DI_2C   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imm(N,r,s)
9280             imm = emitGetInsSC(id);
9281             assert(isValidImmNRS(imm, id->idOpSize()));
9282             code = emitInsCode(ins, fmt);
9283             code |= ((code_t)imm << 10);               // Nrrrrrrssssss
9284             code |= insEncodeDatasize(id->idOpSize()); // X
9285             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9286             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9287             dst += emitOutput_Instr(dst, code);
9288             break;
9289
9290         case IF_DI_2D: // DI_2D   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imr, imms   (N,r,s)
9291             if (ins == INS_asr || ins == INS_lsl || ins == INS_lsr)
9292             {
9293                 imm = emitGetInsSC(id);
9294                 assert(isValidImmShift(imm, id->idOpSize()));
9295
9296                 // Shift immediates are aliases of the SBFM/UBFM instructions
9297                 // that actually take 2 registers and 2 constants,
9298                 // Since we stored the shift immediate value
9299                 // we need to calculate the N,R and S values here.
9300
9301                 bitMaskImm bmi;
9302                 bmi.immNRS = 0;
9303
9304                 bmi.immN = (size == EA_8BYTE) ? 1 : 0;
9305                 bmi.immR = imm;
9306                 bmi.immS = (size == EA_8BYTE) ? 0x3f : 0x1f;
9307
9308                 // immR and immS are now set correctly for INS_asr and INS_lsr
9309                 // but for INS_lsl we have to adjust the values for immR and immS
9310                 //
9311                 if (ins == INS_lsl)
9312                 {
9313                     bmi.immR = -imm & bmi.immS;
9314                     bmi.immS = bmi.immS - imm;
9315                 }
9316
9317                 // setup imm with the proper 13 bit value N:R:S
9318                 //
9319                 imm = bmi.immNRS;
9320             }
9321             else
9322             {
9323                 // The other instructions have already have encoded N,R and S values
9324                 imm = emitGetInsSC(id);
9325             }
9326             assert(isValidImmNRS(imm, id->idOpSize()));
9327
9328             code = emitInsCode(ins, fmt);
9329             code |= ((code_t)imm << 10);               // Nrrrrrrssssss
9330             code |= insEncodeDatasize(id->idOpSize()); // X
9331             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9332             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9333             dst += emitOutput_Instr(dst, code);
9334             break;
9335
9336         case IF_DR_1D: // DR_1D   X............... cccc.......ddddd      Rd       cond
9337             imm = emitGetInsSC(id);
9338             assert(isValidImmCond(imm));
9339             {
9340                 condFlagsImm cfi;
9341                 cfi.immCFVal = (unsigned)imm;
9342                 code         = emitInsCode(ins, fmt);
9343                 code |= insEncodeDatasize(id->idOpSize()); // X
9344                 code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9345                 code |= insEncodeInvertedCond(cfi.cond);   // cccc
9346                 dst += emitOutput_Instr(dst, code);
9347             }
9348             break;
9349
9350         case IF_DR_2A: // DR_2A   X..........mmmmm ......nnnnn.....         Rn Rm
9351             assert(insOptsNone(id->idInsOpt()));
9352             code = emitInsCode(ins, fmt);
9353             code |= insEncodeDatasize(id->idOpSize()); // X
9354             code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9355             code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9356             dst += emitOutput_Instr(dst, code);
9357             break;
9358
9359         case IF_DR_2B: // DR_2B   X.......sh.mmmmm ssssssnnnnn.....         Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
9360             code = emitInsCode(ins, fmt);
9361             imm  = emitGetInsSC(id);
9362             assert(isValidImmShift(imm, id->idOpSize()));
9363             code |= insEncodeDatasize(id->idOpSize());        // X
9364             code |= insEncodeShiftType(id->idInsOpt());       // sh
9365             code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9366             code |= insEncodeReg_Rn(id->idReg1());            // nnnnn
9367             code |= insEncodeReg_Rm(id->idReg2());            // mmmmm
9368             dst += emitOutput_Instr(dst, code);
9369             break;
9370
9371         case IF_DR_2C: // DR_2C   X..........mmmmm ooosssnnnnn.....         Rn Rm ext(Rm) LSL imm(0-4)
9372             code = emitInsCode(ins, fmt);
9373             imm  = emitGetInsSC(id);
9374             assert((imm >= 0) && (imm <= 4));          // imm [0..4]
9375             code |= insEncodeDatasize(id->idOpSize()); // X
9376             code |= insEncodeExtend(id->idInsOpt());   // ooo
9377             code |= insEncodeExtendScale(imm);         // sss
9378             code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9379             code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9380             dst += emitOutput_Instr(dst, code);
9381             break;
9382
9383         case IF_DR_2D: // DR_2D   X..........nnnnn cccc..nnnnnddddd      Rd Rn    cond
9384             imm = emitGetInsSC(id);
9385             assert(isValidImmCond(imm));
9386             {
9387                 condFlagsImm cfi;
9388                 cfi.immCFVal = (unsigned)imm;
9389                 code         = emitInsCode(ins, fmt);
9390                 code |= insEncodeDatasize(id->idOpSize()); // X
9391                 code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9392                 code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9393                 code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9394                 code |= insEncodeInvertedCond(cfi.cond);   // cccc
9395                 dst += emitOutput_Instr(dst, code);
9396             }
9397             break;
9398
9399         case IF_DR_2E: // DR_2E   X..........mmmmm ...........ddddd      Rd    Rm
9400             code = emitInsCode(ins, fmt);
9401             code |= insEncodeDatasize(id->idOpSize()); // X
9402             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9403             code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9404             dst += emitOutput_Instr(dst, code);
9405             break;
9406
9407         case IF_DR_2F: // DR_2F   X.......sh.mmmmm ssssss.....ddddd      Rd    Rm {LSL,LSR,ASR} imm(0-63)
9408             code = emitInsCode(ins, fmt);
9409             imm  = emitGetInsSC(id);
9410             assert(isValidImmShift(imm, id->idOpSize()));
9411             code |= insEncodeDatasize(id->idOpSize());        // X
9412             code |= insEncodeShiftType(id->idInsOpt());       // sh
9413             code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9414             code |= insEncodeReg_Rd(id->idReg1());            // ddddd
9415             code |= insEncodeReg_Rm(id->idReg2());            // mmmmm
9416             dst += emitOutput_Instr(dst, code);
9417             break;
9418
9419         case IF_DR_2G: // DR_2G   X............... .....xnnnnnddddd      Rd Rn
9420             code = emitInsCode(ins, fmt);
9421             code |= insEncodeDatasize(id->idOpSize()); // X
9422             if (ins == INS_rev)
9423             {
9424                 if (size == EA_8BYTE)
9425                 {
9426                     code |= 0x00000400; // x - bit at location 10
9427                 }
9428             }
9429             code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9430             code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9431             dst += emitOutput_Instr(dst, code);
9432             break;
9433
9434         case IF_DR_2H: // DR_2H   X........X...... ......nnnnnddddd      Rd Rn
9435             code = emitInsCode(ins, fmt);
9436             code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9437             code |= insEncodeReg_Rd(id->idReg1());             // ddddd
9438             code |= insEncodeReg_Rn(id->idReg2());             // nnnnn
9439             dst += emitOutput_Instr(dst, code);
9440             break;
9441
9442         case IF_DR_2I: // DR_2I   X..........mmmmm cccc..nnnnn.nzcv      Rn Rm    nzcv cond
9443             imm = emitGetInsSC(id);
9444             assert(isValidImmCondFlags(imm));
9445             {
9446                 condFlagsImm cfi;
9447                 cfi.immCFVal = (unsigned)imm;
9448                 code         = emitInsCode(ins, fmt);
9449                 code |= insEncodeDatasize(id->idOpSize()); // X
9450                 code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9451                 code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9452                 code |= insEncodeFlags(cfi.flags);         // nzcv
9453                 code |= insEncodeCond(cfi.cond);           // cccc
9454                 dst += emitOutput_Instr(dst, code);
9455             }
9456             break;
9457
9458         case IF_DR_3A: // DR_3A   X..........mmmmm ......nnnnnmmmmm      Rd Rn Rm
9459             code = emitInsCode(ins, fmt);
9460             code |= insEncodeDatasize(id->idOpSize()); // X
9461             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9462             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9463             if (id->idIsLclVar())
9464             {
9465                 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9466             }
9467             else
9468             {
9469                 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9470             }
9471             dst += emitOutput_Instr(dst, code);
9472             break;
9473
9474         case IF_DR_3B: // DR_3B   X.......sh.mmmmm ssssssnnnnnddddd      Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
9475             code = emitInsCode(ins, fmt);
9476             imm  = emitGetInsSC(id);
9477             assert(isValidImmShift(imm, id->idOpSize()));
9478             code |= insEncodeDatasize(id->idOpSize());        // X
9479             code |= insEncodeReg_Rd(id->idReg1());            // ddddd
9480             code |= insEncodeReg_Rn(id->idReg2());            // nnnnn
9481             code |= insEncodeReg_Rm(id->idReg3());            // mmmmm
9482             code |= insEncodeShiftType(id->idInsOpt());       // sh
9483             code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9484             dst += emitOutput_Instr(dst, code);
9485             break;
9486
9487         case IF_DR_3C: // DR_3C   X..........mmmmm ooosssnnnnnddddd      Rd Rn Rm ext(Rm) LSL imm(0-4)
9488             code = emitInsCode(ins, fmt);
9489             imm  = emitGetInsSC(id);
9490             assert((imm >= 0) && (imm <= 4));          // imm [0..4]
9491             code |= insEncodeDatasize(id->idOpSize()); // X
9492             code |= insEncodeExtend(id->idInsOpt());   // ooo
9493             code |= insEncodeExtendScale(imm);         // sss
9494             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9495             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9496             code |= insEncodeReg_Rm(id->idReg3());     // mmmmm
9497             dst += emitOutput_Instr(dst, code);
9498             break;
9499
9500         case IF_DR_3D: // DR_3D   X..........mmmmm cccc..nnnnnddddd      Rd Rn Rm cond
9501             imm = emitGetInsSC(id);
9502             assert(isValidImmCond(imm));
9503             {
9504                 condFlagsImm cfi;
9505                 cfi.immCFVal = (unsigned)imm;
9506                 code         = emitInsCode(ins, fmt);
9507                 code |= insEncodeDatasize(id->idOpSize()); // X
9508                 code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9509                 code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9510                 code |= insEncodeReg_Rm(id->idReg3());     // mmmmm
9511                 code |= insEncodeCond(cfi.cond);           // cccc
9512                 dst += emitOutput_Instr(dst, code);
9513             }
9514             break;
9515
9516         case IF_DR_3E: // DR_3E   X........X.mmmmm ssssssnnnnnddddd      Rd Rn Rm imm(0-63)
9517             code = emitInsCode(ins, fmt);
9518             imm  = emitGetInsSC(id);
9519             assert(isValidImmShift(imm, id->idOpSize()));
9520             code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9521             code |= insEncodeReg_Rd(id->idReg1());             // ddddd
9522             code |= insEncodeReg_Rn(id->idReg2());             // nnnnn
9523             code |= insEncodeReg_Rm(id->idReg3());             // mmmmm
9524             code |= insEncodeShiftCount(imm, id->idOpSize());  // ssssss
9525             dst += emitOutput_Instr(dst, code);
9526             break;
9527
9528         case IF_DR_4A: // DR_4A   X..........mmmmm .aaaaannnnnmmmmm      Rd Rn Rm Ra
9529             code = emitInsCode(ins, fmt);
9530             code |= insEncodeDatasize(id->idOpSize()); // X
9531             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9532             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9533             code |= insEncodeReg_Rm(id->idReg3());     // mmmmm
9534             code |= insEncodeReg_Ra(id->idReg4());     // aaaaa
9535             dst += emitOutput_Instr(dst, code);
9536             break;
9537
9538         case IF_DV_1A: // DV_1A   .........X.iiiii iii........ddddd      Vd imm8    (fmov - immediate scalar)
9539             imm      = emitGetInsSC(id);
9540             elemsize = id->idOpSize();
9541             code     = emitInsCode(ins, fmt);
9542             code |= insEncodeFloatElemsize(elemsize); // X
9543             code |= ((code_t)imm << 13);              // iiiii iii
9544             code |= insEncodeReg_Vd(id->idReg1());    // ddddd
9545             dst += emitOutput_Instr(dst, code);
9546             break;
9547
9548         case IF_DV_1B: // DV_1B   .QX..........iii cmod..iiiiiddddd      Vd imm8    (immediate vector)
9549             imm      = emitGetInsSC(id) & 0x0ff;
9550             immShift = (emitGetInsSC(id) & 0x700) >> 8;
9551             elemsize = optGetElemsize(id->idInsOpt());
9552             cmode    = 0;
9553             switch (elemsize)
9554             { // cmode
9555                 case EA_1BYTE:
9556                     cmode = 0xE; // 1110
9557                     break;
9558                 case EA_2BYTE:
9559                     cmode = 0x8;
9560                     cmode |= (immShift << 1); // 10x0
9561                     break;
9562                 case EA_4BYTE:
9563                     if (immShift < 4)
9564                     {
9565                         cmode = 0x0;
9566                         cmode |= (immShift << 1); // 0xx0
9567                     }
9568                     else // MSL
9569                     {
9570                         cmode = 0xC;
9571                         if (immShift & 2)
9572                             cmode |= 1; // 110x
9573                     }
9574                     break;
9575                 case EA_8BYTE:
9576                     cmode = 0xE; // 1110
9577                     break;
9578                 default:
9579                     unreached();
9580                     break;
9581             }
9582
9583             code = emitInsCode(ins, fmt);
9584             code |= insEncodeVectorsize(id->idOpSize()); // Q
9585             if ((ins == INS_fmov) || (ins == INS_movi))
9586             {
9587                 if (elemsize == EA_8BYTE)
9588                 {
9589                     code |= 0x20000000; // X
9590                 }
9591             }
9592             if (ins != INS_fmov)
9593             {
9594                 assert((cmode >= 0) && (cmode <= 0xF));
9595                 code |= (cmode << 12); // cmod
9596             }
9597             code |= (((code_t)imm >> 5) << 16);    // iii
9598             code |= (((code_t)imm & 0x1f) << 5);   // iiiii
9599             code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9600             dst += emitOutput_Instr(dst, code);
9601             break;
9602
9603         case IF_DV_1C: // DV_1C   .........X...... ......nnnnn.....      Vn #0.0    (fcmp - with zero)
9604             elemsize = id->idOpSize();
9605             code     = emitInsCode(ins, fmt);
9606             code |= insEncodeFloatElemsize(elemsize); // X
9607             code |= insEncodeReg_Vn(id->idReg1());    // nnnnn
9608             dst += emitOutput_Instr(dst, code);
9609             break;
9610
9611         case IF_DV_2A: // DV_2A   .Q.......X...... ......nnnnnddddd      Vd Vn      (fabs, fcvt - vector)
9612             elemsize = optGetElemsize(id->idInsOpt());
9613             code     = emitInsCode(ins, fmt);
9614             code |= insEncodeVectorsize(id->idOpSize()); // Q
9615             code |= insEncodeFloatElemsize(elemsize);    // X
9616             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9617             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9618             dst += emitOutput_Instr(dst, code);
9619             break;
9620
9621         case IF_DV_2B: // DV_2B   .Q.........iiiii ......nnnnnddddd      Rd Vn[] (umov/smov    - to general)
9622             elemsize = id->idOpSize();
9623             index    = emitGetInsSC(id);
9624             datasize = (elemsize == EA_8BYTE) ? EA_16BYTE : EA_8BYTE;
9625             if (ins == INS_smov)
9626             {
9627                 datasize = EA_16BYTE;
9628             }
9629             code = emitInsCode(ins, fmt);
9630             code |= insEncodeVectorsize(datasize);         // Q
9631             code |= insEncodeVectorIndex(elemsize, index); // iiiii
9632             code |= insEncodeReg_Rd(id->idReg1());         // ddddd
9633             code |= insEncodeReg_Vn(id->idReg2());         // nnnnn
9634             dst += emitOutput_Instr(dst, code);
9635             break;
9636
9637         case IF_DV_2C: // DV_2C   .Q.........iiiii ......nnnnnddddd      Vd Rn   (dup/ins - vector from general)
9638             if (ins == INS_dup)
9639             {
9640                 datasize = id->idOpSize();
9641                 elemsize = optGetElemsize(id->idInsOpt());
9642                 index    = 0;
9643             }
9644             else // INS_ins
9645             {
9646                 datasize = EA_16BYTE;
9647                 elemsize = id->idOpSize();
9648                 index    = emitGetInsSC(id);
9649             }
9650             code = emitInsCode(ins, fmt);
9651             code |= insEncodeVectorsize(datasize);         // Q
9652             code |= insEncodeVectorIndex(elemsize, index); // iiiii
9653             code |= insEncodeReg_Vd(id->idReg1());         // ddddd
9654             code |= insEncodeReg_Rn(id->idReg2());         // nnnnn
9655             dst += emitOutput_Instr(dst, code);
9656             break;
9657
9658         case IF_DV_2D: // DV_2D   .Q.........iiiii ......nnnnnddddd      Vd Vn[]   (dup - vector)
9659             index    = emitGetInsSC(id);
9660             elemsize = optGetElemsize(id->idInsOpt());
9661             code     = emitInsCode(ins, fmt);
9662             code |= insEncodeVectorsize(id->idOpSize());   // Q
9663             code |= insEncodeVectorIndex(elemsize, index); // iiiii
9664             code |= insEncodeReg_Vd(id->idReg1());         // ddddd
9665             code |= insEncodeReg_Vn(id->idReg2());         // nnnnn
9666             dst += emitOutput_Instr(dst, code);
9667             break;
9668
9669         case IF_DV_2E: // DV_2E   ...........iiiii ......nnnnnddddd      Vd Vn[]   (dup - scalar)
9670             index    = emitGetInsSC(id);
9671             elemsize = id->idOpSize();
9672             code     = emitInsCode(ins, fmt);
9673             code |= insEncodeVectorIndex(elemsize, index); // iiiii
9674             code |= insEncodeReg_Vd(id->idReg1());         // ddddd
9675             code |= insEncodeReg_Vn(id->idReg2());         // nnnnn
9676             dst += emitOutput_Instr(dst, code);
9677             break;
9678
9679         case IF_DV_2F: // DV_2F   ...........iiiii .jjjj.nnnnnddddd      Vd[] Vn[] (ins - element)
9680             elemsize = id->idOpSize();
9681             imm      = emitGetInsSC(id);
9682             index    = (imm >> 4) & 0xf;
9683             index2   = imm & 0xf;
9684             code     = emitInsCode(ins, fmt);
9685             code |= insEncodeVectorIndex(elemsize, index);   // iiiii
9686             code |= insEncodeVectorIndex2(elemsize, index2); // jjjj
9687             code |= insEncodeReg_Vd(id->idReg1());           // ddddd
9688             code |= insEncodeReg_Vn(id->idReg2());           // nnnnn
9689             dst += emitOutput_Instr(dst, code);
9690             break;
9691
9692         case IF_DV_2G: // DV_2G   .........X...... ......nnnnnddddd      Vd Vn      (fmov,fcvtXX - register)
9693             elemsize = id->idOpSize();
9694             code     = emitInsCode(ins, fmt);
9695             code |= insEncodeFloatElemsize(elemsize); // X
9696             code |= insEncodeReg_Vd(id->idReg1());    // ddddd
9697             code |= insEncodeReg_Vn(id->idReg2());    // nnnnn
9698             dst += emitOutput_Instr(dst, code);
9699             break;
9700
9701         case IF_DV_2H: // DV_2H   X........X...... ......nnnnnddddd      Rd Vn      (fmov - to general)
9702             elemsize = id->idOpSize();
9703             code     = emitInsCode(ins, fmt);
9704             code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X   X
9705             code |= insEncodeReg_Rd(id->idReg1());            // ddddd
9706             code |= insEncodeReg_Vn(id->idReg2());            // nnnnn
9707             dst += emitOutput_Instr(dst, code);
9708             break;
9709
9710         case IF_DV_2I: // DV_2I   X........X...... ......nnnnnddddd      Vd Rn      (fmov - from general)
9711             elemsize = id->idOpSize();
9712             code     = emitInsCode(ins, fmt);
9713             code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X   X
9714             code |= insEncodeReg_Vd(id->idReg1());            // ddddd
9715             code |= insEncodeReg_Rn(id->idReg2());            // nnnnn
9716             dst += emitOutput_Instr(dst, code);
9717             break;
9718
9719         case IF_DV_2J: // DV_2J   ........SS.....D D.....nnnnnddddd      Vd Vn      (fcvt)
9720             code = emitInsCode(ins, fmt);
9721             code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // SS DD
9722             code |= insEncodeReg_Vd(id->idReg1());            // ddddd
9723             code |= insEncodeReg_Vn(id->idReg2());            // nnnnn
9724             dst += emitOutput_Instr(dst, code);
9725             break;
9726
9727         case IF_DV_2K: // DV_2K   .........X.mmmmm ......nnnnn.....      Vn Vm      (fcmp)
9728             elemsize = id->idOpSize();
9729             code     = emitInsCode(ins, fmt);
9730             code |= insEncodeFloatElemsize(elemsize); // X
9731             code |= insEncodeReg_Vn(id->idReg1());    // nnnnn
9732             code |= insEncodeReg_Vm(id->idReg2());    // mmmmm
9733             dst += emitOutput_Instr(dst, code);
9734             break;
9735
9736         case IF_DV_2L: // DV_2L   ........XX...... ......nnnnnddddd      Vd Vn      (abs, neg - scalar)
9737             elemsize = id->idOpSize();
9738             code     = emitInsCode(ins, fmt);
9739             code |= insEncodeElemsize(elemsize);   // XX
9740             code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9741             code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9742             dst += emitOutput_Instr(dst, code);
9743             break;
9744
9745         case IF_DV_2M: // DV_2M   .Q......XX...... ......nnnnnddddd      Vd Vn      (abs, neg   - vector)
9746             elemsize = optGetElemsize(id->idInsOpt());
9747             code     = emitInsCode(ins, fmt);
9748             code |= insEncodeVectorsize(id->idOpSize()); // Q
9749             code |= insEncodeElemsize(elemsize);         // XX
9750             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9751             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9752             dst += emitOutput_Instr(dst, code);
9753             break;
9754
9755         case IF_DV_2N: // DV_2N   .........iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - scalar)
9756             imm  = emitGetInsSC(id);
9757             code = emitInsCode(ins, fmt);
9758             code |= insEncodeVectorShift(EA_8BYTE, imm); // iiiiiii
9759             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9760             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9761             dst += emitOutput_Instr(dst, code);
9762             break;
9763
9764         case IF_DV_2O: // DV_2O   .Q.......iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - vector)
9765             imm      = emitGetInsSC(id);
9766             elemsize = optGetElemsize(id->idInsOpt());
9767             code     = emitInsCode(ins, fmt);
9768             code |= insEncodeVectorsize(id->idOpSize()); // Q
9769             code |= insEncodeVectorShift(elemsize, imm); // iiiiiii
9770             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9771             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9772             dst += emitOutput_Instr(dst, code);
9773             break;
9774
9775         case IF_DV_3A: // DV_3A   .Q......XX.mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
9776             code     = emitInsCode(ins, fmt);
9777             elemsize = optGetElemsize(id->idInsOpt());
9778             code |= insEncodeVectorsize(id->idOpSize()); // Q
9779             code |= insEncodeElemsize(elemsize);         // XX
9780             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9781             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9782             code |= insEncodeReg_Vm(id->idReg3());       // mmmmm
9783             dst += emitOutput_Instr(dst, code);
9784             break;
9785
9786         case IF_DV_3AI: // DV_3AI  .Q......XXLMmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector)
9787             code     = emitInsCode(ins, fmt);
9788             imm      = emitGetInsSC(id);
9789             elemsize = optGetElemsize(id->idInsOpt());
9790             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
9791             code |= insEncodeVectorsize(id->idOpSize());    // Q
9792             code |= insEncodeElemsize(elemsize);            // XX
9793             code |= insEncodeVectorIndexLMH(elemsize, imm); // LM H
9794             code |= insEncodeReg_Vd(id->idReg1());          // ddddd
9795             code |= insEncodeReg_Vn(id->idReg2());          // nnnnn
9796             code |= insEncodeReg_Vm(id->idReg3());          // mmmmm
9797             dst += emitOutput_Instr(dst, code);
9798             break;
9799
9800         case IF_DV_3B: // DV_3B   .Q.......X.mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
9801             code     = emitInsCode(ins, fmt);
9802             elemsize = optGetElemsize(id->idInsOpt());
9803             code |= insEncodeVectorsize(id->idOpSize()); // Q
9804             code |= insEncodeFloatElemsize(elemsize);    // X
9805             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9806             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9807             code |= insEncodeReg_Vm(id->idReg3());       // mmmmm
9808             dst += emitOutput_Instr(dst, code);
9809             break;
9810
9811         case IF_DV_3BI: // DV_3BI  .Q.......XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector by elem)
9812             code     = emitInsCode(ins, fmt);
9813             imm      = emitGetInsSC(id);
9814             elemsize = optGetElemsize(id->idInsOpt());
9815             assert(isValidVectorIndex(id->idOpSize(), elemsize, imm));
9816             code |= insEncodeVectorsize(id->idOpSize()); // Q
9817             code |= insEncodeFloatElemsize(elemsize);    // X
9818             code |= insEncodeFloatIndex(elemsize, imm);  // L H
9819             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9820             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9821             code |= insEncodeReg_Vm(id->idReg3());       // mmmmm
9822             dst += emitOutput_Instr(dst, code);
9823             break;
9824
9825         case IF_DV_3C: // DV_3C   .Q.........mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
9826             code = emitInsCode(ins, fmt);
9827             code |= insEncodeVectorsize(id->idOpSize()); // Q
9828             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9829             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9830             code |= insEncodeReg_Vm(id->idReg3());       // mmmmm
9831             dst += emitOutput_Instr(dst, code);
9832             break;
9833
9834         case IF_DV_3D: // DV_3D   .........X.mmmmm ......nnnnnddddd      Vd Vn Vm   (scalar)
9835             code = emitInsCode(ins, fmt);
9836             code |= insEncodeFloatElemsize(id->idOpSize()); // X
9837             code |= insEncodeReg_Vd(id->idReg1());          // ddddd
9838             code |= insEncodeReg_Vn(id->idReg2());          // nnnnn
9839             code |= insEncodeReg_Vm(id->idReg3());          // mmmmm
9840             dst += emitOutput_Instr(dst, code);
9841             break;
9842
9843         case IF_DV_3DI: // DV_3DI  .........XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (scalar by elem)
9844             code     = emitInsCode(ins, fmt);
9845             imm      = emitGetInsSC(id);
9846             elemsize = id->idOpSize();
9847             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
9848             code |= insEncodeFloatElemsize(elemsize);   // X
9849             code |= insEncodeFloatIndex(elemsize, imm); // L H
9850             code |= insEncodeReg_Vd(id->idReg1());      // ddddd
9851             code |= insEncodeReg_Vn(id->idReg2());      // nnnnn
9852             code |= insEncodeReg_Vm(id->idReg3());      // mmmmm
9853             dst += emitOutput_Instr(dst, code);
9854             break;
9855
9856         case IF_DV_3E: // DV_3E   ...........mmmmm ......nnnnnddddd      Vd Vn Vm   (scalar)
9857             code = emitInsCode(ins, fmt);
9858             code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9859             code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9860             code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9861             dst += emitOutput_Instr(dst, code);
9862             break;
9863
9864         case IF_DV_4A: // DV_4A   .........X.mmmmm .aaaaannnnnddddd      Vd Va Vn Vm (scalar)
9865             code     = emitInsCode(ins, fmt);
9866             elemsize = id->idOpSize();
9867             code |= insEncodeFloatElemsize(elemsize); // X
9868             code |= insEncodeReg_Vd(id->idReg1());    // ddddd
9869             code |= insEncodeReg_Vn(id->idReg2());    // nnnnn
9870             code |= insEncodeReg_Vm(id->idReg3());    // mmmmm
9871             code |= insEncodeReg_Va(id->idReg4());    // aaaaa
9872             dst += emitOutput_Instr(dst, code);
9873             break;
9874
9875         case IF_SN_0A: // SN_0A   ................ ................
9876             code = emitInsCode(ins, fmt);
9877             dst += emitOutput_Instr(dst, code);
9878             break;
9879
9880         case IF_SI_0A: // SI_0A   ...........iiiii iiiiiiiiiii.....               imm16
9881             imm = emitGetInsSC(id);
9882             assert(isValidUimm16(imm));
9883             code = emitInsCode(ins, fmt);
9884             code |= ((code_t)imm << 5); // iiiii iiiiiiiiiii
9885             dst += emitOutput_Instr(dst, code);
9886             break;
9887
9888         case IF_SI_0B: // SI_0B   ................ ....bbbb........               imm4 - barrier
9889             imm = emitGetInsSC(id);
9890             assert((imm >= 0) && (imm <= 15));
9891             code = emitInsCode(ins, fmt);
9892             code |= ((code_t)imm << 8); // bbbb
9893             dst += emitOutput_Instr(dst, code);
9894             break;
9895
9896         default:
9897             assert(!"Unexpected format");
9898             break;
9899     }
9900
9901     // Determine if any registers now hold GC refs, or whether a register that was overwritten held a GC ref.
9902     // We assume here that "id->idGCref()" is not GC_NONE only if the instruction described by "id" writes a
9903     // GC ref to register "id->idReg1()".  (It may, apparently, also not be GC_NONE in other cases, such as
9904     // for stores, but we ignore those cases here.)
9905     if (emitInsMayWriteToGCReg(id)) // True if "id->idIns()" writes to a register than can hold GC ref.
9906     {
9907         // We assume that "idReg1" is the primary destination register for all instructions
9908         if (id->idGCref() != GCT_NONE)
9909         {
9910             emitGCregLiveUpd(id->idGCref(), id->idReg1(), dst);
9911         }
9912         else
9913         {
9914             emitGCregDeadUpd(id->idReg1(), dst);
9915         }
9916
9917         if (emitInsMayWriteMultipleRegs(id))
9918         {
9919             // INS_ldp etc...
9920             // "idReg2" is the secondary destination register
9921             if (id->idGCrefReg2() != GCT_NONE)
9922             {
9923                 emitGCregLiveUpd(id->idGCrefReg2(), id->idReg2(), dst);
9924             }
9925             else
9926             {
9927                 emitGCregDeadUpd(id->idReg2(), dst);
9928             }
9929         }
9930     }
9931
9932     // Now we determine if the instruction has written to a (local variable) stack location, and either written a GC
9933     // ref or overwritten one.
9934     if (emitInsWritesToLclVarStackLoc(id) || emitInsWritesToLclVarStackLocPair(id))
9935     {
9936         int      varNum = id->idAddr()->iiaLclVar.lvaVarNum();
9937         unsigned ofs    = AlignDown(id->idAddr()->iiaLclVar.lvaOffset(), sizeof(size_t));
9938         bool     FPbased;
9939         int      adr = emitComp->lvaFrameAddress(varNum, &FPbased);
9940         if (id->idGCref() != GCT_NONE)
9941         {
9942             emitGCvarLiveUpd(adr + ofs, varNum, id->idGCref(), dst);
9943         }
9944         else
9945         {
9946             // If the type of the local is a gc ref type, update the liveness.
9947             var_types vt;
9948             if (varNum >= 0)
9949             {
9950                 // "Regular" (non-spill-temp) local.
9951                 vt = var_types(emitComp->lvaTable[varNum].lvType);
9952             }
9953             else
9954             {
9955                 TempDsc* tmpDsc = emitComp->tmpFindNum(varNum);
9956                 vt              = tmpDsc->tdTempType();
9957             }
9958             if (vt == TYP_REF || vt == TYP_BYREF)
9959                 emitGCvarDeadUpd(adr + ofs, dst);
9960         }
9961         if (emitInsWritesToLclVarStackLocPair(id))
9962         {
9963             unsigned ofs2 = ofs + sizeof(size_t);
9964             if (id->idGCrefReg2() != GCT_NONE)
9965             {
9966                 emitGCvarLiveUpd(adr + ofs2, varNum, id->idGCrefReg2(), dst);
9967             }
9968             else
9969             {
9970                 // If the type of the local is a gc ref type, update the liveness.
9971                 var_types vt;
9972                 if (varNum >= 0)
9973                 {
9974                     // "Regular" (non-spill-temp) local.
9975                     vt = var_types(emitComp->lvaTable[varNum].lvType);
9976                 }
9977                 else
9978                 {
9979                     TempDsc* tmpDsc = emitComp->tmpFindNum(varNum);
9980                     vt              = tmpDsc->tdTempType();
9981                 }
9982                 if (vt == TYP_REF || vt == TYP_BYREF)
9983                     emitGCvarDeadUpd(adr + ofs2, dst);
9984             }
9985         }
9986     }
9987
9988 #ifdef DEBUG
9989     /* Make sure we set the instruction descriptor size correctly */
9990
9991     size_t expected = emitSizeOfInsDsc(id);
9992     assert(sz == expected);
9993
9994     if (emitComp->opts.disAsm || emitComp->opts.dspEmit || emitComp->verbose)
9995     {
9996         emitDispIns(id, false, dspOffs, true, emitCurCodeOffs(odst), *dp, (dst - *dp), ig);
9997     }
9998
9999     if (emitComp->compDebugBreak)
10000     {
10001         // For example, set JitBreakEmitOutputInstr=a6 will break when this method is called for
10002         // emitting instruction a6, (i.e. IN00a6 in jitdump).
10003         if ((unsigned)JitConfig.JitBreakEmitOutputInstr() == id->idDebugOnlyInfo()->idNum)
10004         {
10005             assert(!"JitBreakEmitOutputInstr reached");
10006         }
10007     }
10008 #endif
10009
10010     /* All instructions are expected to generate code */
10011
10012     assert(*dp != dst);
10013
10014     *dp = dst;
10015
10016     return sz;
10017 }
10018
10019 /*****************************************************************************/
10020 /*****************************************************************************/
10021
10022 #ifdef DEBUG
10023
10024 /*****************************************************************************
10025  *
10026  *  Display the instruction name
10027  */
10028 void emitter::emitDispInst(instruction ins)
10029 {
10030     const char* insstr = codeGen->genInsName(ins);
10031     size_t      len    = strlen(insstr);
10032
10033     /* Display the instruction name */
10034
10035     printf("%s", insstr);
10036
10037     //
10038     // Add at least one space after the instruction name
10039     // and add spaces until we have reach the normal size of 8
10040     do
10041     {
10042         printf(" ");
10043         len++;
10044     } while (len < 8);
10045 }
10046
10047 /*****************************************************************************
10048  *
10049  *  Display an reloc value
10050  *  If we are formatting for an assembly listing don't print the hex value
10051  *  since it will prevent us from doing assembly diffs
10052  */
10053 void emitter::emitDispReloc(int value, bool addComma)
10054 {
10055     if (emitComp->opts.disAsm)
10056     {
10057         printf("(reloc)");
10058     }
10059     else
10060     {
10061         printf("(reloc 0x%x)", dspPtr(value));
10062     }
10063
10064     if (addComma)
10065         printf(", ");
10066 }
10067
10068 /*****************************************************************************
10069  *
10070  *  Display an immediate value
10071  */
10072 void emitter::emitDispImm(ssize_t imm, bool addComma, bool alwaysHex /* =false */)
10073 {
10074     if (strictArmAsm)
10075     {
10076         printf("#");
10077     }
10078
10079     // Munge any pointers if we want diff-able disassembly
10080     if (emitComp->opts.disDiffable)
10081     {
10082         ssize_t top44bits = (imm >> 20);
10083         if ((top44bits != 0) && (top44bits != -1))
10084             imm = 0xD1FFAB1E;
10085     }
10086
10087     if (!alwaysHex && (imm > -1000) && (imm < 1000))
10088     {
10089         printf("%d", imm);
10090     }
10091     else
10092     {
10093         if ((imm < 0) && ((imm & 0xFFFFFFFF00000000LL) == 0xFFFFFFFF00000000LL))
10094         {
10095             printf("-");
10096             imm = -imm;
10097         }
10098
10099         if ((imm & 0xFFFFFFFF00000000LL) != 0)
10100         {
10101             printf("0x%llx", imm);
10102         }
10103         else
10104         {
10105             printf("0x%02x", imm);
10106         }
10107     }
10108
10109     if (addComma)
10110         printf(", ");
10111 }
10112
10113 /*****************************************************************************
10114  *
10115  *  Display a float zero constant
10116  */
10117 void emitter::emitDispFloatZero()
10118 {
10119     if (strictArmAsm)
10120     {
10121         printf("#");
10122     }
10123     printf("0.0");
10124 }
10125
10126 /*****************************************************************************
10127  *
10128  *  Display an encoded float constant value
10129  */
10130 void emitter::emitDispFloatImm(ssize_t imm8)
10131 {
10132     assert((0 <= imm8) && (imm8 <= 0x0ff));
10133     if (strictArmAsm)
10134     {
10135         printf("#");
10136     }
10137
10138     floatImm8 fpImm;
10139     fpImm.immFPIVal = (unsigned)imm8;
10140     double result   = emitDecodeFloatImm8(fpImm);
10141
10142     printf("%.4f", result);
10143 }
10144
10145 /*****************************************************************************
10146  *
10147  *  Display an immediate that is optionally LSL12.
10148  */
10149 void emitter::emitDispImmOptsLSL12(ssize_t imm, insOpts opt)
10150 {
10151     if (!strictArmAsm && insOptsLSL12(opt))
10152     {
10153         imm <<= 12;
10154     }
10155     emitDispImm(imm, false);
10156     if (strictArmAsm && insOptsLSL12(opt))
10157     {
10158         printf(", LSL #12");
10159     }
10160 }
10161
10162 /*****************************************************************************
10163  *
10164  *  Display an ARM64 condition code for the conditional instructions
10165  */
10166 void emitter::emitDispCond(insCond cond)
10167 {
10168     const static char* armCond[16] = {"eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc",
10169                                       "hi", "ls", "ge", "lt", "gt", "le", "AL", "NV"}; // The last two are invalid
10170     unsigned imm = (unsigned)cond;
10171     assert((0 <= imm) && (imm < ArrLen(armCond)));
10172     printf(armCond[imm]);
10173 }
10174
10175 /*****************************************************************************
10176  *
10177  *  Display an ARM64 flags for the conditional instructions
10178  */
10179 void emitter::emitDispFlags(insCflags flags)
10180 {
10181     const static char* armFlags[16] = {"0", "v",  "c",  "cv",  "z",  "zv",  "zc",  "zcv",
10182                                        "n", "nv", "nc", "ncv", "nz", "nzv", "nzc", "nzcv"};
10183     unsigned imm = (unsigned)flags;
10184     assert((0 <= imm) && (imm < ArrLen(armFlags)));
10185     printf(armFlags[imm]);
10186 }
10187
10188 /*****************************************************************************
10189  *
10190  *  Display an ARM64 'barrier' for the memory barrier instructions
10191  */
10192 void emitter::emitDispBarrier(insBarrier barrier)
10193 {
10194     const static char* armBarriers[16] = {"#0", "oshld", "oshst", "osh", "#4",  "nshld", "nshst", "nsh",
10195                                           "#8", "ishld", "ishst", "ish", "#12", "ld",    "st",    "sy"};
10196     unsigned imm = (unsigned)barrier;
10197     assert((0 <= imm) && (imm < ArrLen(armBarriers)));
10198     printf(armBarriers[imm]);
10199 }
10200
10201 /*****************************************************************************
10202  *
10203  *  Prints the encoding for the Shift Type encoding
10204  */
10205
10206 void emitter::emitDispShiftOpts(insOpts opt)
10207 {
10208     if (opt == INS_OPTS_LSL)
10209         printf(" LSL ");
10210     else if (opt == INS_OPTS_LSR)
10211         printf(" LSR ");
10212     else if (opt == INS_OPTS_ASR)
10213         printf(" ASR ");
10214     else if (opt == INS_OPTS_ROR)
10215         printf(" ROR ");
10216     else if (opt == INS_OPTS_MSL)
10217         printf(" MSL ");
10218     else
10219         assert(!"Bad value");
10220 }
10221
10222 /*****************************************************************************
10223  *
10224  *  Prints the encoding for the Extend Type encoding
10225  */
10226
10227 void emitter::emitDispExtendOpts(insOpts opt)
10228 {
10229     if (opt == INS_OPTS_UXTB)
10230         printf("UXTB");
10231     else if (opt == INS_OPTS_UXTH)
10232         printf("UXTH");
10233     else if (opt == INS_OPTS_UXTW)
10234         printf("UXTW");
10235     else if (opt == INS_OPTS_UXTX)
10236         printf("UXTX");
10237     else if (opt == INS_OPTS_SXTB)
10238         printf("SXTB");
10239     else if (opt == INS_OPTS_SXTH)
10240         printf("SXTH");
10241     else if (opt == INS_OPTS_SXTW)
10242         printf("SXTW");
10243     else if (opt == INS_OPTS_SXTX)
10244         printf("SXTX");
10245     else
10246         assert(!"Bad value");
10247 }
10248
10249 /*****************************************************************************
10250  *
10251  *  Prints the encoding for the Extend Type encoding in loads/stores
10252  */
10253
10254 void emitter::emitDispLSExtendOpts(insOpts opt)
10255 {
10256     if (opt == INS_OPTS_LSL)
10257         printf("LSL");
10258     else if (opt == INS_OPTS_UXTW)
10259         printf("UXTW");
10260     else if (opt == INS_OPTS_UXTX)
10261         printf("UXTX");
10262     else if (opt == INS_OPTS_SXTW)
10263         printf("SXTW");
10264     else if (opt == INS_OPTS_SXTX)
10265         printf("SXTX");
10266     else
10267         assert(!"Bad value");
10268 }
10269
10270 /*****************************************************************************
10271  *
10272  *  Display a register
10273  */
10274 void emitter::emitDispReg(regNumber reg, emitAttr attr, bool addComma)
10275 {
10276     emitAttr size = EA_SIZE(attr);
10277     printf(emitRegName(reg, size));
10278
10279     if (addComma)
10280         printf(", ");
10281 }
10282
10283 /*****************************************************************************
10284  *
10285  *  Display a vector register with an arrangement suffix
10286  */
10287 void emitter::emitDispVectorReg(regNumber reg, insOpts opt, bool addComma)
10288 {
10289     assert(isVectorRegister(reg));
10290     printf(emitVectorRegName(reg));
10291     emitDispArrangement(opt);
10292
10293     if (addComma)
10294         printf(", ");
10295 }
10296
10297 /*****************************************************************************
10298  *
10299  *  Display an vector register index suffix
10300  */
10301 void emitter::emitDispVectorRegIndex(regNumber reg, emitAttr elemsize, ssize_t index, bool addComma)
10302 {
10303     assert(isVectorRegister(reg));
10304     printf(emitVectorRegName(reg));
10305
10306     switch (elemsize)
10307     {
10308         case EA_1BYTE:
10309             printf(".b");
10310             break;
10311         case EA_2BYTE:
10312             printf(".h");
10313             break;
10314         case EA_4BYTE:
10315             printf(".s");
10316             break;
10317         case EA_8BYTE:
10318             printf(".d");
10319             break;
10320         default:
10321             assert(!"invalid elemsize");
10322             break;
10323     }
10324
10325     printf("[%d]", index);
10326
10327     if (addComma)
10328         printf(", ");
10329 }
10330
10331 /*****************************************************************************
10332  *
10333  *  Display an arrangement suffix
10334  */
10335 void emitter::emitDispArrangement(insOpts opt)
10336 {
10337     const char* str = "???";
10338
10339     switch (opt)
10340     {
10341         case INS_OPTS_8B:
10342             str = "8b";
10343             break;
10344         case INS_OPTS_16B:
10345             str = "16b";
10346             break;
10347         case INS_OPTS_4H:
10348             str = "4h";
10349             break;
10350         case INS_OPTS_8H:
10351             str = "8h";
10352             break;
10353         case INS_OPTS_2S:
10354             str = "2s";
10355             break;
10356         case INS_OPTS_4S:
10357             str = "4s";
10358             break;
10359         case INS_OPTS_1D:
10360             str = "1d";
10361             break;
10362         case INS_OPTS_2D:
10363             str = "2d";
10364             break;
10365
10366         default:
10367             assert(!"Invalid insOpt for vector register");
10368     }
10369     printf(".");
10370     printf(str);
10371 }
10372
10373 /*****************************************************************************
10374  *
10375  *  Display a register with an optional shift operation
10376  */
10377 void emitter::emitDispShiftedReg(regNumber reg, insOpts opt, ssize_t imm, emitAttr attr)
10378 {
10379     emitAttr size = EA_SIZE(attr);
10380     assert((imm & 0x003F) == imm);
10381     assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
10382
10383     printf(emitRegName(reg, size));
10384
10385     if (imm > 0)
10386     {
10387         if (strictArmAsm)
10388         {
10389             printf(",");
10390         }
10391         emitDispShiftOpts(opt);
10392         emitDispImm(imm, false);
10393     }
10394 }
10395
10396 /*****************************************************************************
10397  *
10398  *  Display a register with an optional extend and scale operations
10399  */
10400 void emitter::emitDispExtendReg(regNumber reg, insOpts opt, ssize_t imm)
10401 {
10402     assert((imm >= 0) && (imm <= 4));
10403     assert(insOptsNone(opt) || insOptsAnyExtend(opt) || (opt == INS_OPTS_LSL));
10404
10405     // size is based on the extend option, not the instr size.
10406     emitAttr size = insOpts32BitExtend(opt) ? EA_4BYTE : EA_8BYTE;
10407
10408     if (strictArmAsm)
10409     {
10410         if (insOptsNone(opt))
10411         {
10412             emitDispReg(reg, size, false);
10413         }
10414         else
10415         {
10416             emitDispReg(reg, size, true);
10417             if (opt == INS_OPTS_LSL)
10418                 printf("LSL");
10419             else
10420                 emitDispExtendOpts(opt);
10421             if ((imm > 0) || (opt == INS_OPTS_LSL))
10422             {
10423                 printf(" ");
10424                 emitDispImm(imm, false);
10425             }
10426         }
10427     }
10428     else // !strictArmAsm
10429     {
10430         if (insOptsNone(opt))
10431         {
10432             emitDispReg(reg, size, false);
10433         }
10434         else
10435         {
10436             if (opt != INS_OPTS_LSL)
10437             {
10438                 emitDispExtendOpts(opt);
10439                 printf("(");
10440                 emitDispReg(reg, size, false);
10441                 printf(")");
10442             }
10443         }
10444         if (imm > 0)
10445         {
10446             printf("*");
10447             emitDispImm(1 << imm, false);
10448         }
10449     }
10450 }
10451
10452 /*****************************************************************************
10453  *
10454  *  Display an addressing operand [reg + imm]
10455  */
10456 void emitter::emitDispAddrRI(regNumber reg, insOpts opt, ssize_t imm)
10457 {
10458     reg = encodingZRtoSP(reg); // ZR (R31) encodes the SP register
10459
10460     if (strictArmAsm)
10461     {
10462         printf("[");
10463
10464         emitDispReg(reg, EA_8BYTE, false);
10465
10466         if (!insOptsPostIndex(opt) && (imm != 0))
10467         {
10468             printf(",");
10469             emitDispImm(imm, false);
10470         }
10471         printf("]");
10472
10473         if (insOptsPreIndex(opt))
10474         {
10475             printf("!");
10476         }
10477         else if (insOptsPostIndex(opt))
10478         {
10479             printf(",");
10480             emitDispImm(imm, false);
10481         }
10482     }
10483     else // !strictArmAsm
10484     {
10485         printf("[");
10486
10487         const char* operStr = "++";
10488         if (imm < 0)
10489         {
10490             operStr = "--";
10491             imm     = -imm;
10492         }
10493
10494         if (insOptsPreIndex(opt))
10495         {
10496             printf(operStr);
10497         }
10498
10499         emitDispReg(reg, EA_8BYTE, false);
10500
10501         if (insOptsPostIndex(opt))
10502         {
10503             printf(operStr);
10504         }
10505
10506         if (insOptsIndexed(opt))
10507         {
10508             printf(", ");
10509         }
10510         else
10511         {
10512             printf("%c", operStr[1]);
10513         }
10514         emitDispImm(imm, false);
10515         printf("]");
10516     }
10517 }
10518
10519 /*****************************************************************************
10520  *
10521  *  Display an addressing operand [reg + extended reg]
10522  */
10523 void emitter::emitDispAddrRRExt(regNumber reg1, regNumber reg2, insOpts opt, bool isScaled, emitAttr size)
10524 {
10525     reg1 = encodingZRtoSP(reg1); // ZR (R31) encodes the SP register
10526
10527     unsigned scale = 0;
10528     if (isScaled)
10529     {
10530         scale = NaturalScale_helper(size);
10531     }
10532
10533     printf("[");
10534
10535     if (strictArmAsm)
10536     {
10537         emitDispReg(reg1, EA_8BYTE, true);
10538         emitDispExtendReg(reg2, opt, scale);
10539     }
10540     else // !strictArmAsm
10541     {
10542         emitDispReg(reg1, EA_8BYTE, false);
10543         printf("+");
10544         emitDispExtendReg(reg2, opt, scale);
10545     }
10546
10547     printf("]");
10548 }
10549
10550 /*****************************************************************************
10551  *
10552  *  Display (optionally) the instruction encoding in hex
10553  */
10554
10555 void emitter::emitDispInsHex(BYTE* code, size_t sz)
10556 {
10557     // We do not display the instruction hex if we want diff-able disassembly
10558     if (!emitComp->opts.disDiffable)
10559     {
10560         if (sz == 4)
10561         {
10562             printf("  %08X    ", (*((code_t*)code)));
10563         }
10564         else
10565         {
10566             printf("              ");
10567         }
10568     }
10569 }
10570
10571 /****************************************************************************
10572  *
10573  *  Display the given instruction.
10574  */
10575
10576 void emitter::emitDispIns(
10577     instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* pCode, size_t sz, insGroup* ig)
10578 {
10579     if (EMITVERBOSE)
10580     {
10581         unsigned idNum =
10582             id->idDebugOnlyInfo()->idNum; // Do not remove this!  It is needed for VisualStudio conditional breakpoints
10583
10584         printf("IN%04x: ", idNum);
10585     }
10586
10587     if (pCode == NULL)
10588         sz = 0;
10589
10590     if (!emitComp->opts.dspEmit && !isNew && !asmfm && sz)
10591         doffs = true;
10592
10593     /* Display the instruction offset */
10594
10595     emitDispInsOffs(offset, doffs);
10596
10597     /* Display the instruction hex code */
10598
10599     emitDispInsHex(pCode, sz);
10600
10601     printf("      ");
10602
10603     /* Get the instruction and format */
10604
10605     instruction ins = id->idIns();
10606     insFormat   fmt = id->idInsFmt();
10607
10608     emitDispInst(ins);
10609
10610     /* If this instruction has just been added, check its size */
10611
10612     assert(isNew == false || (int)emitSizeOfInsDsc(id) == emitCurIGfreeNext - (BYTE*)id);
10613
10614     /* Figure out the operand size */
10615     emitAttr size = id->idOpSize();
10616     emitAttr attr = size;
10617     if (id->idGCref() == GCT_GCREF)
10618         attr = EA_GCREF;
10619     else if (id->idGCref() == GCT_BYREF)
10620         attr = EA_BYREF;
10621
10622     switch (fmt)
10623     {
10624         code_t       code;
10625         ssize_t      imm;
10626         int          doffs;
10627         bool         isExtendAlias;
10628         bool         canEncode;
10629         bitMaskImm   bmi;
10630         halfwordImm  hwi;
10631         condFlagsImm cfi;
10632         unsigned     scale;
10633         unsigned     immShift;
10634         bool         hasShift;
10635         ssize_t      offs;
10636         const char*  methodName;
10637         emitAttr     elemsize;
10638         emitAttr     datasize;
10639         emitAttr     srcsize;
10640         emitAttr     dstsize;
10641         ssize_t      index;
10642         ssize_t      index2;
10643
10644         case IF_BI_0A: // BI_0A   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
10645         case IF_BI_0B: // BI_0B   ......iiiiiiiiii iiiiiiiiiii.....               simm19:00
10646         case IF_LARGEJMP:
10647         {
10648             if (fmt == IF_LARGEJMP)
10649             {
10650                 printf("(LARGEJMP)");
10651             }
10652             if (id->idAddr()->iiaHasInstrCount())
10653             {
10654                 int instrCount = id->idAddr()->iiaGetInstrCount();
10655
10656                 if (ig == nullptr)
10657                 {
10658                     printf("pc%s%d instructions", (instrCount >= 0) ? "+" : "", instrCount);
10659                 }
10660                 else
10661                 {
10662                     unsigned       insNum  = emitFindInsNum(ig, id);
10663                     UNATIVE_OFFSET srcOffs = ig->igOffs + emitFindOffset(ig, insNum + 1);
10664                     UNATIVE_OFFSET dstOffs = ig->igOffs + emitFindOffset(ig, insNum + 1 + instrCount);
10665                     ssize_t        relOffs = (ssize_t)(emitOffsetToPtr(dstOffs) - emitOffsetToPtr(srcOffs));
10666                     printf("pc%s%d (%d instructions)", (relOffs >= 0) ? "+" : "", relOffs, instrCount);
10667                 }
10668             }
10669             else if (id->idIsBound())
10670             {
10671                 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10672             }
10673             else
10674             {
10675                 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10676             }
10677         }
10678         break;
10679
10680         case IF_BI_0C: // BI_0C   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
10681             if (id->idIsCallAddr())
10682             {
10683                 offs       = (ssize_t)id->idAddr()->iiaAddr;
10684                 methodName = "";
10685             }
10686             else
10687             {
10688                 offs       = 0;
10689                 methodName = emitComp->eeGetMethodFullName((CORINFO_METHOD_HANDLE)id->idDebugOnlyInfo()->idMemCookie);
10690             }
10691
10692             if (offs)
10693             {
10694                 if (id->idIsDspReloc())
10695                     printf("reloc ");
10696                 printf("%08X", offs);
10697             }
10698             else
10699             {
10700                 printf("%s", methodName);
10701             }
10702             break;
10703
10704         case IF_BI_1A: // BI_1A   ......iiiiiiiiii iiiiiiiiiiittttt      Rt       simm19:00
10705             assert(insOptsNone(id->idInsOpt()));
10706             emitDispReg(id->idReg1(), size, true);
10707             if (id->idIsBound())
10708             {
10709                 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10710             }
10711             else
10712             {
10713                 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10714             }
10715             break;
10716
10717         case IF_BI_1B: // BI_1B   B.......bbbbbiii iiiiiiiiiiittttt      Rt imm6, simm14:00
10718             assert(insOptsNone(id->idInsOpt()));
10719             emitDispReg(id->idReg1(), size, true);
10720             emitDispImm(emitGetInsSC(id), true);
10721             if (id->idIsBound())
10722             {
10723                 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10724             }
10725             else
10726             {
10727                 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10728             }
10729             break;
10730
10731         case IF_BR_1A: // BR_1A   ................ ......nnnnn.....         Rn
10732             assert(insOptsNone(id->idInsOpt()));
10733             emitDispReg(id->idReg1(), size, false);
10734             break;
10735
10736         case IF_BR_1B: // BR_1B   ................ ......nnnnn.....         Rn
10737             assert(insOptsNone(id->idInsOpt()));
10738             emitDispReg(id->idReg3(), size, false);
10739             break;
10740
10741         case IF_LS_1A: // LS_1A   XX...V..iiiiiiii iiiiiiiiiiittttt      Rt    PC imm(1MB)
10742         case IF_DI_1E: // DI_1E   .ii.....iiiiiiii iiiiiiiiiiiddddd      Rd       simm21
10743         case IF_LARGELDC:
10744         case IF_LARGEADR:
10745             assert(insOptsNone(id->idInsOpt()));
10746             emitDispReg(id->idReg1(), size, true);
10747             imm = emitGetInsSC(id);
10748
10749             /* Is this actually a reference to a data section? */
10750             if (fmt == IF_LARGEADR)
10751             {
10752                 printf("(LARGEADR)");
10753             }
10754             else if (fmt == IF_LARGELDC)
10755             {
10756                 printf("(LARGELDC)");
10757             }
10758
10759             printf("[");
10760             if (id->idAddr()->iiaIsJitDataOffset())
10761             {
10762                 doffs = Compiler::eeGetJitDataOffs(id->idAddr()->iiaFieldHnd);
10763                 /* Display a data section reference */
10764
10765                 if (doffs & 1)
10766                     printf("@CNS%02u", doffs - 1);
10767                 else
10768                     printf("@RWD%02u", doffs);
10769
10770                 if (imm != 0)
10771                     printf("%+Id", imm);
10772             }
10773             else
10774             {
10775                 assert(imm == 0);
10776                 if (id->idIsReloc())
10777                 {
10778                     printf("RELOC ");
10779                     emitDispImm((ssize_t)id->idAddr()->iiaAddr, false);
10780                 }
10781                 else 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             }
10790             printf("]");
10791             break;
10792
10793         case IF_LS_2A: // LS_2A   .X.......X...... ......nnnnnttttt      Rt Rn
10794             assert(insOptsNone(id->idInsOpt()));
10795             assert(emitGetInsSC(id) == 0);
10796             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10797             emitDispAddrRI(id->idReg2(), id->idInsOpt(), 0);
10798             break;
10799
10800         case IF_LS_2B: // LS_2B   .X.......Xiiiiii iiiiiinnnnnttttt      Rt Rn    imm(0-4095)
10801             assert(insOptsNone(id->idInsOpt()));
10802             imm   = emitGetInsSC(id);
10803             scale = NaturalScale_helper(emitInsLoadStoreSize(id));
10804             imm <<= scale; // The immediate is scaled by the size of the ld/st
10805             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10806             emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
10807             break;
10808
10809         case IF_LS_2C: // LS_2C   .X.......X.iiiii iiiiPPnnnnnttttt      Rt Rn    imm(-256..+255) no/pre/post inc
10810             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
10811             imm = emitGetInsSC(id);
10812             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10813             emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
10814             break;
10815
10816         case IF_LS_3A: // LS_3A   .X.......X.mmmmm oooS..nnnnnttttt      Rt Rn Rm ext(Rm) LSL {}
10817             assert(insOptsLSExtend(id->idInsOpt()));
10818             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10819             if (id->idIsLclVar())
10820             {
10821                 emitDispAddrRRExt(id->idReg2(), codeGen->rsGetRsvdReg(), id->idInsOpt(), false, size);
10822             }
10823             else
10824             {
10825                 emitDispAddrRRExt(id->idReg2(), id->idReg3(), id->idInsOpt(), id->idReg3Scaled(), size);
10826             }
10827             break;
10828
10829         case IF_LS_3B: // LS_3B   X............... .aaaaannnnnddddd      Rt Ra Rn
10830             assert(insOptsNone(id->idInsOpt()));
10831             assert(emitGetInsSC(id) == 0);
10832             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10833             emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10834             emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
10835             break;
10836
10837         case IF_LS_3C: // LS_3C   X.........iiiiii iaaaaannnnnddddd      Rt Ra Rn imm(im7,sh)
10838             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
10839             imm   = emitGetInsSC(id);
10840             scale = NaturalScale_helper(emitInsLoadStoreSize(id));
10841             imm <<= scale;
10842             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10843             emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10844             emitDispAddrRI(id->idReg3(), id->idInsOpt(), imm);
10845             break;
10846
10847         case IF_LS_3D: // LS_3D   .X.......X.mmmmm ......nnnnnttttt      Wm Rt Rn
10848             assert(insOptsNone(id->idInsOpt()));
10849             emitDispReg(id->idReg1(), EA_4BYTE, true);
10850             emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10851             emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
10852             break;
10853
10854         case IF_DI_1A: // DI_1A   X.......shiiiiii iiiiiinnnnn.....      Rn       imm(i12,sh)
10855             emitDispReg(id->idReg1(), size, true);
10856             emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
10857             break;
10858
10859         case IF_DI_1B: // DI_1B   X........hwiiiii iiiiiiiiiiiddddd      Rd       imm(i16,hw)
10860             emitDispReg(id->idReg1(), size, true);
10861             hwi.immHWVal = (unsigned)emitGetInsSC(id);
10862             if (ins == INS_mov)
10863             {
10864                 emitDispImm(emitDecodeHalfwordImm(hwi, size), false);
10865             }
10866             else // movz, movn, movk
10867             {
10868                 emitDispImm(hwi.immVal, false);
10869                 if (hwi.immHW != 0)
10870                 {
10871                     emitDispShiftOpts(INS_OPTS_LSL);
10872                     emitDispImm(hwi.immHW * 16, false);
10873                 }
10874             }
10875             break;
10876
10877         case IF_DI_1C: // DI_1C   X........Nrrrrrr ssssssnnnnn.....         Rn    imm(N,r,s)
10878             emitDispReg(id->idReg1(), size, true);
10879             bmi.immNRS = (unsigned)emitGetInsSC(id);
10880             emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
10881             break;
10882
10883         case IF_DI_1D: // DI_1D   X........Nrrrrrr ssssss.....ddddd      Rd       imm(N,r,s)
10884             emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
10885             bmi.immNRS = (unsigned)emitGetInsSC(id);
10886             emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
10887             break;
10888
10889         case IF_DI_2A: // DI_2A   X.......shiiiiii iiiiiinnnnnddddd      Rd Rn    imm(i12,sh)
10890             if ((ins == INS_add) || (ins == INS_sub))
10891             {
10892                 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
10893                 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
10894             }
10895             else
10896             {
10897                 emitDispReg(id->idReg1(), size, true);
10898                 emitDispReg(id->idReg2(), size, true);
10899             }
10900             emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
10901             break;
10902
10903         case IF_DI_2B: // DI_2B   X........X.nnnnn ssssssnnnnnddddd      Rd Rn    imm(0-63)
10904             emitDispReg(id->idReg1(), size, true);
10905             emitDispReg(id->idReg2(), size, true);
10906             emitDispImm(emitGetInsSC(id), false);
10907             break;
10908
10909         case IF_DI_2C: // DI_2C   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imm(N,r,s)
10910             if (ins == INS_ands)
10911             {
10912                 emitDispReg(id->idReg1(), size, true);
10913             }
10914             else
10915             {
10916                 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
10917             }
10918             emitDispReg(id->idReg2(), size, true);
10919             bmi.immNRS = (unsigned)emitGetInsSC(id);
10920             emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
10921             break;
10922
10923         case IF_DI_2D: // DI_2D   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imr, ims   (N,r,s)
10924             emitDispReg(id->idReg1(), size, true);
10925             emitDispReg(id->idReg2(), size, true);
10926
10927             imm        = emitGetInsSC(id);
10928             bmi.immNRS = (unsigned)imm;
10929
10930             switch (ins)
10931             {
10932                 case INS_bfm:
10933                 case INS_sbfm:
10934                 case INS_ubfm:
10935                     emitDispImm(bmi.immR, true);
10936                     emitDispImm(bmi.immS, false);
10937                     break;
10938
10939                 case INS_bfi:
10940                 case INS_sbfiz:
10941                 case INS_ubfiz:
10942                     emitDispImm(getBitWidth(size) - bmi.immR, true);
10943                     emitDispImm(bmi.immS + 1, false);
10944                     break;
10945
10946                 case INS_bfxil:
10947                 case INS_sbfx:
10948                 case INS_ubfx:
10949                     emitDispImm(bmi.immR, true);
10950                     emitDispImm(bmi.immS - bmi.immR + 1, false);
10951                     break;
10952
10953                 case INS_asr:
10954                 case INS_lsr:
10955                 case INS_lsl:
10956                     emitDispImm(imm, false);
10957                     break;
10958
10959                 default:
10960                     assert(!"Unexpected instruction in IF_DI_2D");
10961             }
10962
10963             break;
10964
10965         case IF_DI_1F: // DI_1F   X..........iiiii cccc..nnnnn.nzcv      Rn imm5  nzcv cond
10966             emitDispReg(id->idReg1(), size, true);
10967             cfi.immCFVal = (unsigned)emitGetInsSC(id);
10968             emitDispImm(cfi.imm5, true);
10969             emitDispFlags(cfi.flags);
10970             printf(",");
10971             emitDispCond(cfi.cond);
10972             break;
10973
10974         case IF_DR_1D: // DR_1D   X............... cccc.......mmmmm      Rd       cond
10975             emitDispReg(id->idReg1(), size, true);
10976             cfi.immCFVal = (unsigned)emitGetInsSC(id);
10977             emitDispCond(cfi.cond);
10978             break;
10979
10980         case IF_DR_2A: // DR_2A   X..........mmmmm ......nnnnn.....         Rn Rm
10981             emitDispReg(id->idReg1(), size, true);
10982             emitDispReg(id->idReg2(), size, false);
10983             break;
10984
10985         case IF_DR_2B: // DR_2B   X.......sh.mmmmm ssssssnnnnn.....         Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
10986             emitDispReg(id->idReg1(), size, true);
10987             emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
10988             break;
10989
10990         case IF_DR_2C: // DR_2C   X..........mmmmm ooosssnnnnn.....         Rn Rm ext(Rm) LSL imm(0-4)
10991             emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
10992             imm = emitGetInsSC(id);
10993             emitDispExtendReg(id->idReg2(), id->idInsOpt(), imm);
10994             break;
10995
10996         case IF_DR_2D: // DR_2D   X..........nnnnn cccc..nnnnnddddd      Rd Rn    cond
10997             emitDispReg(id->idReg1(), size, true);
10998             emitDispReg(id->idReg2(), size, true);
10999             cfi.immCFVal = (unsigned)emitGetInsSC(id);
11000             emitDispCond(cfi.cond);
11001             break;
11002
11003         case IF_DR_2E: // DR_2E   X..........mmmmm ...........ddddd      Rd    Rm
11004             emitDispReg(id->idReg1(), size, true);
11005             emitDispReg(id->idReg2(), size, false);
11006             break;
11007
11008         case IF_DR_2F: // DR_2F   X.......sh.mmmmm ssssss.....ddddd      Rd    Rm {LSL,LSR,ASR} imm(0-63)
11009             emitDispReg(id->idReg1(), size, true);
11010             emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
11011             break;
11012
11013         case IF_DR_2G: // DR_2G   X............... ......nnnnnddddd      Rd Rn
11014             emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11015             emitDispReg(encodingZRtoSP(id->idReg2()), size, false);
11016             break;
11017
11018         case IF_DR_2H: // DR_2H   X........X...... ......nnnnnddddd      Rd Rn
11019             emitDispReg(id->idReg1(), size, true);
11020             emitDispReg(id->idReg2(), size, false);
11021             break;
11022
11023         case IF_DR_2I: // DR_2I   X..........mmmmm cccc..nnnnn.nzcv      Rn Rm    nzcv cond
11024             emitDispReg(id->idReg1(), size, true);
11025             emitDispReg(id->idReg2(), size, true);
11026             cfi.immCFVal = (unsigned)emitGetInsSC(id);
11027             emitDispFlags(cfi.flags);
11028             printf(",");
11029             emitDispCond(cfi.cond);
11030             break;
11031
11032         case IF_DR_3A: // DR_3A   X..........mmmmm ......nnnnnmmmmm      Rd Rn Rm
11033             if ((ins == INS_add) || (ins == INS_sub))
11034             {
11035                 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11036                 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11037             }
11038             else if ((ins == INS_smull) || (ins == INS_smulh))
11039             {
11040                 // Rd is always 8 bytes
11041                 emitDispReg(id->idReg1(), EA_8BYTE, true);
11042
11043                 // Rn, Rm effective size depends on instruction type
11044                 size = (ins == INS_smulh) ? EA_8BYTE : EA_4BYTE;
11045                 emitDispReg(id->idReg2(), size, true);
11046             }
11047             else
11048             {
11049                 emitDispReg(id->idReg1(), size, true);
11050                 emitDispReg(id->idReg2(), size, true);
11051             }
11052             if (id->idIsLclVar())
11053             {
11054                 emitDispReg(codeGen->rsGetRsvdReg(), size, false);
11055             }
11056             else
11057             {
11058                 emitDispReg(id->idReg3(), size, false);
11059             }
11060
11061             break;
11062
11063         case IF_DR_3B: // DR_3B   X.......sh.mmmmm ssssssnnnnnddddd      Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
11064             emitDispReg(id->idReg1(), size, true);
11065             emitDispReg(id->idReg2(), size, true);
11066             emitDispShiftedReg(id->idReg3(), id->idInsOpt(), emitGetInsSC(id), size);
11067             break;
11068
11069         case IF_DR_3C: // DR_3C   X..........mmmmm ooosssnnnnnddddd      Rd Rn Rm ext(Rm) LSL imm(0-4)
11070             emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11071             emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11072             imm = emitGetInsSC(id);
11073             emitDispExtendReg(id->idReg3(), id->idInsOpt(), imm);
11074             break;
11075
11076         case IF_DR_3D: // DR_3D   X..........mmmmm cccc..nnnnnmmmmm      Rd Rn Rm cond
11077             emitDispReg(id->idReg1(), size, true);
11078             emitDispReg(id->idReg2(), size, true);
11079             emitDispReg(id->idReg3(), size, true);
11080             cfi.immCFVal = (unsigned)emitGetInsSC(id);
11081             emitDispCond(cfi.cond);
11082             break;
11083
11084         case IF_DR_3E: // DR_3E   X........X.mmmmm ssssssnnnnnddddd      Rd Rn Rm imm(0-63)
11085             emitDispReg(id->idReg1(), size, true);
11086             emitDispReg(id->idReg2(), size, true);
11087             emitDispReg(id->idReg3(), size, true);
11088             emitDispImm(emitGetInsSC(id), false);
11089             break;
11090
11091         case IF_DR_4A: // DR_4A   X..........mmmmm .aaaaannnnnmmmmm      Rd Rn Rm Ra
11092             emitDispReg(id->idReg1(), size, true);
11093             emitDispReg(id->idReg2(), size, true);
11094             emitDispReg(id->idReg3(), size, true);
11095             emitDispReg(id->idReg4(), size, false);
11096             break;
11097
11098         case IF_DV_1A: // DV_1A   .........X.iiiii iii........ddddd      Vd imm8 (fmov - immediate scalar)
11099             elemsize = id->idOpSize();
11100             emitDispReg(id->idReg1(), elemsize, true);
11101             emitDispFloatImm(emitGetInsSC(id));
11102             break;
11103
11104         case IF_DV_1B: // DV_1B   .QX..........iii cmod..iiiiiddddd      Vd imm8 (immediate vector)
11105             imm      = emitGetInsSC(id) & 0x0ff;
11106             immShift = (emitGetInsSC(id) & 0x700) >> 8;
11107             hasShift = (immShift != 0);
11108             elemsize = optGetElemsize(id->idInsOpt());
11109             if (id->idInsOpt() == INS_OPTS_1D)
11110             {
11111                 assert(elemsize == size);
11112                 emitDispReg(id->idReg1(), size, true);
11113             }
11114             else
11115             {
11116                 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11117             }
11118             if (ins == INS_fmov)
11119             {
11120                 emitDispFloatImm(imm);
11121                 assert(hasShift == false);
11122             }
11123             else
11124             {
11125                 if (elemsize == EA_8BYTE)
11126                 {
11127                     assert(ins == INS_movi);
11128                     ssize_t       imm64 = 0;
11129                     const ssize_t mask8 = 0xFF;
11130                     for (unsigned b = 0; b < 8; b++)
11131                     {
11132                         if (imm & (1 << b))
11133                         {
11134                             imm64 |= (mask8 << (b * 8));
11135                         }
11136                     }
11137                     emitDispImm(imm64, hasShift, true);
11138                 }
11139                 else
11140                 {
11141                     emitDispImm(imm, hasShift, true);
11142                 }
11143                 if (hasShift)
11144                 {
11145                     insOpts  opt   = (immShift & 0x4) ? INS_OPTS_MSL : INS_OPTS_LSL;
11146                     unsigned shift = (immShift & 0x3) * 8;
11147                     emitDispShiftOpts(opt);
11148                     emitDispImm(shift, false);
11149                 }
11150             }
11151             break;
11152
11153         case IF_DV_1C: // DV_1C   .........X...... ......nnnnn.....      Vn #0.0 (fcmp - with zero)
11154             elemsize = id->idOpSize();
11155             emitDispReg(id->idReg1(), elemsize, true);
11156             emitDispFloatZero();
11157             break;
11158
11159         case IF_DV_2A: // DV_2A   .Q.......X...... ......nnnnnddddd      Vd Vn   (fabs, fcvt - vector)
11160         case IF_DV_2M: // DV_2M   .Q......XX...... ......nnnnnddddd      Vd Vn   (abs, neg   - vector)
11161             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11162             emitDispVectorReg(id->idReg2(), id->idInsOpt(), false);
11163             break;
11164
11165         case IF_DV_2N: // DV_2N   .........iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - scalar)
11166             elemsize = id->idOpSize();
11167             emitDispReg(id->idReg1(), elemsize, true);
11168             emitDispReg(id->idReg2(), elemsize, true);
11169             emitDispImm(emitGetInsSC(id), false);
11170             break;
11171
11172         case IF_DV_2O: // DV_2O   .Q.......iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - vector)
11173             imm = emitGetInsSC(id);
11174             // Do we have a sxtl or uxtl instruction?
11175             isExtendAlias = ((ins == INS_sxtl) || (ins == INS_sxtl2) || (ins == INS_uxtl) || (ins == INS_uxtl2));
11176             code          = emitInsCode(ins, fmt);
11177             if (code & 0x00008000) // widen/narrow opcodes
11178             {
11179                 if (code & 0x00002000) // SHL opcodes
11180                 {
11181                     emitDispVectorReg(id->idReg1(), optWidenElemsize(id->idInsOpt()), true);
11182                     emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11183                 }
11184                 else // SHR opcodes
11185                 {
11186                     emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11187                     emitDispVectorReg(id->idReg2(), optWidenElemsize(id->idInsOpt()), !isExtendAlias);
11188                 }
11189             }
11190             else
11191             {
11192                 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11193                 emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11194             }
11195             // Print the immediate unless we have a sxtl or uxtl instruction
11196             if (!isExtendAlias)
11197             {
11198                 emitDispImm(imm, false);
11199             }
11200             break;
11201
11202         case IF_DV_2B: // DV_2B   .Q.........iiiii ......nnnnnddddd      Rd Vn[] (umov/smov    - to general)
11203             srcsize = id->idOpSize();
11204             index   = emitGetInsSC(id);
11205             if (ins == INS_smov)
11206             {
11207                 dstsize = EA_8BYTE;
11208             }
11209             else // INS_umov or INS_mov
11210             {
11211                 dstsize = (srcsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE;
11212             }
11213             emitDispReg(id->idReg1(), dstsize, true);
11214             emitDispVectorRegIndex(id->idReg2(), srcsize, index, false);
11215             break;
11216
11217         case IF_DV_2C: // DV_2C   .Q.........iiiii ......nnnnnddddd      Vd Rn   (dup/ins - vector from general)
11218             if (ins == INS_dup)
11219             {
11220                 datasize = id->idOpSize();
11221                 assert(isValidVectorDatasize(datasize));
11222                 assert(isValidArrangement(datasize, id->idInsOpt()));
11223                 elemsize = optGetElemsize(id->idInsOpt());
11224                 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11225             }
11226             else // INS_ins
11227             {
11228                 elemsize = id->idOpSize();
11229                 index    = emitGetInsSC(id);
11230                 assert(isValidVectorElemsize(elemsize));
11231                 emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11232             }
11233             emitDispReg(id->idReg2(), (elemsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE, false);
11234             break;
11235
11236         case IF_DV_2D: // DV_2D   .Q.........iiiii ......nnnnnddddd      Vd Vn[]   (dup - vector)
11237             datasize = id->idOpSize();
11238             assert(isValidVectorDatasize(datasize));
11239             assert(isValidArrangement(datasize, id->idInsOpt()));
11240             elemsize = optGetElemsize(id->idInsOpt());
11241             index    = emitGetInsSC(id);
11242             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11243             emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11244             break;
11245
11246         case IF_DV_2E: // DV_2E   ...........iiiii ......nnnnnddddd      Vd Vn[]   (dup - scalar)
11247             elemsize = id->idOpSize();
11248             index    = emitGetInsSC(id);
11249             emitDispReg(id->idReg1(), elemsize, true);
11250             emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11251             break;
11252
11253         case IF_DV_2F: // DV_2F   ...........iiiii .jjjj.nnnnnddddd      Vd[] Vn[] (ins - element)
11254             imm      = emitGetInsSC(id);
11255             index    = (imm >> 4) & 0xf;
11256             index2   = imm & 0xf;
11257             elemsize = id->idOpSize();
11258             emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11259             emitDispVectorRegIndex(id->idReg2(), elemsize, index2, false);
11260             break;
11261
11262         case IF_DV_2G: // DV_2G   .........X...... ......nnnnnddddd      Vd Vn      (fmov, fcvtXX - register)
11263         case IF_DV_2K: // DV_2K   .........X.mmmmm ......nnnnn.....      Vn Vm      (fcmp)
11264         case IF_DV_2L: // DV_2L   ........XX...... ......nnnnnddddd      Vd Vn      (abs, neg - scalar)
11265             elemsize = id->idOpSize();
11266             emitDispReg(id->idReg1(), elemsize, true);
11267             emitDispReg(id->idReg2(), elemsize, false);
11268             break;
11269
11270         case IF_DV_2H: // DV_2H   X........X...... ......nnnnnddddd      Rd Vn      (fmov, fcvtXX - to general)
11271         case IF_DV_2I: // DV_2I   X........X...... ......nnnnnddddd      Vd Rn      (fmov, Xcvtf - from general)
11272         case IF_DV_2J: // DV_2J   ........SS.....D D.....nnnnnddddd      Vd Vn      (fcvt)
11273             dstsize = optGetDstsize(id->idInsOpt());
11274             srcsize = optGetSrcsize(id->idInsOpt());
11275
11276             emitDispReg(id->idReg1(), dstsize, true);
11277             emitDispReg(id->idReg2(), srcsize, false);
11278             break;
11279
11280         case IF_DV_3A: // DV_3A   .Q......XX.mmmmm ......nnnnnddddd      Vd Vn Vm  (vector)
11281         case IF_DV_3B: // DV_3B   .Q.........mmmmm ......nnnnnddddd      Vd Vn Vm  (vector)
11282             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11283             emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11284             emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11285             break;
11286
11287         case IF_DV_3C: // DV_3C   .Q.........mmmmm ......nnnnnddddd      Vd Vn Vm  (vector)
11288             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11289             if (ins != INS_mov)
11290             {
11291                 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11292             }
11293             emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11294             break;
11295
11296         case IF_DV_3AI: // DV_3AI  .Q......XXLMmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector by elem)
11297         case IF_DV_3BI: // DV_3BI  .Q........Lmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector by elem)
11298             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11299             emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11300             elemsize = optGetElemsize(id->idInsOpt());
11301             emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11302             break;
11303
11304         case IF_DV_3D: // DV_3D   .........X.mmmmm ......nnnnnddddd      Vd Vn Vm  (scalar)
11305         case IF_DV_3E: // DV_3E   ...........mmmmm ......nnnnnddddd      Vd Vn Vm  (scalar)
11306             emitDispReg(id->idReg1(), size, true);
11307             emitDispReg(id->idReg2(), size, true);
11308             emitDispReg(id->idReg3(), size, false);
11309             break;
11310
11311         case IF_DV_3DI: // DV_3DI  .........XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (scalar by elem)
11312             emitDispReg(id->idReg1(), size, true);
11313             emitDispReg(id->idReg2(), size, true);
11314             elemsize = size;
11315             emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11316             break;
11317
11318         case IF_DV_4A: // DV_4A   .........X.mmmmm .aaaaannnnnddddd      Vd Va Vn Vm (scalar)
11319             emitDispReg(id->idReg1(), size, true);
11320             emitDispReg(id->idReg2(), size, true);
11321             emitDispReg(id->idReg3(), size, true);
11322             emitDispReg(id->idReg4(), size, false);
11323             break;
11324
11325         case IF_SN_0A: // SN_0A   ................ ................
11326             break;
11327
11328         case IF_SI_0A: // SI_0A   ...........iiiii iiiiiiiiiii.....               imm16
11329             emitDispImm(emitGetInsSC(id), false);
11330             break;
11331
11332         case IF_SI_0B: // SI_0B   ................ ....bbbb........               imm4 - barrier
11333             emitDispBarrier((insBarrier)emitGetInsSC(id));
11334             break;
11335
11336         default:
11337             printf("unexpected format %s", emitIfName(id->idInsFmt()));
11338             assert(!"unexpectedFormat");
11339             break;
11340     }
11341
11342     if (id->idDebugOnlyInfo()->idVarRefOffs)
11343     {
11344         printf("\t// ");
11345         emitDispFrameRef(id->idAddr()->iiaLclVar.lvaVarNum(), id->idAddr()->iiaLclVar.lvaOffset(),
11346                          id->idDebugOnlyInfo()->idVarRefOffs, asmfm);
11347     }
11348
11349     printf("\n");
11350 }
11351
11352 /*****************************************************************************
11353  *
11354  *  Display a stack frame reference.
11355  */
11356
11357 void emitter::emitDispFrameRef(int varx, int disp, int offs, bool asmfm)
11358 {
11359     printf("[");
11360
11361     if (varx < 0)
11362         printf("TEMP_%02u", -varx);
11363     else
11364         emitComp->gtDispLclVar(+varx, false);
11365
11366     if (disp < 0)
11367         printf("-0x%02x", -disp);
11368     else if (disp > 0)
11369         printf("+0x%02x", +disp);
11370
11371     printf("]");
11372
11373     if (varx >= 0 && emitComp->opts.varNames)
11374     {
11375         LclVarDsc*  varDsc;
11376         const char* varName;
11377
11378         assert((unsigned)varx < emitComp->lvaCount);
11379         varDsc  = emitComp->lvaTable + varx;
11380         varName = emitComp->compLocalVarName(varx, offs);
11381
11382         if (varName)
11383         {
11384             printf("'%s", varName);
11385
11386             if (disp < 0)
11387                 printf("-%d", -disp);
11388             else if (disp > 0)
11389                 printf("+%d", +disp);
11390
11391             printf("'");
11392         }
11393     }
11394 }
11395
11396 #endif // DEBUG
11397
11398 // Generate code for a load or store operation with a potentially complex addressing mode
11399 // This method handles the case of a GT_IND with contained GT_LEA op1 of the x86 form [base + index*sccale + offset]
11400 // Since Arm64 does not directly support this complex of an addressing mode
11401 // we may generates up to three instructions for this for Arm64
11402 //
11403 void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataReg, GenTreeIndir* indir)
11404 {
11405     emitAttr ldstAttr = isVectorRegister(dataReg) ? attr : emitInsAdjustLoadStoreAttr(ins, attr);
11406
11407     GenTree* addr = indir->Addr();
11408
11409     if (addr->isContained())
11410     {
11411         assert(addr->OperGet() == GT_LCL_VAR_ADDR || addr->OperGet() == GT_LEA);
11412
11413         int   offset = 0;
11414         DWORD lsl    = 0;
11415
11416         if (addr->OperGet() == GT_LEA)
11417         {
11418             offset = addr->AsAddrMode()->Offset();
11419             if (addr->AsAddrMode()->gtScale > 0)
11420             {
11421                 assert(isPow2(addr->AsAddrMode()->gtScale));
11422                 BitScanForward(&lsl, addr->AsAddrMode()->gtScale);
11423             }
11424         }
11425
11426         GenTree* memBase = indir->Base();
11427
11428         if (indir->HasIndex())
11429         {
11430             GenTree* index = indir->Index();
11431
11432             if (offset != 0)
11433             {
11434                 regNumber tmpReg = indir->GetSingleTempReg();
11435
11436                 emitAttr addType = varTypeIsGC(memBase) ? EA_BYREF : EA_PTRSIZE;
11437
11438                 if (emitIns_valid_imm_for_add(offset, EA_8BYTE))
11439                 {
11440                     if (lsl > 0)
11441                     {
11442                         // Generate code to set tmpReg = base + index*scale
11443                         emitIns_R_R_R_I(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum, lsl,
11444                                         INS_OPTS_LSL);
11445                     }
11446                     else // no scale
11447                     {
11448                         // Generate code to set tmpReg = base + index
11449                         emitIns_R_R_R(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum);
11450                     }
11451
11452                     noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11453
11454                     // Then load/store dataReg from/to [tmpReg + offset]
11455                     emitIns_R_R_I(ins, ldstAttr, dataReg, tmpReg, offset);
11456                 }
11457                 else // large offset
11458                 {
11459                     // First load/store tmpReg with the large offset constant
11460                     codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11461                     // Then add the base register
11462                     //      rd = rd + base
11463                     emitIns_R_R_R(INS_add, addType, tmpReg, tmpReg, memBase->gtRegNum);
11464
11465                     noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11466                     noway_assert(tmpReg != index->gtRegNum);
11467
11468                     // Then load/store dataReg from/to [tmpReg + index*scale]
11469                     emitIns_R_R_R_I(ins, ldstAttr, dataReg, tmpReg, index->gtRegNum, lsl, INS_OPTS_LSL);
11470                 }
11471             }
11472             else // (offset == 0)
11473             {
11474                 if (lsl > 0)
11475                 {
11476                     // Then load/store dataReg from/to [memBase + index*scale]
11477                     emitIns_R_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum, lsl, INS_OPTS_LSL);
11478                 }
11479                 else // no scale
11480                 {
11481                     // Then load/store dataReg from/to [memBase + index]
11482                     emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum);
11483                 }
11484             }
11485         }
11486         else // no Index register
11487         {
11488             if (emitIns_valid_imm_for_ldst_offset(offset, EA_SIZE(attr)))
11489             {
11490                 // Then load/store dataReg from/to [memBase + offset]
11491                 emitIns_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, offset);
11492             }
11493             else
11494             {
11495                 // We require a tmpReg to hold the offset
11496                 regNumber tmpReg = indir->GetSingleTempReg();
11497
11498                 // First load/store tmpReg with the large offset constant
11499                 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11500
11501                 // Then load/store dataReg from/to [memBase + tmpReg]
11502                 emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, tmpReg);
11503             }
11504         }
11505     }
11506     else // addr is not contained, so we evaluate it into a register
11507     {
11508         // Then load/store dataReg from/to [addrReg]
11509         emitIns_R_R(ins, ldstAttr, dataReg, addr->gtRegNum);
11510     }
11511 }
11512
11513 // Generates an integer data section constant and returns a field handle representing
11514 // the data offset to access the constant via a load instruction.
11515 // This is called during ngen for any relocatable constants
11516 //
11517 CORINFO_FIELD_HANDLE emitter::emitLiteralConst(ssize_t cnsValIn, emitAttr attr /*=EA_8BYTE*/)
11518 {
11519     ssize_t constValue = cnsValIn;
11520     void*   cnsAddr    = &constValue;
11521     bool    dblAlign;
11522
11523     if (attr == EA_4BYTE)
11524     {
11525         dblAlign = false;
11526     }
11527     else
11528     {
11529         assert(attr == EA_8BYTE);
11530         dblAlign = true;
11531     }
11532
11533     // Access to inline data is 'abstracted' by a special type of static member
11534     // (produced by eeFindJitDataOffs) which the emitter recognizes as being a reference
11535     // to constant data, not a real static field.
11536
11537     UNATIVE_OFFSET cnsSize = (attr == EA_4BYTE) ? 4 : 8;
11538     UNATIVE_OFFSET cnum    = emitDataConst(cnsAddr, cnsSize, dblAlign);
11539     return emitComp->eeFindJitDataOffs(cnum);
11540 }
11541
11542 // Generates a float or double data section constant and returns field handle representing
11543 // the data offset to access the constant.  This is called by emitInsBinary() in case
11544 // of contained float of double constants.
11545 CORINFO_FIELD_HANDLE emitter::emitFltOrDblConst(GenTreeDblCon* tree, emitAttr attr /*=EA_UNKNOWN*/)
11546 {
11547     if (attr == EA_UNKNOWN)
11548     {
11549         attr = emitTypeSize(tree->TypeGet());
11550     }
11551     else
11552     {
11553         assert(emitTypeSize(tree->TypeGet()) == attr);
11554     }
11555
11556     double constValue = tree->gtDblCon.gtDconVal;
11557     void*  cnsAddr;
11558     float  f;
11559     bool   dblAlign;
11560
11561     if (attr == EA_4BYTE)
11562     {
11563         f        = forceCastToFloat(constValue);
11564         cnsAddr  = &f;
11565         dblAlign = false;
11566     }
11567     else
11568     {
11569         cnsAddr  = &constValue;
11570         dblAlign = true;
11571     }
11572
11573     // Access to inline data is 'abstracted' by a special type of static member
11574     // (produced by eeFindJitDataOffs) which the emitter recognizes as being a reference
11575     // to constant data, not a real static field.
11576
11577     UNATIVE_OFFSET cnsSize = (attr == EA_4BYTE) ? 4 : 8;
11578     UNATIVE_OFFSET cnum    = emitDataConst(cnsAddr, cnsSize, dblAlign);
11579     return emitComp->eeFindJitDataOffs(cnum);
11580 }
11581
11582 // The callee must call genConsumeReg() for any non-contained srcs
11583 // and genProduceReg() for any non-contained dsts.
11584
11585 regNumber emitter::emitInsBinary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src)
11586 {
11587     regNumber result = REG_NA;
11588
11589     // dst can only be a reg
11590     assert(!dst->isContained());
11591
11592     // src can be immed or reg
11593     assert(!src->isContained() || src->isContainedIntOrIImmed());
11594
11595     // find immed (if any) - it cannot be a dst
11596     GenTreeIntConCommon* intConst = nullptr;
11597     if (src->isContainedIntOrIImmed())
11598     {
11599         intConst = src->AsIntConCommon();
11600     }
11601
11602     if (intConst)
11603     {
11604         emitIns_R_I(ins, attr, dst->gtRegNum, intConst->IconValue());
11605         return dst->gtRegNum;
11606     }
11607     else
11608     {
11609         emitIns_R_R(ins, attr, dst->gtRegNum, src->gtRegNum);
11610         return dst->gtRegNum;
11611     }
11612 }
11613
11614 // The callee must call genConsumeReg() for any non-contained srcs
11615 // and genProduceReg() for any non-contained dsts.
11616
11617 regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src1, GenTree* src2)
11618 {
11619     regNumber result = REG_NA;
11620
11621     // dst can only be a reg
11622     assert(!dst->isContained());
11623
11624     // find immed (if any) - it cannot be a dst
11625     // Only one src can be an int.
11626     GenTreeIntConCommon* intConst  = nullptr;
11627     GenTree*             nonIntReg = nullptr;
11628
11629     if (varTypeIsFloating(dst))
11630     {
11631         // src1 can only be a reg
11632         assert(!src1->isContained());
11633         // src2 can only be a reg
11634         assert(!src2->isContained());
11635     }
11636     else // not floating point
11637     {
11638         // src2 can be immed or reg
11639         assert(!src2->isContained() || src2->isContainedIntOrIImmed());
11640
11641         // Check src2 first as we can always allow it to be a contained immediate
11642         if (src2->isContainedIntOrIImmed())
11643         {
11644             intConst  = src2->AsIntConCommon();
11645             nonIntReg = src1;
11646         }
11647         // Only for commutative operations do we check src1 and allow it to be a contained immediate
11648         else if (dst->OperIsCommutative())
11649         {
11650             // src1 can be immed or reg
11651             assert(!src1->isContained() || src1->isContainedIntOrIImmed());
11652
11653             // Check src1 and allow it to be a contained immediate
11654             if (src1->isContainedIntOrIImmed())
11655             {
11656                 assert(!src2->isContainedIntOrIImmed());
11657                 intConst  = src1->AsIntConCommon();
11658                 nonIntReg = src2;
11659             }
11660         }
11661         else
11662         {
11663             // src1 can only be a reg
11664             assert(!src1->isContained());
11665         }
11666     }
11667
11668     bool isMulOverflow = false;
11669     if (dst->gtOverflowEx())
11670     {
11671         if ((ins == INS_add) || (ins == INS_adds))
11672         {
11673             ins = INS_adds;
11674         }
11675         else if ((ins == INS_sub) || (ins == INS_subs))
11676         {
11677             ins = INS_subs;
11678         }
11679         else if (ins == INS_mul)
11680         {
11681             isMulOverflow = true;
11682             assert(intConst == nullptr); // overflow format doesn't support an int constant operand
11683         }
11684         else
11685         {
11686             assert(!"Invalid ins for overflow check");
11687         }
11688     }
11689     if (intConst != nullptr)
11690     {
11691         emitIns_R_R_I(ins, attr, dst->gtRegNum, nonIntReg->gtRegNum, intConst->IconValue());
11692     }
11693     else
11694     {
11695         if (isMulOverflow)
11696         {
11697             regNumber extraReg = dst->GetSingleTempReg();
11698             assert(extraReg != dst->gtRegNum);
11699
11700             if ((dst->gtFlags & GTF_UNSIGNED) != 0)
11701             {
11702                 if (attr == EA_4BYTE)
11703                 {
11704                     // Compute 8 byte results from 4 byte by 4 byte multiplication.
11705                     emitIns_R_R_R(INS_umull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11706
11707                     // Get the high result by shifting dst.
11708                     emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11709                 }
11710                 else
11711                 {
11712                     assert(attr == EA_8BYTE);
11713                     // Compute the high result.
11714                     emitIns_R_R_R(INS_umulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11715
11716                     // Now multiply without skewing the high result.
11717                     emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11718                 }
11719
11720                 // zero-sign bit comparison to detect overflow.
11721                 emitIns_R_I(INS_cmp, attr, extraReg, 0);
11722             }
11723             else
11724             {
11725                 int bitShift = 0;
11726                 if (attr == EA_4BYTE)
11727                 {
11728                     // Compute 8 byte results from 4 byte by 4 byte multiplication.
11729                     emitIns_R_R_R(INS_smull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11730
11731                     // Get the high result by shifting dst.
11732                     emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11733
11734                     bitShift = 31;
11735                 }
11736                 else
11737                 {
11738                     assert(attr == EA_8BYTE);
11739                     // Save the high result in a temporary register.
11740                     emitIns_R_R_R(INS_smulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11741
11742                     // Now multiply without skewing the high result.
11743                     emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11744
11745                     bitShift = 63;
11746                 }
11747
11748                 // Sign bit comparison to detect overflow.
11749                 emitIns_R_R_I(INS_cmp, attr, extraReg, dst->gtRegNum, bitShift, INS_OPTS_ASR);
11750             }
11751         }
11752         else
11753         {
11754             // We can just multiply.
11755             emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11756         }
11757     }
11758
11759     if (dst->gtOverflowEx())
11760     {
11761         assert(!varTypeIsFloating(dst));
11762         codeGen->genCheckOverflow(dst);
11763     }
11764
11765     return dst->gtRegNum;
11766 }
11767
11768 #endif // defined(_TARGET_ARM64_)