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