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