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