[Arm64] Add compare vector to zero emitters
[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             // size is determined by instruction
3989             if (ins == INS_xtn)
3990             {
3991                 assert(size == EA_8BYTE);
3992             }
3993             else // ins == INS_xtn2
3994             {
3995                 assert(size == EA_16BYTE);
3996             }
3997             assert(elemsize != EA_8BYTE); // Narrowing must not end with 8 byte data
3998             fmt = IF_DV_2M;
3999             break;
4000
4001         case INS_ldar:
4002         case INS_ldaxr:
4003         case INS_ldxr:
4004         case INS_stlr:
4005             assert(isValidGeneralDatasize(size));
4006
4007             __fallthrough;
4008
4009         case INS_ldarb:
4010         case INS_ldaxrb:
4011         case INS_ldxrb:
4012         case INS_ldarh:
4013         case INS_ldaxrh:
4014         case INS_ldxrh:
4015         case INS_stlrb:
4016         case INS_stlrh:
4017             assert(isValidGeneralLSDatasize(size));
4018             assert(isGeneralRegisterOrZR(reg1));
4019             assert(isGeneralRegisterOrSP(reg2));
4020             assert(insOptsNone(opt));
4021
4022             reg2 = encodingSPtoZR(reg2);
4023
4024             fmt = IF_LS_2A;
4025             break;
4026
4027         case INS_ldr:
4028         case INS_ldrb:
4029         case INS_ldrh:
4030         case INS_ldrsb:
4031         case INS_ldrsh:
4032         case INS_ldrsw:
4033         case INS_str:
4034         case INS_strb:
4035         case INS_strh:
4036
4037         case INS_cmp:
4038         case INS_cmn:
4039         case INS_tst:
4040             assert(insOptsNone(opt));
4041             emitIns_R_R_I(ins, attr, reg1, reg2, 0, INS_OPTS_NONE);
4042             return;
4043
4044         case INS_fmov:
4045             assert(isValidVectorElemsizeFloat(size));
4046
4047             // Is the mov even necessary?
4048             if (reg1 == reg2)
4049             {
4050                 return;
4051             }
4052
4053             if (isVectorRegister(reg1))
4054             {
4055                 if (isVectorRegister(reg2))
4056                 {
4057                     assert(insOptsNone(opt));
4058                     fmt = IF_DV_2G;
4059                 }
4060                 else
4061                 {
4062                     assert(isGeneralRegister(reg2));
4063
4064                     // if the optional conversion specifier is not present we calculate it
4065                     if (opt == INS_OPTS_NONE)
4066                     {
4067                         opt = (size == EA_4BYTE) ? INS_OPTS_4BYTE_TO_S : INS_OPTS_8BYTE_TO_D;
4068                     }
4069                     assert(insOptsConvertIntToFloat(opt));
4070
4071                     fmt = IF_DV_2I;
4072                 }
4073             }
4074             else
4075             {
4076                 assert(isGeneralRegister(reg1));
4077                 assert(isVectorRegister(reg2));
4078
4079                 // if the optional conversion specifier is not present we calculate it
4080                 if (opt == INS_OPTS_NONE)
4081                 {
4082                     opt = (size == EA_4BYTE) ? INS_OPTS_S_TO_4BYTE : INS_OPTS_D_TO_8BYTE;
4083                 }
4084                 assert(insOptsConvertFloatToInt(opt));
4085
4086                 fmt = IF_DV_2H;
4087             }
4088             break;
4089
4090         case INS_fcmp:
4091         case INS_fcmpe:
4092             assert(insOptsNone(opt));
4093             assert(isValidVectorElemsizeFloat(size));
4094             assert(isVectorRegister(reg1));
4095             assert(isVectorRegister(reg2));
4096             fmt = IF_DV_2K;
4097             break;
4098
4099         case INS_fcvtns:
4100         case INS_fcvtnu:
4101         case INS_fcvtas:
4102         case INS_fcvtau:
4103         case INS_fcvtps:
4104         case INS_fcvtpu:
4105         case INS_fcvtms:
4106         case INS_fcvtmu:
4107         case INS_fcvtzs:
4108         case INS_fcvtzu:
4109             if (insOptsAnyArrangement(opt))
4110             {
4111                 // Vector operation
4112                 assert(isVectorRegister(reg1));
4113                 assert(isVectorRegister(reg2));
4114                 assert(isValidVectorDatasize(size));
4115                 assert(isValidArrangement(size, opt));
4116                 elemsize = optGetElemsize(opt);
4117                 assert(isValidVectorElemsizeFloat(elemsize));
4118                 assert(opt != INS_OPTS_1D); // Reserved encoding
4119                 fmt = IF_DV_2A;
4120             }
4121             else
4122             {
4123                 // Scalar operation
4124                 assert(isVectorRegister(reg2));
4125                 if (isVectorRegister(reg1))
4126                 {
4127                     assert(insOptsNone(opt));
4128                     assert(isValidVectorElemsizeFloat(size));
4129                     fmt = IF_DV_2G;
4130                 }
4131                 else
4132                 {
4133                     assert(isGeneralRegister(reg1));
4134                     assert(insOptsConvertFloatToInt(opt));
4135                     assert(isValidVectorElemsizeFloat(size));
4136                     fmt = IF_DV_2H;
4137                 }
4138             }
4139             break;
4140
4141         case INS_fcvtl:
4142         case INS_fcvtl2:
4143         case INS_fcvtn:
4144         case INS_fcvtn2:
4145             assert(isVectorRegister(reg1));
4146             assert(isVectorRegister(reg2));
4147             assert(isValidVectorDatasize(size));
4148             assert(insOptsNone(opt));
4149             assert(size == EA_8BYTE); // Narrowing from Double or Widening to Double (Half not supported)
4150             fmt = IF_DV_2G;
4151             break;
4152
4153         case INS_scvtf:
4154         case INS_ucvtf:
4155             if (insOptsAnyArrangement(opt))
4156             {
4157                 // Vector operation
4158                 assert(isVectorRegister(reg1));
4159                 assert(isVectorRegister(reg2));
4160                 assert(isValidVectorDatasize(size));
4161                 assert(isValidArrangement(size, opt));
4162                 elemsize = optGetElemsize(opt);
4163                 assert(isValidVectorElemsizeFloat(elemsize));
4164                 assert(opt != INS_OPTS_1D); // Reserved encoding
4165                 fmt = IF_DV_2A;
4166             }
4167             else
4168             {
4169                 // Scalar operation
4170                 assert(isVectorRegister(reg1));
4171                 if (isVectorRegister(reg2))
4172                 {
4173                     assert(insOptsNone(opt));
4174                     assert(isValidVectorElemsizeFloat(size));
4175                     fmt = IF_DV_2G;
4176                 }
4177                 else
4178                 {
4179                     assert(isGeneralRegister(reg2));
4180                     assert(insOptsConvertIntToFloat(opt));
4181                     assert(isValidVectorElemsizeFloat(size));
4182                     fmt = IF_DV_2I;
4183                 }
4184             }
4185             break;
4186
4187         case INS_fabs:
4188         case INS_fneg:
4189         case INS_fsqrt:
4190         case INS_frinta:
4191         case INS_frinti:
4192         case INS_frintm:
4193         case INS_frintn:
4194         case INS_frintp:
4195         case INS_frintx:
4196         case INS_frintz:
4197             if (insOptsAnyArrangement(opt))
4198             {
4199                 // Vector operation
4200                 assert(isVectorRegister(reg1));
4201                 assert(isVectorRegister(reg2));
4202                 assert(isValidVectorDatasize(size));
4203                 assert(isValidArrangement(size, opt));
4204                 elemsize = optGetElemsize(opt);
4205                 assert(isValidVectorElemsizeFloat(elemsize));
4206                 assert(opt != INS_OPTS_1D); // Reserved encoding
4207                 fmt = IF_DV_2A;
4208             }
4209             else
4210             {
4211                 // Scalar operation
4212                 assert(insOptsNone(opt));
4213                 assert(isValidVectorElemsizeFloat(size));
4214                 assert(isVectorRegister(reg1));
4215                 assert(isVectorRegister(reg2));
4216                 fmt = IF_DV_2G;
4217             }
4218             break;
4219
4220         case INS_faddp:
4221             // Scalar operation
4222             assert(insOptsNone(opt));
4223             assert(isValidVectorElemsizeFloat(size));
4224             assert(isVectorRegister(reg1));
4225             assert(isVectorRegister(reg2));
4226             fmt = IF_DV_2G;
4227             break;
4228
4229         case INS_fcvt:
4230             assert(insOptsConvertFloatToFloat(opt));
4231             assert(isValidVectorFcvtsize(size));
4232             assert(isVectorRegister(reg1));
4233             assert(isVectorRegister(reg2));
4234             fmt = IF_DV_2J;
4235             break;
4236
4237         case INS_cmeq:
4238         case INS_cmge:
4239         case INS_cmgt:
4240         case INS_cmle:
4241         case INS_cmlt:
4242             assert(isVectorRegister(reg1));
4243             assert(isVectorRegister(reg2));
4244
4245             if (isValidVectorDatasize(size))
4246             {
4247                 // Vector operation
4248                 assert(insOptsAnyArrangement(opt));
4249                 assert(isValidArrangement(size, opt));
4250                 elemsize = optGetElemsize(opt);
4251                 fmt      = IF_DV_2M;
4252             }
4253             else
4254             {
4255                 NYI("Untested");
4256                 // Scalar operation
4257                 assert(size == EA_8BYTE); // Only Double supported
4258                 fmt = IF_DV_2L;
4259             }
4260             break;
4261
4262         case INS_fcmeq:
4263         case INS_fcmge:
4264         case INS_fcmgt:
4265         case INS_fcmle:
4266         case INS_fcmlt:
4267             assert(isVectorRegister(reg1));
4268             assert(isVectorRegister(reg2));
4269
4270             if (isValidVectorDatasize(size))
4271             {
4272                 // Vector operation
4273                 assert(insOptsAnyArrangement(opt));
4274                 assert(isValidArrangement(size, opt));
4275                 elemsize = optGetElemsize(opt);
4276                 assert((elemsize == EA_8BYTE) || (elemsize == EA_4BYTE)); // Only Double/Float supported
4277                 assert(opt != INS_OPTS_1D);                               // Reserved encoding
4278                 fmt = IF_DV_2A;
4279             }
4280             else
4281             {
4282                 NYI("Untested");
4283                 // Scalar operation
4284                 assert((size == EA_8BYTE) || (size == EA_4BYTE)); // Only Double/Float supported
4285                 fmt = IF_DV_2G;
4286             }
4287             break;
4288
4289         default:
4290             unreached();
4291             break;
4292
4293     } // end switch (ins)
4294
4295     assert(fmt != IF_NONE);
4296
4297     instrDesc* id = emitNewInstrSmall(attr);
4298
4299     id->idIns(ins);
4300     id->idInsFmt(fmt);
4301     id->idInsOpt(opt);
4302
4303     id->idReg1(reg1);
4304     id->idReg2(reg2);
4305
4306     dispIns(id);
4307     appendToCurIG(id);
4308 }
4309
4310 /*****************************************************************************
4311  *
4312  *  Add an instruction referencing a register and two constants.
4313  */
4314
4315 void emitter::emitIns_R_I_I(
4316     instruction ins, emitAttr attr, regNumber reg, ssize_t imm1, ssize_t imm2, insOpts opt /* = INS_OPTS_NONE */)
4317 {
4318     emitAttr  size   = EA_SIZE(attr);
4319     insFormat fmt    = IF_NONE;
4320     size_t    immOut = 0; // composed from imm1 and imm2 and stored in the instrDesc
4321
4322     /* Figure out the encoding format of the instruction */
4323     switch (ins)
4324     {
4325         bool        canEncode;
4326         halfwordImm hwi;
4327
4328         case INS_mov:
4329             ins = INS_movz; // INS_mov with LSL is an alias for INS_movz LSL
4330             __fallthrough;
4331
4332         case INS_movk:
4333         case INS_movn:
4334         case INS_movz:
4335             assert(isValidGeneralDatasize(size));
4336             assert(isGeneralRegister(reg));
4337             assert(isValidUimm16(imm1));
4338             assert(insOptsLSL(opt)); // Must be INS_OPTS_LSL
4339
4340             if (size == EA_8BYTE)
4341             {
4342                 assert((imm2 == 0) || (imm2 == 16) || // shift amount: 0, 16, 32 or 48
4343                        (imm2 == 32) || (imm2 == 48));
4344             }
4345             else // EA_4BYTE
4346             {
4347                 assert((imm2 == 0) || (imm2 == 16)); // shift amount: 0 or 16
4348             }
4349
4350             hwi.immHWVal = 0;
4351
4352             switch (imm2)
4353             {
4354                 case 0:
4355                     hwi.immHW = 0;
4356                     canEncode = true;
4357                     break;
4358
4359                 case 16:
4360                     hwi.immHW = 1;
4361                     canEncode = true;
4362                     break;
4363
4364                 case 32:
4365                     hwi.immHW = 2;
4366                     canEncode = true;
4367                     break;
4368
4369                 case 48:
4370                     hwi.immHW = 3;
4371                     canEncode = true;
4372                     break;
4373
4374                 default:
4375                     canEncode = false;
4376             }
4377
4378             if (canEncode)
4379             {
4380                 hwi.immVal = imm1;
4381
4382                 immOut = hwi.immHWVal;
4383                 assert(isValidImmHWVal(immOut, size));
4384                 fmt = IF_DI_1B;
4385             }
4386             break;
4387
4388         default:
4389             unreached();
4390             break;
4391
4392     } // end switch (ins)
4393
4394     assert(fmt != IF_NONE);
4395
4396     instrDesc* id = emitNewInstrSC(attr, immOut);
4397
4398     id->idIns(ins);
4399     id->idInsFmt(fmt);
4400
4401     id->idReg1(reg);
4402
4403     dispIns(id);
4404     appendToCurIG(id);
4405 }
4406
4407 /*****************************************************************************
4408  *
4409  *  Add an instruction referencing two registers and a constant.
4410  */
4411
4412 void emitter::emitIns_R_R_I(
4413     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm, insOpts opt /* = INS_OPTS_NONE */)
4414 {
4415     emitAttr  size       = EA_SIZE(attr);
4416     emitAttr  elemsize   = EA_UNKNOWN;
4417     insFormat fmt        = IF_NONE;
4418     bool      isLdSt     = false;
4419     bool      isSIMD     = false;
4420     bool      isAddSub   = false;
4421     bool      setFlags   = false;
4422     unsigned  scale      = 0;
4423     bool      unscaledOp = false;
4424
4425     /* Figure out the encoding format of the instruction */
4426     switch (ins)
4427     {
4428         bool       canEncode;
4429         bitMaskImm bmi;
4430
4431         case INS_mov:
4432             // Check for the 'mov' aliases for the vector registers
4433             assert(insOptsNone(opt));
4434             assert(isValidVectorElemsize(size));
4435             elemsize = size;
4436             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4437
4438             if (isVectorRegister(reg1))
4439             {
4440                 if (isGeneralRegisterOrZR(reg2))
4441                 {
4442                     fmt = IF_DV_2C; // Alias for 'ins'
4443                     break;
4444                 }
4445                 else if (isVectorRegister(reg2))
4446                 {
4447                     fmt = IF_DV_2E; // Alias for 'dup'
4448                     break;
4449                 }
4450             }
4451             else // isGeneralRegister(reg1)
4452             {
4453                 assert(isGeneralRegister(reg1));
4454                 if (isVectorRegister(reg2))
4455                 {
4456                     fmt = IF_DV_2B; // Alias for 'umov'
4457                     break;
4458                 }
4459             }
4460             assert(!" invalid INS_mov operands");
4461             break;
4462
4463         case INS_lsl:
4464         case INS_lsr:
4465         case INS_asr:
4466             assert(insOptsNone(opt));
4467             assert(isValidGeneralDatasize(size));
4468             assert(isGeneralRegister(reg1));
4469             assert(isGeneralRegister(reg2));
4470             assert(isValidImmShift(imm, size));
4471             fmt = IF_DI_2D;
4472             break;
4473
4474         case INS_ror:
4475             assert(insOptsNone(opt));
4476             assert(isValidGeneralDatasize(size));
4477             assert(isGeneralRegister(reg1));
4478             assert(isGeneralRegister(reg2));
4479             assert(isValidImmShift(imm, size));
4480             fmt = IF_DI_2B;
4481             break;
4482
4483         case INS_sshr:
4484         case INS_ssra:
4485         case INS_srshr:
4486         case INS_srsra:
4487         case INS_shl:
4488         case INS_ushr:
4489         case INS_usra:
4490         case INS_urshr:
4491         case INS_ursra:
4492         case INS_sri:
4493         case INS_sli:
4494             assert(isVectorRegister(reg1));
4495             assert(isVectorRegister(reg2));
4496             if (insOptsAnyArrangement(opt))
4497             {
4498                 // Vector operation
4499                 assert(isValidVectorDatasize(size));
4500                 assert(isValidArrangement(size, opt));
4501                 elemsize = optGetElemsize(opt);
4502                 assert(isValidVectorElemsize(elemsize));
4503                 assert(isValidImmShift(imm, elemsize));
4504                 assert(opt != INS_OPTS_1D); // Reserved encoding
4505                 fmt = IF_DV_2O;
4506                 break;
4507             }
4508             else
4509             {
4510                 // Scalar operation
4511                 assert(insOptsNone(opt));
4512                 assert(size == EA_8BYTE); // only supported size
4513                 assert(isValidImmShift(imm, size));
4514                 fmt = IF_DV_2N;
4515             }
4516             break;
4517
4518         case INS_sxtl:
4519         case INS_uxtl:
4520             assert(imm == 0);
4521             __fallthrough;
4522
4523         case INS_shrn:
4524         case INS_rshrn:
4525         case INS_sshll:
4526         case INS_ushll:
4527             assert(isVectorRegister(reg1));
4528             assert(isVectorRegister(reg2));
4529             // Vector operation
4530             assert(size == EA_8BYTE);
4531             assert(isValidArrangement(size, opt));
4532             elemsize = optGetElemsize(opt);
4533             assert(elemsize != EA_8BYTE); // Reserved encodings
4534             assert(isValidVectorElemsize(elemsize));
4535             assert(isValidImmShift(imm, elemsize));
4536             fmt = IF_DV_2O;
4537             break;
4538
4539         case INS_sxtl2:
4540         case INS_uxtl2:
4541             assert(imm == 0);
4542             __fallthrough;
4543
4544         case INS_shrn2:
4545         case INS_rshrn2:
4546         case INS_sshll2:
4547         case INS_ushll2:
4548             assert(isVectorRegister(reg1));
4549             assert(isVectorRegister(reg2));
4550             // Vector operation
4551             assert(size == EA_16BYTE);
4552             assert(isValidArrangement(size, opt));
4553             elemsize = optGetElemsize(opt);
4554             assert(elemsize != EA_8BYTE); // Reserved encodings
4555             assert(isValidVectorElemsize(elemsize));
4556             assert(isValidImmShift(imm, elemsize));
4557             fmt = IF_DV_2O;
4558             break;
4559
4560         case INS_mvn:
4561         case INS_neg:
4562         case INS_negs:
4563             assert(isValidGeneralDatasize(size));
4564             assert(isGeneralRegister(reg1));
4565             assert(isGeneralRegisterOrZR(reg2));
4566
4567             if (imm == 0)
4568             {
4569                 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4570
4571                 fmt = IF_DR_2E;
4572             }
4573             else
4574             {
4575                 if (ins == INS_mvn)
4576                 {
4577                     assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
4578                 }
4579                 else // neg or negs
4580                 {
4581                     assert(insOptsAluShift(opt)); // a non-zero imm, must select shift kind, can't use ROR
4582                 }
4583                 assert(isValidImmShift(imm, size));
4584                 fmt = IF_DR_2F;
4585             }
4586             break;
4587
4588         case INS_tst:
4589             assert(isValidGeneralDatasize(size));
4590             assert(isGeneralRegisterOrZR(reg1));
4591             assert(isGeneralRegister(reg2));
4592
4593             if (insOptsAnyShift(opt))
4594             {
4595                 assert(isValidImmShift(imm, size) && (imm != 0));
4596                 fmt = IF_DR_2B;
4597             }
4598             else
4599             {
4600                 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4601                 assert(imm == 0);
4602                 fmt = IF_DR_2A;
4603             }
4604             break;
4605
4606         case INS_cmp:
4607         case INS_cmn:
4608             assert(isValidGeneralDatasize(size));
4609             assert(isGeneralRegisterOrSP(reg1));
4610             assert(isGeneralRegister(reg2));
4611
4612             reg1 = encodingSPtoZR(reg1);
4613             if (insOptsAnyExtend(opt))
4614             {
4615                 assert((imm >= 0) && (imm <= 4));
4616
4617                 fmt = IF_DR_2C;
4618             }
4619             else if (imm == 0)
4620             {
4621                 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4622
4623                 fmt = IF_DR_2A;
4624             }
4625             else
4626             {
4627                 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
4628                 assert(isValidImmShift(imm, size));
4629                 fmt = IF_DR_2B;
4630             }
4631             break;
4632
4633         case INS_ands:
4634         case INS_and:
4635         case INS_eor:
4636         case INS_orr:
4637             assert(insOptsNone(opt));
4638             assert(isGeneralRegister(reg2));
4639             if (ins == INS_ands)
4640             {
4641                 assert(isGeneralRegister(reg1));
4642             }
4643             else
4644             {
4645                 assert(isGeneralRegisterOrSP(reg1));
4646                 reg1 = encodingSPtoZR(reg1);
4647             }
4648
4649             bmi.immNRS = 0;
4650             canEncode  = canEncodeBitMaskImm(imm, size, &bmi);
4651             if (canEncode)
4652             {
4653                 imm = bmi.immNRS;
4654                 assert(isValidImmNRS(imm, size));
4655                 fmt = IF_DI_2C;
4656             }
4657             break;
4658
4659         case INS_dup: // by element, imm selects the element of reg2
4660             assert(isVectorRegister(reg1));
4661             if (isVectorRegister(reg2))
4662             {
4663                 if (insOptsAnyArrangement(opt))
4664                 {
4665                     // Vector operation
4666                     assert(isValidVectorDatasize(size));
4667                     assert(isValidArrangement(size, opt));
4668                     elemsize = optGetElemsize(opt);
4669                     assert(isValidVectorElemsize(elemsize));
4670                     assert(isValidVectorIndex(size, elemsize, imm));
4671                     assert(opt != INS_OPTS_1D); // Reserved encoding
4672                     fmt = IF_DV_2D;
4673                     break;
4674                 }
4675                 else
4676                 {
4677                     // Scalar operation
4678                     assert(insOptsNone(opt));
4679                     elemsize = size;
4680                     assert(isValidVectorElemsize(elemsize));
4681                     assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4682                     fmt = IF_DV_2E;
4683                     break;
4684                 }
4685             }
4686             __fallthrough;
4687
4688         case INS_ins: // (MOV from general)
4689             assert(insOptsNone(opt));
4690             assert(isValidVectorElemsize(size));
4691             assert(isVectorRegister(reg1));
4692             assert(isGeneralRegisterOrZR(reg2));
4693             elemsize = size;
4694             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4695             fmt = IF_DV_2C;
4696             break;
4697
4698         case INS_umov: // (MOV to general)
4699             assert(insOptsNone(opt));
4700             assert(isValidVectorElemsize(size));
4701             assert(isGeneralRegister(reg1));
4702             assert(isVectorRegister(reg2));
4703             elemsize = size;
4704             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4705             fmt = IF_DV_2B;
4706             break;
4707
4708         case INS_smov:
4709             assert(insOptsNone(opt));
4710             assert(isValidVectorElemsize(size));
4711             assert(size != EA_8BYTE); // no encoding, use INS_umov
4712             assert(isGeneralRegister(reg1));
4713             assert(isVectorRegister(reg2));
4714             elemsize = size;
4715             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4716             fmt = IF_DV_2B;
4717             break;
4718
4719         case INS_add:
4720         case INS_sub:
4721             setFlags = false;
4722             isAddSub = true;
4723             break;
4724
4725         case INS_adds:
4726         case INS_subs:
4727             setFlags = true;
4728             isAddSub = true;
4729             break;
4730
4731         case INS_ldrsb:
4732         case INS_ldursb:
4733             // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4734             assert(isValidGeneralDatasize(size));
4735             unscaledOp = (ins == INS_ldursb);
4736             scale      = 0;
4737             isLdSt     = true;
4738             break;
4739
4740         case INS_ldrsh:
4741         case INS_ldursh:
4742             // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4743             assert(isValidGeneralDatasize(size));
4744             unscaledOp = (ins == INS_ldursh);
4745             scale      = 1;
4746             isLdSt     = true;
4747             break;
4748
4749         case INS_ldrsw:
4750         case INS_ldursw:
4751             // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4752             assert(size == EA_8BYTE);
4753             unscaledOp = (ins == INS_ldursw);
4754             scale      = 2;
4755             isLdSt     = true;
4756             break;
4757
4758         case INS_ldrb:
4759         case INS_strb:
4760             // size is ignored
4761             unscaledOp = false;
4762             scale      = 0;
4763             isLdSt     = true;
4764             break;
4765
4766         case INS_ldurb:
4767         case INS_sturb:
4768             // size is ignored
4769             unscaledOp = true;
4770             scale      = 0;
4771             isLdSt     = true;
4772             break;
4773
4774         case INS_ldrh:
4775         case INS_strh:
4776             // size is ignored
4777             unscaledOp = false;
4778             scale      = 1;
4779             isLdSt     = true;
4780             break;
4781
4782         case INS_ldurh:
4783         case INS_sturh:
4784             // size is ignored
4785             unscaledOp = true;
4786             scale      = 0;
4787             isLdSt     = true;
4788             break;
4789
4790         case INS_ldr:
4791         case INS_str:
4792             // Is the target a vector register?
4793             if (isVectorRegister(reg1))
4794             {
4795                 assert(isValidVectorLSDatasize(size));
4796                 assert(isGeneralRegisterOrSP(reg2));
4797                 isSIMD = true;
4798             }
4799             else
4800             {
4801                 assert(isValidGeneralDatasize(size));
4802             }
4803             unscaledOp = false;
4804             scale      = NaturalScale_helper(size);
4805             isLdSt     = true;
4806             break;
4807
4808         case INS_ldur:
4809         case INS_stur:
4810             // Is the target a vector register?
4811             if (isVectorRegister(reg1))
4812             {
4813                 assert(isValidVectorLSDatasize(size));
4814                 assert(isGeneralRegisterOrSP(reg2));
4815                 isSIMD = true;
4816             }
4817             else
4818             {
4819                 assert(isValidGeneralDatasize(size));
4820             }
4821             unscaledOp = true;
4822             scale      = 0;
4823             isLdSt     = true;
4824             break;
4825
4826         default:
4827             unreached();
4828             break;
4829
4830     } // end switch (ins)
4831
4832     if (isLdSt)
4833     {
4834         assert(!isAddSub);
4835
4836         if (isSIMD)
4837         {
4838             assert(isValidVectorLSDatasize(size));
4839             assert(isVectorRegister(reg1));
4840             assert((scale >= 0) && (scale <= 4));
4841         }
4842         else
4843         {
4844             assert(isValidGeneralLSDatasize(size));
4845             assert(isGeneralRegisterOrZR(reg1));
4846             assert((scale >= 0) && (scale <= 3));
4847         }
4848
4849         assert(isGeneralRegisterOrSP(reg2));
4850
4851         // Load/Store reserved encodings:
4852         if (insOptsIndexed(opt))
4853         {
4854             assert(reg1 != reg2);
4855         }
4856
4857         reg2 = encodingSPtoZR(reg2);
4858
4859         ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
4860         if (imm == 0)
4861         {
4862             assert(insOptsNone(opt)); // PRE/POST Index doesn't make sense with an immediate of zero
4863
4864             fmt = IF_LS_2A;
4865         }
4866         else if (insOptsIndexed(opt) || unscaledOp || (imm < 0) || ((imm & mask) != 0))
4867         {
4868             if ((imm >= -256) && (imm <= 255))
4869             {
4870                 fmt = IF_LS_2C;
4871             }
4872             else
4873             {
4874                 assert(!"Instruction cannot be encoded: IF_LS_2C");
4875             }
4876         }
4877         else if (imm > 0)
4878         {
4879             assert(insOptsNone(opt));
4880             assert(!unscaledOp);
4881
4882             if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
4883             {
4884                 imm >>= scale; // The immediate is scaled by the size of the ld/st
4885
4886                 fmt = IF_LS_2B;
4887             }
4888             else
4889             {
4890                 assert(!"Instruction cannot be encoded: IF_LS_2B");
4891             }
4892         }
4893     }
4894     else if (isAddSub)
4895     {
4896         assert(!isLdSt);
4897         assert(insOptsNone(opt));
4898
4899         if (setFlags) // Can't encode SP with setFlags
4900         {
4901             assert(isGeneralRegister(reg1));
4902             assert(isGeneralRegister(reg2));
4903         }
4904         else
4905         {
4906             assert(isGeneralRegisterOrSP(reg1));
4907             assert(isGeneralRegisterOrSP(reg2));
4908
4909             // Is it just a mov?
4910             if (imm == 0)
4911             {
4912                 // Is the mov even necessary?
4913                 if (reg1 != reg2)
4914                 {
4915                     emitIns_R_R(INS_mov, attr, reg1, reg2);
4916                 }
4917                 return;
4918             }
4919
4920             reg1 = encodingSPtoZR(reg1);
4921             reg2 = encodingSPtoZR(reg2);
4922         }
4923
4924         if (unsigned_abs(imm) <= 0x0fff)
4925         {
4926             if (imm < 0)
4927             {
4928                 ins = insReverse(ins);
4929                 imm = -imm;
4930             }
4931             assert(isValidUimm12(imm));
4932             fmt = IF_DI_2A;
4933         }
4934         else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
4935         {
4936             // Encoding will use a 12-bit left shift of the immediate
4937             opt = INS_OPTS_LSL12;
4938             if (imm < 0)
4939             {
4940                 ins = insReverse(ins);
4941                 imm = -imm;
4942             }
4943             assert((imm & 0xfff) == 0);
4944             imm >>= 12;
4945             assert(isValidUimm12(imm));
4946             fmt = IF_DI_2A;
4947         }
4948         else
4949         {
4950             assert(!"Instruction cannot be encoded: IF_DI_2A");
4951         }
4952     }
4953
4954     assert(fmt != IF_NONE);
4955
4956     instrDesc* id = emitNewInstrSC(attr, imm);
4957
4958     id->idIns(ins);
4959     id->idInsFmt(fmt);
4960     id->idInsOpt(opt);
4961
4962     id->idReg1(reg1);
4963     id->idReg2(reg2);
4964
4965     dispIns(id);
4966     appendToCurIG(id);
4967 }
4968
4969 /*****************************************************************************
4970 *
4971 *  Add an instruction referencing two registers and a constant.
4972 *  Also checks for a large immediate that needs a second instruction
4973 *  and will load it in reg1
4974 *
4975 *  - Supports instructions: add, adds, sub, subs, and, ands, eor and orr
4976 *  - Requires that reg1 is a general register and not SP or ZR
4977 *  - Requires that reg1 != reg2
4978 */
4979 void emitter::emitIns_R_R_Imm(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm)
4980 {
4981     assert(isGeneralRegister(reg1));
4982     assert(reg1 != reg2);
4983
4984     bool immFits = true;
4985
4986     switch (ins)
4987     {
4988         case INS_add:
4989         case INS_adds:
4990         case INS_sub:
4991         case INS_subs:
4992             immFits = emitter::emitIns_valid_imm_for_add(imm, attr);
4993             break;
4994
4995         case INS_ands:
4996         case INS_and:
4997         case INS_eor:
4998         case INS_orr:
4999             immFits = emitter::emitIns_valid_imm_for_alu(imm, attr);
5000             break;
5001
5002         default:
5003             assert(!"Unsupported instruction in emitIns_R_R_Imm");
5004     }
5005
5006     if (immFits)
5007     {
5008         emitIns_R_R_I(ins, attr, reg1, reg2, imm);
5009     }
5010     else
5011     {
5012         // Load 'imm' into the reg1 register
5013         // then issue:   'ins'  reg1, reg2, reg1
5014         //
5015         codeGen->instGen_Set_Reg_To_Imm(attr, reg1, imm);
5016         emitIns_R_R_R(ins, attr, reg1, reg2, reg1);
5017     }
5018 }
5019
5020 /*****************************************************************************
5021  *
5022  *  Add an instruction referencing three registers.
5023  */
5024
5025 void emitter::emitIns_R_R_R(
5026     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insOpts opt) /* = INS_OPTS_NONE */
5027 {
5028     emitAttr  size     = EA_SIZE(attr);
5029     emitAttr  elemsize = EA_UNKNOWN;
5030     insFormat fmt      = IF_NONE;
5031
5032     /* Figure out the encoding format of the instruction */
5033     switch (ins)
5034     {
5035         case INS_lsl:
5036         case INS_lsr:
5037         case INS_asr:
5038         case INS_ror:
5039         case INS_adc:
5040         case INS_adcs:
5041         case INS_sbc:
5042         case INS_sbcs:
5043         case INS_udiv:
5044         case INS_sdiv:
5045         case INS_mneg:
5046         case INS_smull:
5047         case INS_smnegl:
5048         case INS_smulh:
5049         case INS_umull:
5050         case INS_umnegl:
5051         case INS_umulh:
5052         case INS_lslv:
5053         case INS_lsrv:
5054         case INS_asrv:
5055         case INS_rorv:
5056             assert(insOptsNone(opt));
5057             assert(isValidGeneralDatasize(size));
5058             assert(isGeneralRegister(reg1));
5059             assert(isGeneralRegister(reg2));
5060             assert(isGeneralRegister(reg3));
5061             fmt = IF_DR_3A;
5062             break;
5063
5064         case INS_mul:
5065             if (insOptsNone(opt))
5066             {
5067                 // general register
5068                 assert(isValidGeneralDatasize(size));
5069                 assert(isGeneralRegister(reg1));
5070                 assert(isGeneralRegister(reg2));
5071                 assert(isGeneralRegister(reg3));
5072                 fmt = IF_DR_3A;
5073                 break;
5074             }
5075             __fallthrough;
5076
5077         case INS_mla:
5078         case INS_mls:
5079         case INS_pmul:
5080             assert(insOptsAnyArrangement(opt));
5081             assert(isVectorRegister(reg1));
5082             assert(isVectorRegister(reg2));
5083             assert(isVectorRegister(reg3));
5084             assert(isValidVectorDatasize(size));
5085             assert(isValidArrangement(size, opt));
5086             elemsize = optGetElemsize(opt);
5087             if (ins == INS_pmul)
5088             {
5089                 assert(elemsize == EA_1BYTE); // only supports 8B or 16B
5090             }
5091             else // INS_mul, INS_mla, INS_mls
5092             {
5093                 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
5094             }
5095             fmt = IF_DV_3A;
5096             break;
5097
5098         case INS_add:
5099         case INS_sub:
5100             if (isVectorRegister(reg1))
5101             {
5102                 assert(isVectorRegister(reg2));
5103                 assert(isVectorRegister(reg3));
5104
5105                 if (insOptsAnyArrangement(opt))
5106                 {
5107                     // Vector operation
5108                     assert(opt != INS_OPTS_1D); // Reserved encoding
5109                     assert(isValidVectorDatasize(size));
5110                     assert(isValidArrangement(size, opt));
5111                     fmt = IF_DV_3A;
5112                 }
5113                 else
5114                 {
5115                     // Scalar operation
5116                     assert(insOptsNone(opt));
5117                     assert(size == EA_8BYTE);
5118                     fmt = IF_DV_3E;
5119                 }
5120                 break;
5121             }
5122             __fallthrough;
5123
5124         case INS_adds:
5125         case INS_subs:
5126             emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, INS_OPTS_NONE);
5127             return;
5128
5129         case INS_cmeq:
5130         case INS_cmge:
5131         case INS_cmgt:
5132         case INS_cmhi:
5133         case INS_cmhs:
5134         case INS_ctst:
5135             assert(isVectorRegister(reg1));
5136             assert(isVectorRegister(reg2));
5137             assert(isVectorRegister(reg3));
5138
5139             if (isValidVectorDatasize(size))
5140             {
5141                 // Vector operation
5142                 assert(insOptsAnyArrangement(opt));
5143                 assert(isValidArrangement(size, opt));
5144                 elemsize = optGetElemsize(opt);
5145                 fmt      = IF_DV_3A;
5146             }
5147             else
5148             {
5149                 NYI("Untested");
5150                 // Scalar operation
5151                 assert(size == EA_8BYTE); // Only Double supported
5152                 fmt = IF_DV_3E;
5153             }
5154             break;
5155
5156         case INS_fcmeq:
5157         case INS_fcmge:
5158         case INS_fcmgt:
5159             assert(isVectorRegister(reg1));
5160             assert(isVectorRegister(reg2));
5161             assert(isVectorRegister(reg3));
5162
5163             if (isValidVectorDatasize(size))
5164             {
5165                 // Vector operation
5166                 assert(insOptsAnyArrangement(opt));
5167                 assert(isValidArrangement(size, opt));
5168                 elemsize = optGetElemsize(opt);
5169                 assert((elemsize == EA_8BYTE) || (elemsize == EA_4BYTE)); // Only Double/Float supported
5170                 assert(opt != INS_OPTS_1D);                               // Reserved encoding
5171                 fmt = IF_DV_3B;
5172             }
5173             else
5174             {
5175                 NYI("Untested");
5176                 // Scalar operation
5177                 assert((size == EA_8BYTE) || (size == EA_4BYTE)); // Only Double/Float supported
5178                 fmt = IF_DV_3D;
5179             }
5180             break;
5181
5182         case INS_saba:
5183         case INS_sabd:
5184         case INS_smax:
5185         case INS_smin:
5186         case INS_uaba:
5187         case INS_uabd:
5188         case INS_umax:
5189         case INS_umin:
5190             assert(isVectorRegister(reg1));
5191             assert(isVectorRegister(reg2));
5192             assert(isVectorRegister(reg3));
5193             assert(insOptsAnyArrangement(opt));
5194
5195             // Vector operation
5196             assert(isValidVectorDatasize(size));
5197             assert(isValidArrangement(size, opt));
5198             elemsize = optGetElemsize(opt);
5199             assert(elemsize != EA_8BYTE); // can't use 2D or 1D
5200
5201             fmt = IF_DV_3A;
5202             break;
5203
5204         case INS_mov:
5205             assert(isVectorRegister(reg1));
5206             assert(isVectorRegister(reg2));
5207             assert(reg2 == reg3);
5208             assert(isValidVectorDatasize(size));
5209             // INS_mov is an alias for INS_orr (vector register)
5210             if (opt == INS_OPTS_NONE)
5211             {
5212                 elemsize = EA_1BYTE;
5213                 opt      = optMakeArrangement(size, elemsize);
5214             }
5215             assert(isValidArrangement(size, opt));
5216             fmt = IF_DV_3C;
5217             break;
5218
5219         case INS_and:
5220         case INS_bic:
5221         case INS_eor:
5222         case INS_orr:
5223         case INS_orn:
5224             if (isVectorRegister(reg1))
5225             {
5226                 assert(isValidVectorDatasize(size));
5227                 assert(isVectorRegister(reg2));
5228                 assert(isVectorRegister(reg3));
5229                 if (opt == INS_OPTS_NONE)
5230                 {
5231                     elemsize = EA_1BYTE;
5232                     opt      = optMakeArrangement(size, elemsize);
5233                 }
5234                 assert(isValidArrangement(size, opt));
5235                 fmt = IF_DV_3C;
5236                 break;
5237             }
5238             __fallthrough;
5239
5240         case INS_ands:
5241         case INS_bics:
5242         case INS_eon:
5243             emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, INS_OPTS_NONE);
5244             return;
5245
5246         case INS_bsl:
5247         case INS_bit:
5248         case INS_bif:
5249             assert(isValidVectorDatasize(size));
5250             assert(isVectorRegister(reg1));
5251             assert(isVectorRegister(reg2));
5252             assert(isVectorRegister(reg3));
5253             if (opt == INS_OPTS_NONE)
5254             {
5255                 elemsize = EA_1BYTE;
5256                 opt      = optMakeArrangement(size, elemsize);
5257             }
5258             assert(isValidArrangement(size, opt));
5259             fmt = IF_DV_3C;
5260             break;
5261
5262         case INS_fadd:
5263         case INS_fsub:
5264         case INS_fdiv:
5265         case INS_fmax:
5266         case INS_fmin:
5267         case INS_fabd:
5268         case INS_fmul:
5269         case INS_fmulx:
5270             assert(isVectorRegister(reg1));
5271             assert(isVectorRegister(reg2));
5272             assert(isVectorRegister(reg3));
5273             if (insOptsAnyArrangement(opt))
5274             {
5275                 // Vector operation
5276                 assert(isValidVectorDatasize(size));
5277                 assert(isValidArrangement(size, opt));
5278                 elemsize = optGetElemsize(opt);
5279                 assert(isValidVectorElemsizeFloat(elemsize));
5280                 assert(opt != INS_OPTS_1D); // Reserved encoding
5281                 fmt = IF_DV_3B;
5282             }
5283             else
5284             {
5285                 // Scalar operation
5286                 assert(insOptsNone(opt));
5287                 assert(isValidScalarDatasize(size));
5288                 fmt = IF_DV_3D;
5289             }
5290             break;
5291
5292         case INS_fnmul:
5293             // Scalar operation
5294             assert(insOptsNone(opt));
5295             assert(isVectorRegister(reg1));
5296             assert(isVectorRegister(reg2));
5297             assert(isVectorRegister(reg3));
5298             assert(isValidScalarDatasize(size));
5299             fmt = IF_DV_3D;
5300             break;
5301
5302         case INS_faddp:
5303         case INS_fmla:
5304         case INS_fmls:
5305             assert(isVectorRegister(reg1));
5306             assert(isVectorRegister(reg2));
5307             assert(isVectorRegister(reg3));
5308             assert(insOptsAnyArrangement(opt)); // no scalar encoding, use 4-operand 'fmadd' or 'fmsub'
5309
5310             // Vector operation
5311             assert(isValidVectorDatasize(size));
5312             assert(isValidArrangement(size, opt));
5313             elemsize = optGetElemsize(opt);
5314             assert(isValidVectorElemsizeFloat(elemsize));
5315             assert(opt != INS_OPTS_1D); // Reserved encoding
5316             fmt = IF_DV_3B;
5317             break;
5318
5319         case INS_ldr:
5320         case INS_ldrb:
5321         case INS_ldrh:
5322         case INS_ldrsb:
5323         case INS_ldrsh:
5324         case INS_ldrsw:
5325         case INS_str:
5326         case INS_strb:
5327         case INS_strh:
5328             emitIns_R_R_R_Ext(ins, attr, reg1, reg2, reg3, opt);
5329             return;
5330
5331         case INS_ldp:
5332         case INS_ldpsw:
5333         case INS_ldnp:
5334         case INS_stp:
5335         case INS_stnp:
5336             emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0);
5337             return;
5338
5339         case INS_stxr:
5340         case INS_stxrb:
5341         case INS_stxrh:
5342         case INS_stlxr:
5343         case INS_stlxrb:
5344         case INS_stlxrh:
5345             assert(isGeneralRegisterOrZR(reg1));
5346             assert(isGeneralRegisterOrZR(reg2));
5347             assert(isGeneralRegisterOrSP(reg3));
5348             fmt = IF_LS_3D;
5349             break;
5350
5351         default:
5352             unreached();
5353             break;
5354
5355     } // end switch (ins)
5356
5357     assert(fmt != IF_NONE);
5358
5359     instrDesc* id = emitNewInstr(attr);
5360
5361     id->idIns(ins);
5362     id->idInsFmt(fmt);
5363     id->idInsOpt(opt);
5364
5365     id->idReg1(reg1);
5366     id->idReg2(reg2);
5367     id->idReg3(reg3);
5368
5369     dispIns(id);
5370     appendToCurIG(id);
5371 }
5372
5373 /*****************************************************************************
5374  *
5375  *  Add an instruction referencing three registers and a constant.
5376  */
5377
5378 void emitter::emitIns_R_R_R_I(instruction ins,
5379                               emitAttr    attr,
5380                               regNumber   reg1,
5381                               regNumber   reg2,
5382                               regNumber   reg3,
5383                               ssize_t     imm,
5384                               insOpts     opt /* = INS_OPTS_NONE */,
5385                               emitAttr    attrReg2 /* = EA_UNKNOWN */)
5386 {
5387     emitAttr  size     = EA_SIZE(attr);
5388     emitAttr  elemsize = EA_UNKNOWN;
5389     insFormat fmt      = IF_NONE;
5390     bool      isLdSt   = false;
5391     bool      isSIMD   = false;
5392     bool      isAddSub = false;
5393     bool      setFlags = false;
5394     unsigned  scale    = 0;
5395
5396     /* Figure out the encoding format of the instruction */
5397     switch (ins)
5398     {
5399         case INS_extr:
5400             assert(insOptsNone(opt));
5401             assert(isValidGeneralDatasize(size));
5402             assert(isGeneralRegister(reg1));
5403             assert(isGeneralRegister(reg2));
5404             assert(isGeneralRegister(reg3));
5405             assert(isValidImmShift(imm, size));
5406             fmt = IF_DR_3E;
5407             break;
5408
5409         case INS_and:
5410         case INS_ands:
5411         case INS_eor:
5412         case INS_orr:
5413         case INS_bic:
5414         case INS_bics:
5415         case INS_eon:
5416         case INS_orn:
5417             assert(isValidGeneralDatasize(size));
5418             assert(isGeneralRegister(reg1));
5419             assert(isGeneralRegister(reg2));
5420             assert(isGeneralRegister(reg3));
5421             assert(isValidImmShift(imm, size));
5422             if (imm == 0)
5423             {
5424                 assert(insOptsNone(opt)); // a zero imm, means no shift kind
5425                 fmt = IF_DR_3A;
5426             }
5427             else
5428             {
5429                 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
5430                 fmt = IF_DR_3B;
5431             }
5432             break;
5433
5434         case INS_fmul: // by element, imm[0..3] selects the element of reg3
5435         case INS_fmla:
5436         case INS_fmls:
5437         case INS_fmulx:
5438             assert(isVectorRegister(reg1));
5439             assert(isVectorRegister(reg2));
5440             assert(isVectorRegister(reg3));
5441             if (insOptsAnyArrangement(opt))
5442             {
5443                 // Vector operation
5444                 assert(isValidVectorDatasize(size));
5445                 assert(isValidArrangement(size, opt));
5446                 elemsize = optGetElemsize(opt);
5447                 assert(isValidVectorElemsizeFloat(elemsize));
5448                 assert(isValidVectorIndex(size, elemsize, imm));
5449                 assert(opt != INS_OPTS_1D); // Reserved encoding
5450                 fmt = IF_DV_3BI;
5451             }
5452             else
5453             {
5454                 // Scalar operation
5455                 assert(insOptsNone(opt));
5456                 assert(isValidScalarDatasize(size));
5457                 elemsize = size;
5458                 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
5459                 fmt = IF_DV_3DI;
5460             }
5461             break;
5462
5463         case INS_mul: // by element, imm[0..7] selects the element of reg3
5464         case INS_mla:
5465         case INS_mls:
5466             assert(isVectorRegister(reg1));
5467             assert(isVectorRegister(reg2));
5468             assert(isVectorRegister(reg3));
5469             // Vector operation
5470             assert(insOptsAnyArrangement(opt));
5471             assert(isValidVectorDatasize(size));
5472             assert(isValidArrangement(size, opt));
5473             elemsize = optGetElemsize(opt);
5474             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
5475             // Only has encodings for H or S elemsize
5476             assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE));
5477             // Only has encodings for V0..V15
5478             if ((elemsize == EA_2BYTE) && (reg3 >= REG_V16))
5479             {
5480                 noway_assert(!"Invalid reg3");
5481             }
5482             fmt = IF_DV_3AI;
5483             break;
5484
5485         case INS_add:
5486         case INS_sub:
5487             setFlags = false;
5488             isAddSub = true;
5489             break;
5490
5491         case INS_adds:
5492         case INS_subs:
5493             setFlags = true;
5494             isAddSub = true;
5495             break;
5496
5497         case INS_ldpsw:
5498             scale  = 2;
5499             isLdSt = true;
5500             break;
5501
5502         case INS_ldnp:
5503         case INS_stnp:
5504             assert(insOptsNone(opt)); // Can't use Pre/Post index on these two instructions
5505             __fallthrough;
5506
5507         case INS_ldp:
5508         case INS_stp:
5509             // Is the target a vector register?
5510             if (isVectorRegister(reg1))
5511             {
5512                 scale  = NaturalScale_helper(size);
5513                 isSIMD = true;
5514             }
5515             else
5516             {
5517                 scale = (size == EA_8BYTE) ? 3 : 2;
5518             }
5519             isLdSt = true;
5520             break;
5521
5522         default:
5523             unreached();
5524             break;
5525
5526     } // end switch (ins)
5527
5528     if (isLdSt)
5529     {
5530         assert(!isAddSub);
5531         assert(isGeneralRegisterOrSP(reg3));
5532         assert(insOptsNone(opt) || insOptsIndexed(opt));
5533
5534         if (isSIMD)
5535         {
5536             assert(isValidVectorLSPDatasize(size));
5537             assert(isVectorRegister(reg1));
5538             assert(isVectorRegister(reg2));
5539             assert((scale >= 2) && (scale <= 4));
5540         }
5541         else
5542         {
5543             assert(isValidGeneralDatasize(size));
5544             assert(isGeneralRegisterOrZR(reg1));
5545             assert(isGeneralRegisterOrZR(reg2));
5546             assert((scale == 2) || (scale == 3));
5547         }
5548
5549         // Load/Store Pair reserved encodings:
5550         if (emitInsIsLoad(ins))
5551         {
5552             assert(reg1 != reg2);
5553         }
5554         if (insOptsIndexed(opt))
5555         {
5556             assert(reg1 != reg3);
5557             assert(reg2 != reg3);
5558         }
5559
5560         reg3 = encodingSPtoZR(reg3);
5561
5562         ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
5563         if (imm == 0)
5564         {
5565             assert(insOptsNone(opt)); // PRE/POST Index doesn't make sense with an immediate of zero
5566
5567             fmt = IF_LS_3B;
5568         }
5569         else
5570         {
5571             if ((imm & mask) == 0)
5572             {
5573                 imm >>= scale; // The immediate is scaled by the size of the ld/st
5574
5575                 if ((imm >= -64) && (imm <= 63))
5576                 {
5577                     fmt = IF_LS_3C;
5578                 }
5579             }
5580 #ifdef DEBUG
5581             if (fmt != IF_LS_3C)
5582             {
5583                 assert(!"Instruction cannot be encoded: IF_LS_3C");
5584             }
5585 #endif
5586         }
5587     }
5588     else if (isAddSub)
5589     {
5590         bool reg2IsSP = (reg2 == REG_SP);
5591         assert(!isLdSt);
5592         assert(isValidGeneralDatasize(size));
5593         assert(isGeneralRegister(reg3));
5594
5595         if (setFlags || insOptsAluShift(opt)) // Can't encode SP in reg1 with setFlags or AluShift option
5596         {
5597             assert(isGeneralRegisterOrZR(reg1));
5598         }
5599         else
5600         {
5601             assert(isGeneralRegisterOrSP(reg1));
5602             reg1 = encodingSPtoZR(reg1);
5603         }
5604
5605         if (insOptsAluShift(opt)) // Can't encode SP in reg2 with AluShift option
5606         {
5607             assert(isGeneralRegister(reg2));
5608         }
5609         else
5610         {
5611             assert(isGeneralRegisterOrSP(reg2));
5612             reg2 = encodingSPtoZR(reg2);
5613         }
5614
5615         if (insOptsAnyExtend(opt))
5616         {
5617             assert((imm >= 0) && (imm <= 4));
5618
5619             fmt = IF_DR_3C;
5620         }
5621         else if (insOptsAluShift(opt))
5622         {
5623             // imm should be non-zero and in [1..63]
5624             assert(isValidImmShift(imm, size) && (imm != 0));
5625             fmt = IF_DR_3B;
5626         }
5627         else if (imm == 0)
5628         {
5629             assert(insOptsNone(opt));
5630
5631             if (reg2IsSP)
5632             {
5633                 // To encode the SP register as reg2 we must use the IF_DR_3C encoding
5634                 // and also specify a LSL of zero (imm == 0)
5635                 opt = INS_OPTS_LSL;
5636                 fmt = IF_DR_3C;
5637             }
5638             else
5639             {
5640                 fmt = IF_DR_3A;
5641             }
5642         }
5643         else
5644         {
5645             assert(!"Instruction cannot be encoded: Add/Sub IF_DR_3A");
5646         }
5647     }
5648     assert(fmt != IF_NONE);
5649
5650     instrDesc* id = emitNewInstrCns(attr, imm);
5651
5652     id->idIns(ins);
5653     id->idInsFmt(fmt);
5654     id->idInsOpt(opt);
5655
5656     id->idReg1(reg1);
5657     id->idReg2(reg2);
5658     id->idReg3(reg3);
5659
5660     // Record the attribute for the second register in the pair
5661     id->idGCrefReg2(GCT_NONE);
5662     if (attrReg2 != EA_UNKNOWN)
5663     {
5664         // Record the attribute for the second register in the pair
5665         assert((fmt == IF_LS_3B) || (fmt == IF_LS_3C));
5666         if (EA_IS_GCREF(attrReg2))
5667         {
5668             id->idGCrefReg2(GCT_GCREF);
5669         }
5670         else if (EA_IS_BYREF(attrReg2))
5671         {
5672             id->idGCrefReg2(GCT_BYREF);
5673         }
5674     }
5675
5676     dispIns(id);
5677     appendToCurIG(id);
5678 }
5679
5680 /*****************************************************************************
5681  *
5682  *  Add an instruction referencing three registers, with an extend option
5683  */
5684
5685 void emitter::emitIns_R_R_R_Ext(instruction ins,
5686                                 emitAttr    attr,
5687                                 regNumber   reg1,
5688                                 regNumber   reg2,
5689                                 regNumber   reg3,
5690                                 insOpts     opt,         /* = INS_OPTS_NONE */
5691                                 int         shiftAmount) /* = -1 -- unset   */
5692 {
5693     emitAttr  size   = EA_SIZE(attr);
5694     insFormat fmt    = IF_NONE;
5695     bool      isSIMD = false;
5696     int       scale  = -1;
5697
5698     /* Figure out the encoding format of the instruction */
5699     switch (ins)
5700     {
5701         case INS_ldrb:
5702         case INS_ldrsb:
5703         case INS_strb:
5704             scale = 0;
5705             break;
5706
5707         case INS_ldrh:
5708         case INS_ldrsh:
5709         case INS_strh:
5710             scale = 1;
5711             break;
5712
5713         case INS_ldrsw:
5714             scale = 2;
5715             break;
5716
5717         case INS_ldr:
5718         case INS_str:
5719             // Is the target a vector register?
5720             if (isVectorRegister(reg1))
5721             {
5722                 assert(isValidVectorLSDatasize(size));
5723                 scale  = NaturalScale_helper(size);
5724                 isSIMD = true;
5725             }
5726             else
5727             {
5728                 assert(isValidGeneralDatasize(size));
5729                 scale = (size == EA_8BYTE) ? 3 : 2;
5730             }
5731
5732             break;
5733
5734         default:
5735             unreached();
5736             break;
5737
5738     } // end switch (ins)
5739
5740     assert(scale != -1);
5741     assert(insOptsLSExtend(opt));
5742
5743     if (isSIMD)
5744     {
5745         assert(isValidVectorLSDatasize(size));
5746         assert(isVectorRegister(reg1));
5747     }
5748     else
5749     {
5750         assert(isValidGeneralLSDatasize(size));
5751         assert(isGeneralRegisterOrZR(reg1));
5752     }
5753
5754     assert(isGeneralRegisterOrSP(reg2));
5755     assert(isGeneralRegister(reg3));
5756
5757     // Load/Store reserved encodings:
5758     if (insOptsIndexed(opt))
5759     {
5760         assert(reg1 != reg2);
5761     }
5762
5763     if (shiftAmount == -1)
5764     {
5765         shiftAmount = insOptsLSL(opt) ? scale : 0;
5766     }
5767     assert((shiftAmount == scale) || (shiftAmount == 0));
5768
5769     reg2 = encodingSPtoZR(reg2);
5770     fmt  = IF_LS_3A;
5771
5772     instrDesc* id = emitNewInstr(attr);
5773
5774     id->idIns(ins);
5775     id->idInsFmt(fmt);
5776     id->idInsOpt(opt);
5777
5778     id->idReg1(reg1);
5779     id->idReg2(reg2);
5780     id->idReg3(reg3);
5781     id->idReg3Scaled(shiftAmount == scale);
5782
5783     dispIns(id);
5784     appendToCurIG(id);
5785 }
5786
5787 /*****************************************************************************
5788  *
5789  *  Add an instruction referencing two registers and two constants.
5790  */
5791
5792 void emitter::emitIns_R_R_I_I(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, int imm1, int imm2)
5793 {
5794     emitAttr  size     = EA_SIZE(attr);
5795     emitAttr  elemsize = EA_UNKNOWN;
5796     insFormat fmt      = IF_NONE;
5797     size_t    immOut   = 0; // composed from imm1 and imm2 and stored in the instrDesc
5798
5799     /* Figure out the encoding format of the instruction */
5800     switch (ins)
5801     {
5802         int        lsb;
5803         int        width;
5804         bitMaskImm bmi;
5805
5806         case INS_bfm:
5807         case INS_sbfm:
5808         case INS_ubfm:
5809             assert(isGeneralRegister(reg1));
5810             assert(isGeneralRegister(reg2));
5811             assert(isValidImmShift(imm1, size));
5812             assert(isValidImmShift(imm2, size));
5813             bmi.immNRS = 0;
5814             bmi.immN   = (size == EA_8BYTE);
5815             bmi.immR   = imm1;
5816             bmi.immS   = imm2;
5817             immOut     = bmi.immNRS;
5818             fmt        = IF_DI_2D;
5819             break;
5820
5821         case INS_bfi:
5822         case INS_sbfiz:
5823         case INS_ubfiz:
5824             assert(isGeneralRegister(reg1));
5825             assert(isGeneralRegister(reg2));
5826             lsb   = getBitWidth(size) - imm1;
5827             width = imm2 - 1;
5828             assert(isValidImmShift(lsb, size));
5829             assert(isValidImmShift(width, size));
5830             bmi.immNRS = 0;
5831             bmi.immN   = (size == EA_8BYTE);
5832             bmi.immR   = lsb;
5833             bmi.immS   = width;
5834             immOut     = bmi.immNRS;
5835             fmt        = IF_DI_2D;
5836             break;
5837
5838         case INS_bfxil:
5839         case INS_sbfx:
5840         case INS_ubfx:
5841             assert(isGeneralRegister(reg1));
5842             assert(isGeneralRegister(reg2));
5843             lsb   = imm1;
5844             width = imm2 + imm1 - 1;
5845             assert(isValidImmShift(lsb, size));
5846             assert(isValidImmShift(width, size));
5847             bmi.immNRS = 0;
5848             bmi.immN   = (size == EA_8BYTE);
5849             bmi.immR   = imm1;
5850             bmi.immS   = imm2 + imm1 - 1;
5851             immOut     = bmi.immNRS;
5852             fmt        = IF_DI_2D;
5853             break;
5854
5855         case INS_mov:
5856         case INS_ins:
5857             assert(isVectorRegister(reg1));
5858             assert(isVectorRegister(reg2));
5859             elemsize = size;
5860             assert(isValidVectorElemsize(elemsize));
5861             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm1));
5862             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm2));
5863             immOut = (imm1 << 4) + imm2;
5864             fmt    = IF_DV_2F;
5865             break;
5866
5867         default:
5868             unreached();
5869             break;
5870     }
5871     assert(fmt != IF_NONE);
5872
5873     instrDesc* id = emitNewInstrSC(attr, immOut);
5874
5875     id->idIns(ins);
5876     id->idInsFmt(fmt);
5877
5878     id->idReg1(reg1);
5879     id->idReg2(reg2);
5880
5881     dispIns(id);
5882     appendToCurIG(id);
5883 }
5884
5885 /*****************************************************************************
5886  *
5887  *  Add an instruction referencing four registers.
5888  */
5889
5890 void emitter::emitIns_R_R_R_R(
5891     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, regNumber reg4)
5892 {
5893     emitAttr  size = EA_SIZE(attr);
5894     insFormat fmt  = IF_NONE;
5895
5896     /* Figure out the encoding format of the instruction */
5897     switch (ins)
5898     {
5899         case INS_madd:
5900         case INS_msub:
5901         case INS_smaddl:
5902         case INS_smsubl:
5903         case INS_umaddl:
5904         case INS_umsubl:
5905             assert(isValidGeneralDatasize(size));
5906             assert(isGeneralRegister(reg1));
5907             assert(isGeneralRegister(reg2));
5908             assert(isGeneralRegister(reg3));
5909             assert(isGeneralRegister(reg4));
5910             fmt = IF_DR_4A;
5911             break;
5912
5913         case INS_fmadd:
5914         case INS_fmsub:
5915         case INS_fnmadd:
5916         case INS_fnmsub:
5917             // Scalar operation
5918             assert(isValidScalarDatasize(size));
5919             assert(isVectorRegister(reg1));
5920             assert(isVectorRegister(reg2));
5921             assert(isVectorRegister(reg3));
5922             assert(isVectorRegister(reg4));
5923             fmt = IF_DV_4A;
5924             break;
5925
5926         case INS_invalid:
5927             fmt = IF_NONE;
5928             break;
5929
5930         default:
5931             unreached();
5932             break;
5933     }
5934     assert(fmt != IF_NONE);
5935
5936     instrDesc* id = emitNewInstr(attr);
5937
5938     id->idIns(ins);
5939     id->idInsFmt(fmt);
5940
5941     id->idReg1(reg1);
5942     id->idReg2(reg2);
5943     id->idReg3(reg3);
5944     id->idReg4(reg4);
5945
5946     dispIns(id);
5947     appendToCurIG(id);
5948 }
5949
5950 /*****************************************************************************
5951  *
5952  *  Add an instruction referencing a register and a condition code
5953  */
5954
5955 void emitter::emitIns_R_COND(instruction ins, emitAttr attr, regNumber reg, insCond cond)
5956 {
5957     emitAttr     size = EA_SIZE(attr);
5958     insFormat    fmt  = IF_NONE;
5959     condFlagsImm cfi;
5960     cfi.immCFVal = 0;
5961
5962     /* Figure out the encoding format of the instruction */
5963     switch (ins)
5964     {
5965         case INS_cset:
5966         case INS_csetm:
5967             assert(isGeneralRegister(reg));
5968             cfi.cond = cond;
5969             fmt      = IF_DR_1D;
5970             break;
5971
5972         default:
5973             unreached();
5974             break;
5975
5976     } // end switch (ins)
5977
5978     assert(fmt != IF_NONE);
5979     assert(isValidImmCond(cfi.immCFVal));
5980
5981     instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
5982
5983     id->idIns(ins);
5984     id->idInsFmt(fmt);
5985     id->idInsOpt(INS_OPTS_NONE);
5986
5987     id->idReg1(reg);
5988
5989     dispIns(id);
5990     appendToCurIG(id);
5991 }
5992
5993 /*****************************************************************************
5994  *
5995  *  Add an instruction referencing two registers and a condition code
5996  */
5997
5998 void emitter::emitIns_R_R_COND(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insCond cond)
5999 {
6000     emitAttr     size = EA_SIZE(attr);
6001     insFormat    fmt  = IF_NONE;
6002     condFlagsImm cfi;
6003     cfi.immCFVal = 0;
6004
6005     /* Figure out the encoding format of the instruction */
6006     switch (ins)
6007     {
6008         case INS_cinc:
6009         case INS_cinv:
6010         case INS_cneg:
6011             assert(isGeneralRegister(reg1));
6012             assert(isGeneralRegister(reg2));
6013             cfi.cond = cond;
6014             fmt      = IF_DR_2D;
6015             break;
6016         default:
6017             unreached();
6018             break;
6019
6020     } // end switch (ins)
6021
6022     assert(fmt != IF_NONE);
6023     assert(isValidImmCond(cfi.immCFVal));
6024
6025     instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6026
6027     id->idIns(ins);
6028     id->idInsFmt(fmt);
6029     id->idInsOpt(INS_OPTS_NONE);
6030
6031     id->idReg1(reg1);
6032     id->idReg2(reg2);
6033
6034     dispIns(id);
6035     appendToCurIG(id);
6036 }
6037
6038 /*****************************************************************************
6039  *
6040  *  Add an instruction referencing two registers and a condition code
6041  */
6042
6043 void emitter::emitIns_R_R_R_COND(
6044     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insCond cond)
6045 {
6046     emitAttr     size = EA_SIZE(attr);
6047     insFormat    fmt  = IF_NONE;
6048     condFlagsImm cfi;
6049     cfi.immCFVal = 0;
6050
6051     /* Figure out the encoding format of the instruction */
6052     switch (ins)
6053     {
6054         case INS_csel:
6055         case INS_csinc:
6056         case INS_csinv:
6057         case INS_csneg:
6058             assert(isGeneralRegister(reg1));
6059             assert(isGeneralRegister(reg2));
6060             assert(isGeneralRegister(reg3));
6061             cfi.cond = cond;
6062             fmt      = IF_DR_3D;
6063             break;
6064
6065         default:
6066             unreached();
6067             break;
6068
6069     } // end switch (ins)
6070
6071     assert(fmt != IF_NONE);
6072     assert(isValidImmCond(cfi.immCFVal));
6073
6074     instrDesc* id = emitNewInstr(attr);
6075
6076     id->idIns(ins);
6077     id->idInsFmt(fmt);
6078     id->idInsOpt(INS_OPTS_NONE);
6079
6080     id->idReg1(reg1);
6081     id->idReg2(reg2);
6082     id->idReg3(reg3);
6083     id->idSmallCns(cfi.immCFVal);
6084
6085     dispIns(id);
6086     appendToCurIG(id);
6087 }
6088
6089 /*****************************************************************************
6090  *
6091  *  Add an instruction referencing two registers the flags and a condition code
6092  */
6093
6094 void emitter::emitIns_R_R_FLAGS_COND(
6095     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insCflags flags, insCond cond)
6096 {
6097     emitAttr     size = EA_SIZE(attr);
6098     insFormat    fmt  = IF_NONE;
6099     condFlagsImm cfi;
6100     cfi.immCFVal = 0;
6101
6102     /* Figure out the encoding format of the instruction */
6103     switch (ins)
6104     {
6105         case INS_ccmp:
6106         case INS_ccmn:
6107             assert(isGeneralRegister(reg1));
6108             assert(isGeneralRegister(reg2));
6109             cfi.flags = flags;
6110             cfi.cond  = cond;
6111             fmt       = IF_DR_2I;
6112             break;
6113         default:
6114             unreached();
6115             break;
6116     } // end switch (ins)
6117
6118     assert(fmt != IF_NONE);
6119     assert(isValidImmCondFlags(cfi.immCFVal));
6120
6121     instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6122
6123     id->idIns(ins);
6124     id->idInsFmt(fmt);
6125     id->idInsOpt(INS_OPTS_NONE);
6126
6127     id->idReg1(reg1);
6128     id->idReg2(reg2);
6129
6130     dispIns(id);
6131     appendToCurIG(id);
6132 }
6133
6134 /*****************************************************************************
6135  *
6136  *  Add an instruction referencing a register, an immediate, the flags and a condition code
6137  */
6138
6139 void emitter::emitIns_R_I_FLAGS_COND(
6140     instruction ins, emitAttr attr, regNumber reg, int imm, insCflags flags, insCond cond)
6141 {
6142     emitAttr     size = EA_SIZE(attr);
6143     insFormat    fmt  = IF_NONE;
6144     condFlagsImm cfi;
6145     cfi.immCFVal = 0;
6146
6147     /* Figure out the encoding format of the instruction */
6148     switch (ins)
6149     {
6150         case INS_ccmp:
6151         case INS_ccmn:
6152             assert(isGeneralRegister(reg));
6153             if (imm < 0)
6154             {
6155                 ins = insReverse(ins);
6156                 imm = -imm;
6157             }
6158             if ((imm >= 0) && (imm <= 31))
6159             {
6160                 cfi.imm5  = imm;
6161                 cfi.flags = flags;
6162                 cfi.cond  = cond;
6163                 fmt       = IF_DI_1F;
6164             }
6165             else
6166             {
6167                 assert(!"Instruction cannot be encoded: ccmp/ccmn imm5");
6168             }
6169             break;
6170         default:
6171             unreached();
6172             break;
6173     } // end switch (ins)
6174
6175     assert(fmt != IF_NONE);
6176     assert(isValidImmCondFlagsImm5(cfi.immCFVal));
6177
6178     instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6179
6180     id->idIns(ins);
6181     id->idInsFmt(fmt);
6182     id->idInsOpt(INS_OPTS_NONE);
6183
6184     id->idReg1(reg);
6185
6186     dispIns(id);
6187     appendToCurIG(id);
6188 }
6189
6190 /*****************************************************************************
6191  *
6192  *  Add a memory barrier instruction with a 'barrier' immediate
6193  */
6194
6195 void emitter::emitIns_BARR(instruction ins, insBarrier barrier)
6196 {
6197     insFormat fmt = IF_NONE;
6198     ssize_t   imm = 0;
6199
6200     /* Figure out the encoding format of the instruction */
6201     switch (ins)
6202     {
6203         case INS_dsb:
6204         case INS_dmb:
6205         case INS_isb:
6206
6207             fmt = IF_SI_0B;
6208             imm = (ssize_t)barrier;
6209             break;
6210         default:
6211             unreached();
6212             break;
6213     } // end switch (ins)
6214
6215     assert(fmt != IF_NONE);
6216
6217     instrDesc* id = emitNewInstrSC(EA_8BYTE, imm);
6218
6219     id->idIns(ins);
6220     id->idInsFmt(fmt);
6221     id->idInsOpt(INS_OPTS_NONE);
6222
6223     dispIns(id);
6224     appendToCurIG(id);
6225 }
6226
6227 /*****************************************************************************
6228  *
6229  *  Add an instruction with a static data member operand. If 'size' is 0, the
6230  *  instruction operates on the address of the static member instead of its
6231  *  value (e.g. "push offset clsvar", rather than "push dword ptr [clsvar]").
6232  */
6233
6234 void emitter::emitIns_C(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, int offs)
6235 {
6236     NYI("emitIns_C");
6237 }
6238
6239 /*****************************************************************************
6240  *
6241  *  Add an instruction referencing stack-based local variable.
6242  */
6243
6244 void emitter::emitIns_S(instruction ins, emitAttr attr, int varx, int offs)
6245 {
6246     NYI("emitIns_S");
6247 }
6248
6249 /*****************************************************************************
6250  *
6251  *  Add an instruction referencing a register and a stack-based local variable.
6252  */
6253 void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
6254 {
6255     emitAttr  size  = EA_SIZE(attr);
6256     insFormat fmt   = IF_NONE;
6257     int       disp  = 0;
6258     unsigned  scale = 0;
6259
6260     assert(offs >= 0);
6261
6262     // TODO-ARM64-CQ: use unscaled loads?
6263     /* Figure out the encoding format of the instruction */
6264     switch (ins)
6265     {
6266         case INS_strb:
6267         case INS_ldrb:
6268         case INS_ldrsb:
6269             scale = 0;
6270             break;
6271
6272         case INS_strh:
6273         case INS_ldrh:
6274         case INS_ldrsh:
6275             scale = 1;
6276             break;
6277
6278         case INS_ldrsw:
6279             scale = 2;
6280             break;
6281
6282         case INS_str:
6283         case INS_ldr:
6284             assert(isValidGeneralDatasize(size) || isValidVectorDatasize(size));
6285             scale = genLog2(EA_SIZE_IN_BYTES(size));
6286             break;
6287
6288         case INS_lea:
6289             assert(size == EA_8BYTE);
6290             scale = 0;
6291             break;
6292
6293         default:
6294             NYI("emitIns_R_S"); // FP locals?
6295             return;
6296
6297     } // end switch (ins)
6298
6299     /* Figure out the variable's frame position */
6300     ssize_t imm;
6301     int     base;
6302     bool    FPbased;
6303
6304     base = emitComp->lvaFrameAddress(varx, &FPbased);
6305     disp = base + offs;
6306     assert((scale >= 0) && (scale <= 4));
6307
6308     regNumber reg2 = FPbased ? REG_FPBASE : REG_SPBASE;
6309     reg2           = encodingSPtoZR(reg2);
6310
6311     if (ins == INS_lea)
6312     {
6313         if (disp >= 0)
6314         {
6315             ins = INS_add;
6316             imm = disp;
6317         }
6318         else
6319         {
6320             ins = INS_sub;
6321             imm = -disp;
6322         }
6323
6324         if (imm <= 0x0fff)
6325         {
6326             fmt = IF_DI_2A; // add reg1,reg2,#disp
6327         }
6328         else
6329         {
6330             regNumber rsvdReg = codeGen->rsGetRsvdReg();
6331             codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6332             fmt = IF_DR_3A; // add reg1,reg2,rsvdReg
6333         }
6334     }
6335     else
6336     {
6337         bool    useRegForImm = false;
6338         ssize_t mask         = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6339
6340         imm = disp;
6341         if (imm == 0)
6342         {
6343             fmt = IF_LS_2A;
6344         }
6345         else if ((imm < 0) || ((imm & mask) != 0))
6346         {
6347             if ((imm >= -256) && (imm <= 255))
6348             {
6349                 fmt = IF_LS_2C;
6350             }
6351             else
6352             {
6353                 useRegForImm = true;
6354             }
6355         }
6356         else if (imm > 0)
6357         {
6358             if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
6359             {
6360                 imm >>= scale; // The immediate is scaled by the size of the ld/st
6361
6362                 fmt = IF_LS_2B;
6363             }
6364             else
6365             {
6366                 useRegForImm = true;
6367             }
6368         }
6369
6370         if (useRegForImm)
6371         {
6372             regNumber rsvdReg = codeGen->rsGetRsvdReg();
6373             codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6374             fmt = IF_LS_3A;
6375         }
6376     }
6377
6378     assert(fmt != IF_NONE);
6379
6380     instrDesc* id = emitNewInstrCns(attr, imm);
6381
6382     id->idIns(ins);
6383     id->idInsFmt(fmt);
6384     id->idInsOpt(INS_OPTS_NONE);
6385
6386     id->idReg1(reg1);
6387     id->idReg2(reg2);
6388     id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6389     id->idSetIsLclVar();
6390
6391 #ifdef DEBUG
6392     id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6393 #endif
6394
6395     dispIns(id);
6396     appendToCurIG(id);
6397 }
6398
6399 /*****************************************************************************
6400  *
6401  *  Add an instruction referencing two register and consectutive stack-based local variable slots.
6402  */
6403 void emitter::emitIns_R_R_S_S(
6404     instruction ins, emitAttr attr1, emitAttr attr2, regNumber reg1, regNumber reg2, int varx, int offs)
6405 {
6406     assert((ins == INS_ldp) || (ins == INS_ldnp));
6407     assert(EA_8BYTE == EA_SIZE(attr1));
6408     assert(EA_8BYTE == EA_SIZE(attr2));
6409     assert(isGeneralRegisterOrZR(reg1));
6410     assert(isGeneralRegisterOrZR(reg2));
6411     assert(offs >= 0);
6412
6413     insFormat      fmt   = IF_LS_3B;
6414     int            disp  = 0;
6415     const unsigned scale = 3;
6416
6417     /* Figure out the variable's frame position */
6418     int  base;
6419     bool FPbased;
6420
6421     base = emitComp->lvaFrameAddress(varx, &FPbased);
6422     disp = base + offs;
6423
6424     // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6425     regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE;
6426     reg3           = encodingSPtoZR(reg3);
6427
6428     bool    useRegForAdr = true;
6429     ssize_t imm          = disp;
6430     ssize_t mask         = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6431     if (imm == 0)
6432     {
6433         useRegForAdr = false;
6434     }
6435     else
6436     {
6437         if ((imm & mask) == 0)
6438         {
6439             ssize_t immShift = imm >> scale; // The immediate is scaled by the size of the ld/st
6440
6441             if ((immShift >= -64) && (immShift <= 63))
6442             {
6443                 fmt          = IF_LS_3C;
6444                 useRegForAdr = false;
6445                 imm          = immShift;
6446             }
6447         }
6448     }
6449
6450     if (useRegForAdr)
6451     {
6452         regNumber rsvd = codeGen->rsGetRsvdReg();
6453         emitIns_R_R_Imm(INS_add, EA_PTRSIZE, rsvd, reg3, imm);
6454         reg3 = rsvd;
6455         imm  = 0;
6456     }
6457
6458     assert(fmt != IF_NONE);
6459
6460     instrDesc* id = emitNewInstrCns(attr1, imm);
6461
6462     id->idIns(ins);
6463     id->idInsFmt(fmt);
6464     id->idInsOpt(INS_OPTS_NONE);
6465
6466     // Record the attribute for the second register in the pair
6467     if (EA_IS_GCREF(attr2))
6468     {
6469         id->idGCrefReg2(GCT_GCREF);
6470     }
6471     else if (EA_IS_BYREF(attr2))
6472     {
6473         id->idGCrefReg2(GCT_BYREF);
6474     }
6475     else
6476     {
6477         id->idGCrefReg2(GCT_NONE);
6478     }
6479
6480     id->idReg1(reg1);
6481     id->idReg2(reg2);
6482     id->idReg3(reg3);
6483     id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6484     id->idSetIsLclVar();
6485
6486 #ifdef DEBUG
6487     id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6488 #endif
6489
6490     dispIns(id);
6491     appendToCurIG(id);
6492 }
6493
6494 /*****************************************************************************
6495  *
6496  *  Add an instruction referencing a stack-based local variable and a register
6497  */
6498 void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
6499 {
6500     assert(offs >= 0);
6501     emitAttr  size          = EA_SIZE(attr);
6502     insFormat fmt           = IF_NONE;
6503     int       disp          = 0;
6504     unsigned  scale         = 0;
6505     bool      isVectorStore = false;
6506
6507     // TODO-ARM64-CQ: use unscaled loads?
6508     /* Figure out the encoding format of the instruction */
6509     switch (ins)
6510     {
6511         case INS_strb:
6512             scale = 0;
6513             assert(isGeneralRegisterOrZR(reg1));
6514             break;
6515
6516         case INS_strh:
6517             scale = 1;
6518             assert(isGeneralRegisterOrZR(reg1));
6519             break;
6520
6521         case INS_str:
6522             if (isGeneralRegisterOrZR(reg1))
6523             {
6524                 assert(isValidGeneralDatasize(size));
6525                 scale = (size == EA_8BYTE) ? 3 : 2;
6526             }
6527             else
6528             {
6529                 assert(isVectorRegister(reg1));
6530                 assert(isValidVectorLSDatasize(size));
6531                 scale         = NaturalScale_helper(size);
6532                 isVectorStore = true;
6533             }
6534             break;
6535
6536         default:
6537             NYI("emitIns_S_R"); // FP locals?
6538             return;
6539
6540     } // end switch (ins)
6541
6542     /* Figure out the variable's frame position */
6543     int  base;
6544     bool FPbased;
6545
6546     base = emitComp->lvaFrameAddress(varx, &FPbased);
6547     disp = base + offs;
6548     assert(scale >= 0);
6549     if (isVectorStore)
6550     {
6551         assert(scale <= 4);
6552     }
6553     else
6554     {
6555         assert(scale <= 3);
6556     }
6557
6558     // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6559     regNumber reg2 = FPbased ? REG_FPBASE : REG_SPBASE;
6560     reg2           = encodingSPtoZR(reg2);
6561
6562     bool    useRegForImm = false;
6563     ssize_t imm          = disp;
6564     ssize_t mask         = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6565     if (imm == 0)
6566     {
6567         fmt = IF_LS_2A;
6568     }
6569     else if ((imm < 0) || ((imm & mask) != 0))
6570     {
6571         if ((imm >= -256) && (imm <= 255))
6572         {
6573             fmt = IF_LS_2C;
6574         }
6575         else
6576         {
6577             useRegForImm = true;
6578         }
6579     }
6580     else if (imm > 0)
6581     {
6582         if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
6583         {
6584             imm >>= scale; // The immediate is scaled by the size of the ld/st
6585
6586             fmt = IF_LS_2B;
6587         }
6588         else
6589         {
6590             useRegForImm = true;
6591         }
6592     }
6593
6594     if (useRegForImm)
6595     {
6596         // The reserved register is not stored in idReg3() since that field overlaps with iiaLclVar.
6597         // It is instead implicit when idSetIsLclVar() is set, with this encoding format.
6598         regNumber rsvdReg = codeGen->rsGetRsvdReg();
6599         codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6600         fmt = IF_LS_3A;
6601     }
6602
6603     assert(fmt != IF_NONE);
6604
6605     instrDesc* id = emitNewInstrCns(attr, imm);
6606
6607     id->idIns(ins);
6608     id->idInsFmt(fmt);
6609     id->idInsOpt(INS_OPTS_NONE);
6610
6611     id->idReg1(reg1);
6612     id->idReg2(reg2);
6613     id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6614     id->idSetIsLclVar();
6615
6616 #ifdef DEBUG
6617     id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6618 #endif
6619
6620     dispIns(id);
6621     appendToCurIG(id);
6622 }
6623
6624 /*****************************************************************************
6625  *
6626  *  Add an instruction referencing consecutive stack-based local variable slots and two registers
6627  */
6628 void emitter::emitIns_S_S_R_R(
6629     instruction ins, emitAttr attr1, emitAttr attr2, regNumber reg1, regNumber reg2, int varx, int offs)
6630 {
6631     assert((ins == INS_stp) || (ins == INS_stnp));
6632     assert(EA_8BYTE == EA_SIZE(attr1));
6633     assert(EA_8BYTE == EA_SIZE(attr2));
6634     assert(isGeneralRegisterOrZR(reg1));
6635     assert(isGeneralRegisterOrZR(reg2));
6636     assert(offs >= 0);
6637
6638     insFormat      fmt   = IF_LS_3B;
6639     int            disp  = 0;
6640     const unsigned scale = 3;
6641
6642     /* Figure out the variable's frame position */
6643     int  base;
6644     bool FPbased;
6645
6646     base = emitComp->lvaFrameAddress(varx, &FPbased);
6647     disp = base + offs;
6648
6649     // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6650     regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE;
6651     reg3           = encodingSPtoZR(reg3);
6652
6653     bool    useRegForAdr = true;
6654     ssize_t imm          = disp;
6655     ssize_t mask         = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6656     if (imm == 0)
6657     {
6658         useRegForAdr = false;
6659     }
6660     else
6661     {
6662         if ((imm & mask) == 0)
6663         {
6664             ssize_t immShift = imm >> scale; // The immediate is scaled by the size of the ld/st
6665
6666             if ((immShift >= -64) && (immShift <= 63))
6667             {
6668                 fmt          = IF_LS_3C;
6669                 useRegForAdr = false;
6670                 imm          = immShift;
6671             }
6672         }
6673     }
6674
6675     if (useRegForAdr)
6676     {
6677         regNumber rsvd = codeGen->rsGetRsvdReg();
6678         emitIns_R_R_Imm(INS_add, EA_PTRSIZE, rsvd, reg3, imm);
6679         reg3 = rsvd;
6680         imm  = 0;
6681     }
6682
6683     assert(fmt != IF_NONE);
6684
6685     instrDesc* id = emitNewInstrCns(attr1, imm);
6686
6687     id->idIns(ins);
6688     id->idInsFmt(fmt);
6689     id->idInsOpt(INS_OPTS_NONE);
6690
6691     // Record the attribute for the second register in the pair
6692     if (EA_IS_GCREF(attr2))
6693     {
6694         id->idGCrefReg2(GCT_GCREF);
6695     }
6696     else if (EA_IS_BYREF(attr2))
6697     {
6698         id->idGCrefReg2(GCT_BYREF);
6699     }
6700     else
6701     {
6702         id->idGCrefReg2(GCT_NONE);
6703     }
6704
6705     id->idReg1(reg1);
6706     id->idReg2(reg2);
6707     id->idReg3(reg3);
6708     id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6709     id->idSetIsLclVar();
6710
6711 #ifdef DEBUG
6712     id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6713 #endif
6714
6715     dispIns(id);
6716     appendToCurIG(id);
6717 }
6718
6719 /*****************************************************************************
6720  *
6721  *  Add an instruction referencing stack-based local variable and an immediate
6722  */
6723 void emitter::emitIns_S_I(instruction ins, emitAttr attr, int varx, int offs, int val)
6724 {
6725     NYI("emitIns_S_I");
6726 }
6727
6728 /*****************************************************************************
6729  *
6730  *  Add an instruction with a register + static member operands.
6731  *  Constant is stored into JIT data which is adjacent to code.
6732  *  No relocation is needed. PC-relative offset will be encoded directly into instruction.
6733  *
6734  */
6735 void emitter::emitIns_R_C(
6736     instruction ins, emitAttr attr, regNumber reg, regNumber addrReg, CORINFO_FIELD_HANDLE fldHnd, int offs)
6737 {
6738     assert(offs >= 0);
6739     assert(instrDesc::fitsInSmallCns(offs));
6740
6741     emitAttr      size = EA_SIZE(attr);
6742     insFormat     fmt  = IF_NONE;
6743     int           disp = 0;
6744     instrDescJmp* id   = emitNewInstrJmp();
6745
6746     switch (ins)
6747     {
6748         case INS_adr:
6749             // This is case to get address to the constant data.
6750             fmt = IF_LARGEADR;
6751             assert(isGeneralRegister(reg));
6752             assert(isValidGeneralDatasize(size));
6753             break;
6754
6755         case INS_ldr:
6756             fmt = IF_LARGELDC;
6757             if (isVectorRegister(reg))
6758             {
6759                 assert(isValidScalarDatasize(size));
6760                 // For vector (float/double) register, we should have an integer address reg to
6761                 // compute long address which consists of page address and page offset.
6762                 // For integer constant, this is not needed since the dest reg can be used to
6763                 // compute address as well as contain the final contents.
6764                 assert(isGeneralRegister(reg) || (addrReg != REG_NA));
6765             }
6766             else
6767             {
6768                 assert(isGeneralRegister(reg));
6769                 assert(isValidGeneralDatasize(size));
6770             }
6771             break;
6772         default:
6773             unreached();
6774     }
6775
6776     assert(fmt != IF_NONE);
6777
6778     id->idIns(ins);
6779     id->idInsFmt(fmt);
6780     id->idInsOpt(INS_OPTS_NONE);
6781     id->idSmallCns(offs);
6782     id->idOpSize(size);
6783     id->idAddr()->iiaFieldHnd = fldHnd;
6784     id->idSetIsBound(); // We won't patch address since we will know the exact distance once JIT code and data are
6785                         // allocated together.
6786
6787     id->idReg1(reg); // destination register that will get the constant value.
6788     if (addrReg != REG_NA)
6789     {
6790         id->idReg2(addrReg); // integer register to compute long address (used for vector dest when we end up with long
6791                              // address)
6792     }
6793     id->idjShort = false; // Assume loading constant from long address
6794
6795     // Keep it long if it's in cold code.
6796     id->idjKeepLong = emitComp->fgIsBlockCold(emitComp->compCurBB);
6797
6798 #ifdef DEBUG
6799     if (emitComp->opts.compLongAddress)
6800         id->idjKeepLong = 1;
6801 #endif // DEBUG
6802
6803     // If it's possible to be shortened, then put it in jump list
6804     // to be revisited by emitJumpDistBind.
6805     if (!id->idjKeepLong)
6806     {
6807         /* Record the jump's IG and offset within it */
6808         id->idjIG   = emitCurIG;
6809         id->idjOffs = emitCurIGsize;
6810
6811         /* Append this jump to this IG's jump list */
6812         id->idjNext      = emitCurIGjmpList;
6813         emitCurIGjmpList = id;
6814
6815 #if EMITTER_STATS
6816         emitTotalIGjmps++;
6817 #endif
6818     }
6819
6820     dispIns(id);
6821     appendToCurIG(id);
6822 }
6823
6824 /*****************************************************************************
6825  *
6826  *  Add an instruction with a static member + constant.
6827  */
6828
6829 void emitter::emitIns_C_I(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, ssize_t offs, ssize_t val)
6830 {
6831     NYI("emitIns_C_I");
6832 }
6833
6834 /*****************************************************************************
6835  *
6836  *  Add an instruction with a static member + register operands.
6837  */
6838
6839 void emitter::emitIns_C_R(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, regNumber reg, int offs)
6840 {
6841     assert(!"emitIns_C_R not supported for RyuJIT backend");
6842 }
6843
6844 void emitter::emitIns_R_AR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
6845 {
6846     NYI("emitIns_R_AR");
6847 }
6848
6849 // This computes address from the immediate which is relocatable.
6850 void emitter::emitIns_R_AI(instruction ins, emitAttr attr, regNumber ireg, ssize_t addr)
6851 {
6852     assert(EA_IS_RELOC(attr));
6853     emitAttr      size    = EA_SIZE(attr);
6854     insFormat     fmt     = IF_DI_1E;
6855     bool          needAdd = false;
6856     instrDescJmp* id      = emitNewInstrJmp();
6857
6858     switch (ins)
6859     {
6860         case INS_adrp:
6861             // This computes page address.
6862             // page offset is needed using add.
6863             needAdd = true;
6864             break;
6865         case INS_adr:
6866             break;
6867         default:
6868             unreached();
6869     }
6870
6871     id->idIns(ins);
6872     id->idInsFmt(fmt);
6873     id->idInsOpt(INS_OPTS_NONE);
6874     id->idOpSize(size);
6875     id->idAddr()->iiaAddr = (BYTE*)addr;
6876     id->idReg1(ireg);
6877     id->idSetIsDspReloc();
6878
6879     dispIns(id);
6880     appendToCurIG(id);
6881
6882     if (needAdd)
6883     {
6884         // add reg, reg, imm
6885         ins           = INS_add;
6886         fmt           = IF_DI_2A;
6887         instrDesc* id = emitAllocInstr(attr);
6888         assert(id->idIsReloc());
6889
6890         id->idIns(ins);
6891         id->idInsFmt(fmt);
6892         id->idInsOpt(INS_OPTS_NONE);
6893         id->idOpSize(size);
6894         id->idAddr()->iiaAddr = (BYTE*)addr;
6895         id->idReg1(ireg);
6896         id->idReg2(ireg);
6897
6898         dispIns(id);
6899         appendToCurIG(id);
6900     }
6901 }
6902
6903 void emitter::emitIns_AR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
6904 {
6905     NYI("emitIns_AR_R");
6906 }
6907
6908 void emitter::emitIns_R_ARR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
6909 {
6910     NYI("emitIns_R_ARR");
6911 }
6912
6913 void emitter::emitIns_ARR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
6914 {
6915     NYI("emitIns_R_ARR");
6916 }
6917
6918 void emitter::emitIns_R_ARX(
6919     instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, unsigned mul, int disp)
6920 {
6921     NYI("emitIns_R_ARR");
6922 }
6923
6924 /*****************************************************************************
6925  *
6926  *  Record that a jump instruction uses the short encoding
6927  *
6928  */
6929 void emitter::emitSetShortJump(instrDescJmp* id)
6930 {
6931     if (id->idjKeepLong)
6932         return;
6933
6934     insFormat fmt = IF_NONE;
6935     if (emitIsCondJump(id))
6936     {
6937         switch (id->idIns())
6938         {
6939             case INS_cbz:
6940             case INS_cbnz:
6941                 fmt = IF_BI_1A;
6942                 break;
6943             case INS_tbz:
6944             case INS_tbnz:
6945                 fmt = IF_BI_1B;
6946                 break;
6947             default:
6948                 fmt = IF_BI_0B;
6949                 break;
6950         }
6951     }
6952     else if (emitIsLoadLabel(id))
6953     {
6954         fmt = IF_DI_1E;
6955     }
6956     else if (emitIsLoadConstant(id))
6957     {
6958         fmt = IF_LS_1A;
6959     }
6960     else
6961     {
6962         unreached();
6963     }
6964
6965     id->idInsFmt(fmt);
6966     id->idjShort = true;
6967 }
6968
6969 /*****************************************************************************
6970  *
6971  *  Add a label instruction.
6972  */
6973
6974 void emitter::emitIns_R_L(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
6975 {
6976     assert(dst->bbFlags & BBF_JMP_TARGET);
6977
6978     insFormat fmt = IF_NONE;
6979
6980     switch (ins)
6981     {
6982         case INS_adr:
6983             fmt = IF_LARGEADR;
6984             break;
6985         default:
6986             unreached();
6987     }
6988
6989     instrDescJmp* id = emitNewInstrJmp();
6990
6991     id->idIns(ins);
6992     id->idInsFmt(fmt);
6993     id->idjShort             = false;
6994     id->idAddr()->iiaBBlabel = dst;
6995     id->idReg1(reg);
6996     id->idOpSize(EA_PTRSIZE);
6997
6998 #ifdef DEBUG
6999     // Mark the catch return
7000     if (emitComp->compCurBB->bbJumpKind == BBJ_EHCATCHRET)
7001     {
7002         id->idDebugOnlyInfo()->idCatchRet = true;
7003     }
7004 #endif // DEBUG
7005
7006     id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7007
7008 #ifdef DEBUG
7009     if (emitComp->opts.compLongAddress)
7010         id->idjKeepLong = 1;
7011 #endif // DEBUG
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 /*****************************************************************************
7032  *
7033  *  Add a data label instruction.
7034  */
7035
7036 void emitter::emitIns_R_D(instruction ins, emitAttr attr, unsigned offs, regNumber reg)
7037 {
7038     NYI("emitIns_R_D");
7039 }
7040
7041 void emitter::emitIns_J_R(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
7042 {
7043     assert((ins == INS_cbz) || (ins == INS_cbnz));
7044
7045     assert(dst != nullptr);
7046     assert((dst->bbFlags & BBF_JMP_TARGET) != 0);
7047
7048     insFormat fmt = IF_LARGEJMP;
7049
7050     instrDescJmp* id = emitNewInstrJmp();
7051
7052     id->idIns(ins);
7053     id->idInsFmt(fmt);
7054     id->idReg1(reg);
7055     id->idjShort = false;
7056     id->idOpSize(EA_SIZE(attr));
7057
7058     id->idAddr()->iiaBBlabel = dst;
7059     id->idjKeepLong          = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7060
7061     /* Record the jump's IG and offset within it */
7062
7063     id->idjIG   = emitCurIG;
7064     id->idjOffs = emitCurIGsize;
7065
7066     /* Append this jump to this IG's jump list */
7067
7068     id->idjNext      = emitCurIGjmpList;
7069     emitCurIGjmpList = id;
7070
7071 #if EMITTER_STATS
7072     emitTotalIGjmps++;
7073 #endif
7074
7075     dispIns(id);
7076     appendToCurIG(id);
7077 }
7078
7079 void emitter::emitIns_J_R_I(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg, int imm)
7080 {
7081     assert((ins == INS_tbz) || (ins == INS_tbnz));
7082
7083     assert(dst != nullptr);
7084     assert((dst->bbFlags & BBF_JMP_TARGET) != 0);
7085     assert((EA_SIZE(attr) == EA_4BYTE) || (EA_SIZE(attr) == EA_8BYTE));
7086     assert(imm < ((EA_SIZE(attr) == EA_4BYTE) ? 32 : 64));
7087
7088     insFormat fmt = IF_LARGEJMP;
7089
7090     instrDescJmp* id = emitNewInstrJmp();
7091
7092     id->idIns(ins);
7093     id->idInsFmt(fmt);
7094     id->idReg1(reg);
7095     id->idjShort = false;
7096     id->idSmallCns(imm);
7097     id->idOpSize(EA_SIZE(attr));
7098
7099     id->idAddr()->iiaBBlabel = dst;
7100     id->idjKeepLong          = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7101
7102     /* Record the jump's IG and offset within it */
7103
7104     id->idjIG   = emitCurIG;
7105     id->idjOffs = emitCurIGsize;
7106
7107     /* Append this jump to this IG's jump list */
7108
7109     id->idjNext      = emitCurIGjmpList;
7110     emitCurIGjmpList = id;
7111
7112 #if EMITTER_STATS
7113     emitTotalIGjmps++;
7114 #endif
7115
7116     dispIns(id);
7117     appendToCurIG(id);
7118 }
7119
7120 void emitter::emitIns_J(instruction ins, BasicBlock* dst, int instrCount)
7121 {
7122     insFormat fmt = IF_NONE;
7123
7124     if (dst != nullptr)
7125     {
7126         assert(dst->bbFlags & BBF_JMP_TARGET);
7127     }
7128     else
7129     {
7130         assert(instrCount != 0);
7131     }
7132
7133     /* Figure out the encoding format of the instruction */
7134
7135     bool idjShort = false;
7136     switch (ins)
7137     {
7138         case INS_bl_local:
7139         case INS_b:
7140             // Unconditional jump is a single form.
7141             idjShort = true;
7142             fmt      = IF_BI_0A;
7143             break;
7144
7145         case INS_beq:
7146         case INS_bne:
7147         case INS_bhs:
7148         case INS_blo:
7149         case INS_bmi:
7150         case INS_bpl:
7151         case INS_bvs:
7152         case INS_bvc:
7153         case INS_bhi:
7154         case INS_bls:
7155         case INS_bge:
7156         case INS_blt:
7157         case INS_bgt:
7158         case INS_ble:
7159             // Assume conditional jump is long.
7160             fmt = IF_LARGEJMP;
7161             break;
7162
7163         default:
7164             unreached();
7165             break;
7166     }
7167
7168     instrDescJmp* id = emitNewInstrJmp();
7169
7170     id->idIns(ins);
7171     id->idInsFmt(fmt);
7172     id->idjShort = idjShort;
7173
7174 #ifdef DEBUG
7175     // Mark the finally call
7176     if (ins == INS_bl_local && emitComp->compCurBB->bbJumpKind == BBJ_CALLFINALLY)
7177     {
7178         id->idDebugOnlyInfo()->idFinallyCall = true;
7179     }
7180 #endif // DEBUG
7181
7182     if (dst != nullptr)
7183     {
7184         id->idAddr()->iiaBBlabel = dst;
7185
7186         // Skip unconditional jump that has a single form.
7187         // TODO-ARM64-NYI: enable hot/cold splittingNYI.
7188         // The target needs to be relocated.
7189         if (!idjShort)
7190         {
7191             id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7192
7193 #ifdef DEBUG
7194             if (emitComp->opts.compLongAddress) // Force long branches
7195                 id->idjKeepLong = 1;
7196 #endif // DEBUG
7197         }
7198     }
7199     else
7200     {
7201         id->idAddr()->iiaSetInstrCount(instrCount);
7202         id->idjKeepLong = false;
7203         /* This jump must be short */
7204         emitSetShortJump(id);
7205         id->idSetIsBound();
7206     }
7207
7208     /* Record the jump's IG and offset within it */
7209
7210     id->idjIG   = emitCurIG;
7211     id->idjOffs = emitCurIGsize;
7212
7213     /* Append this jump to this IG's jump list */
7214
7215     id->idjNext      = emitCurIGjmpList;
7216     emitCurIGjmpList = id;
7217
7218 #if EMITTER_STATS
7219     emitTotalIGjmps++;
7220 #endif
7221
7222     dispIns(id);
7223     appendToCurIG(id);
7224 }
7225
7226 /*****************************************************************************
7227  *
7228  *  Add a call instruction (direct or indirect).
7229  *      argSize<0 means that the caller will pop the arguments
7230  *
7231  * The other arguments are interpreted depending on callType as shown:
7232  * Unless otherwise specified, ireg,xreg,xmul,disp should have default values.
7233  *
7234  * EC_FUNC_TOKEN       : addr is the method address
7235  * EC_FUNC_ADDR        : addr is the absolute address of the function
7236  *
7237  * If callType is one of these emitCallTypes, addr has to be NULL.
7238  * EC_INDIR_R          : "call ireg".
7239  *
7240  * For ARM xreg, xmul and disp are never used and should always be 0/REG_NA.
7241  *
7242  *  Please consult the "debugger team notification" comment in genFnProlog().
7243  */
7244
7245 void emitter::emitIns_Call(EmitCallType          callType,
7246                            CORINFO_METHOD_HANDLE methHnd,
7247                            INDEBUG_LDISASM_COMMA(CORINFO_SIG_INFO* sigInfo) // used to report call sites to the EE
7248                            void*            addr,
7249                            ssize_t          argSize,
7250                            emitAttr         retSize,
7251                            emitAttr         secondRetSize,
7252                            VARSET_VALARG_TP ptrVars,
7253                            regMaskTP        gcrefRegs,
7254                            regMaskTP        byrefRegs,
7255                            IL_OFFSETX       ilOffset /* = BAD_IL_OFFSET */,
7256                            regNumber        ireg /* = REG_NA */,
7257                            regNumber        xreg /* = REG_NA */,
7258                            unsigned         xmul /* = 0     */,
7259                            ssize_t          disp /* = 0     */,
7260                            bool             isJump /* = false */,
7261                            bool             isNoGC /* = false */,
7262                            bool             isProfLeaveCB /* = false */)
7263 {
7264     /* Sanity check the arguments depending on callType */
7265
7266     assert(callType < EC_COUNT);
7267     assert((callType != EC_FUNC_TOKEN && callType != EC_FUNC_ADDR) ||
7268            (ireg == REG_NA && xreg == REG_NA && xmul == 0 && disp == 0));
7269     assert(callType < EC_INDIR_R || addr == NULL);
7270     assert(callType != EC_INDIR_R || (ireg < REG_COUNT && xreg == REG_NA && xmul == 0 && disp == 0));
7271
7272     // ARM never uses these
7273     assert(xreg == REG_NA && xmul == 0 && disp == 0);
7274
7275     // Our stack level should be always greater than the bytes of arguments we push. Just
7276     // a sanity test.
7277     assert((unsigned)abs(argSize) <= codeGen->genStackLevel);
7278
7279     int        argCnt;
7280     instrDesc* id;
7281
7282     /* This is the saved set of registers after a normal call */
7283     regMaskTP savedSet = RBM_CALLEE_SAVED;
7284
7285     /* some special helper calls have a different saved set registers */
7286
7287     if (isNoGC)
7288     {
7289         assert(emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
7290
7291         // Get the set of registers that this call kills and remove it from the saved set.
7292         savedSet = RBM_ALLINT & ~emitComp->compNoGCHelperCallKillSet(Compiler::eeGetHelperNum(methHnd));
7293
7294         // In case of Leave profiler callback, we need to preserve liveness of REG_PROFILER_RET_SCRATCH
7295         if (isProfLeaveCB)
7296         {
7297             savedSet |= RBM_PROFILER_RET_SCRATCH;
7298         }
7299     }
7300     else
7301     {
7302         assert(!emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
7303     }
7304
7305     /* Trim out any callee-trashed registers from the live set */
7306
7307     gcrefRegs &= savedSet;
7308     byrefRegs &= savedSet;
7309
7310 #ifdef DEBUG
7311     if (EMIT_GC_VERBOSE)
7312     {
7313         printf("Call: GCvars=%s ", VarSetOps::ToString(emitComp, ptrVars));
7314         dumpConvertedVarSet(emitComp, ptrVars);
7315         printf(", gcrefRegs=");
7316         printRegMaskInt(gcrefRegs);
7317         emitDispRegSet(gcrefRegs);
7318         printf(", byrefRegs=");
7319         printRegMaskInt(byrefRegs);
7320         emitDispRegSet(byrefRegs);
7321         printf("\n");
7322     }
7323 #endif
7324
7325     assert(argSize % REGSIZE_BYTES == 0);
7326     argCnt = (int)(argSize / (int)REGSIZE_BYTES);
7327
7328     /* Managed RetVal: emit sequence point for the call */
7329     if (emitComp->opts.compDbgInfo && ilOffset != BAD_IL_OFFSET)
7330     {
7331         codeGen->genIPmappingAdd(ilOffset, false);
7332     }
7333
7334     /*
7335         We need to allocate the appropriate instruction descriptor based
7336         on whether this is a direct/indirect call, and whether we need to
7337         record an updated set of live GC variables.
7338      */
7339
7340     if (callType >= EC_INDIR_R)
7341     {
7342         /* Indirect call, virtual calls */
7343
7344         assert(callType == EC_INDIR_R);
7345
7346         id = emitNewInstrCallInd(argCnt, disp, ptrVars, gcrefRegs, byrefRegs, retSize, secondRetSize);
7347     }
7348     else
7349     {
7350         /* Helper/static/nonvirtual/function calls (direct or through handle),
7351            and calls to an absolute addr. */
7352
7353         assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
7354
7355         id = emitNewInstrCallDir(argCnt, ptrVars, gcrefRegs, byrefRegs, retSize, secondRetSize);
7356     }
7357
7358     /* Update the emitter's live GC ref sets */
7359
7360     VarSetOps::Assign(emitComp, emitThisGCrefVars, ptrVars);
7361     emitThisGCrefRegs = gcrefRegs;
7362     emitThisByrefRegs = byrefRegs;
7363
7364     /* Set the instruction - special case jumping a function */
7365     instruction ins;
7366     insFormat   fmt = IF_NONE;
7367
7368     id->idSetIsNoGC(isNoGC);
7369
7370     /* Record the address: method, indirection, or funcptr */
7371
7372     if (callType > EC_FUNC_ADDR)
7373     {
7374         /* This is an indirect call (either a virtual call or func ptr call) */
7375
7376         switch (callType)
7377         {
7378             case EC_INDIR_R: // the address is in a register
7379
7380                 id->idSetIsCallRegPtr();
7381
7382                 if (isJump)
7383                 {
7384                     ins = INS_br_tail; // INS_br_tail  Reg
7385                 }
7386                 else
7387                 {
7388                     ins = INS_blr; // INS_blr Reg
7389                 }
7390                 fmt = IF_BR_1B;
7391
7392                 id->idIns(ins);
7393                 id->idInsFmt(fmt);
7394
7395                 id->idReg3(ireg);
7396                 assert(xreg == REG_NA);
7397                 break;
7398
7399             default:
7400                 NO_WAY("unexpected instruction");
7401                 break;
7402         }
7403     }
7404     else
7405     {
7406         /* This is a simple direct call: "call helper/method/addr" */
7407
7408         assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
7409
7410         assert(addr != NULL);
7411
7412         if (isJump)
7413         {
7414             ins = INS_b_tail; // INS_b_tail imm28
7415         }
7416         else
7417         {
7418             ins = INS_bl; // INS_bl imm28
7419         }
7420         fmt = IF_BI_0C;
7421
7422         id->idIns(ins);
7423         id->idInsFmt(fmt);
7424
7425         id->idAddr()->iiaAddr = (BYTE*)addr;
7426
7427         if (callType == EC_FUNC_ADDR)
7428         {
7429             id->idSetIsCallAddr();
7430         }
7431
7432         if (emitComp->opts.compReloc)
7433         {
7434             id->idSetIsDspReloc();
7435         }
7436     }
7437
7438 #ifdef DEBUG
7439     if (EMIT_GC_VERBOSE)
7440     {
7441         if (id->idIsLargeCall())
7442         {
7443             printf("[%02u] Rec call GC vars = %s\n", id->idDebugOnlyInfo()->idNum,
7444                    VarSetOps::ToString(emitComp, ((instrDescCGCA*)id)->idcGCvars));
7445         }
7446     }
7447
7448     id->idDebugOnlyInfo()->idMemCookie = (size_t)methHnd; // method token
7449     id->idDebugOnlyInfo()->idCallSig   = sigInfo;
7450 #endif // DEBUG
7451
7452 #ifdef LATE_DISASM
7453     if (addr != nullptr)
7454     {
7455         codeGen->getDisAssembler().disSetMethod((size_t)addr, methHnd);
7456     }
7457 #endif // LATE_DISASM
7458
7459     dispIns(id);
7460     appendToCurIG(id);
7461 }
7462
7463 /*****************************************************************************
7464  *
7465  *  Returns true if 'imm' is valid Cond encoding
7466  */
7467
7468 /*static*/ bool emitter::isValidImmCond(ssize_t imm)
7469 {
7470     // range check the ssize_t value, to make sure it is a small unsigned value
7471     // and that only the bits in the cfi.cond are set
7472     if ((imm < 0) || (imm > 0xF))
7473         return false;
7474
7475     condFlagsImm cfi;
7476     cfi.immCFVal = (unsigned)imm;
7477
7478     return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7479 }
7480
7481 /*****************************************************************************
7482  *
7483  *  Returns true if 'imm' is valid Cond/Flags encoding
7484  */
7485
7486 /*static*/ bool emitter::isValidImmCondFlags(ssize_t imm)
7487 {
7488     // range check the ssize_t value, to make sure it is a small unsigned value
7489     // and that only the bits in the cfi.cond or cfi.flags are set
7490     if ((imm < 0) || (imm > 0xFF))
7491         return false;
7492
7493     condFlagsImm cfi;
7494     cfi.immCFVal = (unsigned)imm;
7495
7496     return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7497 }
7498
7499 /*****************************************************************************
7500  *
7501  *  Returns true if 'imm' is valid Cond/Flags/Imm5 encoding
7502  */
7503
7504 /*static*/ bool emitter::isValidImmCondFlagsImm5(ssize_t imm)
7505 {
7506     // range check the ssize_t value, to make sure it is a small unsigned value
7507     // and that only the bits in the cfi.cond, cfi.flags or cfi.imm5 are set
7508     if ((imm < 0) || (imm > 0x1FFF))
7509         return false;
7510
7511     condFlagsImm cfi;
7512     cfi.immCFVal = (unsigned)imm;
7513
7514     return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7515 }
7516
7517 /*****************************************************************************
7518  *
7519  *  Returns an encoding for the specified register used in the 'Rd' position
7520  */
7521
7522 /*static*/ emitter::code_t emitter::insEncodeReg_Rd(regNumber reg)
7523 {
7524     assert(isIntegerRegister(reg));
7525     emitter::code_t ureg = (emitter::code_t)reg;
7526     assert((ureg >= 0) && (ureg <= 31));
7527     return ureg;
7528 }
7529
7530 /*****************************************************************************
7531  *
7532  *  Returns an encoding for the specified register used in the 'Rt' position
7533  */
7534
7535 /*static*/ emitter::code_t emitter::insEncodeReg_Rt(regNumber reg)
7536 {
7537     assert(isIntegerRegister(reg));
7538     emitter::code_t ureg = (emitter::code_t)reg;
7539     assert((ureg >= 0) && (ureg <= 31));
7540     return ureg;
7541 }
7542
7543 /*****************************************************************************
7544  *
7545  *  Returns an encoding for the specified register used in the 'Rn' position
7546  */
7547
7548 /*static*/ emitter::code_t emitter::insEncodeReg_Rn(regNumber reg)
7549 {
7550     assert(isIntegerRegister(reg));
7551     emitter::code_t ureg = (emitter::code_t)reg;
7552     assert((ureg >= 0) && (ureg <= 31));
7553     return ureg << 5;
7554 }
7555
7556 /*****************************************************************************
7557  *
7558  *  Returns an encoding for the specified register used in the 'Rm' position
7559  */
7560
7561 /*static*/ emitter::code_t emitter::insEncodeReg_Rm(regNumber reg)
7562 {
7563     assert(isIntegerRegister(reg));
7564     emitter::code_t ureg = (emitter::code_t)reg;
7565     assert((ureg >= 0) && (ureg <= 31));
7566     return ureg << 16;
7567 }
7568
7569 /*****************************************************************************
7570  *
7571  *  Returns an encoding for the specified register used in the 'Ra' position
7572  */
7573
7574 /*static*/ emitter::code_t emitter::insEncodeReg_Ra(regNumber reg)
7575 {
7576     assert(isIntegerRegister(reg));
7577     emitter::code_t ureg = (emitter::code_t)reg;
7578     assert((ureg >= 0) && (ureg <= 31));
7579     return ureg << 10;
7580 }
7581
7582 /*****************************************************************************
7583  *
7584  *  Returns an encoding for the specified register used in the 'Vd' position
7585  */
7586
7587 /*static*/ emitter::code_t emitter::insEncodeReg_Vd(regNumber reg)
7588 {
7589     assert(emitter::isVectorRegister(reg));
7590     emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7591     assert((ureg >= 0) && (ureg <= 31));
7592     return ureg;
7593 }
7594
7595 /*****************************************************************************
7596  *
7597  *  Returns an encoding for the specified register used in the 'Vt' position
7598  */
7599
7600 /*static*/ emitter::code_t emitter::insEncodeReg_Vt(regNumber reg)
7601 {
7602     assert(emitter::isVectorRegister(reg));
7603     emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7604     assert((ureg >= 0) && (ureg <= 31));
7605     return ureg;
7606 }
7607
7608 /*****************************************************************************
7609  *
7610  *  Returns an encoding for the specified register used in the 'Vn' position
7611  */
7612
7613 /*static*/ emitter::code_t emitter::insEncodeReg_Vn(regNumber reg)
7614 {
7615     assert(emitter::isVectorRegister(reg));
7616     emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7617     assert((ureg >= 0) && (ureg <= 31));
7618     return ureg << 5;
7619 }
7620
7621 /*****************************************************************************
7622  *
7623  *  Returns an encoding for the specified register used in the 'Vm' position
7624  */
7625
7626 /*static*/ emitter::code_t emitter::insEncodeReg_Vm(regNumber reg)
7627 {
7628     assert(emitter::isVectorRegister(reg));
7629     emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7630     assert((ureg >= 0) && (ureg <= 31));
7631     return ureg << 16;
7632 }
7633
7634 /*****************************************************************************
7635  *
7636  *  Returns an encoding for the specified register used in the 'Va' position
7637  */
7638
7639 /*static*/ emitter::code_t emitter::insEncodeReg_Va(regNumber reg)
7640 {
7641     assert(emitter::isVectorRegister(reg));
7642     emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7643     assert((ureg >= 0) && (ureg <= 31));
7644     return ureg << 10;
7645 }
7646
7647 /*****************************************************************************
7648  *
7649  *  Returns an encoding for the specified condition code.
7650  */
7651
7652 /*static*/ emitter::code_t emitter::insEncodeCond(insCond cond)
7653 {
7654     emitter::code_t uimm = (emitter::code_t)cond;
7655     return uimm << 12;
7656 }
7657
7658 /*****************************************************************************
7659  *
7660  *  Returns an encoding for the condition code with the lowest bit inverted (marked by invert(<cond>) in the
7661  *  architecture manual).
7662  */
7663
7664 /*static*/ emitter::code_t emitter::insEncodeInvertedCond(insCond cond)
7665 {
7666     emitter::code_t uimm = (emitter::code_t)cond;
7667     uimm ^= 1; // invert the lowest bit
7668     return uimm << 12;
7669 }
7670
7671 /*****************************************************************************
7672  *
7673  *  Returns an encoding for the specified flags.
7674  */
7675
7676 /*static*/ emitter::code_t emitter::insEncodeFlags(insCflags flags)
7677 {
7678     emitter::code_t uimm = (emitter::code_t)flags;
7679     return uimm;
7680 }
7681
7682 /*****************************************************************************
7683  *
7684  *  Returns the encoding for the Shift Count bits to be used for Arm64 encodings
7685  */
7686
7687 /*static*/ emitter::code_t emitter::insEncodeShiftCount(ssize_t imm, emitAttr size)
7688 {
7689     assert((imm & 0x003F) == imm);
7690     assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
7691
7692     return (emitter::code_t)imm << 10;
7693 }
7694
7695 /*****************************************************************************
7696  *
7697  *  Returns the encoding to select a 64-bit datasize for an Arm64 instruction
7698  */
7699
7700 /*static*/ emitter::code_t emitter::insEncodeDatasize(emitAttr size)
7701 {
7702     if (size == EA_8BYTE)
7703     {
7704         return 0x80000000; // set the bit at location 31
7705     }
7706     else
7707     {
7708         assert(size == EA_4BYTE);
7709         return 0;
7710     }
7711 }
7712
7713 /*****************************************************************************
7714  *
7715  *  Returns the encoding to select the datasize for the general load/store Arm64 instructions
7716  *
7717  */
7718
7719 /*static*/ emitter::code_t emitter::insEncodeDatasizeLS(emitter::code_t code, emitAttr size)
7720 {
7721     bool exclusive = ((code & 0x35000000) == 0);
7722
7723     if ((code & 0x00800000) && !exclusive) // Is this a sign-extending opcode? (i.e. ldrsw, ldrsh, ldrsb)
7724     {
7725         if ((code & 0x80000000) == 0) // Is it a ldrsh or ldrsb and not ldrsw ?
7726         {
7727             if (EA_SIZE(size) != EA_8BYTE) // Do we need to encode the 32-bit Rt size bit?
7728             {
7729                 return 0x00400000; // set the bit at location 22
7730             }
7731         }
7732     }
7733     else if (code & 0x80000000) // Is this a ldr/str/ldur/stur opcode?
7734     {
7735         if (EA_SIZE(size) == EA_8BYTE) // Do we need to encode the 64-bit size bit?
7736         {
7737             return 0x40000000; // set the bit at location 30
7738         }
7739     }
7740     return 0;
7741 }
7742
7743 /*****************************************************************************
7744  *
7745  *  Returns the encoding to select the datasize for the vector load/store Arm64 instructions
7746  *
7747  */
7748
7749 /*static*/ emitter::code_t emitter::insEncodeDatasizeVLS(emitter::code_t code, emitAttr size)
7750 {
7751     code_t result = 0;
7752
7753     // Check bit 29
7754     if ((code & 0x20000000) == 0)
7755     {
7756         // LDR literal
7757
7758         if (size == EA_16BYTE)
7759         {
7760             // set the operation size in bit 31
7761             result = 0x80000000;
7762         }
7763         else if (size == EA_8BYTE)
7764         {
7765             // set the operation size in bit 30
7766             result = 0x40000000;
7767         }
7768         else
7769         {
7770             assert(size == EA_4BYTE);
7771             // no bits are set
7772             result = 0x00000000;
7773         }
7774     }
7775     else
7776     {
7777         // LDR non-literal
7778
7779         if (size == EA_16BYTE)
7780         {
7781             // The operation size in bits 31 and 30 are zero
7782             // Bit 23 specifies a 128-bit Load/Store
7783             result = 0x00800000;
7784         }
7785         else if (size == EA_8BYTE)
7786         {
7787             // set the operation size in bits 31 and 30
7788             result = 0xC0000000;
7789         }
7790         else if (size == EA_4BYTE)
7791         {
7792             // set the operation size in bit 31
7793             result = 0x80000000;
7794         }
7795         else if (size == EA_2BYTE)
7796         {
7797             // set the operation size in bit 30
7798             result = 0x40000000;
7799         }
7800         else
7801         {
7802             assert(size == EA_1BYTE);
7803             // The operation size in bits 31 and 30 are zero
7804             result = 0x00000000;
7805         }
7806     }
7807
7808     // Or in bit 26 to indicate a Vector register is used as 'target'
7809     result |= 0x04000000;
7810
7811     return result;
7812 }
7813
7814 /*****************************************************************************
7815  *
7816  *  Returns the encoding to select the datasize for the vector load/store Arm64 instructions
7817  *
7818  */
7819
7820 /*static*/ emitter::code_t emitter::insEncodeDatasizeVPLS(emitter::code_t code, emitAttr size)
7821 {
7822     code_t result = 0;
7823
7824     if (size == EA_16BYTE)
7825     {
7826         // The operation size in bits 31 and 30 are zero
7827         // Bit 23 specifies a 128-bit Load/Store
7828         result = 0x80000000;
7829     }
7830     else if (size == EA_8BYTE)
7831     {
7832         // set the operation size in bits 31 and 30
7833         result = 0x40000000;
7834     }
7835     else if (size == EA_4BYTE)
7836     {
7837         // set the operation size in bit 31
7838         result = 0x00000000;
7839     }
7840
7841     // Or in bit 26 to indicate a Vector register is used as 'target'
7842     result |= 0x04000000;
7843
7844     return result;
7845 }
7846
7847 /*****************************************************************************
7848  *
7849  *  Returns the encoding to set the size bit and the N bits for a 'bitfield' instruction
7850  *
7851  */
7852
7853 /*static*/ emitter::code_t emitter::insEncodeDatasizeBF(emitter::code_t code, emitAttr size)
7854 {
7855     // is bit 30 equal to 0?
7856     if ((code & 0x40000000) == 0) // is the opcode one of extr, sxtb, sxth or sxtw
7857     {
7858         if (size == EA_8BYTE) // Do we need to set the sf and N bits?
7859         {
7860             return 0x80400000; // set the sf-bit at location 31 and the N-bit at location 22
7861         }
7862     }
7863     return 0; // don't set any bits
7864 }
7865
7866 /*****************************************************************************
7867  *
7868  *  Returns the encoding to select the 64/128-bit datasize for an Arm64 vector instruction
7869  */
7870
7871 /*static*/ emitter::code_t emitter::insEncodeVectorsize(emitAttr size)
7872 {
7873     if (size == EA_16BYTE)
7874     {
7875         return 0x40000000; // set the bit at location 30
7876     }
7877     else
7878     {
7879         assert(size == EA_8BYTE);
7880         return 0;
7881     }
7882 }
7883
7884 /*****************************************************************************
7885  *
7886  *  Returns the encoding to select 'index' for an Arm64 vector elem instruction
7887  */
7888 /*static*/ emitter::code_t emitter::insEncodeVectorIndex(emitAttr elemsize, ssize_t index)
7889 {
7890     code_t bits = (code_t)index;
7891     if (elemsize == EA_1BYTE)
7892     {
7893         bits <<= 1;
7894         bits |= 1;
7895     }
7896     else if (elemsize == EA_2BYTE)
7897     {
7898         bits <<= 2;
7899         bits |= 2;
7900     }
7901     else if (elemsize == EA_4BYTE)
7902     {
7903         bits <<= 3;
7904         bits |= 4;
7905     }
7906     else
7907     {
7908         assert(elemsize == EA_8BYTE);
7909         bits <<= 4;
7910         bits |= 8;
7911     }
7912     assert((bits >= 1) && (bits <= 0x1f));
7913
7914     return (bits << 16); // bits at locations [20,19,18,17,16]
7915 }
7916
7917 /*****************************************************************************
7918  *
7919  *  Returns the encoding to select 'index2' for an Arm64 'ins' elem instruction
7920  */
7921 /*static*/ emitter::code_t emitter::insEncodeVectorIndex2(emitAttr elemsize, ssize_t index2)
7922 {
7923     code_t bits = (code_t)index2;
7924     if (elemsize == EA_1BYTE)
7925     {
7926         // bits are correct
7927     }
7928     else if (elemsize == EA_2BYTE)
7929     {
7930         bits <<= 1;
7931     }
7932     else if (elemsize == EA_4BYTE)
7933     {
7934         bits <<= 2;
7935     }
7936     else
7937     {
7938         assert(elemsize == EA_8BYTE);
7939         bits <<= 3;
7940     }
7941     assert((bits >= 0) && (bits <= 0xf));
7942
7943     return (bits << 11); // bits at locations [14,13,12,11]
7944 }
7945
7946 /*****************************************************************************
7947  *
7948  *  Returns the encoding to select the 'index' for an Arm64 'mul' by elem instruction
7949  */
7950 /*static*/ emitter::code_t emitter::insEncodeVectorIndexLMH(emitAttr elemsize, ssize_t index)
7951 {
7952     code_t bits = 0;
7953
7954     if (elemsize == EA_2BYTE)
7955     {
7956         assert((index >= 0) && (index <= 7));
7957         if (index & 0x4)
7958         {
7959             bits |= (1 << 11); // set bit 11 'H'
7960         }
7961         if (index & 0x2)
7962         {
7963             bits |= (1 << 21); // set bit 21 'L'
7964         }
7965         if (index & 0x1)
7966         {
7967             bits |= (1 << 20); // set bit 20 'M'
7968         }
7969     }
7970     else if (elemsize == EA_4BYTE)
7971     {
7972         assert((index >= 0) && (index <= 3));
7973         if (index & 0x2)
7974         {
7975             bits |= (1 << 11); // set bit 11 'H'
7976         }
7977         if (index & 0x1)
7978         {
7979             bits |= (1 << 21); // set bit 21 'L'
7980         }
7981     }
7982     else
7983     {
7984         assert(!"Invalid 'elemsize' value");
7985     }
7986
7987     return bits;
7988 }
7989
7990 /*****************************************************************************
7991  *
7992  *   Returns the encoding to shift by 'shift' for an Arm64 vector or scalar instruction
7993  */
7994
7995 /*static*/ emitter::code_t emitter::insEncodeVectorShift(emitAttr size, ssize_t shift)
7996 {
7997     assert(shift < getBitWidth(size));
7998
7999     code_t imm = (code_t)(getBitWidth(size) + shift);
8000
8001     return imm << 16;
8002 }
8003
8004 /*****************************************************************************
8005  *
8006  *  Returns the encoding to select the 1/2/4/8 byte elemsize for an Arm64 vector instruction
8007  */
8008
8009 /*static*/ emitter::code_t emitter::insEncodeElemsize(emitAttr size)
8010 {
8011     if (size == EA_8BYTE)
8012     {
8013         return 0x00C00000; // set the bit at location 23 and 22
8014     }
8015     else if (size == EA_4BYTE)
8016     {
8017         return 0x00800000; // set the bit at location 23
8018     }
8019     else if (size == EA_2BYTE)
8020     {
8021         return 0x00400000; // set the bit at location 22
8022     }
8023     assert(size == EA_1BYTE);
8024     return 0x00000000;
8025 }
8026
8027 /*****************************************************************************
8028  *
8029  *  Returns the encoding to select the 4/8 byte elemsize for an Arm64 float vector instruction
8030  */
8031
8032 /*static*/ emitter::code_t emitter::insEncodeFloatElemsize(emitAttr size)
8033 {
8034     if (size == EA_8BYTE)
8035     {
8036         return 0x00400000; // set the bit at location 22
8037     }
8038     assert(size == EA_4BYTE);
8039     return 0x00000000;
8040 }
8041
8042 // Returns the encoding to select the index for an Arm64 float vector by elem instruction
8043 /*static*/ emitter::code_t emitter::insEncodeFloatIndex(emitAttr elemsize, ssize_t index)
8044 {
8045     code_t result = 0x00000000;
8046     if (elemsize == EA_8BYTE)
8047     {
8048         assert((index >= 0) && (index <= 1));
8049         if (index == 1)
8050         {
8051             result |= 0x00000800; // 'H' - set the bit at location 11
8052         }
8053     }
8054     else
8055     {
8056         assert(elemsize == EA_4BYTE);
8057         assert((index >= 0) && (index <= 3));
8058         if (index & 2)
8059         {
8060             result |= 0x00000800; // 'H' - set the bit at location 11
8061         }
8062         if (index & 1)
8063         {
8064             result |= 0x00200000; // 'L' - set the bit at location 21
8065         }
8066     }
8067     return result;
8068 }
8069
8070 /*****************************************************************************
8071  *
8072  *  Returns the encoding to select the fcvt operation for Arm64 instructions
8073  */
8074 /*static*/ emitter::code_t emitter::insEncodeConvertOpt(insFormat fmt, insOpts conversion)
8075 {
8076     code_t result = 0;
8077     switch (conversion)
8078     {
8079         case INS_OPTS_S_TO_D: // Single to Double
8080             assert(fmt == IF_DV_2J);
8081             result = 0x00008000; // type=00, opc=01
8082             break;
8083
8084         case INS_OPTS_D_TO_S: // Double to Single
8085             assert(fmt == IF_DV_2J);
8086             result = 0x00400000; // type=01, opc=00
8087             break;
8088
8089         case INS_OPTS_H_TO_S: // Half to Single
8090             assert(fmt == IF_DV_2J);
8091             result = 0x00C00000; // type=11, opc=00
8092             break;
8093
8094         case INS_OPTS_H_TO_D: // Half to Double
8095             assert(fmt == IF_DV_2J);
8096             result = 0x00C08000; // type=11, opc=01
8097             break;
8098
8099         case INS_OPTS_S_TO_H: // Single to Half
8100             assert(fmt == IF_DV_2J);
8101             result = 0x00018000; // type=00, opc=11
8102             break;
8103
8104         case INS_OPTS_D_TO_H: // Double to Half
8105             assert(fmt == IF_DV_2J);
8106             result = 0x00418000; // type=01, opc=11
8107             break;
8108
8109         case INS_OPTS_S_TO_4BYTE: // Single to INT32
8110             assert(fmt == IF_DV_2H);
8111             result = 0x00000000; // sf=0, type=00
8112             break;
8113
8114         case INS_OPTS_D_TO_4BYTE: // Double to INT32
8115             assert(fmt == IF_DV_2H);
8116             result = 0x00400000; // sf=0, type=01
8117             break;
8118
8119         case INS_OPTS_S_TO_8BYTE: // Single to INT64
8120             assert(fmt == IF_DV_2H);
8121             result = 0x80000000; // sf=1, type=00
8122             break;
8123
8124         case INS_OPTS_D_TO_8BYTE: // Double to INT64
8125             assert(fmt == IF_DV_2H);
8126             result = 0x80400000; // sf=1, type=01
8127             break;
8128
8129         case INS_OPTS_4BYTE_TO_S: // INT32 to Single
8130             assert(fmt == IF_DV_2I);
8131             result = 0x00000000; // sf=0, type=00
8132             break;
8133
8134         case INS_OPTS_4BYTE_TO_D: // INT32 to Double
8135             assert(fmt == IF_DV_2I);
8136             result = 0x00400000; // sf=0, type=01
8137             break;
8138
8139         case INS_OPTS_8BYTE_TO_S: // INT64 to Single
8140             assert(fmt == IF_DV_2I);
8141             result = 0x80000000; // sf=1, type=00
8142             break;
8143
8144         case INS_OPTS_8BYTE_TO_D: // INT64 to Double
8145             assert(fmt == IF_DV_2I);
8146             result = 0x80400000; // sf=1, type=01
8147             break;
8148
8149         default:
8150             assert(!"Invalid 'conversion' value");
8151             break;
8152     }
8153     return result;
8154 }
8155
8156 /*****************************************************************************
8157  *
8158  *  Returns the encoding to have the Rn register be updated Pre/Post indexed
8159  *  or not updated
8160  */
8161
8162 /*static*/ emitter::code_t emitter::insEncodeIndexedOpt(insOpts opt)
8163 {
8164     assert(emitter::insOptsNone(opt) || emitter::insOptsIndexed(opt));
8165
8166     if (emitter::insOptsIndexed(opt))
8167     {
8168         if (emitter::insOptsPostIndex(opt))
8169         {
8170             return 0x00000400; // set the bit at location 10
8171         }
8172         else
8173         {
8174             assert(emitter::insOptsPreIndex(opt));
8175             return 0x00000C00; // set the bit at location 10 and 11
8176         }
8177     }
8178     else
8179     {
8180         assert(emitter::insOptsNone(opt));
8181         return 0; // bits 10 and 11 are zero
8182     }
8183 }
8184
8185 /*****************************************************************************
8186  *
8187  *  Returns the encoding for a ldp/stp instruction to have the Rn register
8188  *  be updated Pre/Post indexed or not updated
8189  */
8190
8191 /*static*/ emitter::code_t emitter::insEncodePairIndexedOpt(instruction ins, insOpts opt)
8192 {
8193     assert(emitter::insOptsNone(opt) || emitter::insOptsIndexed(opt));
8194
8195     if ((ins == INS_ldnp) || (ins == INS_stnp))
8196     {
8197         assert(emitter::insOptsNone(opt));
8198         return 0; // bits 23 and 24 are zero
8199     }
8200     else
8201     {
8202         if (emitter::insOptsIndexed(opt))
8203         {
8204             if (emitter::insOptsPostIndex(opt))
8205             {
8206                 return 0x00800000; // set the bit at location 23
8207             }
8208             else
8209             {
8210                 assert(emitter::insOptsPreIndex(opt));
8211                 return 0x01800000; // set the bit at location 24 and 23
8212             }
8213         }
8214         else
8215         {
8216             assert(emitter::insOptsNone(opt));
8217             return 0x01000000; // set the bit at location 24
8218         }
8219     }
8220 }
8221
8222 /*****************************************************************************
8223  *
8224  *  Returns the encoding to apply a Shift Type on the Rm register
8225  */
8226
8227 /*static*/ emitter::code_t emitter::insEncodeShiftType(insOpts opt)
8228 {
8229     if (emitter::insOptsNone(opt))
8230     {
8231         // None implies the we encode LSL (with a zero immediate)
8232         opt = INS_OPTS_LSL;
8233     }
8234     assert(emitter::insOptsAnyShift(opt));
8235
8236     emitter::code_t option = (emitter::code_t)opt - (emitter::code_t)INS_OPTS_LSL;
8237     assert(option <= 3);
8238
8239     return option << 22; // bits 23, 22
8240 }
8241
8242 /*****************************************************************************
8243  *
8244  *  Returns the encoding to apply a 12 bit left shift to the immediate
8245  */
8246
8247 /*static*/ emitter::code_t emitter::insEncodeShiftImm12(insOpts opt)
8248 {
8249     if (emitter::insOptsLSL12(opt))
8250     {
8251         return 0x00400000; // set the bit at location 22
8252     }
8253     return 0;
8254 }
8255
8256 /*****************************************************************************
8257  *
8258  *  Returns the encoding to have the Rm register use an extend operation
8259  */
8260
8261 /*static*/ emitter::code_t emitter::insEncodeExtend(insOpts opt)
8262 {
8263     if (emitter::insOptsNone(opt) || (opt == INS_OPTS_LSL))
8264     {
8265         // None or LSL implies the we encode UXTX
8266         opt = INS_OPTS_UXTX;
8267     }
8268     assert(emitter::insOptsAnyExtend(opt));
8269
8270     emitter::code_t option = (emitter::code_t)opt - (emitter::code_t)INS_OPTS_UXTB;
8271     assert(option <= 7);
8272
8273     return option << 13; // bits 15,14,13
8274 }
8275
8276 /*****************************************************************************
8277  *
8278  *  Returns the encoding to scale the Rm register by {0,1,2,3,4}
8279  *  when using an extend operation
8280  */
8281
8282 /*static*/ emitter::code_t emitter::insEncodeExtendScale(ssize_t imm)
8283 {
8284     assert((imm >= 0) && (imm <= 4));
8285
8286     return (emitter::code_t)imm << 10; // bits 12,11,10
8287 }
8288
8289 /*****************************************************************************
8290  *
8291  *  Returns the encoding to have the Rm register be auto scaled by the ld/st size
8292  */
8293
8294 /*static*/ emitter::code_t emitter::insEncodeReg3Scale(bool isScaled)
8295 {
8296     if (isScaled)
8297     {
8298         return 0x00001000; // set the bit at location 12
8299     }
8300     else
8301     {
8302         return 0;
8303     }
8304 }
8305
8306 BYTE* emitter::emitOutputLoadLabel(BYTE* dst, BYTE* srcAddr, BYTE* dstAddr, instrDescJmp* id)
8307 {
8308     instruction ins    = id->idIns();
8309     insFormat   fmt    = id->idInsFmt();
8310     regNumber   dstReg = id->idReg1();
8311     if (id->idjShort)
8312     {
8313         // adr x, [rel addr] --  compute address: current addr(ip) + rel addr.
8314         assert(ins == INS_adr);
8315         assert(fmt == IF_DI_1E);
8316         ssize_t distVal = (ssize_t)(dstAddr - srcAddr);
8317         dst             = emitOutputShortAddress(dst, ins, fmt, distVal, dstReg);
8318     }
8319     else
8320     {
8321         // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8322         assert(fmt == IF_LARGEADR);
8323         ssize_t relPageAddr =
8324             (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8325         dst = emitOutputShortAddress(dst, INS_adrp, IF_DI_1E, relPageAddr, dstReg);
8326
8327         // add x, x, page offs -- compute address = page addr + page offs
8328         ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8329         assert(isValidUimm12(imm12));
8330         code_t code =
8331             emitInsCode(INS_add, IF_DI_2A);  // DI_2A  X0010001shiiiiii iiiiiinnnnnddddd   1100 0000   imm(i12, sh)
8332         code |= insEncodeDatasize(EA_8BYTE); // X
8333         code |= ((code_t)imm12 << 10);       // iiiiiiiiiiii
8334         code |= insEncodeReg_Rd(dstReg);     // ddddd
8335         code |= insEncodeReg_Rn(dstReg);     // nnnnn
8336         dst += emitOutput_Instr(dst, code);
8337     }
8338     return dst;
8339 }
8340
8341 /*****************************************************************************
8342  *
8343  *  Output a local jump or other instruction with a pc-relative immediate.
8344  *  Note that this may be invoked to overwrite an existing jump instruction at 'dst'
8345  *  to handle forward branch patching.
8346  */
8347
8348 BYTE* emitter::emitOutputLJ(insGroup* ig, BYTE* dst, instrDesc* i)
8349 {
8350     instrDescJmp* id = (instrDescJmp*)i;
8351
8352     unsigned srcOffs;
8353     unsigned dstOffs;
8354     BYTE*    srcAddr;
8355     BYTE*    dstAddr;
8356     ssize_t  distVal;
8357     ssize_t  loBits;
8358
8359     // Set default ins/fmt from id.
8360     instruction ins = id->idIns();
8361     insFormat   fmt = id->idInsFmt();
8362
8363     bool loadLabel    = false;
8364     bool isJump       = false;
8365     bool loadConstant = false;
8366
8367     switch (ins)
8368     {
8369         default:
8370             isJump = true;
8371             break;
8372
8373         case INS_tbz:
8374         case INS_tbnz:
8375         case INS_cbz:
8376         case INS_cbnz:
8377             isJump = true;
8378             break;
8379
8380         case INS_ldr:
8381         case INS_ldrsw:
8382             loadConstant = true;
8383             break;
8384
8385         case INS_adr:
8386         case INS_adrp:
8387             loadLabel = true;
8388             break;
8389     }
8390
8391     /* Figure out the distance to the target */
8392
8393     srcOffs = emitCurCodeOffs(dst);
8394     srcAddr = emitOffsetToPtr(srcOffs);
8395
8396     if (id->idAddr()->iiaIsJitDataOffset())
8397     {
8398         assert(loadConstant || loadLabel);
8399         int doff = id->idAddr()->iiaGetJitDataOffset();
8400         assert(doff >= 0);
8401         ssize_t imm = emitGetInsSC(id);
8402         assert((imm >= 0) && (imm < 0x1000)); // 0x1000 is arbitrary, currently 'imm' is always 0
8403
8404         unsigned dataOffs = (unsigned)(doff + imm);
8405         assert(dataOffs < emitDataSize());
8406         dstAddr = emitDataOffsetToPtr(dataOffs);
8407
8408         regNumber dstReg  = id->idReg1();
8409         regNumber addrReg = dstReg; // an integer register to compute long address.
8410         emitAttr  opSize  = id->idOpSize();
8411
8412         if (loadConstant)
8413         {
8414             if (id->idjShort)
8415             {
8416                 // ldr x/v, [rel addr] -- load constant from current addr(ip) + rel addr.
8417                 assert(ins == INS_ldr);
8418                 assert(fmt == IF_LS_1A);
8419                 distVal = (ssize_t)(dstAddr - srcAddr);
8420                 dst     = emitOutputShortConstant(dst, ins, fmt, distVal, dstReg, opSize);
8421             }
8422             else
8423             {
8424                 // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8425                 assert(fmt == IF_LARGELDC);
8426                 ssize_t relPageAddr =
8427                     (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8428                 if (isVectorRegister(dstReg))
8429                 {
8430                     // Update addrReg with the reserved integer register
8431                     // since we cannot use dstReg (vector) to load constant directly from memory.
8432                     addrReg = id->idReg2();
8433                     assert(isGeneralRegister(addrReg));
8434                 }
8435                 ins = INS_adrp;
8436                 fmt = IF_DI_1E;
8437                 dst = emitOutputShortAddress(dst, ins, fmt, relPageAddr, addrReg);
8438
8439                 // ldr x, [x, page offs] -- load constant from page address + page offset into integer register.
8440                 ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8441                 assert(isValidUimm12(imm12));
8442                 ins = INS_ldr;
8443                 fmt = IF_LS_2B;
8444                 dst = emitOutputShortConstant(dst, ins, fmt, imm12, addrReg, opSize);
8445
8446                 // fmov v, d -- copy constant in integer register to vector register.
8447                 // This is needed only for vector constant.
8448                 if (addrReg != dstReg)
8449                 {
8450                     //  fmov    Vd,Rn                DV_2I  X00111100X100111 000000nnnnnddddd   1E27 0000   Vd,Rn
8451                     //  (scalar, from general)
8452                     assert(isVectorRegister(dstReg) && isGeneralRegister(addrReg));
8453                     ins         = INS_fmov;
8454                     fmt         = IF_DV_2I;
8455                     code_t code = emitInsCode(ins, fmt);
8456
8457                     code |= insEncodeReg_Vd(dstReg);  // ddddd
8458                     code |= insEncodeReg_Rn(addrReg); // nnnnn
8459                     if (id->idOpSize() == EA_8BYTE)
8460                     {
8461                         code |= 0x80400000; // X ... X
8462                     }
8463                     dst += emitOutput_Instr(dst, code);
8464                 }
8465             }
8466         }
8467         else
8468         {
8469             assert(loadLabel);
8470             dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8471         }
8472
8473         return dst;
8474     }
8475
8476     assert(loadLabel || isJump);
8477
8478     if (id->idAddr()->iiaHasInstrCount())
8479     {
8480         assert(ig != NULL);
8481         int      instrCount = id->idAddr()->iiaGetInstrCount();
8482         unsigned insNum     = emitFindInsNum(ig, id);
8483         if (instrCount < 0)
8484         {
8485             // Backward branches using instruction count must be within the same instruction group.
8486             assert(insNum + 1 >= (unsigned)(-instrCount));
8487         }
8488         dstOffs = ig->igOffs + emitFindOffset(ig, (insNum + 1 + instrCount));
8489         dstAddr = emitOffsetToPtr(dstOffs);
8490     }
8491     else
8492     {
8493         dstOffs = id->idAddr()->iiaIGlabel->igOffs;
8494         dstAddr = emitOffsetToPtr(dstOffs);
8495     }
8496
8497     distVal = (ssize_t)(dstAddr - srcAddr);
8498
8499     if (dstOffs <= srcOffs)
8500     {
8501 #if DEBUG_EMIT
8502         /* This is a backward jump - distance is known at this point */
8503
8504         if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8505         {
8506             size_t blkOffs = id->idjIG->igOffs;
8507
8508             if (INTERESTING_JUMP_NUM == 0)
8509                 printf("[3] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8510             printf("[3] Jump  block is at %08X - %02X = %08X\n", blkOffs, emitOffsAdj, blkOffs - emitOffsAdj);
8511             printf("[3] Jump        is at %08X - %02X = %08X\n", srcOffs, emitOffsAdj, srcOffs - emitOffsAdj);
8512             printf("[3] Label block is at %08X - %02X = %08X\n", dstOffs, emitOffsAdj, dstOffs - emitOffsAdj);
8513         }
8514 #endif
8515     }
8516     else
8517     {
8518         /* This is a  forward jump - distance will be an upper limit */
8519
8520         emitFwdJumps = true;
8521
8522         /* The target offset will be closer by at least 'emitOffsAdj', but only if this
8523            jump doesn't cross the hot-cold boundary. */
8524
8525         if (!emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8526         {
8527             dstOffs -= emitOffsAdj;
8528             distVal -= emitOffsAdj;
8529         }
8530
8531         /* Record the location of the jump for later patching */
8532
8533         id->idjOffs = dstOffs;
8534
8535         /* Are we overflowing the id->idjOffs bitfield? */
8536         if (id->idjOffs != dstOffs)
8537             IMPL_LIMITATION("Method is too large");
8538
8539 #if DEBUG_EMIT
8540         if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8541         {
8542             size_t blkOffs = id->idjIG->igOffs;
8543
8544             if (INTERESTING_JUMP_NUM == 0)
8545                 printf("[4] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8546             printf("[4] Jump  block is at %08X\n", blkOffs);
8547             printf("[4] Jump        is at %08X\n", srcOffs);
8548             printf("[4] Label block is at %08X - %02X = %08X\n", dstOffs + emitOffsAdj, emitOffsAdj, dstOffs);
8549         }
8550 #endif
8551     }
8552
8553 #ifdef DEBUG
8554     if (0 && emitComp->verbose)
8555     {
8556         size_t sz          = 4;
8557         int    distValSize = id->idjShort ? 4 : 8;
8558         printf("; %s jump [%08X/%03u] from %0*X to %0*X: dist = %08XH\n", (dstOffs <= srcOffs) ? "Fwd" : "Bwd",
8559                dspPtr(id), id->idDebugOnlyInfo()->idNum, distValSize, srcOffs + sz, distValSize, dstOffs, distVal);
8560     }
8561 #endif
8562
8563     /* For forward jumps, record the address of the distance value */
8564     id->idjTemp.idjAddr = (distVal > 0) ? dst : NULL;
8565
8566     if (emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8567     {
8568         assert(!id->idjShort);
8569         NYI_ARM64("Relocation Support for long address");
8570     }
8571
8572     assert(insOptsNone(id->idInsOpt()));
8573
8574     if (isJump)
8575     {
8576         if (id->idjShort)
8577         {
8578             // Short conditional/unconditional jump
8579             assert(!id->idjKeepLong);
8580             assert(emitJumpCrossHotColdBoundary(srcOffs, dstOffs) == false);
8581             assert((fmt == IF_BI_0A) || (fmt == IF_BI_0B) || (fmt == IF_BI_1A) || (fmt == IF_BI_1B));
8582         }
8583         else
8584         {
8585             // Long conditional jump
8586             assert(fmt == IF_LARGEJMP);
8587             // This is a pseudo-instruction format representing a large conditional branch, to allow
8588             // us to get a greater branch target range than we can get by using a straightforward conditional
8589             // branch. It is encoded as a short conditional branch that branches around a long unconditional
8590             // branch.
8591             //
8592             // Conceptually, we have:
8593             //
8594             //      b<cond> L_target
8595             //
8596             // The code we emit is:
8597             //
8598             //      b<!cond> L_not  // 4 bytes. Note that we reverse the condition.
8599             //      b L_target      // 4 bytes
8600             //   L_not:
8601             //
8602             // Note that we don't actually insert any blocks: we simply encode "b <!cond> L_not" as a branch with
8603             // the correct offset. Note also that this works for both integer and floating-point conditions, because
8604             // the condition inversion takes ordered/unordered into account, preserving NaN behavior. For example,
8605             // "GT" (greater than) is inverted to "LE" (less than, equal, or unordered).
8606
8607             instruction reverseIns;
8608             insFormat   reverseFmt;
8609
8610             switch (ins)
8611             {
8612                 case INS_cbz:
8613                     reverseIns = INS_cbnz;
8614                     reverseFmt = IF_BI_1A;
8615                     break;
8616                 case INS_cbnz:
8617                     reverseIns = INS_cbz;
8618                     reverseFmt = IF_BI_1A;
8619                     break;
8620                 case INS_tbz:
8621                     reverseIns = INS_tbnz;
8622                     reverseFmt = IF_BI_1B;
8623                     break;
8624                 case INS_tbnz:
8625                     reverseIns = INS_tbz;
8626                     reverseFmt = IF_BI_1B;
8627                     break;
8628                 default:
8629                     reverseIns = emitJumpKindToIns(emitReverseJumpKind(emitInsToJumpKind(ins)));
8630                     reverseFmt = IF_BI_0B;
8631             }
8632
8633             dst =
8634                 emitOutputShortBranch(dst,
8635                                       reverseIns, // reverse the conditional instruction
8636                                       reverseFmt,
8637                                       8, /* 8 bytes from start of this large conditional pseudo-instruction to L_not. */
8638                                       id);
8639
8640             // Now, pretend we've got a normal unconditional branch, and fall through to the code to emit that.
8641             ins = INS_b;
8642             fmt = IF_BI_0A;
8643
8644             // The distVal was computed based on the beginning of the pseudo-instruction,
8645             // So subtract the size of the conditional branch so that it is relative to the
8646             // unconditional branch.
8647             distVal -= 4;
8648         }
8649
8650         dst = emitOutputShortBranch(dst, ins, fmt, distVal, id);
8651     }
8652     else if (loadLabel)
8653     {
8654         dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8655     }
8656
8657     return dst;
8658 }
8659
8660 /*****************************************************************************
8661 *
8662 *  Output a short branch instruction.
8663 */
8664 BYTE* emitter::emitOutputShortBranch(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, instrDescJmp* id)
8665 {
8666     code_t code = emitInsCode(ins, fmt);
8667
8668     ssize_t loBits = (distVal & 3);
8669     noway_assert(loBits == 0);
8670     distVal >>= 2; // branch offset encodings are scaled by 4.
8671
8672     if (fmt == IF_BI_0A)
8673     {
8674         // INS_b or INS_bl_local
8675         noway_assert(isValidSimm26(distVal));
8676         distVal &= 0x3FFFFFFLL;
8677         code |= distVal;
8678     }
8679     else if (fmt == IF_BI_0B) // BI_0B   01010100iiiiiiii iiiiiiiiiiiXXXXX      simm19:00
8680     {
8681         // INS_beq, INS_bne, etc...
8682         noway_assert(isValidSimm19(distVal));
8683         distVal &= 0x7FFFFLL;
8684         code |= distVal << 5;
8685     }
8686     else if (fmt == IF_BI_1A) // BI_1A   X.......iiiiiiii iiiiiiiiiiittttt      Rt simm19:00
8687     {
8688         // INS_cbz or INS_cbnz
8689         assert(id != nullptr);
8690         code |= insEncodeDatasize(id->idOpSize()); // X
8691         code |= insEncodeReg_Rt(id->idReg1());     // ttttt
8692
8693         noway_assert(isValidSimm19(distVal));
8694         distVal &= 0x7FFFFLL; // 19 bits
8695         code |= distVal << 5;
8696     }
8697     else if (fmt == IF_BI_1B) // BI_1B   B.......bbbbbiii iiiiiiiiiiittttt      Rt imm6, simm14:00
8698     {
8699         // INS_tbz or INS_tbnz
8700         assert(id != nullptr);
8701         ssize_t imm = emitGetInsSC(id);
8702         assert(isValidImmShift(imm, id->idOpSize()));
8703
8704         if (imm & 0x20) // test bit 32-63 ?
8705         {
8706             code |= 0x80000000; // B
8707         }
8708         code |= ((imm & 0x1F) << 19);          // bbbbb
8709         code |= insEncodeReg_Rt(id->idReg1()); // ttttt
8710
8711         noway_assert(isValidSimm14(distVal));
8712         distVal &= 0x3FFFLL; // 14 bits
8713         code |= distVal << 5;
8714     }
8715     else
8716     {
8717         assert(!"Unknown fmt for emitOutputShortBranch");
8718     }
8719
8720     dst += emitOutput_Instr(dst, code);
8721
8722     return dst;
8723 }
8724
8725 /*****************************************************************************
8726 *
8727 *  Output a short address instruction.
8728 */
8729 BYTE* emitter::emitOutputShortAddress(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, regNumber reg)
8730 {
8731     ssize_t loBits = (distVal & 3);
8732     distVal >>= 2;
8733
8734     code_t code = emitInsCode(ins, fmt);
8735     if (fmt == IF_DI_1E) // DI_1E   .ii.....iiiiiiii iiiiiiiiiiiddddd      Rd simm21
8736     {
8737         // INS_adr or INS_adrp
8738         code |= insEncodeReg_Rd(reg); // ddddd
8739
8740         noway_assert(isValidSimm19(distVal));
8741         distVal &= 0x7FFFFLL; // 19 bits
8742         code |= distVal << 5;
8743         code |= loBits << 29; //  2 bits
8744     }
8745     else
8746     {
8747         assert(!"Unknown fmt for emitOutputShortAddress");
8748     }
8749
8750     dst += emitOutput_Instr(dst, code);
8751
8752     return dst;
8753 }
8754
8755 /*****************************************************************************
8756 *
8757 *  Output a short constant instruction.
8758 */
8759 BYTE* emitter::emitOutputShortConstant(
8760     BYTE* dst, instruction ins, insFormat fmt, ssize_t imm, regNumber reg, emitAttr opSize)
8761 {
8762     code_t code = emitInsCode(ins, fmt);
8763
8764     if (fmt == IF_LS_1A)
8765     {
8766         // LS_1A   XX...V..iiiiiiii iiiiiiiiiiittttt      Rt simm21
8767         // INS_ldr or INS_ldrsw (PC-Relative)
8768
8769         ssize_t loBits = (imm & 3);
8770         noway_assert(loBits == 0);
8771         ssize_t distVal = imm >>= 2; // load offset encodings are scaled by 4.
8772
8773         noway_assert(isValidSimm19(distVal));
8774
8775         // Is the target a vector register?
8776         if (isVectorRegister(reg))
8777         {
8778             code |= insEncodeDatasizeVLS(code, opSize); // XX V
8779             code |= insEncodeReg_Vt(reg);               // ttttt
8780         }
8781         else
8782         {
8783             assert(isGeneralRegister(reg));
8784             // insEncodeDatasizeLS is not quite right for this case.
8785             // So just specialize it.
8786             if ((ins == INS_ldr) && (opSize == EA_8BYTE))
8787             {
8788                 // set the operation size in bit 30
8789                 code |= 0x40000000;
8790             }
8791
8792             code |= insEncodeReg_Rt(reg); // ttttt
8793         }
8794
8795         distVal &= 0x7FFFFLL; // 19 bits
8796         code |= distVal << 5;
8797     }
8798     else if (fmt == IF_LS_2B)
8799     {
8800         //  ldr     Rt,[Xn+pimm12]       LS_2B  1X11100101iiiiii iiiiiinnnnnttttt   B940 0000   imm(0-4095<<{2,3})
8801         // INS_ldr or INS_ldrsw (PC-Relative)
8802         noway_assert(isValidUimm12(imm));
8803         assert(isGeneralRegister(reg));
8804
8805         if (opSize == EA_8BYTE)
8806         {
8807             // insEncodeDatasizeLS is not quite right for this case.
8808             // So just specialize it.
8809             if (ins == INS_ldr)
8810             {
8811                 // set the operation size in bit 30
8812                 code |= 0x40000000;
8813             }
8814             // Low 3 bits should be 0 -- 8 byte JIT data should be aligned on 8 byte.
8815             assert((imm & 7) == 0);
8816             imm >>= 3;
8817         }
8818         else
8819         {
8820             assert(opSize == EA_4BYTE);
8821             // Low 2 bits should be 0 -- 4 byte aligned data.
8822             assert((imm & 3) == 0);
8823             imm >>= 2;
8824         }
8825
8826         code |= insEncodeReg_Rt(reg); // ttttt
8827         code |= insEncodeReg_Rn(reg); // nnnnn
8828         code |= imm << 10;
8829     }
8830     else
8831     {
8832         assert(!"Unknown fmt for emitOutputShortConstant");
8833     }
8834
8835     dst += emitOutput_Instr(dst, code);
8836
8837     return dst;
8838 }
8839 /*****************************************************************************
8840  *
8841  *  Output a call instruction.
8842  */
8843
8844 unsigned emitter::emitOutputCall(insGroup* ig, BYTE* dst, instrDesc* id, code_t code)
8845 {
8846     const unsigned char callInstrSize = sizeof(code_t); // 4 bytes
8847     regMaskTP           gcrefRegs;
8848     regMaskTP           byrefRegs;
8849
8850     VARSET_TP GCvars(VarSetOps::UninitVal());
8851
8852     // Is this a "fat" call descriptor?
8853     if (id->idIsLargeCall())
8854     {
8855         instrDescCGCA* idCall = (instrDescCGCA*)id;
8856         gcrefRegs             = idCall->idcGcrefRegs;
8857         byrefRegs             = idCall->idcByrefRegs;
8858         VarSetOps::Assign(emitComp, GCvars, idCall->idcGCvars);
8859     }
8860     else
8861     {
8862         assert(!id->idIsLargeDsp());
8863         assert(!id->idIsLargeCns());
8864
8865         gcrefRegs = emitDecodeCallGCregs(id);
8866         byrefRegs = 0;
8867         VarSetOps::AssignNoCopy(emitComp, GCvars, VarSetOps::MakeEmpty(emitComp));
8868     }
8869
8870     /* We update the GC info before the call as the variables cannot be
8871         used by the call. Killing variables before the call helps with
8872         boundary conditions if the call is CORINFO_HELP_THROW - see bug 50029.
8873         If we ever track aliased variables (which could be used by the
8874         call), we would have to keep them alive past the call. */
8875
8876     emitUpdateLiveGCvars(GCvars, dst);
8877
8878     // Now output the call instruction and update the 'dst' pointer
8879     //
8880     unsigned outputInstrSize = emitOutput_Instr(dst, code);
8881     dst += outputInstrSize;
8882
8883     // All call instructions are 4-byte in size on ARM64
8884     //
8885     assert(outputInstrSize == callInstrSize);
8886
8887     // If the method returns a GC ref, mark INTRET (R0) appropriately.
8888     if (id->idGCref() == GCT_GCREF)
8889     {
8890         gcrefRegs |= RBM_INTRET;
8891     }
8892     else if (id->idGCref() == GCT_BYREF)
8893     {
8894         byrefRegs |= RBM_INTRET;
8895     }
8896
8897     // If is a multi-register return method is called, mark INTRET_1 (X1) appropriately
8898     if (id->idIsLargeCall())
8899     {
8900         instrDescCGCA* idCall = (instrDescCGCA*)id;
8901         if (idCall->idSecondGCref() == GCT_GCREF)
8902         {
8903             gcrefRegs |= RBM_INTRET_1;
8904         }
8905         else if (idCall->idSecondGCref() == GCT_BYREF)
8906         {
8907             byrefRegs |= RBM_INTRET_1;
8908         }
8909     }
8910
8911     // If the GC register set has changed, report the new set.
8912     if (gcrefRegs != emitThisGCrefRegs)
8913     {
8914         emitUpdateLiveGCregs(GCT_GCREF, gcrefRegs, dst);
8915     }
8916     // If the Byref register set has changed, report the new set.
8917     if (byrefRegs != emitThisByrefRegs)
8918     {
8919         emitUpdateLiveGCregs(GCT_BYREF, byrefRegs, dst);
8920     }
8921
8922     // Some helper calls may be marked as not requiring GC info to be recorded.
8923     if ((!id->idIsNoGC()))
8924     {
8925         // On ARM64, as on AMD64, we don't change the stack pointer to push/pop args.
8926         // So we're not really doing a "stack pop" here (note that "args" is 0), but we use this mechanism
8927         // to record the call for GC info purposes.  (It might be best to use an alternate call,
8928         // and protect "emitStackPop" under the EMIT_TRACK_STACK_DEPTH preprocessor variable.)
8929         emitStackPop(dst, /*isCall*/ true, callInstrSize, /*args*/ 0);
8930
8931         // Do we need to record a call location for GC purposes?
8932         //
8933         if (!emitFullGCinfo)
8934         {
8935             emitRecordGCcall(dst, callInstrSize);
8936         }
8937     }
8938     return callInstrSize;
8939 }
8940
8941 /*****************************************************************************
8942  *
8943  *  Emit a 32-bit Arm64 instruction
8944  */
8945
8946 /*static*/ unsigned emitter::emitOutput_Instr(BYTE* dst, code_t code)
8947 {
8948     assert(sizeof(code_t) == 4);
8949     *((code_t*)dst) = code;
8950
8951     return sizeof(code_t);
8952 }
8953
8954 /*****************************************************************************
8955 *
8956  *  Append the machine code corresponding to the given instruction descriptor
8957  *  to the code block at '*dp'; the base of the code block is 'bp', and 'ig'
8958  *  is the instruction group that contains the instruction. Updates '*dp' to
8959  *  point past the generated code, and returns the size of the instruction
8960  *  descriptor in bytes.
8961  */
8962
8963 size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
8964 {
8965     BYTE*         dst  = *dp;
8966     BYTE*         odst = dst;
8967     code_t        code = 0;
8968     size_t        sz   = emitGetInstrDescSize(id); // TODO-ARM64-Cleanup: on ARM, this is set in each case. why?
8969     instruction   ins  = id->idIns();
8970     insFormat     fmt  = id->idInsFmt();
8971     emitAttr      size = id->idOpSize();
8972     unsigned char callInstrSize = 0;
8973     unsigned      condcode;
8974
8975 #ifdef DEBUG
8976 #if DUMP_GC_TABLES
8977     bool dspOffs = emitComp->opts.dspGCtbls;
8978 #else
8979     bool dspOffs = !emitComp->opts.disDiffable;
8980 #endif
8981 #endif // DEBUG
8982
8983     assert(REG_NA == (int)REG_NA);
8984
8985     VARSET_TP GCvars(VarSetOps::UninitVal());
8986
8987     /* What instruction format have we got? */
8988
8989     switch (fmt)
8990     {
8991         ssize_t  imm;
8992         ssize_t  index;
8993         ssize_t  index2;
8994         unsigned scale;
8995         unsigned cmode;
8996         unsigned immShift;
8997         bool     hasShift;
8998         emitAttr extSize;
8999         emitAttr elemsize;
9000         emitAttr datasize;
9001
9002         case IF_BI_0A: // BI_0A   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
9003         case IF_BI_0B: // BI_0B   ......iiiiiiiiii iiiiiiiiiii.....               simm19:00
9004         case IF_LARGEJMP:
9005             assert(id->idGCref() == GCT_NONE);
9006             assert(id->idIsBound());
9007             dst = emitOutputLJ(ig, dst, id);
9008             sz  = sizeof(instrDescJmp);
9009             break;
9010
9011         case IF_BI_0C: // BI_0C   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
9012             code = emitInsCode(ins, fmt);
9013             sz   = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
9014             dst += emitOutputCall(ig, dst, id, code);
9015             // Always call RecordRelocation so that we wire in a JumpStub when we don't reach
9016             emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_BRANCH26);
9017             break;
9018
9019         case IF_BI_1A: // BI_1A   ......iiiiiiiiii iiiiiiiiiiittttt      Rt       simm19:00
9020             assert(insOptsNone(id->idInsOpt()));
9021             assert(id->idIsBound());
9022
9023             dst = emitOutputLJ(ig, dst, id);
9024             sz  = sizeof(instrDescJmp);
9025             break;
9026
9027         case IF_BI_1B: // BI_1B   B.......bbbbbiii iiiiiiiiiiittttt      Rt imm6, simm14:00
9028             assert(insOptsNone(id->idInsOpt()));
9029             assert(id->idIsBound());
9030
9031             dst = emitOutputLJ(ig, dst, id);
9032             sz  = sizeof(instrDescJmp);
9033             break;
9034
9035         case IF_BR_1A: // BR_1A   ................ ......nnnnn.....         Rn
9036             assert(insOptsNone(id->idInsOpt()));
9037             assert((ins == INS_ret) || (ins == INS_br));
9038             code = emitInsCode(ins, fmt);
9039             code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
9040
9041             dst += emitOutput_Instr(dst, code);
9042             break;
9043
9044         case IF_BR_1B: // BR_1B   ................ ......nnnnn.....         Rn
9045             assert(insOptsNone(id->idInsOpt()));
9046             assert((ins == INS_br_tail) || (ins == INS_blr));
9047             code = emitInsCode(ins, fmt);
9048             code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9049
9050             sz = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
9051             dst += emitOutputCall(ig, dst, id, code);
9052             break;
9053
9054         case IF_LS_1A: // LS_1A   XX...V..iiiiiiii iiiiiiiiiiittttt      Rt    PC imm(1MB)
9055         case IF_LARGELDC:
9056             assert(insOptsNone(id->idInsOpt()));
9057             assert(id->idIsBound());
9058
9059             dst = emitOutputLJ(ig, dst, id);
9060             sz  = sizeof(instrDescJmp);
9061             break;
9062
9063         case IF_LS_2A: // LS_2A   .X.......X...... ......nnnnnttttt      Rt Rn
9064             assert(insOptsNone(id->idInsOpt()));
9065             code = emitInsCode(ins, fmt);
9066             // Is the target a vector register?
9067             if (isVectorRegister(id->idReg1()))
9068             {
9069                 code &= 0x3FFFFFFF;                                 // clear the size bits
9070                 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9071                 code |= insEncodeReg_Vt(id->idReg1());              // ttttt
9072             }
9073             else
9074             {
9075                 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9076                 code |= insEncodeReg_Rt(id->idReg1());             // ttttt
9077             }
9078             code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9079             dst += emitOutput_Instr(dst, code);
9080             break;
9081
9082         case IF_LS_2B: // LS_2B   .X.......Xiiiiii iiiiiinnnnnttttt      Rt Rn    imm(0-4095)
9083             assert(insOptsNone(id->idInsOpt()));
9084             imm = emitGetInsSC(id);
9085             assert(isValidUimm12(imm));
9086             code = emitInsCode(ins, fmt);
9087             // Is the target a vector register?
9088             if (isVectorRegister(id->idReg1()))
9089             {
9090                 code &= 0x3FFFFFFF;                                 // clear the size bits
9091                 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9092                 code |= insEncodeReg_Vt(id->idReg1());              // ttttt
9093             }
9094             else
9095             {
9096                 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9097                 code |= insEncodeReg_Rt(id->idReg1());             // ttttt
9098             }
9099             code |= ((code_t)imm << 10);           // iiiiiiiiiiii
9100             code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9101             dst += emitOutput_Instr(dst, code);
9102             break;
9103
9104         case IF_LS_2C: // LS_2C   .X.......X.iiiii iiiiPPnnnnnttttt      Rt Rn    imm(-256..+255) no/pre/post inc
9105             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9106             imm = emitGetInsSC(id);
9107             assert((imm >= -256) && (imm <= 255)); // signed 9 bits
9108             imm &= 0x1ff;                          // force into unsigned 9 bit representation
9109             code = emitInsCode(ins, fmt);
9110             // Is the target a vector register?
9111             if (isVectorRegister(id->idReg1()))
9112             {
9113                 code &= 0x3FFFFFFF;                                 // clear the size bits
9114                 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9115                 code |= insEncodeReg_Vt(id->idReg1());              // ttttt
9116             }
9117             else
9118             {
9119                 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9120                 code |= insEncodeReg_Rt(id->idReg1());             // ttttt
9121             }
9122             code |= insEncodeIndexedOpt(id->idInsOpt()); // PP
9123             code |= ((code_t)imm << 12);                 // iiiiiiiii
9124             code |= insEncodeReg_Rn(id->idReg2());       // nnnnn
9125             dst += emitOutput_Instr(dst, code);
9126             break;
9127
9128         case IF_LS_3A: // LS_3A   .X.......X.mmmmm oooS..nnnnnttttt      Rt Rn Rm ext(Rm) LSL {}
9129             assert(insOptsLSExtend(id->idInsOpt()));
9130             code = emitInsCode(ins, fmt);
9131             // Is the target a vector register?
9132             if (isVectorRegister(id->idReg1()))
9133             {
9134                 code &= 0x3FFFFFFF;                                 // clear the size bits
9135                 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9136                 code |= insEncodeReg_Vt(id->idReg1());              // ttttt
9137             }
9138             else
9139             {
9140                 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9141                 code |= insEncodeReg_Rt(id->idReg1());             // ttttt
9142             }
9143             code |= insEncodeExtend(id->idInsOpt()); // ooo
9144             code |= insEncodeReg_Rn(id->idReg2());   // nnnnn
9145             if (id->idIsLclVar())
9146             {
9147                 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9148             }
9149             else
9150             {
9151                 code |= insEncodeReg3Scale(id->idReg3Scaled()); // S
9152                 code |= insEncodeReg_Rm(id->idReg3());          // mmmmm
9153             }
9154             dst += emitOutput_Instr(dst, code);
9155             break;
9156
9157         case IF_LS_3B: // LS_3B   X............... .aaaaannnnnddddd      Rd Ra Rn
9158             assert(insOptsNone(id->idInsOpt()));
9159             code = emitInsCode(ins, fmt);
9160             // Is the target a vector register?
9161             if (isVectorRegister(id->idReg1()))
9162             {
9163                 code &= 0x3FFFFFFF;                                  // clear the size bits
9164                 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9165                 code |= insEncodeReg_Vt(id->idReg1());               // ttttt
9166                 code |= insEncodeReg_Va(id->idReg2());               // aaaaa
9167             }
9168             else
9169             {
9170                 code |= insEncodeDatasize(id->idOpSize()); // X
9171                 code |= insEncodeReg_Rt(id->idReg1());     // ttttt
9172                 code |= insEncodeReg_Ra(id->idReg2());     // aaaaa
9173             }
9174             code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9175             dst += emitOutput_Instr(dst, code);
9176             break;
9177
9178         case IF_LS_3C: // LS_3C   X......PP.iiiiii iaaaaannnnnddddd      Rd Ra Rn imm(im7,sh)
9179             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9180             imm = emitGetInsSC(id);
9181             assert((imm >= -64) && (imm <= 63)); // signed 7 bits
9182             imm &= 0x7f;                         // force into unsigned 7 bit representation
9183             code = emitInsCode(ins, fmt);
9184             // Is the target a vector register?
9185             if (isVectorRegister(id->idReg1()))
9186             {
9187                 code &= 0x3FFFFFFF;                                  // clear the size bits
9188                 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9189                 code |= insEncodeReg_Vt(id->idReg1());               // ttttt
9190                 code |= insEncodeReg_Va(id->idReg2());               // aaaaa
9191             }
9192             else
9193             {
9194                 code |= insEncodeDatasize(id->idOpSize()); // X
9195                 code |= insEncodeReg_Rt(id->idReg1());     // ttttt
9196                 code |= insEncodeReg_Ra(id->idReg2());     // aaaaa
9197             }
9198             code |= insEncodePairIndexedOpt(ins, id->idInsOpt()); // PP
9199             code |= ((code_t)imm << 15);                          // iiiiiiiii
9200             code |= insEncodeReg_Rn(id->idReg3());                // nnnnn
9201             dst += emitOutput_Instr(dst, code);
9202             break;
9203
9204         case IF_LS_3D: // LS_3D   .X.......X.mmmmm ......nnnnnttttt      Wm Rt Rn
9205             code = emitInsCode(ins, fmt);
9206             // Arm64 store exclusive unpredictable cases
9207             assert(id->idReg1() != id->idReg2());
9208             assert(id->idReg1() != id->idReg3());
9209             code |= insEncodeDatasizeLS(code, id->idOpSize()); // X
9210             code |= insEncodeReg_Rm(id->idReg1());             // mmmmm
9211             code |= insEncodeReg_Rt(id->idReg2());             // ttttt
9212             code |= insEncodeReg_Rn(id->idReg3());             // nnnnn
9213             dst += emitOutput_Instr(dst, code);
9214             break;
9215
9216         case IF_DI_1A: // DI_1A   X.......shiiiiii iiiiiinnnnn.....         Rn    imm(i12,sh)
9217             assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9218             imm = emitGetInsSC(id);
9219             assert(isValidUimm12(imm));
9220             code = emitInsCode(ins, fmt);
9221             code |= insEncodeDatasize(id->idOpSize());   // X
9222             code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9223             code |= ((code_t)imm << 10);                 // iiiiiiiiiiii
9224             code |= insEncodeReg_Rn(id->idReg1());       // nnnnn
9225             dst += emitOutput_Instr(dst, code);
9226             break;
9227
9228         case IF_DI_1B: // DI_1B   X........hwiiiii iiiiiiiiiiiddddd      Rd       imm(i16,hw)
9229             imm = emitGetInsSC(id);
9230             assert(isValidImmHWVal(imm, id->idOpSize()));
9231             code = emitInsCode(ins, fmt);
9232             code |= insEncodeDatasize(id->idOpSize()); // X
9233             code |= ((code_t)imm << 5);                // hwiiiii iiiiiiiiiii
9234             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9235             dst += emitOutput_Instr(dst, code);
9236             break;
9237
9238         case IF_DI_1C: // DI_1C   X........Nrrrrrr ssssssnnnnn.....         Rn    imm(N,r,s)
9239             imm = emitGetInsSC(id);
9240             assert(isValidImmNRS(imm, id->idOpSize()));
9241             code = emitInsCode(ins, fmt);
9242             code |= ((code_t)imm << 10);               // Nrrrrrrssssss
9243             code |= insEncodeDatasize(id->idOpSize()); // X
9244             code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9245             dst += emitOutput_Instr(dst, code);
9246             break;
9247
9248         case IF_DI_1D: // DI_1D   X........Nrrrrrr ssssss.....ddddd      Rd       imm(N,r,s)
9249             imm = emitGetInsSC(id);
9250             assert(isValidImmNRS(imm, id->idOpSize()));
9251             code = emitInsCode(ins, fmt);
9252             code |= ((code_t)imm << 10);               // Nrrrrrrssssss
9253             code |= insEncodeDatasize(id->idOpSize()); // X
9254             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9255             dst += emitOutput_Instr(dst, code);
9256             break;
9257
9258         case IF_DI_1E: // DI_1E   .ii.....iiiiiiii iiiiiiiiiiiddddd      Rd       simm21
9259         case IF_LARGEADR:
9260             assert(insOptsNone(id->idInsOpt()));
9261             if (id->idIsReloc())
9262             {
9263                 code = emitInsCode(ins, fmt);
9264                 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9265                 dst += emitOutput_Instr(dst, code);
9266                 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEBASE_REL21);
9267             }
9268             else
9269             {
9270                 // Local jmp/load case which does not need a relocation.
9271                 assert(id->idIsBound());
9272                 dst = emitOutputLJ(ig, dst, id);
9273             }
9274             sz = sizeof(instrDescJmp);
9275             break;
9276
9277         case IF_DI_1F: // DI_1F   X..........iiiii cccc..nnnnn.nzcv      Rn imm5  nzcv cond
9278             imm = emitGetInsSC(id);
9279             assert(isValidImmCondFlagsImm5(imm));
9280             {
9281                 condFlagsImm cfi;
9282                 cfi.immCFVal = (unsigned)imm;
9283                 code         = emitInsCode(ins, fmt);
9284                 code |= insEncodeDatasize(id->idOpSize()); // X
9285                 code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9286                 code |= ((code_t)cfi.imm5 << 16);          // iiiii
9287                 code |= insEncodeFlags(cfi.flags);         // nzcv
9288                 code |= insEncodeCond(cfi.cond);           // cccc
9289                 dst += emitOutput_Instr(dst, code);
9290             }
9291             break;
9292
9293         case IF_DI_2A: // DI_2A   X.......shiiiiii iiiiiinnnnnddddd      Rd Rn    imm(i12,sh)
9294             assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9295             imm = emitGetInsSC(id);
9296             assert(isValidUimm12(imm));
9297             code = emitInsCode(ins, fmt);
9298             code |= insEncodeDatasize(id->idOpSize());   // X
9299             code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9300             code |= ((code_t)imm << 10);                 // iiiiiiiiiiii
9301             code |= insEncodeReg_Rd(id->idReg1());       // ddddd
9302             code |= insEncodeReg_Rn(id->idReg2());       // nnnnn
9303             dst += emitOutput_Instr(dst, code);
9304
9305             if (id->idIsReloc())
9306             {
9307                 assert(sz == sizeof(instrDesc));
9308                 assert(id->idAddr()->iiaAddr != nullptr);
9309                 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEOFFSET_12A);
9310             }
9311             break;
9312
9313         case IF_DI_2B: // DI_2B   X.........Xnnnnn ssssssnnnnnddddd      Rd Rn    imm(0-63)
9314             code = emitInsCode(ins, fmt);
9315             imm  = emitGetInsSC(id);
9316             assert(isValidImmShift(imm, id->idOpSize()));
9317             code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9318             code |= insEncodeReg_Rd(id->idReg1());             // ddddd
9319             code |= insEncodeReg_Rn(id->idReg2());             // nnnnn
9320             code |= insEncodeReg_Rm(id->idReg2());             // Reg2 also in mmmmm
9321             code |= insEncodeShiftCount(imm, id->idOpSize());  // ssssss
9322             dst += emitOutput_Instr(dst, code);
9323             break;
9324
9325         case IF_DI_2C: // DI_2C   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imm(N,r,s)
9326             imm = emitGetInsSC(id);
9327             assert(isValidImmNRS(imm, id->idOpSize()));
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_DI_2D: // DI_2D   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imr, imms   (N,r,s)
9337             if (ins == INS_asr || ins == INS_lsl || ins == INS_lsr)
9338             {
9339                 imm = emitGetInsSC(id);
9340                 assert(isValidImmShift(imm, id->idOpSize()));
9341
9342                 // Shift immediates are aliases of the SBFM/UBFM instructions
9343                 // that actually take 2 registers and 2 constants,
9344                 // Since we stored the shift immediate value
9345                 // we need to calculate the N,R and S values here.
9346
9347                 bitMaskImm bmi;
9348                 bmi.immNRS = 0;
9349
9350                 bmi.immN = (size == EA_8BYTE) ? 1 : 0;
9351                 bmi.immR = imm;
9352                 bmi.immS = (size == EA_8BYTE) ? 0x3f : 0x1f;
9353
9354                 // immR and immS are now set correctly for INS_asr and INS_lsr
9355                 // but for INS_lsl we have to adjust the values for immR and immS
9356                 //
9357                 if (ins == INS_lsl)
9358                 {
9359                     bmi.immR = -imm & bmi.immS;
9360                     bmi.immS = bmi.immS - imm;
9361                 }
9362
9363                 // setup imm with the proper 13 bit value N:R:S
9364                 //
9365                 imm = bmi.immNRS;
9366             }
9367             else
9368             {
9369                 // The other instructions have already have encoded N,R and S values
9370                 imm = emitGetInsSC(id);
9371             }
9372             assert(isValidImmNRS(imm, id->idOpSize()));
9373
9374             code = emitInsCode(ins, fmt);
9375             code |= ((code_t)imm << 10);               // Nrrrrrrssssss
9376             code |= insEncodeDatasize(id->idOpSize()); // X
9377             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9378             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9379             dst += emitOutput_Instr(dst, code);
9380             break;
9381
9382         case IF_DR_1D: // DR_1D   X............... cccc.......ddddd      Rd       cond
9383             imm = emitGetInsSC(id);
9384             assert(isValidImmCond(imm));
9385             {
9386                 condFlagsImm cfi;
9387                 cfi.immCFVal = (unsigned)imm;
9388                 code         = emitInsCode(ins, fmt);
9389                 code |= insEncodeDatasize(id->idOpSize()); // X
9390                 code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9391                 code |= insEncodeInvertedCond(cfi.cond);   // cccc
9392                 dst += emitOutput_Instr(dst, code);
9393             }
9394             break;
9395
9396         case IF_DR_2A: // DR_2A   X..........mmmmm ......nnnnn.....         Rn Rm
9397             assert(insOptsNone(id->idInsOpt()));
9398             code = emitInsCode(ins, fmt);
9399             code |= insEncodeDatasize(id->idOpSize()); // X
9400             code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9401             code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9402             dst += emitOutput_Instr(dst, code);
9403             break;
9404
9405         case IF_DR_2B: // DR_2B   X.......sh.mmmmm ssssssnnnnn.....         Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
9406             code = emitInsCode(ins, fmt);
9407             imm  = emitGetInsSC(id);
9408             assert(isValidImmShift(imm, id->idOpSize()));
9409             code |= insEncodeDatasize(id->idOpSize());        // X
9410             code |= insEncodeShiftType(id->idInsOpt());       // sh
9411             code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9412             code |= insEncodeReg_Rn(id->idReg1());            // nnnnn
9413             code |= insEncodeReg_Rm(id->idReg2());            // mmmmm
9414             dst += emitOutput_Instr(dst, code);
9415             break;
9416
9417         case IF_DR_2C: // DR_2C   X..........mmmmm ooosssnnnnn.....         Rn Rm ext(Rm) LSL imm(0-4)
9418             code = emitInsCode(ins, fmt);
9419             imm  = emitGetInsSC(id);
9420             assert((imm >= 0) && (imm <= 4));          // imm [0..4]
9421             code |= insEncodeDatasize(id->idOpSize()); // X
9422             code |= insEncodeExtend(id->idInsOpt());   // ooo
9423             code |= insEncodeExtendScale(imm);         // sss
9424             code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9425             code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9426             dst += emitOutput_Instr(dst, code);
9427             break;
9428
9429         case IF_DR_2D: // DR_2D   X..........nnnnn cccc..nnnnnddddd      Rd Rn    cond
9430             imm = emitGetInsSC(id);
9431             assert(isValidImmCond(imm));
9432             {
9433                 condFlagsImm cfi;
9434                 cfi.immCFVal = (unsigned)imm;
9435                 code         = emitInsCode(ins, fmt);
9436                 code |= insEncodeDatasize(id->idOpSize()); // X
9437                 code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9438                 code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9439                 code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9440                 code |= insEncodeInvertedCond(cfi.cond);   // cccc
9441                 dst += emitOutput_Instr(dst, code);
9442             }
9443             break;
9444
9445         case IF_DR_2E: // DR_2E   X..........mmmmm ...........ddddd      Rd    Rm
9446             code = emitInsCode(ins, fmt);
9447             code |= insEncodeDatasize(id->idOpSize()); // X
9448             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9449             code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9450             dst += emitOutput_Instr(dst, code);
9451             break;
9452
9453         case IF_DR_2F: // DR_2F   X.......sh.mmmmm ssssss.....ddddd      Rd    Rm {LSL,LSR,ASR} imm(0-63)
9454             code = emitInsCode(ins, fmt);
9455             imm  = emitGetInsSC(id);
9456             assert(isValidImmShift(imm, id->idOpSize()));
9457             code |= insEncodeDatasize(id->idOpSize());        // X
9458             code |= insEncodeShiftType(id->idInsOpt());       // sh
9459             code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9460             code |= insEncodeReg_Rd(id->idReg1());            // ddddd
9461             code |= insEncodeReg_Rm(id->idReg2());            // mmmmm
9462             dst += emitOutput_Instr(dst, code);
9463             break;
9464
9465         case IF_DR_2G: // DR_2G   X............... .....xnnnnnddddd      Rd Rn
9466             code = emitInsCode(ins, fmt);
9467             code |= insEncodeDatasize(id->idOpSize()); // X
9468             if (ins == INS_rev)
9469             {
9470                 if (size == EA_8BYTE)
9471                 {
9472                     code |= 0x00000400; // x - bit at location 10
9473                 }
9474             }
9475             code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9476             code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9477             dst += emitOutput_Instr(dst, code);
9478             break;
9479
9480         case IF_DR_2H: // DR_2H   X........X...... ......nnnnnddddd      Rd Rn
9481             code = emitInsCode(ins, fmt);
9482             code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9483             code |= insEncodeReg_Rd(id->idReg1());             // ddddd
9484             code |= insEncodeReg_Rn(id->idReg2());             // nnnnn
9485             dst += emitOutput_Instr(dst, code);
9486             break;
9487
9488         case IF_DR_2I: // DR_2I   X..........mmmmm cccc..nnnnn.nzcv      Rn Rm    nzcv cond
9489             imm = emitGetInsSC(id);
9490             assert(isValidImmCondFlags(imm));
9491             {
9492                 condFlagsImm cfi;
9493                 cfi.immCFVal = (unsigned)imm;
9494                 code         = emitInsCode(ins, fmt);
9495                 code |= insEncodeDatasize(id->idOpSize()); // X
9496                 code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9497                 code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9498                 code |= insEncodeFlags(cfi.flags);         // nzcv
9499                 code |= insEncodeCond(cfi.cond);           // cccc
9500                 dst += emitOutput_Instr(dst, code);
9501             }
9502             break;
9503
9504         case IF_DR_3A: // DR_3A   X..........mmmmm ......nnnnnmmmmm      Rd Rn Rm
9505             code = emitInsCode(ins, fmt);
9506             code |= insEncodeDatasize(id->idOpSize()); // X
9507             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9508             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9509             if (id->idIsLclVar())
9510             {
9511                 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9512             }
9513             else
9514             {
9515                 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9516             }
9517             dst += emitOutput_Instr(dst, code);
9518             break;
9519
9520         case IF_DR_3B: // DR_3B   X.......sh.mmmmm ssssssnnnnnddddd      Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
9521             code = emitInsCode(ins, fmt);
9522             imm  = emitGetInsSC(id);
9523             assert(isValidImmShift(imm, id->idOpSize()));
9524             code |= insEncodeDatasize(id->idOpSize());        // X
9525             code |= insEncodeReg_Rd(id->idReg1());            // ddddd
9526             code |= insEncodeReg_Rn(id->idReg2());            // nnnnn
9527             code |= insEncodeReg_Rm(id->idReg3());            // mmmmm
9528             code |= insEncodeShiftType(id->idInsOpt());       // sh
9529             code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9530             dst += emitOutput_Instr(dst, code);
9531             break;
9532
9533         case IF_DR_3C: // DR_3C   X..........mmmmm ooosssnnnnnddddd      Rd Rn Rm ext(Rm) LSL imm(0-4)
9534             code = emitInsCode(ins, fmt);
9535             imm  = emitGetInsSC(id);
9536             assert((imm >= 0) && (imm <= 4));          // imm [0..4]
9537             code |= insEncodeDatasize(id->idOpSize()); // X
9538             code |= insEncodeExtend(id->idInsOpt());   // ooo
9539             code |= insEncodeExtendScale(imm);         // sss
9540             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9541             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9542             code |= insEncodeReg_Rm(id->idReg3());     // mmmmm
9543             dst += emitOutput_Instr(dst, code);
9544             break;
9545
9546         case IF_DR_3D: // DR_3D   X..........mmmmm cccc..nnnnnddddd      Rd Rn Rm cond
9547             imm = emitGetInsSC(id);
9548             assert(isValidImmCond(imm));
9549             {
9550                 condFlagsImm cfi;
9551                 cfi.immCFVal = (unsigned)imm;
9552                 code         = emitInsCode(ins, fmt);
9553                 code |= insEncodeDatasize(id->idOpSize()); // X
9554                 code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9555                 code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9556                 code |= insEncodeReg_Rm(id->idReg3());     // mmmmm
9557                 code |= insEncodeCond(cfi.cond);           // cccc
9558                 dst += emitOutput_Instr(dst, code);
9559             }
9560             break;
9561
9562         case IF_DR_3E: // DR_3E   X........X.mmmmm ssssssnnnnnddddd      Rd Rn Rm imm(0-63)
9563             code = emitInsCode(ins, fmt);
9564             imm  = emitGetInsSC(id);
9565             assert(isValidImmShift(imm, id->idOpSize()));
9566             code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9567             code |= insEncodeReg_Rd(id->idReg1());             // ddddd
9568             code |= insEncodeReg_Rn(id->idReg2());             // nnnnn
9569             code |= insEncodeReg_Rm(id->idReg3());             // mmmmm
9570             code |= insEncodeShiftCount(imm, id->idOpSize());  // ssssss
9571             dst += emitOutput_Instr(dst, code);
9572             break;
9573
9574         case IF_DR_4A: // DR_4A   X..........mmmmm .aaaaannnnnmmmmm      Rd Rn Rm Ra
9575             code = emitInsCode(ins, fmt);
9576             code |= insEncodeDatasize(id->idOpSize()); // X
9577             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9578             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9579             code |= insEncodeReg_Rm(id->idReg3());     // mmmmm
9580             code |= insEncodeReg_Ra(id->idReg4());     // aaaaa
9581             dst += emitOutput_Instr(dst, code);
9582             break;
9583
9584         case IF_DV_1A: // DV_1A   .........X.iiiii iii........ddddd      Vd imm8    (fmov - immediate scalar)
9585             imm      = emitGetInsSC(id);
9586             elemsize = id->idOpSize();
9587             code     = emitInsCode(ins, fmt);
9588             code |= insEncodeFloatElemsize(elemsize); // X
9589             code |= ((code_t)imm << 13);              // iiiii iii
9590             code |= insEncodeReg_Vd(id->idReg1());    // ddddd
9591             dst += emitOutput_Instr(dst, code);
9592             break;
9593
9594         case IF_DV_1B: // DV_1B   .QX..........iii cmod..iiiiiddddd      Vd imm8    (immediate vector)
9595             imm      = emitGetInsSC(id) & 0x0ff;
9596             immShift = (emitGetInsSC(id) & 0x700) >> 8;
9597             elemsize = optGetElemsize(id->idInsOpt());
9598             cmode    = 0;
9599             switch (elemsize)
9600             { // cmode
9601                 case EA_1BYTE:
9602                     cmode = 0xE; // 1110
9603                     break;
9604                 case EA_2BYTE:
9605                     cmode = 0x8;
9606                     cmode |= (immShift << 1); // 10x0
9607                     break;
9608                 case EA_4BYTE:
9609                     if (immShift < 4)
9610                     {
9611                         cmode = 0x0;
9612                         cmode |= (immShift << 1); // 0xx0
9613                     }
9614                     else // MSL
9615                     {
9616                         cmode = 0xC;
9617                         if (immShift & 2)
9618                             cmode |= 1; // 110x
9619                     }
9620                     break;
9621                 case EA_8BYTE:
9622                     cmode = 0xE; // 1110
9623                     break;
9624                 default:
9625                     unreached();
9626                     break;
9627             }
9628
9629             code = emitInsCode(ins, fmt);
9630             code |= insEncodeVectorsize(id->idOpSize()); // Q
9631             if ((ins == INS_fmov) || (ins == INS_movi))
9632             {
9633                 if (elemsize == EA_8BYTE)
9634                 {
9635                     code |= 0x20000000; // X
9636                 }
9637             }
9638             if (ins != INS_fmov)
9639             {
9640                 assert((cmode >= 0) && (cmode <= 0xF));
9641                 code |= (cmode << 12); // cmod
9642             }
9643             code |= (((code_t)imm >> 5) << 16);    // iii
9644             code |= (((code_t)imm & 0x1f) << 5);   // iiiii
9645             code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9646             dst += emitOutput_Instr(dst, code);
9647             break;
9648
9649         case IF_DV_1C: // DV_1C   .........X...... ......nnnnn.....      Vn #0.0    (fcmp - with zero)
9650             elemsize = id->idOpSize();
9651             code     = emitInsCode(ins, fmt);
9652             code |= insEncodeFloatElemsize(elemsize); // X
9653             code |= insEncodeReg_Vn(id->idReg1());    // nnnnn
9654             dst += emitOutput_Instr(dst, code);
9655             break;
9656
9657         case IF_DV_2A: // DV_2A   .Q.......X...... ......nnnnnddddd      Vd Vn      (fabs, fcvt - vector)
9658             elemsize = optGetElemsize(id->idInsOpt());
9659             code     = emitInsCode(ins, fmt);
9660             code |= insEncodeVectorsize(id->idOpSize()); // Q
9661             code |= insEncodeFloatElemsize(elemsize);    // X
9662             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9663             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9664             dst += emitOutput_Instr(dst, code);
9665             break;
9666
9667         case IF_DV_2B: // DV_2B   .Q.........iiiii ......nnnnnddddd      Rd Vn[] (umov/smov    - to general)
9668             elemsize = id->idOpSize();
9669             index    = emitGetInsSC(id);
9670             datasize = (elemsize == EA_8BYTE) ? EA_16BYTE : EA_8BYTE;
9671             if (ins == INS_smov)
9672             {
9673                 datasize = EA_16BYTE;
9674             }
9675             code = emitInsCode(ins, fmt);
9676             code |= insEncodeVectorsize(datasize);         // Q
9677             code |= insEncodeVectorIndex(elemsize, index); // iiiii
9678             code |= insEncodeReg_Rd(id->idReg1());         // ddddd
9679             code |= insEncodeReg_Vn(id->idReg2());         // nnnnn
9680             dst += emitOutput_Instr(dst, code);
9681             break;
9682
9683         case IF_DV_2C: // DV_2C   .Q.........iiiii ......nnnnnddddd      Vd Rn   (dup/ins - vector from general)
9684             if (ins == INS_dup)
9685             {
9686                 datasize = id->idOpSize();
9687                 elemsize = optGetElemsize(id->idInsOpt());
9688                 index    = 0;
9689             }
9690             else // INS_ins
9691             {
9692                 datasize = EA_16BYTE;
9693                 elemsize = id->idOpSize();
9694                 index    = emitGetInsSC(id);
9695             }
9696             code = emitInsCode(ins, fmt);
9697             code |= insEncodeVectorsize(datasize);         // Q
9698             code |= insEncodeVectorIndex(elemsize, index); // iiiii
9699             code |= insEncodeReg_Vd(id->idReg1());         // ddddd
9700             code |= insEncodeReg_Rn(id->idReg2());         // nnnnn
9701             dst += emitOutput_Instr(dst, code);
9702             break;
9703
9704         case IF_DV_2D: // DV_2D   .Q.........iiiii ......nnnnnddddd      Vd Vn[]   (dup - vector)
9705             index    = emitGetInsSC(id);
9706             elemsize = optGetElemsize(id->idInsOpt());
9707             code     = emitInsCode(ins, fmt);
9708             code |= insEncodeVectorsize(id->idOpSize());   // Q
9709             code |= insEncodeVectorIndex(elemsize, index); // iiiii
9710             code |= insEncodeReg_Vd(id->idReg1());         // ddddd
9711             code |= insEncodeReg_Vn(id->idReg2());         // nnnnn
9712             dst += emitOutput_Instr(dst, code);
9713             break;
9714
9715         case IF_DV_2E: // DV_2E   ...........iiiii ......nnnnnddddd      Vd Vn[]   (dup - scalar)
9716             index    = emitGetInsSC(id);
9717             elemsize = id->idOpSize();
9718             code     = emitInsCode(ins, fmt);
9719             code |= insEncodeVectorIndex(elemsize, index); // iiiii
9720             code |= insEncodeReg_Vd(id->idReg1());         // ddddd
9721             code |= insEncodeReg_Vn(id->idReg2());         // nnnnn
9722             dst += emitOutput_Instr(dst, code);
9723             break;
9724
9725         case IF_DV_2F: // DV_2F   ...........iiiii .jjjj.nnnnnddddd      Vd[] Vn[] (ins - element)
9726             elemsize = id->idOpSize();
9727             imm      = emitGetInsSC(id);
9728             index    = (imm >> 4) & 0xf;
9729             index2   = imm & 0xf;
9730             code     = emitInsCode(ins, fmt);
9731             code |= insEncodeVectorIndex(elemsize, index);   // iiiii
9732             code |= insEncodeVectorIndex2(elemsize, index2); // jjjj
9733             code |= insEncodeReg_Vd(id->idReg1());           // ddddd
9734             code |= insEncodeReg_Vn(id->idReg2());           // nnnnn
9735             dst += emitOutput_Instr(dst, code);
9736             break;
9737
9738         case IF_DV_2G: // DV_2G   .........X...... ......nnnnnddddd      Vd Vn      (fmov,fcvtXX - register)
9739             elemsize = id->idOpSize();
9740             code     = emitInsCode(ins, fmt);
9741             code |= insEncodeFloatElemsize(elemsize); // X
9742             code |= insEncodeReg_Vd(id->idReg1());    // ddddd
9743             code |= insEncodeReg_Vn(id->idReg2());    // nnnnn
9744             dst += emitOutput_Instr(dst, code);
9745             break;
9746
9747         case IF_DV_2H: // DV_2H   X........X...... ......nnnnnddddd      Rd Vn      (fmov - to general)
9748             elemsize = id->idOpSize();
9749             code     = emitInsCode(ins, fmt);
9750             code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X   X
9751             code |= insEncodeReg_Rd(id->idReg1());            // ddddd
9752             code |= insEncodeReg_Vn(id->idReg2());            // nnnnn
9753             dst += emitOutput_Instr(dst, code);
9754             break;
9755
9756         case IF_DV_2I: // DV_2I   X........X...... ......nnnnnddddd      Vd Rn      (fmov - from general)
9757             elemsize = id->idOpSize();
9758             code     = emitInsCode(ins, fmt);
9759             code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X   X
9760             code |= insEncodeReg_Vd(id->idReg1());            // ddddd
9761             code |= insEncodeReg_Rn(id->idReg2());            // nnnnn
9762             dst += emitOutput_Instr(dst, code);
9763             break;
9764
9765         case IF_DV_2J: // DV_2J   ........SS.....D D.....nnnnnddddd      Vd Vn      (fcvt)
9766             code = emitInsCode(ins, fmt);
9767             code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // SS DD
9768             code |= insEncodeReg_Vd(id->idReg1());            // ddddd
9769             code |= insEncodeReg_Vn(id->idReg2());            // nnnnn
9770             dst += emitOutput_Instr(dst, code);
9771             break;
9772
9773         case IF_DV_2K: // DV_2K   .........X.mmmmm ......nnnnn.....      Vn Vm      (fcmp)
9774             elemsize = id->idOpSize();
9775             code     = emitInsCode(ins, fmt);
9776             code |= insEncodeFloatElemsize(elemsize); // X
9777             code |= insEncodeReg_Vn(id->idReg1());    // nnnnn
9778             code |= insEncodeReg_Vm(id->idReg2());    // mmmmm
9779             dst += emitOutput_Instr(dst, code);
9780             break;
9781
9782         case IF_DV_2L: // DV_2L   ........XX...... ......nnnnnddddd      Vd Vn      (abs, neg - scalar)
9783             elemsize = id->idOpSize();
9784             code     = emitInsCode(ins, fmt);
9785             code |= insEncodeElemsize(elemsize);   // XX
9786             code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9787             code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9788             dst += emitOutput_Instr(dst, code);
9789             break;
9790
9791         case IF_DV_2M: // DV_2M   .Q......XX...... ......nnnnnddddd      Vd Vn      (abs, neg   - vector)
9792             elemsize = optGetElemsize(id->idInsOpt());
9793             code     = emitInsCode(ins, fmt);
9794             code |= insEncodeVectorsize(id->idOpSize()); // Q
9795             code |= insEncodeElemsize(elemsize);         // XX
9796             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9797             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9798             dst += emitOutput_Instr(dst, code);
9799             break;
9800
9801         case IF_DV_2N: // DV_2N   .........iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - scalar)
9802             imm  = emitGetInsSC(id);
9803             code = emitInsCode(ins, fmt);
9804             code |= insEncodeVectorShift(EA_8BYTE, imm); // iiiiiii
9805             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9806             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9807             dst += emitOutput_Instr(dst, code);
9808             break;
9809
9810         case IF_DV_2O: // DV_2O   .Q.......iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - vector)
9811             imm      = emitGetInsSC(id);
9812             elemsize = optGetElemsize(id->idInsOpt());
9813             code     = emitInsCode(ins, fmt);
9814             code |= insEncodeVectorsize(id->idOpSize()); // Q
9815             code |= insEncodeVectorShift(elemsize, imm); // iiiiiii
9816             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9817             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9818             dst += emitOutput_Instr(dst, code);
9819             break;
9820
9821         case IF_DV_3A: // DV_3A   .Q......XX.mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
9822             code     = emitInsCode(ins, fmt);
9823             elemsize = optGetElemsize(id->idInsOpt());
9824             code |= insEncodeVectorsize(id->idOpSize()); // Q
9825             code |= insEncodeElemsize(elemsize);         // XX
9826             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9827             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9828             code |= insEncodeReg_Vm(id->idReg3());       // mmmmm
9829             dst += emitOutput_Instr(dst, code);
9830             break;
9831
9832         case IF_DV_3AI: // DV_3AI  .Q......XXLMmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector)
9833             code     = emitInsCode(ins, fmt);
9834             imm      = emitGetInsSC(id);
9835             elemsize = optGetElemsize(id->idInsOpt());
9836             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
9837             code |= insEncodeVectorsize(id->idOpSize());    // Q
9838             code |= insEncodeElemsize(elemsize);            // XX
9839             code |= insEncodeVectorIndexLMH(elemsize, imm); // LM H
9840             code |= insEncodeReg_Vd(id->idReg1());          // ddddd
9841             code |= insEncodeReg_Vn(id->idReg2());          // nnnnn
9842             code |= insEncodeReg_Vm(id->idReg3());          // mmmmm
9843             dst += emitOutput_Instr(dst, code);
9844             break;
9845
9846         case IF_DV_3B: // DV_3B   .Q.......X.mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
9847             code     = emitInsCode(ins, fmt);
9848             elemsize = optGetElemsize(id->idInsOpt());
9849             code |= insEncodeVectorsize(id->idOpSize()); // Q
9850             code |= insEncodeFloatElemsize(elemsize);    // X
9851             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9852             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9853             code |= insEncodeReg_Vm(id->idReg3());       // mmmmm
9854             dst += emitOutput_Instr(dst, code);
9855             break;
9856
9857         case IF_DV_3BI: // DV_3BI  .Q.......XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector by elem)
9858             code     = emitInsCode(ins, fmt);
9859             imm      = emitGetInsSC(id);
9860             elemsize = optGetElemsize(id->idInsOpt());
9861             assert(isValidVectorIndex(id->idOpSize(), elemsize, imm));
9862             code |= insEncodeVectorsize(id->idOpSize()); // Q
9863             code |= insEncodeFloatElemsize(elemsize);    // X
9864             code |= insEncodeFloatIndex(elemsize, imm);  // L H
9865             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9866             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9867             code |= insEncodeReg_Vm(id->idReg3());       // mmmmm
9868             dst += emitOutput_Instr(dst, code);
9869             break;
9870
9871         case IF_DV_3C: // DV_3C   .Q.........mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
9872             code = emitInsCode(ins, fmt);
9873             code |= insEncodeVectorsize(id->idOpSize()); // Q
9874             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9875             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9876             code |= insEncodeReg_Vm(id->idReg3());       // mmmmm
9877             dst += emitOutput_Instr(dst, code);
9878             break;
9879
9880         case IF_DV_3D: // DV_3D   .........X.mmmmm ......nnnnnddddd      Vd Vn Vm   (scalar)
9881             code = emitInsCode(ins, fmt);
9882             code |= insEncodeFloatElemsize(id->idOpSize()); // X
9883             code |= insEncodeReg_Vd(id->idReg1());          // ddddd
9884             code |= insEncodeReg_Vn(id->idReg2());          // nnnnn
9885             code |= insEncodeReg_Vm(id->idReg3());          // mmmmm
9886             dst += emitOutput_Instr(dst, code);
9887             break;
9888
9889         case IF_DV_3DI: // DV_3DI  .........XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (scalar by elem)
9890             code     = emitInsCode(ins, fmt);
9891             imm      = emitGetInsSC(id);
9892             elemsize = id->idOpSize();
9893             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
9894             code |= insEncodeFloatElemsize(elemsize);   // X
9895             code |= insEncodeFloatIndex(elemsize, imm); // L H
9896             code |= insEncodeReg_Vd(id->idReg1());      // ddddd
9897             code |= insEncodeReg_Vn(id->idReg2());      // nnnnn
9898             code |= insEncodeReg_Vm(id->idReg3());      // mmmmm
9899             dst += emitOutput_Instr(dst, code);
9900             break;
9901
9902         case IF_DV_3E: // DV_3E   ...........mmmmm ......nnnnnddddd      Vd Vn Vm   (scalar)
9903             code = emitInsCode(ins, fmt);
9904             code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9905             code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9906             code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9907             dst += emitOutput_Instr(dst, code);
9908             break;
9909
9910         case IF_DV_4A: // DV_4A   .........X.mmmmm .aaaaannnnnddddd      Vd Va Vn Vm (scalar)
9911             code     = emitInsCode(ins, fmt);
9912             elemsize = id->idOpSize();
9913             code |= insEncodeFloatElemsize(elemsize); // X
9914             code |= insEncodeReg_Vd(id->idReg1());    // ddddd
9915             code |= insEncodeReg_Vn(id->idReg2());    // nnnnn
9916             code |= insEncodeReg_Vm(id->idReg3());    // mmmmm
9917             code |= insEncodeReg_Va(id->idReg4());    // aaaaa
9918             dst += emitOutput_Instr(dst, code);
9919             break;
9920
9921         case IF_SN_0A: // SN_0A   ................ ................
9922             code = emitInsCode(ins, fmt);
9923             dst += emitOutput_Instr(dst, code);
9924             break;
9925
9926         case IF_SI_0A: // SI_0A   ...........iiiii iiiiiiiiiii.....               imm16
9927             imm = emitGetInsSC(id);
9928             assert(isValidUimm16(imm));
9929             code = emitInsCode(ins, fmt);
9930             code |= ((code_t)imm << 5); // iiiii iiiiiiiiiii
9931             dst += emitOutput_Instr(dst, code);
9932             break;
9933
9934         case IF_SI_0B: // SI_0B   ................ ....bbbb........               imm4 - barrier
9935             imm = emitGetInsSC(id);
9936             assert((imm >= 0) && (imm <= 15));
9937             code = emitInsCode(ins, fmt);
9938             code |= ((code_t)imm << 8); // bbbb
9939             dst += emitOutput_Instr(dst, code);
9940             break;
9941
9942         default:
9943             assert(!"Unexpected format");
9944             break;
9945     }
9946
9947     // Determine if any registers now hold GC refs, or whether a register that was overwritten held a GC ref.
9948     // We assume here that "id->idGCref()" is not GC_NONE only if the instruction described by "id" writes a
9949     // GC ref to register "id->idReg1()".  (It may, apparently, also not be GC_NONE in other cases, such as
9950     // for stores, but we ignore those cases here.)
9951     if (emitInsMayWriteToGCReg(id)) // True if "id->idIns()" writes to a register than can hold GC ref.
9952     {
9953         // We assume that "idReg1" is the primary destination register for all instructions
9954         if (id->idGCref() != GCT_NONE)
9955         {
9956             emitGCregLiveUpd(id->idGCref(), id->idReg1(), dst);
9957         }
9958         else
9959         {
9960             emitGCregDeadUpd(id->idReg1(), dst);
9961         }
9962
9963         if (emitInsMayWriteMultipleRegs(id))
9964         {
9965             // INS_ldp etc...
9966             // "idReg2" is the secondary destination register
9967             if (id->idGCrefReg2() != GCT_NONE)
9968             {
9969                 emitGCregLiveUpd(id->idGCrefReg2(), id->idReg2(), dst);
9970             }
9971             else
9972             {
9973                 emitGCregDeadUpd(id->idReg2(), dst);
9974             }
9975         }
9976     }
9977
9978     // Now we determine if the instruction has written to a (local variable) stack location, and either written a GC
9979     // ref or overwritten one.
9980     if (emitInsWritesToLclVarStackLoc(id) || emitInsWritesToLclVarStackLocPair(id))
9981     {
9982         int      varNum = id->idAddr()->iiaLclVar.lvaVarNum();
9983         unsigned ofs    = AlignDown(id->idAddr()->iiaLclVar.lvaOffset(), TARGET_POINTER_SIZE);
9984         bool     FPbased;
9985         int      adr = emitComp->lvaFrameAddress(varNum, &FPbased);
9986         if (id->idGCref() != GCT_NONE)
9987         {
9988             emitGCvarLiveUpd(adr + ofs, varNum, id->idGCref(), dst);
9989         }
9990         else
9991         {
9992             // If the type of the local is a gc ref type, update the liveness.
9993             var_types vt;
9994             if (varNum >= 0)
9995             {
9996                 // "Regular" (non-spill-temp) local.
9997                 vt = var_types(emitComp->lvaTable[varNum].lvType);
9998             }
9999             else
10000             {
10001                 TempDsc* tmpDsc = emitComp->tmpFindNum(varNum);
10002                 vt              = tmpDsc->tdTempType();
10003             }
10004             if (vt == TYP_REF || vt == TYP_BYREF)
10005                 emitGCvarDeadUpd(adr + ofs, dst);
10006         }
10007         if (emitInsWritesToLclVarStackLocPair(id))
10008         {
10009             unsigned ofs2 = ofs + TARGET_POINTER_SIZE;
10010             if (id->idGCrefReg2() != GCT_NONE)
10011             {
10012                 emitGCvarLiveUpd(adr + ofs2, varNum, id->idGCrefReg2(), dst);
10013             }
10014             else
10015             {
10016                 // If the type of the local is a gc ref type, update the liveness.
10017                 var_types vt;
10018                 if (varNum >= 0)
10019                 {
10020                     // "Regular" (non-spill-temp) local.
10021                     vt = var_types(emitComp->lvaTable[varNum].lvType);
10022                 }
10023                 else
10024                 {
10025                     TempDsc* tmpDsc = emitComp->tmpFindNum(varNum);
10026                     vt              = tmpDsc->tdTempType();
10027                 }
10028                 if (vt == TYP_REF || vt == TYP_BYREF)
10029                     emitGCvarDeadUpd(adr + ofs2, dst);
10030             }
10031         }
10032     }
10033
10034 #ifdef DEBUG
10035     /* Make sure we set the instruction descriptor size correctly */
10036
10037     size_t expected = emitSizeOfInsDsc(id);
10038     assert(sz == expected);
10039
10040     if (emitComp->opts.disAsm || emitComp->opts.dspEmit || emitComp->verbose)
10041     {
10042         emitDispIns(id, false, dspOffs, true, emitCurCodeOffs(odst), *dp, (dst - *dp), ig);
10043     }
10044
10045     if (emitComp->compDebugBreak)
10046     {
10047         // For example, set JitBreakEmitOutputInstr=a6 will break when this method is called for
10048         // emitting instruction a6, (i.e. IN00a6 in jitdump).
10049         if ((unsigned)JitConfig.JitBreakEmitOutputInstr() == id->idDebugOnlyInfo()->idNum)
10050         {
10051             assert(!"JitBreakEmitOutputInstr reached");
10052         }
10053     }
10054 #endif
10055
10056     /* All instructions are expected to generate code */
10057
10058     assert(*dp != dst);
10059
10060     *dp = dst;
10061
10062     return sz;
10063 }
10064
10065 /*****************************************************************************/
10066 /*****************************************************************************/
10067
10068 #ifdef DEBUG
10069
10070 /*****************************************************************************
10071  *
10072  *  Display the instruction name
10073  */
10074 void emitter::emitDispInst(instruction ins)
10075 {
10076     const char* insstr = codeGen->genInsName(ins);
10077     size_t      len    = strlen(insstr);
10078
10079     /* Display the instruction name */
10080
10081     printf("%s", insstr);
10082
10083     //
10084     // Add at least one space after the instruction name
10085     // and add spaces until we have reach the normal size of 8
10086     do
10087     {
10088         printf(" ");
10089         len++;
10090     } while (len < 8);
10091 }
10092
10093 /*****************************************************************************
10094  *
10095  *  Display an reloc value
10096  *  If we are formatting for an assembly listing don't print the hex value
10097  *  since it will prevent us from doing assembly diffs
10098  */
10099 void emitter::emitDispReloc(int value, bool addComma)
10100 {
10101     if (emitComp->opts.disAsm)
10102     {
10103         printf("(reloc)");
10104     }
10105     else
10106     {
10107         printf("(reloc 0x%x)", dspPtr(value));
10108     }
10109
10110     if (addComma)
10111         printf(", ");
10112 }
10113
10114 /*****************************************************************************
10115  *
10116  *  Display an immediate value
10117  */
10118 void emitter::emitDispImm(ssize_t imm, bool addComma, bool alwaysHex /* =false */)
10119 {
10120     if (strictArmAsm)
10121     {
10122         printf("#");
10123     }
10124
10125     // Munge any pointers if we want diff-able disassembly.
10126     // Since some may be emitted as partial words, print as diffable anything that has
10127     // significant bits beyond the lowest 8-bits.
10128     if (emitComp->opts.disDiffable)
10129     {
10130         ssize_t top56bits = (imm >> 8);
10131         if ((top56bits != 0) && (top56bits != -1))
10132             imm = 0xD1FFAB1E;
10133     }
10134
10135     if (!alwaysHex && (imm > -1000) && (imm < 1000))
10136     {
10137         printf("%d", imm);
10138     }
10139     else
10140     {
10141         if ((imm < 0) && ((imm & 0xFFFFFFFF00000000LL) == 0xFFFFFFFF00000000LL))
10142         {
10143             printf("-");
10144             imm = -imm;
10145         }
10146
10147         if ((imm & 0xFFFFFFFF00000000LL) != 0)
10148         {
10149             printf("0x%llx", imm);
10150         }
10151         else
10152         {
10153             printf("0x%02x", imm);
10154         }
10155     }
10156
10157     if (addComma)
10158         printf(", ");
10159 }
10160
10161 /*****************************************************************************
10162  *
10163  *  Display a float zero constant
10164  */
10165 void emitter::emitDispFloatZero()
10166 {
10167     if (strictArmAsm)
10168     {
10169         printf("#");
10170     }
10171     printf("0.0");
10172 }
10173
10174 /*****************************************************************************
10175  *
10176  *  Display an encoded float constant value
10177  */
10178 void emitter::emitDispFloatImm(ssize_t imm8)
10179 {
10180     assert((0 <= imm8) && (imm8 <= 0x0ff));
10181     if (strictArmAsm)
10182     {
10183         printf("#");
10184     }
10185
10186     floatImm8 fpImm;
10187     fpImm.immFPIVal = (unsigned)imm8;
10188     double result   = emitDecodeFloatImm8(fpImm);
10189
10190     printf("%.4f", result);
10191 }
10192
10193 /*****************************************************************************
10194  *
10195  *  Display an immediate that is optionally LSL12.
10196  */
10197 void emitter::emitDispImmOptsLSL12(ssize_t imm, insOpts opt)
10198 {
10199     if (!strictArmAsm && insOptsLSL12(opt))
10200     {
10201         imm <<= 12;
10202     }
10203     emitDispImm(imm, false);
10204     if (strictArmAsm && insOptsLSL12(opt))
10205     {
10206         printf(", LSL #12");
10207     }
10208 }
10209
10210 /*****************************************************************************
10211  *
10212  *  Display an ARM64 condition code for the conditional instructions
10213  */
10214 void emitter::emitDispCond(insCond cond)
10215 {
10216     const static char* armCond[16] = {"eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc",
10217                                       "hi", "ls", "ge", "lt", "gt", "le", "AL", "NV"}; // The last two are invalid
10218     unsigned imm = (unsigned)cond;
10219     assert((0 <= imm) && (imm < ArrLen(armCond)));
10220     printf(armCond[imm]);
10221 }
10222
10223 /*****************************************************************************
10224  *
10225  *  Display an ARM64 flags for the conditional instructions
10226  */
10227 void emitter::emitDispFlags(insCflags flags)
10228 {
10229     const static char* armFlags[16] = {"0", "v",  "c",  "cv",  "z",  "zv",  "zc",  "zcv",
10230                                        "n", "nv", "nc", "ncv", "nz", "nzv", "nzc", "nzcv"};
10231     unsigned imm = (unsigned)flags;
10232     assert((0 <= imm) && (imm < ArrLen(armFlags)));
10233     printf(armFlags[imm]);
10234 }
10235
10236 /*****************************************************************************
10237  *
10238  *  Display an ARM64 'barrier' for the memory barrier instructions
10239  */
10240 void emitter::emitDispBarrier(insBarrier barrier)
10241 {
10242     const static char* armBarriers[16] = {"#0", "oshld", "oshst", "osh", "#4",  "nshld", "nshst", "nsh",
10243                                           "#8", "ishld", "ishst", "ish", "#12", "ld",    "st",    "sy"};
10244     unsigned imm = (unsigned)barrier;
10245     assert((0 <= imm) && (imm < ArrLen(armBarriers)));
10246     printf(armBarriers[imm]);
10247 }
10248
10249 /*****************************************************************************
10250  *
10251  *  Prints the encoding for the Shift Type encoding
10252  */
10253
10254 void emitter::emitDispShiftOpts(insOpts opt)
10255 {
10256     if (opt == INS_OPTS_LSL)
10257         printf(" LSL ");
10258     else if (opt == INS_OPTS_LSR)
10259         printf(" LSR ");
10260     else if (opt == INS_OPTS_ASR)
10261         printf(" ASR ");
10262     else if (opt == INS_OPTS_ROR)
10263         printf(" ROR ");
10264     else if (opt == INS_OPTS_MSL)
10265         printf(" MSL ");
10266     else
10267         assert(!"Bad value");
10268 }
10269
10270 /*****************************************************************************
10271  *
10272  *  Prints the encoding for the Extend Type encoding
10273  */
10274
10275 void emitter::emitDispExtendOpts(insOpts opt)
10276 {
10277     if (opt == INS_OPTS_UXTB)
10278         printf("UXTB");
10279     else if (opt == INS_OPTS_UXTH)
10280         printf("UXTH");
10281     else if (opt == INS_OPTS_UXTW)
10282         printf("UXTW");
10283     else if (opt == INS_OPTS_UXTX)
10284         printf("UXTX");
10285     else if (opt == INS_OPTS_SXTB)
10286         printf("SXTB");
10287     else if (opt == INS_OPTS_SXTH)
10288         printf("SXTH");
10289     else if (opt == INS_OPTS_SXTW)
10290         printf("SXTW");
10291     else if (opt == INS_OPTS_SXTX)
10292         printf("SXTX");
10293     else
10294         assert(!"Bad value");
10295 }
10296
10297 /*****************************************************************************
10298  *
10299  *  Prints the encoding for the Extend Type encoding in loads/stores
10300  */
10301
10302 void emitter::emitDispLSExtendOpts(insOpts opt)
10303 {
10304     if (opt == INS_OPTS_LSL)
10305         printf("LSL");
10306     else if (opt == INS_OPTS_UXTW)
10307         printf("UXTW");
10308     else if (opt == INS_OPTS_UXTX)
10309         printf("UXTX");
10310     else if (opt == INS_OPTS_SXTW)
10311         printf("SXTW");
10312     else if (opt == INS_OPTS_SXTX)
10313         printf("SXTX");
10314     else
10315         assert(!"Bad value");
10316 }
10317
10318 /*****************************************************************************
10319  *
10320  *  Display a register
10321  */
10322 void emitter::emitDispReg(regNumber reg, emitAttr attr, bool addComma)
10323 {
10324     emitAttr size = EA_SIZE(attr);
10325     printf(emitRegName(reg, size));
10326
10327     if (addComma)
10328         printf(", ");
10329 }
10330
10331 /*****************************************************************************
10332  *
10333  *  Display a vector register with an arrangement suffix
10334  */
10335 void emitter::emitDispVectorReg(regNumber reg, insOpts opt, bool addComma)
10336 {
10337     assert(isVectorRegister(reg));
10338     printf(emitVectorRegName(reg));
10339     emitDispArrangement(opt);
10340
10341     if (addComma)
10342         printf(", ");
10343 }
10344
10345 /*****************************************************************************
10346  *
10347  *  Display an vector register index suffix
10348  */
10349 void emitter::emitDispVectorRegIndex(regNumber reg, emitAttr elemsize, ssize_t index, bool addComma)
10350 {
10351     assert(isVectorRegister(reg));
10352     printf(emitVectorRegName(reg));
10353
10354     switch (elemsize)
10355     {
10356         case EA_1BYTE:
10357             printf(".b");
10358             break;
10359         case EA_2BYTE:
10360             printf(".h");
10361             break;
10362         case EA_4BYTE:
10363             printf(".s");
10364             break;
10365         case EA_8BYTE:
10366             printf(".d");
10367             break;
10368         default:
10369             assert(!"invalid elemsize");
10370             break;
10371     }
10372
10373     printf("[%d]", index);
10374
10375     if (addComma)
10376         printf(", ");
10377 }
10378
10379 /*****************************************************************************
10380  *
10381  *  Display an arrangement suffix
10382  */
10383 void emitter::emitDispArrangement(insOpts opt)
10384 {
10385     const char* str = "???";
10386
10387     switch (opt)
10388     {
10389         case INS_OPTS_8B:
10390             str = "8b";
10391             break;
10392         case INS_OPTS_16B:
10393             str = "16b";
10394             break;
10395         case INS_OPTS_4H:
10396             str = "4h";
10397             break;
10398         case INS_OPTS_8H:
10399             str = "8h";
10400             break;
10401         case INS_OPTS_2S:
10402             str = "2s";
10403             break;
10404         case INS_OPTS_4S:
10405             str = "4s";
10406             break;
10407         case INS_OPTS_1D:
10408             str = "1d";
10409             break;
10410         case INS_OPTS_2D:
10411             str = "2d";
10412             break;
10413
10414         default:
10415             assert(!"Invalid insOpt for vector register");
10416     }
10417     printf(".");
10418     printf(str);
10419 }
10420
10421 /*****************************************************************************
10422  *
10423  *  Display a register with an optional shift operation
10424  */
10425 void emitter::emitDispShiftedReg(regNumber reg, insOpts opt, ssize_t imm, emitAttr attr)
10426 {
10427     emitAttr size = EA_SIZE(attr);
10428     assert((imm & 0x003F) == imm);
10429     assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
10430
10431     printf(emitRegName(reg, size));
10432
10433     if (imm > 0)
10434     {
10435         if (strictArmAsm)
10436         {
10437             printf(",");
10438         }
10439         emitDispShiftOpts(opt);
10440         emitDispImm(imm, false);
10441     }
10442 }
10443
10444 /*****************************************************************************
10445  *
10446  *  Display a register with an optional extend and scale operations
10447  */
10448 void emitter::emitDispExtendReg(regNumber reg, insOpts opt, ssize_t imm)
10449 {
10450     assert((imm >= 0) && (imm <= 4));
10451     assert(insOptsNone(opt) || insOptsAnyExtend(opt) || (opt == INS_OPTS_LSL));
10452
10453     // size is based on the extend option, not the instr size.
10454     emitAttr size = insOpts32BitExtend(opt) ? EA_4BYTE : EA_8BYTE;
10455
10456     if (strictArmAsm)
10457     {
10458         if (insOptsNone(opt))
10459         {
10460             emitDispReg(reg, size, false);
10461         }
10462         else
10463         {
10464             emitDispReg(reg, size, true);
10465             if (opt == INS_OPTS_LSL)
10466                 printf("LSL");
10467             else
10468                 emitDispExtendOpts(opt);
10469             if ((imm > 0) || (opt == INS_OPTS_LSL))
10470             {
10471                 printf(" ");
10472                 emitDispImm(imm, false);
10473             }
10474         }
10475     }
10476     else // !strictArmAsm
10477     {
10478         if (insOptsNone(opt))
10479         {
10480             emitDispReg(reg, size, false);
10481         }
10482         else
10483         {
10484             if (opt != INS_OPTS_LSL)
10485             {
10486                 emitDispExtendOpts(opt);
10487                 printf("(");
10488                 emitDispReg(reg, size, false);
10489                 printf(")");
10490             }
10491         }
10492         if (imm > 0)
10493         {
10494             printf("*");
10495             emitDispImm(1 << imm, false);
10496         }
10497     }
10498 }
10499
10500 /*****************************************************************************
10501  *
10502  *  Display an addressing operand [reg + imm]
10503  */
10504 void emitter::emitDispAddrRI(regNumber reg, insOpts opt, ssize_t imm)
10505 {
10506     reg = encodingZRtoSP(reg); // ZR (R31) encodes the SP register
10507
10508     if (strictArmAsm)
10509     {
10510         printf("[");
10511
10512         emitDispReg(reg, EA_8BYTE, false);
10513
10514         if (!insOptsPostIndex(opt) && (imm != 0))
10515         {
10516             printf(",");
10517             emitDispImm(imm, false);
10518         }
10519         printf("]");
10520
10521         if (insOptsPreIndex(opt))
10522         {
10523             printf("!");
10524         }
10525         else if (insOptsPostIndex(opt))
10526         {
10527             printf(",");
10528             emitDispImm(imm, false);
10529         }
10530     }
10531     else // !strictArmAsm
10532     {
10533         printf("[");
10534
10535         const char* operStr = "++";
10536         if (imm < 0)
10537         {
10538             operStr = "--";
10539             imm     = -imm;
10540         }
10541
10542         if (insOptsPreIndex(opt))
10543         {
10544             printf(operStr);
10545         }
10546
10547         emitDispReg(reg, EA_8BYTE, false);
10548
10549         if (insOptsPostIndex(opt))
10550         {
10551             printf(operStr);
10552         }
10553
10554         if (insOptsIndexed(opt))
10555         {
10556             printf(", ");
10557         }
10558         else
10559         {
10560             printf("%c", operStr[1]);
10561         }
10562         emitDispImm(imm, false);
10563         printf("]");
10564     }
10565 }
10566
10567 /*****************************************************************************
10568  *
10569  *  Display an addressing operand [reg + extended reg]
10570  */
10571 void emitter::emitDispAddrRRExt(regNumber reg1, regNumber reg2, insOpts opt, bool isScaled, emitAttr size)
10572 {
10573     reg1 = encodingZRtoSP(reg1); // ZR (R31) encodes the SP register
10574
10575     unsigned scale = 0;
10576     if (isScaled)
10577     {
10578         scale = NaturalScale_helper(size);
10579     }
10580
10581     printf("[");
10582
10583     if (strictArmAsm)
10584     {
10585         emitDispReg(reg1, EA_8BYTE, true);
10586         emitDispExtendReg(reg2, opt, scale);
10587     }
10588     else // !strictArmAsm
10589     {
10590         emitDispReg(reg1, EA_8BYTE, false);
10591         printf("+");
10592         emitDispExtendReg(reg2, opt, scale);
10593     }
10594
10595     printf("]");
10596 }
10597
10598 /*****************************************************************************
10599  *
10600  *  Display (optionally) the instruction encoding in hex
10601  */
10602
10603 void emitter::emitDispInsHex(BYTE* code, size_t sz)
10604 {
10605     // We do not display the instruction hex if we want diff-able disassembly
10606     if (!emitComp->opts.disDiffable)
10607     {
10608         if (sz == 4)
10609         {
10610             printf("  %08X    ", (*((code_t*)code)));
10611         }
10612         else
10613         {
10614             printf("              ");
10615         }
10616     }
10617 }
10618
10619 /****************************************************************************
10620  *
10621  *  Display the given instruction.
10622  */
10623
10624 void emitter::emitDispIns(
10625     instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* pCode, size_t sz, insGroup* ig)
10626 {
10627     if (EMITVERBOSE)
10628     {
10629         unsigned idNum =
10630             id->idDebugOnlyInfo()->idNum; // Do not remove this!  It is needed for VisualStudio conditional breakpoints
10631
10632         printf("IN%04x: ", idNum);
10633     }
10634
10635     if (pCode == NULL)
10636         sz = 0;
10637
10638     if (!emitComp->opts.dspEmit && !isNew && !asmfm && sz)
10639         doffs = true;
10640
10641     /* Display the instruction offset */
10642
10643     emitDispInsOffs(offset, doffs);
10644
10645     /* Display the instruction hex code */
10646
10647     emitDispInsHex(pCode, sz);
10648
10649     printf("      ");
10650
10651     /* Get the instruction and format */
10652
10653     instruction ins = id->idIns();
10654     insFormat   fmt = id->idInsFmt();
10655
10656     emitDispInst(ins);
10657
10658     /* If this instruction has just been added, check its size */
10659
10660     assert(isNew == false || (int)emitSizeOfInsDsc(id) == emitCurIGfreeNext - (BYTE*)id);
10661
10662     /* Figure out the operand size */
10663     emitAttr size = id->idOpSize();
10664     emitAttr attr = size;
10665     if (id->idGCref() == GCT_GCREF)
10666         attr = EA_GCREF;
10667     else if (id->idGCref() == GCT_BYREF)
10668         attr = EA_BYREF;
10669
10670     switch (fmt)
10671     {
10672         code_t       code;
10673         ssize_t      imm;
10674         int          doffs;
10675         bool         isExtendAlias;
10676         bool         canEncode;
10677         bitMaskImm   bmi;
10678         halfwordImm  hwi;
10679         condFlagsImm cfi;
10680         unsigned     scale;
10681         unsigned     immShift;
10682         bool         hasShift;
10683         ssize_t      offs;
10684         const char*  methodName;
10685         emitAttr     elemsize;
10686         emitAttr     datasize;
10687         emitAttr     srcsize;
10688         emitAttr     dstsize;
10689         ssize_t      index;
10690         ssize_t      index2;
10691
10692         case IF_BI_0A: // BI_0A   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
10693         case IF_BI_0B: // BI_0B   ......iiiiiiiiii iiiiiiiiiii.....               simm19:00
10694         case IF_LARGEJMP:
10695         {
10696             if (fmt == IF_LARGEJMP)
10697             {
10698                 printf("(LARGEJMP)");
10699             }
10700             if (id->idAddr()->iiaHasInstrCount())
10701             {
10702                 int instrCount = id->idAddr()->iiaGetInstrCount();
10703
10704                 if (ig == nullptr)
10705                 {
10706                     printf("pc%s%d instructions", (instrCount >= 0) ? "+" : "", instrCount);
10707                 }
10708                 else
10709                 {
10710                     unsigned       insNum  = emitFindInsNum(ig, id);
10711                     UNATIVE_OFFSET srcOffs = ig->igOffs + emitFindOffset(ig, insNum + 1);
10712                     UNATIVE_OFFSET dstOffs = ig->igOffs + emitFindOffset(ig, insNum + 1 + instrCount);
10713                     ssize_t        relOffs = (ssize_t)(emitOffsetToPtr(dstOffs) - emitOffsetToPtr(srcOffs));
10714                     printf("pc%s%d (%d instructions)", (relOffs >= 0) ? "+" : "", relOffs, instrCount);
10715                 }
10716             }
10717             else if (id->idIsBound())
10718             {
10719                 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10720             }
10721             else
10722             {
10723                 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10724             }
10725         }
10726         break;
10727
10728         case IF_BI_0C: // BI_0C   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
10729             if (id->idIsCallAddr())
10730             {
10731                 offs       = (ssize_t)id->idAddr()->iiaAddr;
10732                 methodName = "";
10733             }
10734             else
10735             {
10736                 offs       = 0;
10737                 methodName = emitComp->eeGetMethodFullName((CORINFO_METHOD_HANDLE)id->idDebugOnlyInfo()->idMemCookie);
10738             }
10739
10740             if (offs)
10741             {
10742                 if (id->idIsDspReloc())
10743                     printf("reloc ");
10744                 printf("%08X", offs);
10745             }
10746             else
10747             {
10748                 printf("%s", methodName);
10749             }
10750             break;
10751
10752         case IF_BI_1A: // BI_1A   ......iiiiiiiiii iiiiiiiiiiittttt      Rt       simm19:00
10753             assert(insOptsNone(id->idInsOpt()));
10754             emitDispReg(id->idReg1(), size, true);
10755             if (id->idIsBound())
10756             {
10757                 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10758             }
10759             else
10760             {
10761                 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10762             }
10763             break;
10764
10765         case IF_BI_1B: // BI_1B   B.......bbbbbiii iiiiiiiiiiittttt      Rt imm6, simm14:00
10766             assert(insOptsNone(id->idInsOpt()));
10767             emitDispReg(id->idReg1(), size, true);
10768             emitDispImm(emitGetInsSC(id), true);
10769             if (id->idIsBound())
10770             {
10771                 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10772             }
10773             else
10774             {
10775                 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10776             }
10777             break;
10778
10779         case IF_BR_1A: // BR_1A   ................ ......nnnnn.....         Rn
10780             assert(insOptsNone(id->idInsOpt()));
10781             emitDispReg(id->idReg1(), size, false);
10782             break;
10783
10784         case IF_BR_1B: // BR_1B   ................ ......nnnnn.....         Rn
10785             assert(insOptsNone(id->idInsOpt()));
10786             emitDispReg(id->idReg3(), size, false);
10787             break;
10788
10789         case IF_LS_1A: // LS_1A   XX...V..iiiiiiii iiiiiiiiiiittttt      Rt    PC imm(1MB)
10790         case IF_DI_1E: // DI_1E   .ii.....iiiiiiii iiiiiiiiiiiddddd      Rd       simm21
10791         case IF_LARGELDC:
10792         case IF_LARGEADR:
10793             assert(insOptsNone(id->idInsOpt()));
10794             emitDispReg(id->idReg1(), size, true);
10795             imm = emitGetInsSC(id);
10796
10797             /* Is this actually a reference to a data section? */
10798             if (fmt == IF_LARGEADR)
10799             {
10800                 printf("(LARGEADR)");
10801             }
10802             else if (fmt == IF_LARGELDC)
10803             {
10804                 printf("(LARGELDC)");
10805             }
10806
10807             printf("[");
10808             if (id->idAddr()->iiaIsJitDataOffset())
10809             {
10810                 doffs = Compiler::eeGetJitDataOffs(id->idAddr()->iiaFieldHnd);
10811                 /* Display a data section reference */
10812
10813                 if (doffs & 1)
10814                     printf("@CNS%02u", doffs - 1);
10815                 else
10816                     printf("@RWD%02u", doffs);
10817
10818                 if (imm != 0)
10819                     printf("%+Id", imm);
10820             }
10821             else
10822             {
10823                 assert(imm == 0);
10824                 if (id->idIsReloc())
10825                 {
10826                     printf("RELOC ");
10827                     emitDispImm((ssize_t)id->idAddr()->iiaAddr, false);
10828                 }
10829                 else if (id->idIsBound())
10830                 {
10831                     printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10832                 }
10833                 else
10834                 {
10835                     printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10836                 }
10837             }
10838             printf("]");
10839             break;
10840
10841         case IF_LS_2A: // LS_2A   .X.......X...... ......nnnnnttttt      Rt Rn
10842             assert(insOptsNone(id->idInsOpt()));
10843             assert(emitGetInsSC(id) == 0);
10844             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10845             emitDispAddrRI(id->idReg2(), id->idInsOpt(), 0);
10846             break;
10847
10848         case IF_LS_2B: // LS_2B   .X.......Xiiiiii iiiiiinnnnnttttt      Rt Rn    imm(0-4095)
10849             assert(insOptsNone(id->idInsOpt()));
10850             imm   = emitGetInsSC(id);
10851             scale = NaturalScale_helper(emitInsLoadStoreSize(id));
10852             imm <<= scale; // The immediate is scaled by the size of the ld/st
10853             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10854             emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
10855             break;
10856
10857         case IF_LS_2C: // LS_2C   .X.......X.iiiii iiiiPPnnnnnttttt      Rt Rn    imm(-256..+255) no/pre/post inc
10858             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
10859             imm = emitGetInsSC(id);
10860             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10861             emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
10862             break;
10863
10864         case IF_LS_3A: // LS_3A   .X.......X.mmmmm oooS..nnnnnttttt      Rt Rn Rm ext(Rm) LSL {}
10865             assert(insOptsLSExtend(id->idInsOpt()));
10866             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10867             if (id->idIsLclVar())
10868             {
10869                 emitDispAddrRRExt(id->idReg2(), codeGen->rsGetRsvdReg(), id->idInsOpt(), false, size);
10870             }
10871             else
10872             {
10873                 emitDispAddrRRExt(id->idReg2(), id->idReg3(), id->idInsOpt(), id->idReg3Scaled(), size);
10874             }
10875             break;
10876
10877         case IF_LS_3B: // LS_3B   X............... .aaaaannnnnddddd      Rt Ra Rn
10878             assert(insOptsNone(id->idInsOpt()));
10879             assert(emitGetInsSC(id) == 0);
10880             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10881             emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10882             emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
10883             break;
10884
10885         case IF_LS_3C: // LS_3C   X.........iiiiii iaaaaannnnnddddd      Rt Ra Rn imm(im7,sh)
10886             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
10887             imm   = emitGetInsSC(id);
10888             scale = NaturalScale_helper(emitInsLoadStoreSize(id));
10889             imm <<= scale;
10890             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10891             emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10892             emitDispAddrRI(id->idReg3(), id->idInsOpt(), imm);
10893             break;
10894
10895         case IF_LS_3D: // LS_3D   .X.......X.mmmmm ......nnnnnttttt      Wm Rt Rn
10896             assert(insOptsNone(id->idInsOpt()));
10897             emitDispReg(id->idReg1(), EA_4BYTE, true);
10898             emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10899             emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
10900             break;
10901
10902         case IF_DI_1A: // DI_1A   X.......shiiiiii iiiiiinnnnn.....      Rn       imm(i12,sh)
10903             emitDispReg(id->idReg1(), size, true);
10904             emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
10905             break;
10906
10907         case IF_DI_1B: // DI_1B   X........hwiiiii iiiiiiiiiiiddddd      Rd       imm(i16,hw)
10908             emitDispReg(id->idReg1(), size, true);
10909             hwi.immHWVal = (unsigned)emitGetInsSC(id);
10910             if (ins == INS_mov)
10911             {
10912                 emitDispImm(emitDecodeHalfwordImm(hwi, size), false);
10913             }
10914             else // movz, movn, movk
10915             {
10916                 emitDispImm(hwi.immVal, false);
10917                 if (hwi.immHW != 0)
10918                 {
10919                     emitDispShiftOpts(INS_OPTS_LSL);
10920                     emitDispImm(hwi.immHW * 16, false);
10921                 }
10922             }
10923             break;
10924
10925         case IF_DI_1C: // DI_1C   X........Nrrrrrr ssssssnnnnn.....         Rn    imm(N,r,s)
10926             emitDispReg(id->idReg1(), size, true);
10927             bmi.immNRS = (unsigned)emitGetInsSC(id);
10928             emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
10929             break;
10930
10931         case IF_DI_1D: // DI_1D   X........Nrrrrrr ssssss.....ddddd      Rd       imm(N,r,s)
10932             emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
10933             bmi.immNRS = (unsigned)emitGetInsSC(id);
10934             emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
10935             break;
10936
10937         case IF_DI_2A: // DI_2A   X.......shiiiiii iiiiiinnnnnddddd      Rd Rn    imm(i12,sh)
10938             if ((ins == INS_add) || (ins == INS_sub))
10939             {
10940                 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
10941                 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
10942             }
10943             else
10944             {
10945                 emitDispReg(id->idReg1(), size, true);
10946                 emitDispReg(id->idReg2(), size, true);
10947             }
10948             emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
10949             break;
10950
10951         case IF_DI_2B: // DI_2B   X........X.nnnnn ssssssnnnnnddddd      Rd Rn    imm(0-63)
10952             emitDispReg(id->idReg1(), size, true);
10953             emitDispReg(id->idReg2(), size, true);
10954             emitDispImm(emitGetInsSC(id), false);
10955             break;
10956
10957         case IF_DI_2C: // DI_2C   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imm(N,r,s)
10958             if (ins == INS_ands)
10959             {
10960                 emitDispReg(id->idReg1(), size, true);
10961             }
10962             else
10963             {
10964                 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
10965             }
10966             emitDispReg(id->idReg2(), size, true);
10967             bmi.immNRS = (unsigned)emitGetInsSC(id);
10968             emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
10969             break;
10970
10971         case IF_DI_2D: // DI_2D   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imr, ims   (N,r,s)
10972             emitDispReg(id->idReg1(), size, true);
10973             emitDispReg(id->idReg2(), size, true);
10974
10975             imm        = emitGetInsSC(id);
10976             bmi.immNRS = (unsigned)imm;
10977
10978             switch (ins)
10979             {
10980                 case INS_bfm:
10981                 case INS_sbfm:
10982                 case INS_ubfm:
10983                     emitDispImm(bmi.immR, true);
10984                     emitDispImm(bmi.immS, false);
10985                     break;
10986
10987                 case INS_bfi:
10988                 case INS_sbfiz:
10989                 case INS_ubfiz:
10990                     emitDispImm(getBitWidth(size) - bmi.immR, true);
10991                     emitDispImm(bmi.immS + 1, false);
10992                     break;
10993
10994                 case INS_bfxil:
10995                 case INS_sbfx:
10996                 case INS_ubfx:
10997                     emitDispImm(bmi.immR, true);
10998                     emitDispImm(bmi.immS - bmi.immR + 1, false);
10999                     break;
11000
11001                 case INS_asr:
11002                 case INS_lsr:
11003                 case INS_lsl:
11004                     emitDispImm(imm, false);
11005                     break;
11006
11007                 default:
11008                     assert(!"Unexpected instruction in IF_DI_2D");
11009             }
11010
11011             break;
11012
11013         case IF_DI_1F: // DI_1F   X..........iiiii cccc..nnnnn.nzcv      Rn imm5  nzcv cond
11014             emitDispReg(id->idReg1(), size, true);
11015             cfi.immCFVal = (unsigned)emitGetInsSC(id);
11016             emitDispImm(cfi.imm5, true);
11017             emitDispFlags(cfi.flags);
11018             printf(",");
11019             emitDispCond(cfi.cond);
11020             break;
11021
11022         case IF_DR_1D: // DR_1D   X............... cccc.......mmmmm      Rd       cond
11023             emitDispReg(id->idReg1(), size, true);
11024             cfi.immCFVal = (unsigned)emitGetInsSC(id);
11025             emitDispCond(cfi.cond);
11026             break;
11027
11028         case IF_DR_2A: // DR_2A   X..........mmmmm ......nnnnn.....         Rn Rm
11029             emitDispReg(id->idReg1(), size, true);
11030             emitDispReg(id->idReg2(), size, false);
11031             break;
11032
11033         case IF_DR_2B: // DR_2B   X.......sh.mmmmm ssssssnnnnn.....         Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
11034             emitDispReg(id->idReg1(), size, true);
11035             emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
11036             break;
11037
11038         case IF_DR_2C: // DR_2C   X..........mmmmm ooosssnnnnn.....         Rn Rm ext(Rm) LSL imm(0-4)
11039             emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11040             imm = emitGetInsSC(id);
11041             emitDispExtendReg(id->idReg2(), id->idInsOpt(), imm);
11042             break;
11043
11044         case IF_DR_2D: // DR_2D   X..........nnnnn cccc..nnnnnddddd      Rd Rn    cond
11045             emitDispReg(id->idReg1(), size, true);
11046             emitDispReg(id->idReg2(), size, true);
11047             cfi.immCFVal = (unsigned)emitGetInsSC(id);
11048             emitDispCond(cfi.cond);
11049             break;
11050
11051         case IF_DR_2E: // DR_2E   X..........mmmmm ...........ddddd      Rd    Rm
11052             emitDispReg(id->idReg1(), size, true);
11053             emitDispReg(id->idReg2(), size, false);
11054             break;
11055
11056         case IF_DR_2F: // DR_2F   X.......sh.mmmmm ssssss.....ddddd      Rd    Rm {LSL,LSR,ASR} imm(0-63)
11057             emitDispReg(id->idReg1(), size, true);
11058             emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
11059             break;
11060
11061         case IF_DR_2G: // DR_2G   X............... ......nnnnnddddd      Rd Rn
11062             emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11063             emitDispReg(encodingZRtoSP(id->idReg2()), size, false);
11064             break;
11065
11066         case IF_DR_2H: // DR_2H   X........X...... ......nnnnnddddd      Rd Rn
11067             emitDispReg(id->idReg1(), size, true);
11068             emitDispReg(id->idReg2(), size, false);
11069             break;
11070
11071         case IF_DR_2I: // DR_2I   X..........mmmmm cccc..nnnnn.nzcv      Rn Rm    nzcv cond
11072             emitDispReg(id->idReg1(), size, true);
11073             emitDispReg(id->idReg2(), size, true);
11074             cfi.immCFVal = (unsigned)emitGetInsSC(id);
11075             emitDispFlags(cfi.flags);
11076             printf(",");
11077             emitDispCond(cfi.cond);
11078             break;
11079
11080         case IF_DR_3A: // DR_3A   X..........mmmmm ......nnnnnmmmmm      Rd Rn Rm
11081             if ((ins == INS_add) || (ins == INS_sub))
11082             {
11083                 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11084                 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11085             }
11086             else if ((ins == INS_smull) || (ins == INS_smulh))
11087             {
11088                 // Rd is always 8 bytes
11089                 emitDispReg(id->idReg1(), EA_8BYTE, true);
11090
11091                 // Rn, Rm effective size depends on instruction type
11092                 size = (ins == INS_smulh) ? EA_8BYTE : EA_4BYTE;
11093                 emitDispReg(id->idReg2(), size, true);
11094             }
11095             else
11096             {
11097                 emitDispReg(id->idReg1(), size, true);
11098                 emitDispReg(id->idReg2(), size, true);
11099             }
11100             if (id->idIsLclVar())
11101             {
11102                 emitDispReg(codeGen->rsGetRsvdReg(), size, false);
11103             }
11104             else
11105             {
11106                 emitDispReg(id->idReg3(), size, false);
11107             }
11108
11109             break;
11110
11111         case IF_DR_3B: // DR_3B   X.......sh.mmmmm ssssssnnnnnddddd      Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
11112             emitDispReg(id->idReg1(), size, true);
11113             emitDispReg(id->idReg2(), size, true);
11114             emitDispShiftedReg(id->idReg3(), id->idInsOpt(), emitGetInsSC(id), size);
11115             break;
11116
11117         case IF_DR_3C: // DR_3C   X..........mmmmm ooosssnnnnnddddd      Rd Rn Rm ext(Rm) LSL imm(0-4)
11118             emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11119             emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11120             imm = emitGetInsSC(id);
11121             emitDispExtendReg(id->idReg3(), id->idInsOpt(), imm);
11122             break;
11123
11124         case IF_DR_3D: // DR_3D   X..........mmmmm cccc..nnnnnmmmmm      Rd Rn Rm cond
11125             emitDispReg(id->idReg1(), size, true);
11126             emitDispReg(id->idReg2(), size, true);
11127             emitDispReg(id->idReg3(), size, true);
11128             cfi.immCFVal = (unsigned)emitGetInsSC(id);
11129             emitDispCond(cfi.cond);
11130             break;
11131
11132         case IF_DR_3E: // DR_3E   X........X.mmmmm ssssssnnnnnddddd      Rd Rn Rm imm(0-63)
11133             emitDispReg(id->idReg1(), size, true);
11134             emitDispReg(id->idReg2(), size, true);
11135             emitDispReg(id->idReg3(), size, true);
11136             emitDispImm(emitGetInsSC(id), false);
11137             break;
11138
11139         case IF_DR_4A: // DR_4A   X..........mmmmm .aaaaannnnnmmmmm      Rd Rn Rm Ra
11140             emitDispReg(id->idReg1(), size, true);
11141             emitDispReg(id->idReg2(), size, true);
11142             emitDispReg(id->idReg3(), size, true);
11143             emitDispReg(id->idReg4(), size, false);
11144             break;
11145
11146         case IF_DV_1A: // DV_1A   .........X.iiiii iii........ddddd      Vd imm8 (fmov - immediate scalar)
11147             elemsize = id->idOpSize();
11148             emitDispReg(id->idReg1(), elemsize, true);
11149             emitDispFloatImm(emitGetInsSC(id));
11150             break;
11151
11152         case IF_DV_1B: // DV_1B   .QX..........iii cmod..iiiiiddddd      Vd imm8 (immediate vector)
11153             imm      = emitGetInsSC(id) & 0x0ff;
11154             immShift = (emitGetInsSC(id) & 0x700) >> 8;
11155             hasShift = (immShift != 0);
11156             elemsize = optGetElemsize(id->idInsOpt());
11157             if (id->idInsOpt() == INS_OPTS_1D)
11158             {
11159                 assert(elemsize == size);
11160                 emitDispReg(id->idReg1(), size, true);
11161             }
11162             else
11163             {
11164                 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11165             }
11166             if (ins == INS_fmov)
11167             {
11168                 emitDispFloatImm(imm);
11169                 assert(hasShift == false);
11170             }
11171             else
11172             {
11173                 if (elemsize == EA_8BYTE)
11174                 {
11175                     assert(ins == INS_movi);
11176                     ssize_t       imm64 = 0;
11177                     const ssize_t mask8 = 0xFF;
11178                     for (unsigned b = 0; b < 8; b++)
11179                     {
11180                         if (imm & (1 << b))
11181                         {
11182                             imm64 |= (mask8 << (b * 8));
11183                         }
11184                     }
11185                     emitDispImm(imm64, hasShift, true);
11186                 }
11187                 else
11188                 {
11189                     emitDispImm(imm, hasShift, true);
11190                 }
11191                 if (hasShift)
11192                 {
11193                     insOpts  opt   = (immShift & 0x4) ? INS_OPTS_MSL : INS_OPTS_LSL;
11194                     unsigned shift = (immShift & 0x3) * 8;
11195                     emitDispShiftOpts(opt);
11196                     emitDispImm(shift, false);
11197                 }
11198             }
11199             break;
11200
11201         case IF_DV_1C: // DV_1C   .........X...... ......nnnnn.....      Vn #0.0 (fcmp - with zero)
11202             elemsize = id->idOpSize();
11203             emitDispReg(id->idReg1(), elemsize, true);
11204             emitDispFloatZero();
11205             break;
11206
11207         case IF_DV_2A: // DV_2A   .Q.......X...... ......nnnnnddddd      Vd Vn   (fabs, fcvt - vector)
11208         case IF_DV_2M: // DV_2M   .Q......XX...... ......nnnnnddddd      Vd Vn   (abs, neg   - vector)
11209             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11210             emitDispVectorReg(id->idReg2(), id->idInsOpt(), false);
11211             break;
11212
11213         case IF_DV_2N: // DV_2N   .........iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - scalar)
11214             elemsize = id->idOpSize();
11215             emitDispReg(id->idReg1(), elemsize, true);
11216             emitDispReg(id->idReg2(), elemsize, true);
11217             emitDispImm(emitGetInsSC(id), false);
11218             break;
11219
11220         case IF_DV_2O: // DV_2O   .Q.......iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - vector)
11221             imm = emitGetInsSC(id);
11222             // Do we have a sxtl or uxtl instruction?
11223             isExtendAlias = ((ins == INS_sxtl) || (ins == INS_sxtl2) || (ins == INS_uxtl) || (ins == INS_uxtl2));
11224             code          = emitInsCode(ins, fmt);
11225             if (code & 0x00008000) // widen/narrow opcodes
11226             {
11227                 if (code & 0x00002000) // SHL opcodes
11228                 {
11229                     emitDispVectorReg(id->idReg1(), optWidenElemsize(id->idInsOpt()), true);
11230                     emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11231                 }
11232                 else // SHR opcodes
11233                 {
11234                     emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11235                     emitDispVectorReg(id->idReg2(), optWidenElemsize(id->idInsOpt()), !isExtendAlias);
11236                 }
11237             }
11238             else
11239             {
11240                 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11241                 emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11242             }
11243             // Print the immediate unless we have a sxtl or uxtl instruction
11244             if (!isExtendAlias)
11245             {
11246                 emitDispImm(imm, false);
11247             }
11248             break;
11249
11250         case IF_DV_2B: // DV_2B   .Q.........iiiii ......nnnnnddddd      Rd Vn[] (umov/smov    - to general)
11251             srcsize = id->idOpSize();
11252             index   = emitGetInsSC(id);
11253             if (ins == INS_smov)
11254             {
11255                 dstsize = EA_8BYTE;
11256             }
11257             else // INS_umov or INS_mov
11258             {
11259                 dstsize = (srcsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE;
11260             }
11261             emitDispReg(id->idReg1(), dstsize, true);
11262             emitDispVectorRegIndex(id->idReg2(), srcsize, index, false);
11263             break;
11264
11265         case IF_DV_2C: // DV_2C   .Q.........iiiii ......nnnnnddddd      Vd Rn   (dup/ins - vector from general)
11266             if (ins == INS_dup)
11267             {
11268                 datasize = id->idOpSize();
11269                 assert(isValidVectorDatasize(datasize));
11270                 assert(isValidArrangement(datasize, id->idInsOpt()));
11271                 elemsize = optGetElemsize(id->idInsOpt());
11272                 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11273             }
11274             else // INS_ins
11275             {
11276                 elemsize = id->idOpSize();
11277                 index    = emitGetInsSC(id);
11278                 assert(isValidVectorElemsize(elemsize));
11279                 emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11280             }
11281             emitDispReg(id->idReg2(), (elemsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE, false);
11282             break;
11283
11284         case IF_DV_2D: // DV_2D   .Q.........iiiii ......nnnnnddddd      Vd Vn[]   (dup - vector)
11285             datasize = id->idOpSize();
11286             assert(isValidVectorDatasize(datasize));
11287             assert(isValidArrangement(datasize, id->idInsOpt()));
11288             elemsize = optGetElemsize(id->idInsOpt());
11289             index    = emitGetInsSC(id);
11290             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11291             emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11292             break;
11293
11294         case IF_DV_2E: // DV_2E   ...........iiiii ......nnnnnddddd      Vd Vn[]   (dup - scalar)
11295             elemsize = id->idOpSize();
11296             index    = emitGetInsSC(id);
11297             emitDispReg(id->idReg1(), elemsize, true);
11298             emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11299             break;
11300
11301         case IF_DV_2F: // DV_2F   ...........iiiii .jjjj.nnnnnddddd      Vd[] Vn[] (ins - element)
11302             imm      = emitGetInsSC(id);
11303             index    = (imm >> 4) & 0xf;
11304             index2   = imm & 0xf;
11305             elemsize = id->idOpSize();
11306             emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11307             emitDispVectorRegIndex(id->idReg2(), elemsize, index2, false);
11308             break;
11309
11310         case IF_DV_2G: // DV_2G   .........X...... ......nnnnnddddd      Vd Vn      (fmov, fcvtXX - register)
11311         case IF_DV_2K: // DV_2K   .........X.mmmmm ......nnnnn.....      Vn Vm      (fcmp)
11312         case IF_DV_2L: // DV_2L   ........XX...... ......nnnnnddddd      Vd Vn      (abs, neg - scalar)
11313             elemsize = id->idOpSize();
11314             emitDispReg(id->idReg1(), elemsize, true);
11315             emitDispReg(id->idReg2(), elemsize, false);
11316             break;
11317
11318         case IF_DV_2H: // DV_2H   X........X...... ......nnnnnddddd      Rd Vn      (fmov, fcvtXX - to general)
11319         case IF_DV_2I: // DV_2I   X........X...... ......nnnnnddddd      Vd Rn      (fmov, Xcvtf - from general)
11320         case IF_DV_2J: // DV_2J   ........SS.....D D.....nnnnnddddd      Vd Vn      (fcvt)
11321             dstsize = optGetDstsize(id->idInsOpt());
11322             srcsize = optGetSrcsize(id->idInsOpt());
11323
11324             emitDispReg(id->idReg1(), dstsize, true);
11325             emitDispReg(id->idReg2(), srcsize, false);
11326             break;
11327
11328         case IF_DV_3A: // DV_3A   .Q......XX.mmmmm ......nnnnnddddd      Vd Vn Vm  (vector)
11329         case IF_DV_3B: // DV_3B   .Q.........mmmmm ......nnnnnddddd      Vd Vn Vm  (vector)
11330             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11331             emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11332             emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11333             break;
11334
11335         case IF_DV_3C: // DV_3C   .Q.........mmmmm ......nnnnnddddd      Vd Vn Vm  (vector)
11336             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11337             if (ins != INS_mov)
11338             {
11339                 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11340             }
11341             emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11342             break;
11343
11344         case IF_DV_3AI: // DV_3AI  .Q......XXLMmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector by elem)
11345         case IF_DV_3BI: // DV_3BI  .Q........Lmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector by elem)
11346             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11347             emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11348             elemsize = optGetElemsize(id->idInsOpt());
11349             emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11350             break;
11351
11352         case IF_DV_3D: // DV_3D   .........X.mmmmm ......nnnnnddddd      Vd Vn Vm  (scalar)
11353         case IF_DV_3E: // DV_3E   ...........mmmmm ......nnnnnddddd      Vd Vn Vm  (scalar)
11354             emitDispReg(id->idReg1(), size, true);
11355             emitDispReg(id->idReg2(), size, true);
11356             emitDispReg(id->idReg3(), size, false);
11357             break;
11358
11359         case IF_DV_3DI: // DV_3DI  .........XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (scalar by elem)
11360             emitDispReg(id->idReg1(), size, true);
11361             emitDispReg(id->idReg2(), size, true);
11362             elemsize = size;
11363             emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11364             break;
11365
11366         case IF_DV_4A: // DV_4A   .........X.mmmmm .aaaaannnnnddddd      Vd Va Vn Vm (scalar)
11367             emitDispReg(id->idReg1(), size, true);
11368             emitDispReg(id->idReg2(), size, true);
11369             emitDispReg(id->idReg3(), size, true);
11370             emitDispReg(id->idReg4(), size, false);
11371             break;
11372
11373         case IF_SN_0A: // SN_0A   ................ ................
11374             break;
11375
11376         case IF_SI_0A: // SI_0A   ...........iiiii iiiiiiiiiii.....               imm16
11377             emitDispImm(emitGetInsSC(id), false);
11378             break;
11379
11380         case IF_SI_0B: // SI_0B   ................ ....bbbb........               imm4 - barrier
11381             emitDispBarrier((insBarrier)emitGetInsSC(id));
11382             break;
11383
11384         default:
11385             printf("unexpected format %s", emitIfName(id->idInsFmt()));
11386             assert(!"unexpectedFormat");
11387             break;
11388     }
11389
11390     if (id->idDebugOnlyInfo()->idVarRefOffs)
11391     {
11392         printf("\t// ");
11393         emitDispFrameRef(id->idAddr()->iiaLclVar.lvaVarNum(), id->idAddr()->iiaLclVar.lvaOffset(),
11394                          id->idDebugOnlyInfo()->idVarRefOffs, asmfm);
11395     }
11396
11397     printf("\n");
11398 }
11399
11400 /*****************************************************************************
11401  *
11402  *  Display a stack frame reference.
11403  */
11404
11405 void emitter::emitDispFrameRef(int varx, int disp, int offs, bool asmfm)
11406 {
11407     printf("[");
11408
11409     if (varx < 0)
11410         printf("TEMP_%02u", -varx);
11411     else
11412         emitComp->gtDispLclVar(+varx, false);
11413
11414     if (disp < 0)
11415         printf("-0x%02x", -disp);
11416     else if (disp > 0)
11417         printf("+0x%02x", +disp);
11418
11419     printf("]");
11420
11421     if (varx >= 0 && emitComp->opts.varNames)
11422     {
11423         LclVarDsc*  varDsc;
11424         const char* varName;
11425
11426         assert((unsigned)varx < emitComp->lvaCount);
11427         varDsc  = emitComp->lvaTable + varx;
11428         varName = emitComp->compLocalVarName(varx, offs);
11429
11430         if (varName)
11431         {
11432             printf("'%s", varName);
11433
11434             if (disp < 0)
11435                 printf("-%d", -disp);
11436             else if (disp > 0)
11437                 printf("+%d", +disp);
11438
11439             printf("'");
11440         }
11441     }
11442 }
11443
11444 #endif // DEBUG
11445
11446 // Generate code for a load or store operation with a potentially complex addressing mode
11447 // This method handles the case of a GT_IND with contained GT_LEA op1 of the x86 form [base + index*sccale + offset]
11448 // Since Arm64 does not directly support this complex of an addressing mode
11449 // we may generates up to three instructions for this for Arm64
11450 //
11451 void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataReg, GenTreeIndir* indir)
11452 {
11453     emitAttr ldstAttr = isVectorRegister(dataReg) ? attr : emitInsAdjustLoadStoreAttr(ins, attr);
11454
11455     GenTree* addr = indir->Addr();
11456
11457     if (addr->isContained())
11458     {
11459         assert(addr->OperGet() == GT_LCL_VAR_ADDR || addr->OperGet() == GT_LEA);
11460
11461         int   offset = 0;
11462         DWORD lsl    = 0;
11463
11464         if (addr->OperGet() == GT_LEA)
11465         {
11466             offset = addr->AsAddrMode()->Offset();
11467             if (addr->AsAddrMode()->gtScale > 0)
11468             {
11469                 assert(isPow2(addr->AsAddrMode()->gtScale));
11470                 BitScanForward(&lsl, addr->AsAddrMode()->gtScale);
11471             }
11472         }
11473
11474         GenTree* memBase = indir->Base();
11475
11476         if (indir->HasIndex())
11477         {
11478             GenTree* index = indir->Index();
11479
11480             if (offset != 0)
11481             {
11482                 regNumber tmpReg = indir->GetSingleTempReg();
11483
11484                 emitAttr addType = varTypeIsGC(memBase) ? EA_BYREF : EA_PTRSIZE;
11485
11486                 if (emitIns_valid_imm_for_add(offset, EA_8BYTE))
11487                 {
11488                     if (lsl > 0)
11489                     {
11490                         // Generate code to set tmpReg = base + index*scale
11491                         emitIns_R_R_R_I(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum, lsl,
11492                                         INS_OPTS_LSL);
11493                     }
11494                     else // no scale
11495                     {
11496                         // Generate code to set tmpReg = base + index
11497                         emitIns_R_R_R(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum);
11498                     }
11499
11500                     noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11501
11502                     // Then load/store dataReg from/to [tmpReg + offset]
11503                     emitIns_R_R_I(ins, ldstAttr, dataReg, tmpReg, offset);
11504                 }
11505                 else // large offset
11506                 {
11507                     // First load/store tmpReg with the large offset constant
11508                     codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11509                     // Then add the base register
11510                     //      rd = rd + base
11511                     emitIns_R_R_R(INS_add, addType, tmpReg, tmpReg, memBase->gtRegNum);
11512
11513                     noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11514                     noway_assert(tmpReg != index->gtRegNum);
11515
11516                     // Then load/store dataReg from/to [tmpReg + index*scale]
11517                     emitIns_R_R_R_I(ins, ldstAttr, dataReg, tmpReg, index->gtRegNum, lsl, INS_OPTS_LSL);
11518                 }
11519             }
11520             else // (offset == 0)
11521             {
11522                 if (lsl > 0)
11523                 {
11524                     // Then load/store dataReg from/to [memBase + index*scale]
11525                     emitIns_R_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum, lsl, INS_OPTS_LSL);
11526                 }
11527                 else // no scale
11528                 {
11529                     // Then load/store dataReg from/to [memBase + index]
11530                     emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum);
11531                 }
11532             }
11533         }
11534         else // no Index register
11535         {
11536             if (emitIns_valid_imm_for_ldst_offset(offset, EA_SIZE(attr)))
11537             {
11538                 // Then load/store dataReg from/to [memBase + offset]
11539                 emitIns_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, offset);
11540             }
11541             else
11542             {
11543                 // We require a tmpReg to hold the offset
11544                 regNumber tmpReg = indir->GetSingleTempReg();
11545
11546                 // First load/store tmpReg with the large offset constant
11547                 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11548
11549                 // Then load/store dataReg from/to [memBase + tmpReg]
11550                 emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, tmpReg);
11551             }
11552         }
11553     }
11554     else // addr is not contained, so we evaluate it into a register
11555     {
11556         // Then load/store dataReg from/to [addrReg]
11557         emitIns_R_R(ins, ldstAttr, dataReg, addr->gtRegNum);
11558     }
11559 }
11560
11561 // The callee must call genConsumeReg() for any non-contained srcs
11562 // and genProduceReg() for any non-contained dsts.
11563
11564 regNumber emitter::emitInsBinary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src)
11565 {
11566     regNumber result = REG_NA;
11567
11568     // dst can only be a reg
11569     assert(!dst->isContained());
11570
11571     // src can be immed or reg
11572     assert(!src->isContained() || src->isContainedIntOrIImmed());
11573
11574     // find immed (if any) - it cannot be a dst
11575     GenTreeIntConCommon* intConst = nullptr;
11576     if (src->isContainedIntOrIImmed())
11577     {
11578         intConst = src->AsIntConCommon();
11579     }
11580
11581     if (intConst)
11582     {
11583         emitIns_R_I(ins, attr, dst->gtRegNum, intConst->IconValue());
11584         return dst->gtRegNum;
11585     }
11586     else
11587     {
11588         emitIns_R_R(ins, attr, dst->gtRegNum, src->gtRegNum);
11589         return dst->gtRegNum;
11590     }
11591 }
11592
11593 // The callee must call genConsumeReg() for any non-contained srcs
11594 // and genProduceReg() for any non-contained dsts.
11595
11596 regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src1, GenTree* src2)
11597 {
11598     regNumber result = REG_NA;
11599
11600     // dst can only be a reg
11601     assert(!dst->isContained());
11602
11603     // find immed (if any) - it cannot be a dst
11604     // Only one src can be an int.
11605     GenTreeIntConCommon* intConst  = nullptr;
11606     GenTree*             nonIntReg = nullptr;
11607
11608     if (varTypeIsFloating(dst))
11609     {
11610         // src1 can only be a reg
11611         assert(!src1->isContained());
11612         // src2 can only be a reg
11613         assert(!src2->isContained());
11614     }
11615     else // not floating point
11616     {
11617         // src2 can be immed or reg
11618         assert(!src2->isContained() || src2->isContainedIntOrIImmed());
11619
11620         // Check src2 first as we can always allow it to be a contained immediate
11621         if (src2->isContainedIntOrIImmed())
11622         {
11623             intConst  = src2->AsIntConCommon();
11624             nonIntReg = src1;
11625         }
11626         // Only for commutative operations do we check src1 and allow it to be a contained immediate
11627         else if (dst->OperIsCommutative())
11628         {
11629             // src1 can be immed or reg
11630             assert(!src1->isContained() || src1->isContainedIntOrIImmed());
11631
11632             // Check src1 and allow it to be a contained immediate
11633             if (src1->isContainedIntOrIImmed())
11634             {
11635                 assert(!src2->isContainedIntOrIImmed());
11636                 intConst  = src1->AsIntConCommon();
11637                 nonIntReg = src2;
11638             }
11639         }
11640         else
11641         {
11642             // src1 can only be a reg
11643             assert(!src1->isContained());
11644         }
11645     }
11646
11647     bool isMulOverflow = false;
11648     if (dst->gtOverflowEx())
11649     {
11650         if ((ins == INS_add) || (ins == INS_adds))
11651         {
11652             ins = INS_adds;
11653         }
11654         else if ((ins == INS_sub) || (ins == INS_subs))
11655         {
11656             ins = INS_subs;
11657         }
11658         else if (ins == INS_mul)
11659         {
11660             isMulOverflow = true;
11661             assert(intConst == nullptr); // overflow format doesn't support an int constant operand
11662         }
11663         else
11664         {
11665             assert(!"Invalid ins for overflow check");
11666         }
11667     }
11668     if (intConst != nullptr)
11669     {
11670         emitIns_R_R_I(ins, attr, dst->gtRegNum, nonIntReg->gtRegNum, intConst->IconValue());
11671     }
11672     else
11673     {
11674         if (isMulOverflow)
11675         {
11676             regNumber extraReg = dst->GetSingleTempReg();
11677             assert(extraReg != dst->gtRegNum);
11678
11679             if ((dst->gtFlags & GTF_UNSIGNED) != 0)
11680             {
11681                 if (attr == EA_4BYTE)
11682                 {
11683                     // Compute 8 byte results from 4 byte by 4 byte multiplication.
11684                     emitIns_R_R_R(INS_umull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11685
11686                     // Get the high result by shifting dst.
11687                     emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11688                 }
11689                 else
11690                 {
11691                     assert(attr == EA_8BYTE);
11692                     // Compute the high result.
11693                     emitIns_R_R_R(INS_umulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11694
11695                     // Now multiply without skewing the high result.
11696                     emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11697                 }
11698
11699                 // zero-sign bit comparison to detect overflow.
11700                 emitIns_R_I(INS_cmp, attr, extraReg, 0);
11701             }
11702             else
11703             {
11704                 int bitShift = 0;
11705                 if (attr == EA_4BYTE)
11706                 {
11707                     // Compute 8 byte results from 4 byte by 4 byte multiplication.
11708                     emitIns_R_R_R(INS_smull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11709
11710                     // Get the high result by shifting dst.
11711                     emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11712
11713                     bitShift = 31;
11714                 }
11715                 else
11716                 {
11717                     assert(attr == EA_8BYTE);
11718                     // Save the high result in a temporary register.
11719                     emitIns_R_R_R(INS_smulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11720
11721                     // Now multiply without skewing the high result.
11722                     emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11723
11724                     bitShift = 63;
11725                 }
11726
11727                 // Sign bit comparison to detect overflow.
11728                 emitIns_R_R_I(INS_cmp, attr, extraReg, dst->gtRegNum, bitShift, INS_OPTS_ASR);
11729             }
11730         }
11731         else
11732         {
11733             // We can just multiply.
11734             emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11735         }
11736     }
11737
11738     if (dst->gtOverflowEx())
11739     {
11740         assert(!varTypeIsFloating(dst));
11741         codeGen->genCheckOverflow(dst);
11742     }
11743
11744     return dst->gtRegNum;
11745 }
11746
11747 #endif // defined(_TARGET_ARM64_)