Eliminate gtLsraInfo from GenTree
[platform/upstream/coreclr.git] / src / jit / emitarm64.cpp
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4
5 /*XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
6 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
7 XX                                                                           XX
8 XX                             emitArm64.cpp                                 XX
9 XX                                                                           XX
10 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
11 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
12 */
13
14 #include "jitpch.h"
15 #ifdef _MSC_VER
16 #pragma hdrstop
17 #endif
18
19 #if defined(_TARGET_ARM64_)
20
21 /*****************************************************************************/
22 /*****************************************************************************/
23
24 #include "instr.h"
25 #include "emit.h"
26 #include "codegen.h"
27
28 /* static */ bool emitter::strictArmAsm = true;
29
30 /*****************************************************************************/
31
32 const instruction emitJumpKindInstructions[] = {
33     INS_nop,
34
35 #define JMP_SMALL(en, rev, ins) INS_##ins,
36 #include "emitjmps.h"
37 };
38
39 const emitJumpKind emitReverseJumpKinds[] = {
40     EJ_NONE,
41
42 #define JMP_SMALL(en, rev, ins) EJ_##rev,
43 #include "emitjmps.h"
44 };
45
46 /*****************************************************************************
47  * Look up the instruction for a jump kind
48  */
49
50 /*static*/ instruction emitter::emitJumpKindToIns(emitJumpKind jumpKind)
51 {
52     assert((unsigned)jumpKind < ArrLen(emitJumpKindInstructions));
53     return emitJumpKindInstructions[jumpKind];
54 }
55
56 /*****************************************************************************
57 * Look up the jump kind for an instruction. It better be a conditional
58 * branch instruction with a jump kind!
59 */
60
61 /*static*/ emitJumpKind emitter::emitInsToJumpKind(instruction ins)
62 {
63     for (unsigned i = 0; i < ArrLen(emitJumpKindInstructions); i++)
64     {
65         if (ins == emitJumpKindInstructions[i])
66         {
67             emitJumpKind ret = (emitJumpKind)i;
68             assert(EJ_NONE < ret && ret < EJ_COUNT);
69             return ret;
70         }
71     }
72     unreached();
73 }
74
75 /*****************************************************************************
76  * Reverse the conditional jump
77  */
78
79 /*static*/ emitJumpKind emitter::emitReverseJumpKind(emitJumpKind jumpKind)
80 {
81     assert(jumpKind < EJ_COUNT);
82     return emitReverseJumpKinds[jumpKind];
83 }
84
85 /*****************************************************************************
86  *
87  *  Return the allocated size (in bytes) of the given instruction descriptor.
88  */
89
90 size_t emitter::emitSizeOfInsDsc(instrDesc* id)
91 {
92     assert(!emitIsTinyInsDsc(id));
93
94     if (emitIsScnsInsDsc(id))
95         return SMALL_IDSC_SIZE;
96
97     assert((unsigned)id->idInsFmt() < emitFmtCount);
98
99     ID_OPS idOp      = (ID_OPS)emitFmtToOps[id->idInsFmt()];
100     bool   isCallIns = (id->idIns() == INS_bl) || (id->idIns() == INS_blr) || (id->idIns() == INS_b_tail) ||
101                      (id->idIns() == INS_br_tail);
102     bool maybeCallIns = (id->idIns() == INS_b) || (id->idIns() == INS_br);
103
104     switch (idOp)
105     {
106         case ID_OP_NONE:
107             break;
108
109         case ID_OP_JMP:
110             return sizeof(instrDescJmp);
111
112         case ID_OP_CALL:
113             assert(isCallIns || maybeCallIns);
114             if (id->idIsLargeCall())
115             {
116                 /* Must be a "fat" call descriptor */
117                 return sizeof(instrDescCGCA);
118             }
119             else
120             {
121                 assert(!id->idIsLargeDsp());
122                 assert(!id->idIsLargeCns());
123                 return sizeof(instrDesc);
124             }
125             break;
126
127         default:
128             NO_WAY("unexpected instruction descriptor format");
129             break;
130     }
131
132     if (id->idIsLargeCns())
133     {
134         if (id->idIsLargeDsp())
135             return sizeof(instrDescCnsDsp);
136         else
137             return sizeof(instrDescCns);
138     }
139     else
140     {
141         if (id->idIsLargeDsp())
142             return sizeof(instrDescDsp);
143         else
144             return sizeof(instrDesc);
145     }
146 }
147
148 #ifdef DEBUG
149 /*****************************************************************************
150  *
151  *  The following called for each recorded instruction -- use for debugging.
152  */
153 void emitter::emitInsSanityCheck(instrDesc* id)
154 {
155     /* What instruction format have we got? */
156
157     switch (id->idInsFmt())
158     {
159         instruction ins;
160         emitAttr    elemsize;
161         emitAttr    datasize;
162         emitAttr    dstsize;
163         emitAttr    srcsize;
164         ssize_t     imm;
165         unsigned    immShift;
166         ssize_t     index;
167         ssize_t     index2;
168
169         case IF_BI_0A: // BI_0A   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
170             break;
171
172         case IF_BI_0B: // BI_0B   ......iiiiiiiiii iiiiiiiiiiii....               simm19:00
173             break;
174
175         case IF_LARGEJMP:
176         case IF_LARGEADR:
177         case IF_LARGELDC:
178             break;
179
180         case IF_BI_0C: // BI_0C   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
181             break;
182
183         case IF_BI_1A: // BI_1A   ......iiiiiiiiii iiiiiiiiiiittttt      Rt       simm19:00
184             assert(isValidGeneralDatasize(id->idOpSize()));
185             assert(isGeneralRegister(id->idReg1()));
186             break;
187
188         case IF_BI_1B: // BI_1B   B.......bbbbbiii iiiiiiiiiiittttt      Rt imm6, simm14:00
189             assert(isValidGeneralDatasize(id->idOpSize()));
190             assert(isGeneralRegister(id->idReg1()));
191             assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
192             break;
193
194         case IF_BR_1A: // BR_1A   ................ ......nnnnn.....         Rn
195             assert(isGeneralRegister(id->idReg1()));
196             break;
197
198         case IF_BR_1B: // BR_1B   ................ ......nnnnn.....         Rn
199             assert(isGeneralRegister(id->idReg3()));
200             break;
201
202         case IF_LS_1A: // LS_1A   .X......iiiiiiii iiiiiiiiiiittttt      Rt    PC imm(1MB)
203             assert(isGeneralRegister(id->idReg1()) || isVectorRegister(id->idReg1()));
204             assert(insOptsNone(id->idInsOpt()));
205             break;
206
207         case IF_LS_2A:                                // LS_2A   .X.......X...... ......nnnnnttttt      Rt Rn
208             assert(isIntegerRegister(id->idReg1()) || // ZR
209                    isVectorRegister(id->idReg1()));
210             assert(isIntegerRegister(id->idReg2())); // SP
211             assert(emitGetInsSC(id) == 0);
212             assert(insOptsNone(id->idInsOpt()));
213             break;
214
215         case IF_LS_2B: // LS_2B   .X.......Xiiiiii iiiiiinnnnnttttt      Rt Rn    imm(0-4095)
216             assert(isIntegerRegister(id->idReg1()) || // ZR
217                    isVectorRegister(id->idReg1()));
218             assert(isIntegerRegister(id->idReg2())); // SP
219             assert(isValidUimm12(emitGetInsSC(id)));
220             assert(insOptsNone(id->idInsOpt()));
221             break;
222
223         case IF_LS_2C: // LS_2C   .X.......X.iiiii iiiiPPnnnnnttttt      Rt Rn    imm(-256..+255) no/pre/post inc
224             assert(isIntegerRegister(id->idReg1()) || // ZR
225                    isVectorRegister(id->idReg1()));
226             assert(isIntegerRegister(id->idReg2())); // SP
227             assert(emitGetInsSC(id) >= -0x100);
228             assert(emitGetInsSC(id) < 0x100);
229             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
230             break;
231
232         case IF_LS_3A: // LS_3A   .X.......X.mmmmm oooS..nnnnnttttt      Rt Rn Rm ext(Rm) LSL {}
233             assert(isIntegerRegister(id->idReg1()) || // ZR
234                    isVectorRegister(id->idReg1()));
235             assert(isIntegerRegister(id->idReg2())); // SP
236             if (id->idIsLclVar())
237             {
238                 assert(isGeneralRegister(codeGen->rsGetRsvdReg()));
239             }
240             else
241             {
242                 assert(isGeneralRegister(id->idReg3()));
243             }
244             assert(insOptsLSExtend(id->idInsOpt()));
245             break;
246
247         case IF_LS_3B: // LS_3B   X............... .aaaaannnnnttttt      Rt Ra Rn
248             assert((isValidGeneralDatasize(id->idOpSize()) && isIntegerRegister(id->idReg1())) ||
249                    (isValidVectorLSPDatasize(id->idOpSize()) && isVectorRegister(id->idReg1())));
250             assert(isIntegerRegister(id->idReg1()) || // ZR
251                    isVectorRegister(id->idReg1()));
252             assert(isIntegerRegister(id->idReg2()) || // ZR
253                    isVectorRegister(id->idReg2()));
254             assert(isIntegerRegister(id->idReg3())); // SP
255             assert(emitGetInsSC(id) == 0);
256             assert(insOptsNone(id->idInsOpt()));
257             break;
258
259         case IF_LS_3C: // LS_3C   X.........iiiiii iaaaaannnnnttttt      Rt Ra Rn imm(im7,sh)
260             assert((isValidGeneralDatasize(id->idOpSize()) && isIntegerRegister(id->idReg1())) ||
261                    (isValidVectorLSPDatasize(id->idOpSize()) && isVectorRegister(id->idReg1())));
262             assert(isIntegerRegister(id->idReg1()) || // ZR
263                    isVectorRegister(id->idReg1()));
264             assert(isIntegerRegister(id->idReg2()) || // ZR
265                    isVectorRegister(id->idReg2()));
266             assert(isIntegerRegister(id->idReg3())); // SP
267             assert(emitGetInsSC(id) >= -0x40);
268             assert(emitGetInsSC(id) < 0x40);
269             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
270             break;
271
272         case IF_LS_3D: // LS_3D   .X.......X.mmmmm ......nnnnnttttt      Wm Rt Rn
273             assert(isIntegerRegister(id->idReg1()));
274             assert(isIntegerRegister(id->idReg2()));
275             assert(isIntegerRegister(id->idReg3()));
276             assert(emitGetInsSC(id) == 0);
277             assert(!id->idIsLclVar());
278             assert(insOptsNone(id->idInsOpt()));
279             break;
280
281         case IF_DI_1A: // DI_1A   X.......shiiiiii iiiiiinnnnn.....         Rn    imm(i12,sh)
282             assert(isValidGeneralDatasize(id->idOpSize()));
283             assert(isGeneralRegister(id->idReg1()));
284             assert(isValidUimm12(emitGetInsSC(id)));
285             assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
286             break;
287
288         case IF_DI_1B: // DI_1B   X........hwiiiii iiiiiiiiiiiddddd      Rd       imm(i16,hw)
289             assert(isValidGeneralDatasize(id->idOpSize()));
290             assert(isGeneralRegister(id->idReg1()));
291             assert(isValidImmHWVal(emitGetInsSC(id), id->idOpSize()));
292             break;
293
294         case IF_DI_1C: // DI_1C   X........Nrrrrrr ssssssnnnnn.....         Rn    imm(N,r,s)
295             assert(isValidGeneralDatasize(id->idOpSize()));
296             assert(isGeneralRegister(id->idReg1()));
297             assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
298             break;
299
300         case IF_DI_1D: // DI_1D   X........Nrrrrrr ssssss.....ddddd      Rd       imm(N,r,s)
301             assert(isValidGeneralDatasize(id->idOpSize()));
302             assert(isIntegerRegister(id->idReg1())); // SP
303             assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
304             break;
305
306         case IF_DI_1E: // DI_1E   .ii.....iiiiiiii iiiiiiiiiiiddddd      Rd       simm21
307             assert(isGeneralRegister(id->idReg1()));
308             break;
309
310         case IF_DI_1F: // DI_1F   X..........iiiii cccc..nnnnn.nzcv      Rn imm5  nzcv cond
311             assert(isValidGeneralDatasize(id->idOpSize()));
312             assert(isGeneralRegister(id->idReg1()));
313             assert(isValidImmCondFlagsImm5(emitGetInsSC(id)));
314             break;
315
316         case IF_DI_2A: // DI_2A   X.......shiiiiii iiiiiinnnnnddddd      Rd Rn    imm(i12,sh)
317             assert(isValidGeneralDatasize(id->idOpSize()));
318             assert(isIntegerRegister(id->idReg1())); // SP
319             assert(isIntegerRegister(id->idReg2())); // SP
320             assert(isValidUimm12(emitGetInsSC(id)));
321             assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
322             break;
323
324         case IF_DI_2B: // DI_2B   X.........Xnnnnn ssssssnnnnnddddd      Rd Rn    imm(0-63)
325             assert(isValidGeneralDatasize(id->idOpSize()));
326             assert(isGeneralRegister(id->idReg1()));
327             assert(isGeneralRegister(id->idReg2()));
328             assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
329             break;
330
331         case IF_DI_2C: // DI_2C   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imm(N,r,s)
332             assert(isValidGeneralDatasize(id->idOpSize()));
333             assert(isIntegerRegister(id->idReg1())); // SP
334             assert(isGeneralRegister(id->idReg2()));
335             assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
336             break;
337
338         case IF_DI_2D: // DI_2D   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imr, imms   (N,r,s)
339             assert(isValidGeneralDatasize(id->idOpSize()));
340             assert(isGeneralRegister(id->idReg1()));
341             assert(isGeneralRegister(id->idReg2()));
342             assert(isValidImmNRS(emitGetInsSC(id), id->idOpSize()));
343             break;
344
345         case IF_DR_1D: // DR_1D   X............... cccc.......ddddd      Rd       cond
346             assert(isValidGeneralDatasize(id->idOpSize()));
347             assert(isGeneralRegister(id->idReg1()));
348             assert(isValidImmCond(emitGetInsSC(id)));
349             break;
350
351         case IF_DR_2A: // DR_2A   X..........mmmmm ......nnnnn.....         Rn Rm
352             assert(isValidGeneralDatasize(id->idOpSize()));
353             assert(isGeneralRegister(id->idReg1()));
354             assert(isGeneralRegister(id->idReg2()));
355             break;
356
357         case IF_DR_2B: // DR_2B   X.......sh.mmmmm ssssssnnnnn.....         Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
358             assert(isValidGeneralDatasize(id->idOpSize()));
359             assert(isIntegerRegister(id->idReg1())); // ZR
360             assert(isGeneralRegister(id->idReg2()));
361             assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
362             if (!insOptsNone(id->idInsOpt()))
363             {
364                 if (id->idIns() == INS_tst) // tst allows ROR, cmp/cmn don't
365                 {
366                     assert(insOptsAnyShift(id->idInsOpt()));
367                 }
368                 else
369                 {
370                     assert(insOptsAluShift(id->idInsOpt()));
371                 }
372             }
373             assert(insOptsNone(id->idInsOpt()) || (emitGetInsSC(id) > 0));
374             break;
375
376         case IF_DR_2C: // DR_2C   X..........mmmmm ooosssnnnnn.....         Rn Rm ext(Rm) LSL imm(0-4)
377             assert(isValidGeneralDatasize(id->idOpSize()));
378             assert(isIntegerRegister(id->idReg1())); // SP
379             assert(isGeneralRegister(id->idReg2()));
380             assert(insOptsNone(id->idInsOpt()) || insOptsLSL(id->idInsOpt()) || insOptsAnyExtend(id->idInsOpt()));
381             assert(emitGetInsSC(id) >= 0);
382             assert(emitGetInsSC(id) <= 4);
383             if (insOptsLSL(id->idInsOpt()))
384             {
385                 assert(emitGetInsSC(id) > 0);
386             }
387             break;
388
389         case IF_DR_2D: // DR_2D   X..........nnnnn cccc..nnnnnmmmmm      Rd Rn    cond
390             assert(isValidGeneralDatasize(id->idOpSize()));
391             assert(isGeneralRegister(id->idReg1()));
392             assert(isGeneralRegister(id->idReg2()));
393             assert(isValidImmCond(emitGetInsSC(id)));
394             break;
395
396         case IF_DR_2E: // DR_2E   X..........mmmmm ...........ddddd      Rd    Rm
397             assert(isValidGeneralDatasize(id->idOpSize()));
398             assert(isGeneralRegister(id->idReg1()));
399             assert(isIntegerRegister(id->idReg2())); // ZR
400             break;
401
402         case IF_DR_2F: // DR_2F   X.......sh.mmmmm ssssss.....ddddd      Rd    Rm {LSL,LSR,ASR} imm(0-63)
403             assert(isValidGeneralDatasize(id->idOpSize()));
404             assert(isGeneralRegister(id->idReg1()));
405             assert(isGeneralRegister(id->idReg2()));
406             assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
407             assert(insOptsNone(id->idInsOpt()) || insOptsAluShift(id->idInsOpt()));
408             assert(insOptsNone(id->idInsOpt()) || (emitGetInsSC(id) > 0));
409             break;
410
411         case IF_DR_2G: // DR_2G   X............... ......nnnnnddddd      Rd    Rm
412             assert(isValidGeneralDatasize(id->idOpSize()));
413             assert(isIntegerRegister(id->idReg1())); // SP
414             assert(isIntegerRegister(id->idReg2())); // SP
415             break;
416
417         case IF_DR_2H: // DR_2H   X........X...... ......nnnnnddddd      Rd Rn
418             assert(isValidGeneralDatasize(id->idOpSize()));
419             assert(isGeneralRegister(id->idReg1()));
420             assert(isGeneralRegister(id->idReg2()));
421             break;
422
423         case IF_DR_2I: // DR_2I   X..........mmmmm cccc..nnnnn.nzcv      Rn Rm    nzcv cond
424             assert(isValidGeneralDatasize(id->idOpSize()));
425             assert(isGeneralRegister(id->idReg1()));
426             assert(isGeneralRegister(id->idReg2()));
427             assert(isValidImmCondFlags(emitGetInsSC(id)));
428             break;
429
430         case IF_DR_3A: // DR_3A   X..........mmmmm ......nnnnnmmmmm      Rd Rn Rm
431             assert(isValidGeneralDatasize(id->idOpSize()));
432             assert(isIntegerRegister(id->idReg1())); // SP
433             assert(isIntegerRegister(id->idReg2())); // SP
434             if (id->idIsLclVar())
435             {
436                 assert(isGeneralRegister(codeGen->rsGetRsvdReg()));
437             }
438             else
439             {
440                 assert(isGeneralRegister(id->idReg3()));
441             }
442             assert(insOptsNone(id->idInsOpt()));
443             break;
444
445         case IF_DR_3B: // DR_3B   X.......sh.mmmmm ssssssnnnnnddddd      Rd Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
446             assert(isValidGeneralDatasize(id->idOpSize()));
447             assert(isGeneralRegister(id->idReg1()));
448             assert(isGeneralRegister(id->idReg2()));
449             assert(isGeneralRegister(id->idReg3()));
450             assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
451             assert(insOptsNone(id->idInsOpt()) || insOptsAnyShift(id->idInsOpt()));
452             assert(insOptsNone(id->idInsOpt()) || (emitGetInsSC(id) > 0));
453             break;
454
455         case IF_DR_3C: // DR_3C   X..........mmmmm ooosssnnnnnddddd      Rd Rn Rm ext(Rm) LSL imm(0-4)
456             assert(isValidGeneralDatasize(id->idOpSize()));
457             assert(isIntegerRegister(id->idReg1())); // SP
458             assert(isIntegerRegister(id->idReg2())); // SP
459             assert(isGeneralRegister(id->idReg3()));
460             assert(insOptsNone(id->idInsOpt()) || insOptsLSL(id->idInsOpt()) || insOptsAnyExtend(id->idInsOpt()));
461             assert(emitGetInsSC(id) >= 0);
462             assert(emitGetInsSC(id) <= 4);
463             if (insOptsLSL(id->idInsOpt()))
464             {
465                 assert((emitGetInsSC(id) > 0) ||
466                        (id->idReg2() == REG_ZR)); // REG_ZR encodes SP and we allow a shift of zero
467             }
468             break;
469
470         case IF_DR_3D: // DR_3D   X..........mmmmm cccc..nnnnnmmmmm      Rd Rn Rm cond
471             assert(isValidGeneralDatasize(id->idOpSize()));
472             assert(isGeneralRegister(id->idReg1()));
473             assert(isGeneralRegister(id->idReg2()));
474             assert(isGeneralRegister(id->idReg3()));
475             assert(isValidImmCond(emitGetInsSC(id)));
476             break;
477
478         case IF_DR_3E: // DR_3E   X........X.mmmmm ssssssnnnnnddddd      Rd Rn Rm imm(0-63)
479             assert(isValidGeneralDatasize(id->idOpSize()));
480             assert(isGeneralRegister(id->idReg1()));
481             assert(isGeneralRegister(id->idReg2()));
482             assert(isGeneralRegister(id->idReg3()));
483             assert(isValidImmShift(emitGetInsSC(id), id->idOpSize()));
484             assert(insOptsNone(id->idInsOpt()));
485             break;
486
487         case IF_DR_4A: // DR_4A   X..........mmmmm .aaaaannnnnddddd      Rd Rn Rm Ra
488             assert(isValidGeneralDatasize(id->idOpSize()));
489             assert(isGeneralRegister(id->idReg1()));
490             assert(isGeneralRegister(id->idReg2()));
491             assert(isGeneralRegister(id->idReg3()));
492             assert(isGeneralRegister(id->idReg4()));
493             break;
494
495         case IF_DV_1A: // DV_1A   .........X.iiiii iii........ddddd      Vd imm8    (fmov - immediate scalar)
496             assert(insOptsNone(id->idInsOpt()));
497             elemsize = id->idOpSize();
498             assert(isValidVectorElemsizeFloat(elemsize));
499             assert(isVectorRegister(id->idReg1()));
500             assert(isValidUimm8(emitGetInsSC(id)));
501             break;
502
503         case IF_DV_1B: // DV_1B   .QX..........iii cmod..iiiiiddddd      Vd imm8    (immediate vector)
504             ins      = id->idIns();
505             imm      = emitGetInsSC(id) & 0x0ff;
506             immShift = (emitGetInsSC(id) & 0x700) >> 8;
507             assert(immShift >= 0);
508             datasize = id->idOpSize();
509             assert(isValidVectorDatasize(datasize));
510             assert(isValidArrangement(datasize, id->idInsOpt()));
511             elemsize = optGetElemsize(id->idInsOpt());
512             if (ins == INS_fmov)
513             {
514                 assert(isValidVectorElemsizeFloat(elemsize));
515                 assert(id->idInsOpt() != INS_OPTS_1D); // Reserved encoding
516                 assert(immShift == 0);
517             }
518             else
519             {
520                 assert(isValidVectorElemsize(elemsize));
521                 assert((immShift != 4) && (immShift != 7)); // always invalid values
522                 if (ins != INS_movi)                        // INS_mvni, INS_orr, INS_bic
523                 {
524                     assert((elemsize != EA_1BYTE) && (elemsize != EA_8BYTE)); // only H or S
525                     if (elemsize == EA_2BYTE)
526                     {
527                         assert(immShift < 2);
528                     }
529                     else // (elemsize == EA_4BYTE)
530                     {
531                         if (ins != INS_mvni)
532                         {
533                             assert(immShift < 4);
534                         }
535                     }
536                 }
537             }
538             assert(isVectorRegister(id->idReg1()));
539             assert(isValidUimm8(imm));
540             break;
541
542         case IF_DV_1C: // DV_1C   .........X...... ......nnnnn.....      Vn #0.0    (fcmp - with zero)
543             assert(insOptsNone(id->idInsOpt()));
544             elemsize = id->idOpSize();
545             assert(isValidVectorElemsizeFloat(elemsize));
546             assert(isVectorRegister(id->idReg1()));
547             break;
548
549         case IF_DV_2A: // DV_2A   .Q.......X...... ......nnnnnddddd      Vd Vn      (fabs, fcvt - vector)
550         case IF_DV_2M: // DV_2M   .Q......XX...... ......nnnnnddddd      Vd Vn      (abs, neg   - vector)
551             assert(isValidVectorDatasize(id->idOpSize()));
552             assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
553             assert(isVectorRegister(id->idReg1()));
554             assert(isVectorRegister(id->idReg2()));
555             break;
556
557         case IF_DV_2N: // DV_2N   .........iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - scalar)
558             assert(id->idOpSize() == EA_8BYTE);
559             assert(insOptsNone(id->idInsOpt()));
560             assert(isVectorRegister(id->idReg1()));
561             assert(isVectorRegister(id->idReg2()));
562             assert(isValidImmShift(emitGetInsSC(id), EA_8BYTE));
563             break;
564
565         case IF_DV_2O: // DV_2O   .Q.......iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - vector)
566             assert(isValidVectorDatasize(id->idOpSize()));
567             assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
568             assert(isVectorRegister(id->idReg1()));
569             assert(isVectorRegister(id->idReg2()));
570             elemsize = optGetElemsize(id->idInsOpt());
571             assert(isValidImmShift(emitGetInsSC(id), elemsize));
572             break;
573
574         case IF_DV_2B: // DV_2B   .Q.........iiiii ......nnnnnddddd      Rd Vn[]  (umov/smov    - to general)
575             elemsize = id->idOpSize();
576             index    = emitGetInsSC(id);
577             assert(insOptsNone(id->idInsOpt()));
578             assert(isValidVectorIndex(EA_16BYTE, elemsize, index));
579             assert(isValidVectorElemsize(elemsize));
580             assert(isGeneralRegister(id->idReg1()));
581             assert(isVectorRegister(id->idReg2()));
582             break;
583
584         case IF_DV_2C: // DV_2C   .Q.........iiiii ......nnnnnddddd      Vd Rn    (dup/ins - vector from general)
585             if (id->idIns() == INS_dup)
586             {
587                 datasize = id->idOpSize();
588                 assert(isValidVectorDatasize(datasize));
589                 assert(isValidArrangement(datasize, id->idInsOpt()));
590                 elemsize = optGetElemsize(id->idInsOpt());
591             }
592             else // INS_ins
593             {
594                 datasize = EA_16BYTE;
595                 elemsize = id->idOpSize();
596                 assert(isValidVectorElemsize(elemsize));
597             }
598             assert(isVectorRegister(id->idReg1()));
599             assert(isGeneralRegisterOrZR(id->idReg2()));
600             break;
601
602         case IF_DV_2D: // DV_2D   .Q.........iiiii ......nnnnnddddd      Vd Vn[]  (dup - vector)
603             datasize = id->idOpSize();
604             assert(isValidVectorDatasize(datasize));
605             assert(isValidArrangement(datasize, id->idInsOpt()));
606             elemsize = optGetElemsize(id->idInsOpt());
607             index    = emitGetInsSC(id);
608             assert(isValidVectorIndex(datasize, elemsize, index));
609             assert(isVectorRegister(id->idReg1()));
610             assert(isVectorRegister(id->idReg2()));
611             break;
612
613         case IF_DV_2E: // DV_2E   ...........iiiii ......nnnnnddddd      Vd Vn[]  (dup - scalar)
614             elemsize = id->idOpSize();
615             index    = emitGetInsSC(id);
616             assert(isValidVectorIndex(EA_16BYTE, elemsize, index));
617             assert(isValidVectorElemsize(elemsize));
618             assert(isVectorRegister(id->idReg1()));
619             assert(isVectorRegister(id->idReg2()));
620             break;
621
622         case IF_DV_2F: // DV_2F   ...........iiiii .jjjj.nnnnnddddd      Vd[] Vn[] (ins - element)
623             imm      = emitGetInsSC(id);
624             index    = (imm >> 4) & 0xf;
625             index2   = imm & 0xf;
626             elemsize = id->idOpSize();
627             assert(isValidVectorElemsize(elemsize));
628             assert(isValidVectorIndex(EA_16BYTE, elemsize, index));
629             assert(isValidVectorIndex(EA_16BYTE, elemsize, index2));
630             assert(isVectorRegister(id->idReg1()));
631             assert(isVectorRegister(id->idReg2()));
632             break;
633
634         case IF_DV_2L: // DV_2L   ........XX...... ......nnnnnddddd      Vd Vn      (abs, neg - scalar)
635             assert(id->idOpSize() == EA_8BYTE); // only type D is supported
636             __fallthrough;
637
638         case IF_DV_2G: // DV_2G   .........X...... ......nnnnnddddd      Vd Vn      (fmov, fcvtXX - register)
639         case IF_DV_2K: // DV_2K   .........X.mmmmm ......nnnnn.....      Vn Vm      (fcmp)
640             assert(insOptsNone(id->idInsOpt()));
641             assert(isValidVectorElemsizeFloat(id->idOpSize()));
642             assert(isVectorRegister(id->idReg1()));
643             assert(isVectorRegister(id->idReg2()));
644             break;
645
646         case IF_DV_2H: // DV_2H   X........X...... ......nnnnnddddd      Rd Vn      (fmov/fcvtXX - to general)
647             assert(insOptsConvertFloatToInt(id->idInsOpt()));
648             dstsize = optGetDstsize(id->idInsOpt());
649             srcsize = optGetSrcsize(id->idInsOpt());
650             assert(isValidGeneralDatasize(dstsize));
651             assert(isValidVectorElemsizeFloat(srcsize));
652             assert(dstsize == id->idOpSize());
653             assert(isGeneralRegister(id->idReg1()));
654             assert(isVectorRegister(id->idReg2()));
655             break;
656
657         case IF_DV_2I: // DV_2I   X........X...... ......nnnnnddddd      Vd Rn      (fmov/Xcvtf - from general)
658             assert(insOptsConvertIntToFloat(id->idInsOpt()));
659             dstsize = optGetDstsize(id->idInsOpt());
660             srcsize = optGetSrcsize(id->idInsOpt());
661             assert(isValidGeneralDatasize(srcsize));
662             assert(isValidVectorElemsizeFloat(dstsize));
663             assert(dstsize == id->idOpSize());
664             assert(isVectorRegister(id->idReg1()));
665             assert(isGeneralRegister(id->idReg2()));
666             break;
667
668         case IF_DV_2J: // DV_2J   ........SS.....D D.....nnnnnddddd      Vd Vn      (fcvt)
669             assert(insOptsConvertFloatToFloat(id->idInsOpt()));
670             dstsize = optGetDstsize(id->idInsOpt());
671             srcsize = optGetSrcsize(id->idInsOpt());
672             assert(isValidVectorFcvtsize(srcsize));
673             assert(isValidVectorFcvtsize(dstsize));
674             assert(dstsize == id->idOpSize());
675             assert(isVectorRegister(id->idReg1()));
676             assert(isVectorRegister(id->idReg2()));
677             break;
678
679         case IF_DV_3A: // DV_3A   .Q......XX.mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
680             assert(isValidVectorDatasize(id->idOpSize()));
681             assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
682             assert(isVectorRegister(id->idReg1()));
683             assert(isVectorRegister(id->idReg2()));
684             assert(isVectorRegister(id->idReg3()));
685             elemsize = optGetElemsize(id->idInsOpt());
686             ins      = id->idIns();
687             if (ins == INS_mul)
688             {
689                 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
690             }
691             else if (ins == INS_pmul)
692             {
693                 assert(elemsize == EA_1BYTE); // only supports 8B or 16B
694             }
695             break;
696
697         case IF_DV_3AI: // DV_3AI  .Q......XXLMmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector by elem)
698             assert(isValidVectorDatasize(id->idOpSize()));
699             assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
700             assert(isVectorRegister(id->idReg1()));
701             assert(isVectorRegister(id->idReg2()));
702             assert(isVectorRegister(id->idReg3()));
703             elemsize = optGetElemsize(id->idInsOpt());
704             assert(isValidVectorIndex(EA_16BYTE, elemsize, emitGetInsSC(id)));
705             // Only has encodings for H or S elemsize
706             assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE));
707             break;
708
709         case IF_DV_3B: // DV_3B   .Q.......X.mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
710             assert(isValidVectorDatasize(id->idOpSize()));
711             assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
712             assert(isVectorRegister(id->idReg1()));
713             assert(isVectorRegister(id->idReg2()));
714             assert(isVectorRegister(id->idReg3()));
715             break;
716
717         case IF_DV_3BI: // DV_3BI  .Q.......XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector by elem)
718             assert(isValidVectorDatasize(id->idOpSize()));
719             assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
720             assert(isVectorRegister(id->idReg1()));
721             assert(isVectorRegister(id->idReg2()));
722             assert(isVectorRegister(id->idReg3()));
723             elemsize = optGetElemsize(id->idInsOpt());
724             assert(isValidVectorIndex(id->idOpSize(), elemsize, emitGetInsSC(id)));
725             break;
726
727         case IF_DV_3C: // DV_3C   .Q.........mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
728             assert(isValidVectorDatasize(id->idOpSize()));
729             assert(isValidArrangement(id->idOpSize(), id->idInsOpt()));
730             assert(isVectorRegister(id->idReg1()));
731             assert(isVectorRegister(id->idReg2()));
732             assert(isVectorRegister(id->idReg3()));
733             break;
734
735         case IF_DV_3D: // DV_3D   .........X.mmmmm ......nnnnnddddd      Vd Vn Vm   (scalar)
736             assert(isValidScalarDatasize(id->idOpSize()));
737             assert(insOptsNone(id->idInsOpt()));
738             assert(isVectorRegister(id->idReg1()));
739             assert(isVectorRegister(id->idReg2()));
740             assert(isVectorRegister(id->idReg3()));
741             break;
742
743         case IF_DV_3DI: // DV_3DI  .........XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (scalar by elem)
744             assert(isValidScalarDatasize(id->idOpSize()));
745             assert(insOptsNone(id->idInsOpt()));
746             assert(isVectorRegister(id->idReg1()));
747             assert(isVectorRegister(id->idReg2()));
748             assert(isVectorRegister(id->idReg3()));
749             elemsize = id->idOpSize();
750             assert(isValidVectorIndex(EA_16BYTE, elemsize, emitGetInsSC(id)));
751             break;
752
753         case IF_DV_3E: // DV_3E   ...........mmmmm ......nnnnnddddd      Vd Vn Vm  (scalar)
754             assert(insOptsNone(id->idInsOpt()));
755             assert(id->idOpSize() == EA_8BYTE);
756             assert(isVectorRegister(id->idReg1()));
757             assert(isVectorRegister(id->idReg2()));
758             assert(isVectorRegister(id->idReg3()));
759             break;
760
761         case IF_DV_4A: // DR_4A   .........X.mmmmm .aaaaannnnnddddd      Rd Rn Rm Ra (scalar)
762             assert(isValidGeneralDatasize(id->idOpSize()));
763             assert(isVectorRegister(id->idReg1()));
764             assert(isVectorRegister(id->idReg2()));
765             assert(isVectorRegister(id->idReg3()));
766             assert(isVectorRegister(id->idReg4()));
767             break;
768
769         case IF_SN_0A: // SN_0A   ................ ................
770         case IF_SI_0A: // SI_0A   ...........iiiii iiiiiiiiiii.....               imm16
771         case IF_SI_0B: // SI_0B   ................ ....bbbb........               imm4 - barrier
772             break;
773
774         default:
775             printf("unexpected format %s\n", emitIfName(id->idInsFmt()));
776             assert(!"Unexpected format");
777             break;
778     }
779 }
780 #endif // DEBUG
781
782 bool emitter::emitInsMayWriteToGCReg(instrDesc* id)
783 {
784     instruction ins = id->idIns();
785     insFormat   fmt = id->idInsFmt();
786
787     switch (fmt)
788     {
789
790         // These are the formats with "destination" registers:
791
792         case IF_DI_1B: // DI_1B   X........hwiiiii iiiiiiiiiiiddddd      Rd       imm(i16,hw)
793         case IF_DI_1D: // DI_1D   X........Nrrrrrr ssssss.....ddddd      Rd       imm(N,r,s)
794         case IF_DI_1E: // DI_1E   .ii.....iiiiiiii iiiiiiiiiiiddddd      Rd       simm21
795
796         case IF_DI_2A: // DI_2A   X.......shiiiiii iiiiiinnnnnddddd      Rd Rn    imm(i12,sh)
797         case IF_DI_2B: // DI_2B   X.........Xnnnnn ssssssnnnnnddddd      Rd Rn    imm(0-63)
798         case IF_DI_2C: // DI_2C   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imm(N,r,s)
799         case IF_DI_2D: // DI_2D   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imr, imms   (N,r,s)
800
801         case IF_DR_1D: // DR_1D   X............... cccc.......ddddd      Rd       cond
802
803         case IF_DR_2D: // DR_2D   X..........nnnnn cccc..nnnnnddddd      Rd Rn    cond
804         case IF_DR_2E: // DR_2E   X..........mmmmm ...........ddddd      Rd    Rm
805         case IF_DR_2F: // DR_2F   X.......sh.mmmmm ssssss.....ddddd      Rd    Rm {LSL,LSR,ASR} imm(0-63)
806         case IF_DR_2G: // DR_2G   X............... ......nnnnnddddd      Rd Rn
807         case IF_DR_2H: // DR_2H   X........X...... ......nnnnnddddd      Rd Rn
808
809         case IF_DR_3A: // DR_3A   X..........mmmmm ......nnnnnddddd      Rd Rn Rm
810         case IF_DR_3B: // DR_3B   X.......sh.mmmmm ssssssnnnnnddddd      Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
811         case IF_DR_3C: // DR_3C   X..........mmmmm xxxsssnnnnnddddd      Rd Rn Rm ext(Rm) LSL imm(0-4)
812         case IF_DR_3D: // DR_3D   X..........mmmmm cccc..nnnnnddddd      Rd Rn Rm cond
813         case IF_DR_3E: // DR_3E   X........X.mmmmm ssssssnnnnnddddd      Rd Rn Rm imm(0-63)
814
815         case IF_DR_4A: // DR_4A   X..........mmmmm .aaaaannnnnddddd      Rd Rn Rm Ra
816
817         case IF_DV_2B: // DV_2B   .Q.........iiiii ......nnnnnddddd      Rd Vn[]    (umov - to general)
818         case IF_DV_2H: // DV_2H   X........X...... ......nnnnnddddd      Rd Vn      (fmov - to general)
819
820             return true;
821
822         case IF_DV_2C:  // DV_2C   .Q.........iiiii ......nnnnnddddd      Vd Rn      (dup/ins - vector from general)
823         case IF_DV_2D:  // DV_2D   .Q.........iiiii ......nnnnnddddd      Vd Vn[]    (dup - vector)
824         case IF_DV_2E:  // DV_2E   ...........iiiii ......nnnnnddddd      Vd Vn[]    (dup - scalar)
825         case IF_DV_2F:  // DV_2F   ...........iiiii .jjjj.nnnnnddddd      Vd[] Vn[]  (ins - element)
826         case IF_DV_2G:  // DV_2G   .........X...... ......nnnnnddddd      Vd Vn      (fmov, fcvtXX - register)
827         case IF_DV_2I:  // DV_2I   X........X...... ......nnnnnddddd      Vd Rn      (fmov - from general)
828         case IF_DV_2J:  // DV_2J   ........SS.....D D.....nnnnnddddd      Vd Vn      (fcvt)
829         case IF_DV_2K:  // DV_2K   .........X.mmmmm ......nnnnn.....      Vn Vm      (fcmp)
830         case IF_DV_2L:  // DV_2L   ........XX...... ......nnnnnddddd      Vd Vn      (abs, neg - scalar)
831         case IF_DV_2M:  // DV_2M   .Q......XX...... ......nnnnnddddd      Vd Vn      (abs, neg - vector)
832         case IF_DV_3A:  // DV_3A   .Q......XX.mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
833         case IF_DV_3AI: // DV_3AI  .Q......XXLMmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector)
834         case IF_DV_3B:  // DV_3B   .Q.......X.mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
835         case IF_DV_3BI: // DV_3BI  .Q.......XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector by elem)
836         case IF_DV_3C:  // DV_3C   .Q.........mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
837         case IF_DV_3D:  // DV_3D   .........X.mmmmm ......nnnnnddddd      Vd Vn Vm   (scalar)
838         case IF_DV_3DI: // DV_3DI  .........XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (scalar by elem)
839         case IF_DV_3E:  // DV_3E   ...........mmmmm ......nnnnnddddd      Vd Vn Vm   (scalar)
840         case IF_DV_4A:  // DV_4A   .........X.mmmmm .aaaaannnnnddddd      Vd Va Vn Vm (scalar)
841             // Tracked GC pointers cannot be placed into the SIMD registers.
842             return false;
843
844         // These are the load/store formats with "target" registers:
845
846         case IF_LS_1A: // LS_1A   XX...V..iiiiiiii iiiiiiiiiiittttt      Rt    PC imm(1MB)
847         case IF_LS_2A: // LS_2A   .X.......X...... ......nnnnnttttt      Rt Rn
848         case IF_LS_2B: // LS_2B   .X.......Xiiiiii iiiiiinnnnnttttt      Rt Rn    imm(0-4095)
849         case IF_LS_2C: // LS_2C   .X.......X.iiiii iiiiP.nnnnnttttt      Rt Rn    imm(-256..+255) pre/post inc
850         case IF_LS_3A: // LS_3A   .X.......X.mmmmm xxxS..nnnnnttttt      Rt Rn Rm ext(Rm) LSL {}
851         case IF_LS_3B: // LS_3B   X............... .aaaaannnnnttttt      Rt Ra Rn
852         case IF_LS_3C: // LS_3C   X.........iiiiii iaaaaannnnnttttt      Rt Ra Rn imm(im7,sh)
853         case IF_LS_3D: // LS_3D   .X.......X.mmmmm ......nnnnnttttt      Wm Rt Rn
854
855             // For the Store instructions the "target" register is actually a "source" value
856
857             if (emitInsIsStore(ins))
858             {
859                 return false;
860             }
861             else
862             {
863                 assert(emitInsIsLoad(ins));
864                 return true;
865             }
866
867         default:
868             return false;
869     }
870 }
871
872 bool emitter::emitInsWritesToLclVarStackLoc(instrDesc* id)
873 {
874     if (!id->idIsLclVar())
875         return false;
876
877     instruction ins = id->idIns();
878
879     // This list is related to the list of instructions used to store local vars in emitIns_S_R().
880     // We don't accept writing to float local vars.
881
882     switch (ins)
883     {
884         case INS_strb:
885         case INS_strh:
886         case INS_str:
887         case INS_stur:
888         case INS_sturb:
889         case INS_sturh:
890             return true;
891         default:
892             return false;
893     }
894 }
895
896 bool emitter::emitInsWritesToLclVarStackLocPair(instrDesc* id)
897 {
898     if (!id->idIsLclVar())
899         return false;
900
901     instruction ins = id->idIns();
902
903     // This list is related to the list of instructions used to store local vars in emitIns_S_S_R_R().
904     // We don't accept writing to float local vars.
905
906     switch (ins)
907     {
908         case INS_stnp:
909         case INS_stp:
910             return true;
911         default:
912             return false;
913     }
914 }
915
916 bool emitter::emitInsMayWriteMultipleRegs(instrDesc* id)
917 {
918     instruction ins = id->idIns();
919
920     switch (ins)
921     {
922         case INS_ldp:
923         case INS_ldpsw:
924         case INS_ldnp:
925             return true;
926         default:
927             return false;
928     }
929 }
930
931 // For the small loads/store instruction we adjust the size 'attr'
932 // depending upon whether we have a load or a store
933 //
934 emitAttr emitter::emitInsAdjustLoadStoreAttr(instruction ins, emitAttr attr)
935 {
936     if (EA_SIZE(attr) <= EA_4BYTE)
937     {
938         if (emitInsIsLoad(ins))
939         {
940             // The value of 'ins' encodes the size to load
941             // we use EA_8BYTE here because it is the size we will write (into dataReg)
942             // it is also required when ins is INS_ldrsw
943             //
944             attr = EA_8BYTE;
945         }
946         else
947         {
948             assert(emitInsIsStore(ins));
949
950             // The value of 'ins' encodes the size to store
951             // we use EA_4BYTE here because it is the size of the register
952             // that we want to display when storing small values
953             //
954             attr = EA_4BYTE;
955         }
956     }
957     return attr;
958 }
959
960 // Takes an instrDesc 'id' and uses the instruction 'ins' to determine the
961 // size of the target register that is written or read by the instruction.
962 // Note that even if EA_4BYTE is returned a load instruction will still
963 // always zero the upper 4 bytes of the target register.
964 // This method is required so that we can distinguish between loads that are
965 // sign-extending as they can have two different sizes for their target register.
966 // Additionally for instructions like 'ldr' and 'str' these can load/store
967 // either 4 byte or 8 bytes to/from the target register.
968 // By convention the small unsigned load instructions are considered to write
969 // a 4 byte sized target register, though since these also zero the upper 4 bytes
970 // they could equally be considered to write the unsigned value to full 8 byte register.
971 //
972 emitAttr emitter::emitInsTargetRegSize(instrDesc* id)
973 {
974     instruction ins    = id->idIns();
975     emitAttr    result = EA_UNKNOWN;
976
977     // This is used to determine the size of the target registers for a load/store instruction
978
979     switch (ins)
980     {
981         case INS_ldxrb:
982         case INS_ldarb:
983         case INS_ldaxrb:
984         case INS_stxrb:
985         case INS_stlrb:
986         case INS_stlxrb:
987         case INS_ldrb:
988         case INS_strb:
989         case INS_ldurb:
990         case INS_sturb:
991             result = EA_4BYTE;
992             break;
993
994         case INS_ldxrh:
995         case INS_ldarh:
996         case INS_ldaxrh:
997         case INS_stxrh:
998         case INS_stlrh:
999         case INS_stlxrh:
1000         case INS_ldrh:
1001         case INS_strh:
1002         case INS_ldurh:
1003         case INS_sturh:
1004             result = EA_4BYTE;
1005             break;
1006
1007         case INS_ldrsb:
1008         case INS_ldursb:
1009         case INS_ldrsh:
1010         case INS_ldursh:
1011             if (id->idOpSize() == EA_8BYTE)
1012                 result = EA_8BYTE;
1013             else
1014                 result = EA_4BYTE;
1015             break;
1016
1017         case INS_ldrsw:
1018         case INS_ldursw:
1019         case INS_ldpsw:
1020             result = EA_8BYTE;
1021             break;
1022
1023         case INS_ldp:
1024         case INS_stp:
1025         case INS_ldnp:
1026         case INS_stnp:
1027             result = id->idOpSize();
1028             break;
1029
1030         case INS_ldxr:
1031         case INS_ldar:
1032         case INS_ldaxr:
1033         case INS_stxr:
1034         case INS_stlr:
1035         case INS_stlxr:
1036         case INS_ldr:
1037         case INS_str:
1038         case INS_ldur:
1039         case INS_stur:
1040             result = id->idOpSize();
1041             break;
1042
1043         default:
1044             NO_WAY("unexpected instruction");
1045             break;
1046     }
1047     return result;
1048 }
1049
1050 // Takes an instrDesc and uses the instruction to determine the 'size' of the
1051 // data that is loaded from memory.
1052 //
1053 emitAttr emitter::emitInsLoadStoreSize(instrDesc* id)
1054 {
1055     instruction ins    = id->idIns();
1056     emitAttr    result = EA_UNKNOWN;
1057
1058     // The 'result' returned is the 'size' of the data that is loaded from memory.
1059
1060     switch (ins)
1061     {
1062         case INS_ldarb:
1063         case INS_stlrb:
1064         case INS_ldrb:
1065         case INS_strb:
1066         case INS_ldurb:
1067         case INS_sturb:
1068         case INS_ldrsb:
1069         case INS_ldursb:
1070             result = EA_1BYTE;
1071             break;
1072
1073         case INS_ldarh:
1074         case INS_stlrh:
1075         case INS_ldrh:
1076         case INS_strh:
1077         case INS_ldurh:
1078         case INS_sturh:
1079         case INS_ldrsh:
1080         case INS_ldursh:
1081             result = EA_2BYTE;
1082             break;
1083
1084         case INS_ldrsw:
1085         case INS_ldursw:
1086         case INS_ldpsw:
1087             result = EA_4BYTE;
1088             break;
1089
1090         case INS_ldp:
1091         case INS_stp:
1092         case INS_ldnp:
1093         case INS_stnp:
1094             result = id->idOpSize();
1095             break;
1096
1097         case INS_ldar:
1098         case INS_stlr:
1099         case INS_ldr:
1100         case INS_str:
1101         case INS_ldur:
1102         case INS_stur:
1103             result = id->idOpSize();
1104             break;
1105
1106         default:
1107             NO_WAY("unexpected instruction");
1108             break;
1109     }
1110     return result;
1111 }
1112
1113 /*****************************************************************************/
1114 #ifdef DEBUG
1115
1116 // clang-format off
1117 static const char * const  xRegNames[] =
1118 {
1119     #define REGDEF(name, rnum, mask, xname, wname) xname,
1120     #include "register.h"
1121 };
1122
1123 static const char * const  wRegNames[] =
1124 {
1125     #define REGDEF(name, rnum, mask, xname, wname) wname,
1126     #include "register.h"
1127 };
1128
1129 static const char * const  vRegNames[] =
1130 {
1131     "v0",  "v1",  "v2",  "v3",  "v4", 
1132     "v5",  "v6",  "v7",  "v8",  "v9", 
1133     "v10", "v11", "v12", "v13", "v14", 
1134     "v15", "v16", "v17", "v18", "v19", 
1135     "v20", "v21", "v22", "v23", "v24", 
1136     "v25", "v26", "v27", "v28", "v29",
1137     "v30", "v31"
1138 };
1139
1140 static const char * const  qRegNames[] =
1141 {
1142     "q0",  "q1",  "q2",  "q3",  "q4", 
1143     "q5",  "q6",  "q7",  "q8",  "q9", 
1144     "q10", "q11", "q12", "q13", "q14", 
1145     "q15", "q16", "q17", "q18", "q19", 
1146     "q20", "q21", "q22", "q23", "q24", 
1147     "q25", "q26", "q27", "q28", "q29",
1148     "q30", "q31"
1149 };
1150
1151 static const char * const  hRegNames[] =
1152 {
1153     "h0",  "h1",  "h2",  "h3",  "h4", 
1154     "h5",  "h6",  "h7",  "h8",  "h9", 
1155     "h10", "h11", "h12", "h13", "h14", 
1156     "h15", "h16", "h17", "h18", "h19", 
1157     "h20", "h21", "h22", "h23", "h24", 
1158     "h25", "h26", "h27", "h28", "h29",
1159     "h30", "h31"
1160 };
1161 static const char * const  bRegNames[] =
1162 {
1163     "b0",  "b1",  "b2",  "b3",  "b4", 
1164     "b5",  "b6",  "b7",  "b8",  "b9", 
1165     "b10", "b11", "b12", "b13", "b14", 
1166     "b15", "b16", "b17", "b18", "b19", 
1167     "b20", "b21", "b22", "b23", "b24", 
1168     "b25", "b26", "b27", "b28", "b29",
1169     "b30", "b31"
1170 };
1171 // clang-format on
1172
1173 /*****************************************************************************
1174  *
1175  *  Return a string that represents the given register.
1176  */
1177
1178 const char* emitter::emitRegName(regNumber reg, emitAttr size, bool varName)
1179 {
1180     assert(reg < REG_COUNT);
1181
1182     const char* rn = nullptr;
1183
1184     if (size == EA_8BYTE)
1185     {
1186         rn = xRegNames[reg];
1187     }
1188     else if (size == EA_4BYTE)
1189     {
1190         rn = wRegNames[reg];
1191     }
1192     else if (isVectorRegister(reg))
1193     {
1194         if (size == EA_16BYTE)
1195         {
1196             rn = qRegNames[reg - REG_V0];
1197         }
1198         else if (size == EA_2BYTE)
1199         {
1200             rn = hRegNames[reg - REG_V0];
1201         }
1202         else if (size == EA_1BYTE)
1203         {
1204             rn = bRegNames[reg - REG_V0];
1205         }
1206     }
1207
1208     assert(rn != nullptr);
1209
1210     return rn;
1211 }
1212
1213 /*****************************************************************************
1214  *
1215  *  Return a string that represents the given register.
1216  */
1217
1218 const char* emitter::emitVectorRegName(regNumber reg)
1219 {
1220     assert((reg >= REG_V0) && (reg <= REG_V31));
1221
1222     int index = (int)reg - (int)REG_V0;
1223
1224     return vRegNames[index];
1225 }
1226 #endif // DEBUG
1227
1228 /*****************************************************************************
1229  *
1230  *  Returns the base encoding of the given CPU instruction.
1231  */
1232
1233 emitter::insFormat emitter::emitInsFormat(instruction ins)
1234 {
1235     // clang-format off
1236     const static insFormat insFormats[] =
1237     {
1238         #define INST1(id, nm, fp, ldst, fmt, e1                                ) fmt,
1239         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            ) fmt,
1240         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        ) fmt,
1241         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    ) fmt,
1242         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                ) fmt,
1243         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            ) fmt,
1244         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) fmt,
1245         #include "instrs.h"
1246     };
1247     // clang-format on
1248
1249     assert(ins < ArrLen(insFormats));
1250     assert((insFormats[ins] != IF_NONE));
1251
1252     return insFormats[ins];
1253 }
1254
1255 // INST_FP is 1
1256 #define LD 2
1257 #define ST 4
1258 #define CMP 8
1259
1260 // clang-format off
1261 /*static*/ const BYTE CodeGenInterface::instInfo[] =
1262 {
1263     #define INST1(id, nm, fp, ldst, fmt, e1                                ) ldst | INST_FP*fp,
1264     #define INST2(id, nm, fp, ldst, fmt, e1, e2                            ) ldst | INST_FP*fp,
1265     #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        ) ldst | INST_FP*fp,
1266     #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    ) ldst | INST_FP*fp,
1267     #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                ) ldst | INST_FP*fp,
1268     #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            ) ldst | INST_FP*fp,
1269     #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) ldst | INST_FP*fp,
1270     #include "instrs.h"
1271 };
1272 // clang-format on
1273
1274 /*****************************************************************************
1275  *
1276  *  Returns true if the instruction is some kind of compare or test instruction
1277  */
1278
1279 bool emitter::emitInsIsCompare(instruction ins)
1280 {
1281     // We have pseudo ins like lea which are not included in emitInsLdStTab.
1282     if (ins < ArrLen(CodeGenInterface::instInfo))
1283         return (CodeGenInterface::instInfo[ins] & CMP) ? true : false;
1284     else
1285         return false;
1286 }
1287
1288 /*****************************************************************************
1289  *
1290  *  Returns true if the instruction is some kind of load instruction
1291  */
1292
1293 bool emitter::emitInsIsLoad(instruction ins)
1294 {
1295     // We have pseudo ins like lea which are not included in emitInsLdStTab.
1296     if (ins < ArrLen(CodeGenInterface::instInfo))
1297         return (CodeGenInterface::instInfo[ins] & LD) ? true : false;
1298     else
1299         return false;
1300 }
1301 /*****************************************************************************
1302  *
1303  *  Returns true if the instruction is some kind of store instruction
1304  */
1305
1306 bool emitter::emitInsIsStore(instruction ins)
1307 {
1308     // We have pseudo ins like lea which are not included in emitInsLdStTab.
1309     if (ins < ArrLen(CodeGenInterface::instInfo))
1310         return (CodeGenInterface::instInfo[ins] & ST) ? true : false;
1311     else
1312         return false;
1313 }
1314
1315 /*****************************************************************************
1316  *
1317  *  Returns true if the instruction is some kind of load/store instruction
1318  */
1319
1320 bool emitter::emitInsIsLoadOrStore(instruction ins)
1321 {
1322     // We have pseudo ins like lea which are not included in emitInsLdStTab.
1323     if (ins < ArrLen(CodeGenInterface::instInfo))
1324         return (CodeGenInterface::instInfo[ins] & (LD | ST)) ? true : false;
1325     else
1326         return false;
1327 }
1328
1329 #undef LD
1330 #undef ST
1331 #undef CMP
1332
1333 /*****************************************************************************
1334  *
1335  *  Returns the specific encoding of the given CPU instruction and format
1336  */
1337
1338 emitter::code_t emitter::emitInsCode(instruction ins, insFormat fmt)
1339 {
1340     // clang-format off
1341     const static code_t insCodes1[] =
1342     {
1343         #define INST1(id, nm, fp, ldst, fmt, e1                                ) e1,
1344         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            ) e1,
1345         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        ) e1,
1346         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    ) e1,
1347         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                ) e1,
1348         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            ) e1,
1349         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e1,
1350         #include "instrs.h"
1351     };
1352     const static code_t insCodes2[] =
1353     {
1354         #define INST1(id, nm, fp, ldst, fmt, e1                                )
1355         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            ) e2,
1356         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        ) e2,
1357         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    ) e2,
1358         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                ) e2,
1359         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            ) e2,
1360         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e2,
1361         #include "instrs.h"
1362     };
1363     const static code_t insCodes3[] =
1364     {
1365         #define INST1(id, nm, fp, ldst, fmt, e1                                )
1366         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            )
1367         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        ) e3,
1368         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    ) e3,
1369         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                ) e3,
1370         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            ) e3,
1371         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e3,
1372         #include "instrs.h"
1373     };
1374     const static code_t insCodes4[] =
1375     {
1376         #define INST1(id, nm, fp, ldst, fmt, e1                                )
1377         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            )
1378         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        )
1379         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    ) e4,
1380         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                ) e4,
1381         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            ) e4,
1382         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e4,
1383         #include "instrs.h"
1384     };
1385     const static code_t insCodes5[] =
1386     {
1387         #define INST1(id, nm, fp, ldst, fmt, e1                                )
1388         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            )
1389         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        )
1390         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    )
1391         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                ) e5,
1392         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            ) e5,
1393         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e5,
1394         #include "instrs.h"
1395     };
1396     const static code_t insCodes6[] =
1397     {
1398         #define INST1(id, nm, fp, ldst, fmt, e1                                )
1399         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            )
1400         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        )
1401         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    )
1402         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                )
1403         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            ) e6,
1404         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e6,
1405         #include "instrs.h"
1406     };
1407     const static code_t insCodes7[] =
1408     {
1409         #define INST1(id, nm, fp, ldst, fmt, e1                                )
1410         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            )
1411         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        )
1412         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    )
1413         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                )
1414         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            )
1415         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e7,
1416         #include "instrs.h"
1417     };
1418     const static code_t insCodes8[] =
1419     {
1420         #define INST1(id, nm, fp, ldst, fmt, e1                                )
1421         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            )
1422         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        )
1423         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    )
1424         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                )
1425         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            )
1426         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e8,
1427         #include "instrs.h"
1428     };
1429     const static code_t insCodes9[] =
1430     {
1431         #define INST1(id, nm, fp, ldst, fmt, e1                                )
1432         #define INST2(id, nm, fp, ldst, fmt, e1, e2                            )
1433         #define INST3(id, nm, fp, ldst, fmt, e1, e2, e3                        )
1434         #define INST4(id, nm, fp, ldst, fmt, e1, e2, e3, e4                    )
1435         #define INST5(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5                )
1436         #define INST6(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6            )
1437         #define INST9(id, nm, fp, ldst, fmt, e1, e2, e3, e4, e5, e6, e7, e8, e9) e9,
1438         #include "instrs.h"
1439     };
1440     // clang-format on
1441
1442     const static insFormat formatEncode9[9] = {IF_DR_2E, IF_DR_2G, IF_DI_1B, IF_DI_1D, IF_DV_3C,
1443                                                IF_DV_2B, IF_DV_2C, IF_DV_2E, IF_DV_2F};
1444     const static insFormat formatEncode6A[6] = {IF_DR_3A, IF_DR_3B, IF_DR_3C, IF_DI_2A, IF_DV_3A, IF_DV_3E};
1445     const static insFormat formatEncode5A[5] = {IF_LS_2A, IF_LS_2B, IF_LS_2C, IF_LS_3A, IF_LS_1A};
1446     const static insFormat formatEncode5B[5] = {IF_DV_2G, IF_DV_2H, IF_DV_2I, IF_DV_1A, IF_DV_1B};
1447     const static insFormat formatEncode5C[5] = {IF_DR_3A, IF_DR_3B, IF_DI_2C, IF_DV_3C, IF_DV_1B};
1448     const static insFormat formatEncode4A[4] = {IF_LS_2A, IF_LS_2B, IF_LS_2C, IF_LS_3A};
1449     const static insFormat formatEncode4B[4] = {IF_DR_3A, IF_DR_3B, IF_DR_3C, IF_DI_2A};
1450     const static insFormat formatEncode4C[4] = {IF_DR_2A, IF_DR_2B, IF_DR_2C, IF_DI_1A};
1451     const static insFormat formatEncode4D[4] = {IF_DV_3B, IF_DV_3D, IF_DV_3BI, IF_DV_3DI};
1452     const static insFormat formatEncode4E[4] = {IF_DR_3A, IF_DR_3B, IF_DI_2C, IF_DV_3C};
1453     const static insFormat formatEncode4F[4] = {IF_DR_3A, IF_DR_3B, IF_DV_3C, IF_DV_1B};
1454     const static insFormat formatEncode4G[4] = {IF_DR_2E, IF_DR_2F, IF_DV_2M, IF_DV_2L};
1455     const static insFormat formatEncode4H[4] = {IF_DV_3E, IF_DV_3A, IF_DV_2L, IF_DV_2M};
1456     const static insFormat formatEncode4I[4] = {IF_DV_3D, IF_DV_3B, IF_DV_2G, IF_DV_2A};
1457     const static insFormat formatEncode3A[3] = {IF_DR_3A, IF_DR_3B, IF_DI_2C};
1458     const static insFormat formatEncode3B[3] = {IF_DR_2A, IF_DR_2B, IF_DI_1C};
1459     const static insFormat formatEncode3C[3] = {IF_DR_3A, IF_DR_3B, IF_DV_3C};
1460     const static insFormat formatEncode3D[3] = {IF_DV_2C, IF_DV_2D, IF_DV_2E};
1461     const static insFormat formatEncode3E[3] = {IF_DV_3B, IF_DV_3BI, IF_DV_3DI};
1462     const static insFormat formatEncode3F[3] = {IF_DV_2A, IF_DV_2G, IF_DV_2H};
1463     const static insFormat formatEncode3G[3] = {IF_DV_2A, IF_DV_2G, IF_DV_2I};
1464     const static insFormat formatEncode3H[3] = {IF_DR_3A, IF_DV_3A, IF_DV_3AI};
1465     const static insFormat formatEncode3I[3] = {IF_DR_2E, IF_DR_2F, IF_DV_2M};
1466     const static insFormat formatEncode2A[2] = {IF_DR_2E, IF_DR_2F};
1467     const static insFormat formatEncode2B[2] = {IF_DR_3A, IF_DR_3B};
1468     const static insFormat formatEncode2C[2] = {IF_DR_3A, IF_DI_2D};
1469     const static insFormat formatEncode2D[2] = {IF_DR_3A, IF_DI_2B};
1470     const static insFormat formatEncode2E[2] = {IF_LS_3B, IF_LS_3C};
1471     const static insFormat formatEncode2F[2] = {IF_DR_2I, IF_DI_1F};
1472     const static insFormat formatEncode2G[2] = {IF_DV_3B, IF_DV_3D};
1473     const static insFormat formatEncode2H[2] = {IF_DV_2C, IF_DV_2F};
1474     const static insFormat formatEncode2I[2] = {IF_DV_2K, IF_DV_1C};
1475     const static insFormat formatEncode2J[2] = {IF_DV_2A, IF_DV_2G};
1476     const static insFormat formatEncode2K[2] = {IF_DV_2M, IF_DV_2L};
1477     const static insFormat formatEncode2L[2] = {IF_DV_2G, IF_DV_2M};
1478     const static insFormat formatEncode2M[2] = {IF_DV_3A, IF_DV_3AI};
1479     const static insFormat formatEncode2N[2] = {IF_DV_2N, IF_DV_2O};
1480     const static insFormat formatEncode2O[2] = {IF_DV_3E, IF_DV_3A};
1481     const static insFormat formatEncode2P[2] = {IF_DV_2G, IF_DV_3B};
1482
1483     code_t    code           = BAD_CODE;
1484     insFormat insFmt         = emitInsFormat(ins);
1485     bool      encoding_found = false;
1486     int       index          = -1;
1487
1488     switch (insFmt)
1489     {
1490         case IF_EN9:
1491             for (index = 0; index < 9; index++)
1492             {
1493                 if (fmt == formatEncode9[index])
1494                 {
1495                     encoding_found = true;
1496                     break;
1497                 }
1498             }
1499             break;
1500
1501         case IF_EN6A:
1502             for (index = 0; index < 6; index++)
1503             {
1504                 if (fmt == formatEncode6A[index])
1505                 {
1506                     encoding_found = true;
1507                     break;
1508                 }
1509             }
1510             break;
1511
1512         case IF_EN5A:
1513             for (index = 0; index < 5; index++)
1514             {
1515                 if (fmt == formatEncode5A[index])
1516                 {
1517                     encoding_found = true;
1518                     break;
1519                 }
1520             }
1521             break;
1522
1523         case IF_EN5B:
1524             for (index = 0; index < 5; index++)
1525             {
1526                 if (fmt == formatEncode5B[index])
1527                 {
1528                     encoding_found = true;
1529                     break;
1530                 }
1531             }
1532             break;
1533
1534         case IF_EN5C:
1535             for (index = 0; index < 5; index++)
1536             {
1537                 if (fmt == formatEncode5C[index])
1538                 {
1539                     encoding_found = true;
1540                     break;
1541                 }
1542             }
1543             break;
1544
1545         case IF_EN4A:
1546             for (index = 0; index < 4; index++)
1547             {
1548                 if (fmt == formatEncode4A[index])
1549                 {
1550                     encoding_found = true;
1551                     break;
1552                 }
1553             }
1554             break;
1555
1556         case IF_EN4B:
1557             for (index = 0; index < 4; index++)
1558             {
1559                 if (fmt == formatEncode4B[index])
1560                 {
1561                     encoding_found = true;
1562                     break;
1563                 }
1564             }
1565             break;
1566
1567         case IF_EN4C:
1568             for (index = 0; index < 4; index++)
1569             {
1570                 if (fmt == formatEncode4C[index])
1571                 {
1572                     encoding_found = true;
1573                     break;
1574                 }
1575             }
1576             break;
1577
1578         case IF_EN4D:
1579             for (index = 0; index < 4; index++)
1580             {
1581                 if (fmt == formatEncode4D[index])
1582                 {
1583                     encoding_found = true;
1584                     break;
1585                 }
1586             }
1587             break;
1588
1589         case IF_EN4E:
1590             for (index = 0; index < 4; index++)
1591             {
1592                 if (fmt == formatEncode4E[index])
1593                 {
1594                     encoding_found = true;
1595                     break;
1596                 }
1597             }
1598             break;
1599
1600         case IF_EN4F:
1601             for (index = 0; index < 4; index++)
1602             {
1603                 if (fmt == formatEncode4F[index])
1604                 {
1605                     encoding_found = true;
1606                     break;
1607                 }
1608             }
1609             break;
1610
1611         case IF_EN4G:
1612             for (index = 0; index < 4; index++)
1613             {
1614                 if (fmt == formatEncode4G[index])
1615                 {
1616                     encoding_found = true;
1617                     break;
1618                 }
1619             }
1620             break;
1621
1622         case IF_EN4H:
1623             for (index = 0; index < 4; index++)
1624             {
1625                 if (fmt == formatEncode4H[index])
1626                 {
1627                     encoding_found = true;
1628                     break;
1629                 }
1630             }
1631             break;
1632
1633         case IF_EN4I:
1634             for (index = 0; index < 4; index++)
1635             {
1636                 if (fmt == formatEncode4I[index])
1637                 {
1638                     encoding_found = true;
1639                     break;
1640                 }
1641             }
1642             break;
1643
1644         case IF_EN3A:
1645             for (index = 0; index < 3; index++)
1646             {
1647                 if (fmt == formatEncode3A[index])
1648                 {
1649                     encoding_found = true;
1650                     break;
1651                 }
1652             }
1653             break;
1654
1655         case IF_EN3B:
1656             for (index = 0; index < 3; index++)
1657             {
1658                 if (fmt == formatEncode3B[index])
1659                 {
1660                     encoding_found = true;
1661                     break;
1662                 }
1663             }
1664             break;
1665
1666         case IF_EN3C:
1667             for (index = 0; index < 3; index++)
1668             {
1669                 if (fmt == formatEncode3C[index])
1670                 {
1671                     encoding_found = true;
1672                     break;
1673                 }
1674             }
1675             break;
1676
1677         case IF_EN3D:
1678             for (index = 0; index < 3; index++)
1679             {
1680                 if (fmt == formatEncode3D[index])
1681                 {
1682                     encoding_found = true;
1683                     break;
1684                 }
1685             }
1686             break;
1687
1688         case IF_EN3E:
1689             for (index = 0; index < 3; index++)
1690             {
1691                 if (fmt == formatEncode3E[index])
1692                 {
1693                     encoding_found = true;
1694                     break;
1695                 }
1696             }
1697             break;
1698
1699         case IF_EN3F:
1700             for (index = 0; index < 3; index++)
1701             {
1702                 if (fmt == formatEncode3F[index])
1703                 {
1704                     encoding_found = true;
1705                     break;
1706                 }
1707             }
1708             break;
1709
1710         case IF_EN3G:
1711             for (index = 0; index < 3; index++)
1712             {
1713                 if (fmt == formatEncode3G[index])
1714                 {
1715                     encoding_found = true;
1716                     break;
1717                 }
1718             }
1719             break;
1720
1721         case IF_EN3H:
1722             for (index = 0; index < 3; index++)
1723             {
1724                 if (fmt == formatEncode3H[index])
1725                 {
1726                     encoding_found = true;
1727                     break;
1728                 }
1729             }
1730             break;
1731
1732         case IF_EN3I:
1733             for (index = 0; index < 3; index++)
1734             {
1735                 if (fmt == formatEncode3I[index])
1736                 {
1737                     encoding_found = true;
1738                     break;
1739                 }
1740             }
1741             break;
1742
1743         case IF_EN2A:
1744             for (index = 0; index < 2; index++)
1745             {
1746                 if (fmt == formatEncode2A[index])
1747                 {
1748                     encoding_found = true;
1749                     break;
1750                 }
1751             }
1752             break;
1753
1754         case IF_EN2B:
1755             for (index = 0; index < 2; index++)
1756             {
1757                 if (fmt == formatEncode2B[index])
1758                 {
1759                     encoding_found = true;
1760                     break;
1761                 }
1762             }
1763             break;
1764
1765         case IF_EN2C:
1766             for (index = 0; index < 2; index++)
1767             {
1768                 if (fmt == formatEncode2C[index])
1769                 {
1770                     encoding_found = true;
1771                     break;
1772                 }
1773             }
1774             break;
1775
1776         case IF_EN2D:
1777             for (index = 0; index < 2; index++)
1778             {
1779                 if (fmt == formatEncode2D[index])
1780                 {
1781                     encoding_found = true;
1782                     break;
1783                 }
1784             }
1785             break;
1786
1787         case IF_EN2E:
1788             for (index = 0; index < 2; index++)
1789             {
1790                 if (fmt == formatEncode2E[index])
1791                 {
1792                     encoding_found = true;
1793                     break;
1794                 }
1795             }
1796             break;
1797
1798         case IF_EN2F:
1799             for (index = 0; index < 2; index++)
1800             {
1801                 if (fmt == formatEncode2F[index])
1802                 {
1803                     encoding_found = true;
1804                     break;
1805                 }
1806             }
1807             break;
1808
1809         case IF_EN2G:
1810             for (index = 0; index < 2; index++)
1811             {
1812                 if (fmt == formatEncode2G[index])
1813                 {
1814                     encoding_found = true;
1815                     break;
1816                 }
1817             }
1818             break;
1819
1820         case IF_EN2H:
1821             for (index = 0; index < 2; index++)
1822             {
1823                 if (fmt == formatEncode2H[index])
1824                 {
1825                     encoding_found = true;
1826                     break;
1827                 }
1828             }
1829             break;
1830
1831         case IF_EN2I:
1832             for (index = 0; index < 2; index++)
1833             {
1834                 if (fmt == formatEncode2I[index])
1835                 {
1836                     encoding_found = true;
1837                     break;
1838                 }
1839             }
1840             break;
1841
1842         case IF_EN2J:
1843             for (index = 0; index < 2; index++)
1844             {
1845                 if (fmt == formatEncode2J[index])
1846                 {
1847                     encoding_found = true;
1848                     break;
1849                 }
1850             }
1851             break;
1852
1853         case IF_EN2K:
1854             for (index = 0; index < 2; index++)
1855             {
1856                 if (fmt == formatEncode2K[index])
1857                 {
1858                     encoding_found = true;
1859                     break;
1860                 }
1861             }
1862             break;
1863
1864         case IF_EN2L:
1865             for (index = 0; index < 2; index++)
1866             {
1867                 if (fmt == formatEncode2L[index])
1868                 {
1869                     encoding_found = true;
1870                     break;
1871                 }
1872             }
1873             break;
1874
1875         case IF_EN2M:
1876             for (index = 0; index < 2; index++)
1877             {
1878                 if (fmt == formatEncode2M[index])
1879                 {
1880                     encoding_found = true;
1881                     break;
1882                 }
1883             }
1884             break;
1885
1886         case IF_EN2N:
1887             for (index = 0; index < 2; index++)
1888             {
1889                 if (fmt == formatEncode2N[index])
1890                 {
1891                     encoding_found = true;
1892                     break;
1893                 }
1894             }
1895             break;
1896
1897         case IF_EN2O:
1898             for (index = 0; index < 2; index++)
1899             {
1900                 if (fmt == formatEncode2O[index])
1901                 {
1902                     encoding_found = true;
1903                     break;
1904                 }
1905             }
1906             break;
1907
1908         case IF_EN2P:
1909             for (index = 0; index < 2; index++)
1910             {
1911                 if (fmt == formatEncode2P[index])
1912                 {
1913                     encoding_found = true;
1914                     break;
1915                 }
1916             }
1917             break;
1918
1919         case IF_BI_0A:
1920         case IF_BI_0B:
1921         case IF_BI_0C:
1922         case IF_BI_1A:
1923         case IF_BI_1B:
1924         case IF_BR_1A:
1925         case IF_BR_1B:
1926         case IF_LS_1A:
1927         case IF_LS_2A:
1928         case IF_LS_2B:
1929         case IF_LS_2C:
1930         case IF_LS_3A:
1931         case IF_LS_3B:
1932         case IF_LS_3C:
1933         case IF_LS_3D:
1934         case IF_DI_1A:
1935         case IF_DI_1B:
1936         case IF_DI_1C:
1937         case IF_DI_1D:
1938         case IF_DI_1E:
1939         case IF_DI_1F:
1940         case IF_DI_2A:
1941         case IF_DI_2B:
1942         case IF_DI_2C:
1943         case IF_DI_2D:
1944         case IF_DR_1D:
1945         case IF_DR_2A:
1946         case IF_DR_2B:
1947         case IF_DR_2C:
1948         case IF_DR_2D:
1949         case IF_DR_2E:
1950         case IF_DR_2F:
1951         case IF_DR_2G:
1952         case IF_DR_2H:
1953         case IF_DR_2I:
1954         case IF_DR_3A:
1955         case IF_DR_3B:
1956         case IF_DR_3C:
1957         case IF_DR_3D:
1958         case IF_DR_3E:
1959         case IF_DR_4A:
1960         case IF_DV_1A:
1961         case IF_DV_1B:
1962         case IF_DV_1C:
1963         case IF_DV_2A:
1964         case IF_DV_2B:
1965         case IF_DV_2C:
1966         case IF_DV_2D:
1967         case IF_DV_2E:
1968         case IF_DV_2F:
1969         case IF_DV_2G:
1970         case IF_DV_2H:
1971         case IF_DV_2I:
1972         case IF_DV_2J:
1973         case IF_DV_2K:
1974         case IF_DV_2L:
1975         case IF_DV_2M:
1976         case IF_DV_2N:
1977         case IF_DV_2O:
1978         case IF_DV_3A:
1979         case IF_DV_3AI:
1980         case IF_DV_3B:
1981         case IF_DV_3BI:
1982         case IF_DV_3C:
1983         case IF_DV_3D:
1984         case IF_DV_3DI:
1985         case IF_DV_3E:
1986         case IF_DV_4A:
1987         case IF_SN_0A:
1988         case IF_SI_0A:
1989         case IF_SI_0B:
1990
1991             index          = 0;
1992             encoding_found = true;
1993             break;
1994
1995         default:
1996
1997             encoding_found = false;
1998             break;
1999     }
2000
2001     assert(encoding_found);
2002
2003     switch (index)
2004     {
2005         case 0:
2006             assert(ins < ArrLen(insCodes1));
2007             code = insCodes1[ins];
2008             break;
2009         case 1:
2010             assert(ins < ArrLen(insCodes2));
2011             code = insCodes2[ins];
2012             break;
2013         case 2:
2014             assert(ins < ArrLen(insCodes3));
2015             code = insCodes3[ins];
2016             break;
2017         case 3:
2018             assert(ins < ArrLen(insCodes4));
2019             code = insCodes4[ins];
2020             break;
2021         case 4:
2022             assert(ins < ArrLen(insCodes5));
2023             code = insCodes5[ins];
2024             break;
2025         case 5:
2026             assert(ins < ArrLen(insCodes6));
2027             code = insCodes6[ins];
2028             break;
2029         case 6:
2030             assert(ins < ArrLen(insCodes7));
2031             code = insCodes7[ins];
2032             break;
2033         case 7:
2034             assert(ins < ArrLen(insCodes8));
2035             code = insCodes8[ins];
2036             break;
2037         case 8:
2038             assert(ins < ArrLen(insCodes9));
2039             code = insCodes9[ins];
2040             break;
2041     }
2042
2043     assert((code != BAD_CODE));
2044
2045     return code;
2046 }
2047
2048 // true if this 'imm' can be encoded as a input operand to a mov instruction
2049 /*static*/ bool emitter::emitIns_valid_imm_for_mov(INT64 imm, emitAttr size)
2050 {
2051     // Check for "MOV (wide immediate)".
2052     if (canEncodeHalfwordImm(imm, size))
2053         return true;
2054
2055     // Next try the ones-complement form of 'halfword immediate' imm(i16,hw),
2056     // namely "MOV (inverted wide immediate)".
2057     ssize_t notOfImm = NOT_helper(imm, getBitWidth(size));
2058     if (canEncodeHalfwordImm(notOfImm, size))
2059         return true;
2060
2061     // Finally try "MOV (bitmask immediate)" imm(N,r,s)
2062     if (canEncodeBitMaskImm(imm, size))
2063         return true;
2064
2065     return false;
2066 }
2067
2068 // true if this 'imm' can be encoded as a input operand to a vector movi instruction
2069 /*static*/ bool emitter::emitIns_valid_imm_for_movi(INT64 imm, emitAttr elemsize)
2070 {
2071     if (elemsize == EA_8BYTE)
2072     {
2073         UINT64 uimm = imm;
2074         while (uimm != 0)
2075         {
2076             INT64 loByte = uimm & 0xFF;
2077             if ((loByte == 0) || (loByte == 0xFF))
2078             {
2079                 uimm >>= 8;
2080             }
2081             else
2082             {
2083                 return false;
2084             }
2085         }
2086         assert(uimm == 0);
2087         return true;
2088     }
2089     else
2090     {
2091         // First try the standard 'byteShifted immediate' imm(i8,bySh)
2092         if (canEncodeByteShiftedImm(imm, elemsize, true))
2093             return true;
2094
2095         // Next try the ones-complement form of the 'immediate' imm(i8,bySh)
2096         ssize_t notOfImm = NOT_helper(imm, getBitWidth(elemsize));
2097         if (canEncodeByteShiftedImm(notOfImm, elemsize, true))
2098             return true;
2099     }
2100     return false;
2101 }
2102
2103 // true if this 'imm' can be encoded as a input operand to a fmov instruction
2104 /*static*/ bool emitter::emitIns_valid_imm_for_fmov(double immDbl)
2105 {
2106     if (canEncodeFloatImm8(immDbl))
2107         return true;
2108
2109     return false;
2110 }
2111
2112 // true if this 'imm' can be encoded as a input operand to an add instruction
2113 /*static*/ bool emitter::emitIns_valid_imm_for_add(INT64 imm, emitAttr size)
2114 {
2115     if (unsigned_abs(imm) <= 0x0fff)
2116         return true;
2117     else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
2118         return true;
2119
2120     return false;
2121 }
2122
2123 // true if this 'imm' can be encoded as a input operand to an non-add/sub alu instruction
2124 /*static*/ bool emitter::emitIns_valid_imm_for_cmp(INT64 imm, emitAttr size)
2125 {
2126     return emitIns_valid_imm_for_add(imm, size);
2127 }
2128
2129 // true if this 'imm' can be encoded as a input operand to an non-add/sub alu instruction
2130 /*static*/ bool emitter::emitIns_valid_imm_for_alu(INT64 imm, emitAttr size)
2131 {
2132     if (canEncodeBitMaskImm(imm, size))
2133         return true;
2134
2135     return false;
2136 }
2137
2138 // true if this 'imm' can be encoded as the offset in a ldr/str instruction
2139 /*static*/ bool emitter::emitIns_valid_imm_for_ldst_offset(INT64 imm, emitAttr attr)
2140 {
2141     if (imm == 0)
2142         return true; // Encodable using IF_LS_2A
2143
2144     if ((imm >= -256) && (imm <= 255))
2145         return true; // Encodable using IF_LS_2C (or possibly IF_LS_2B)
2146
2147     if (imm < 0)
2148         return false; // not encodable
2149
2150     emitAttr size  = EA_SIZE(attr);
2151     unsigned scale = NaturalScale_helper(size);
2152     ssize_t  mask  = size - 1; // the mask of low bits that must be zero to encode the immediate
2153
2154     if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
2155         return true; // Encodable using IF_LS_2B
2156
2157     return false; // not encodable
2158 }
2159
2160 /************************************************************************
2161  *
2162  *   A helper method to return the natural scale for an EA 'size'
2163  */
2164
2165 /*static*/ unsigned emitter::NaturalScale_helper(emitAttr size)
2166 {
2167     assert(size == EA_1BYTE || size == EA_2BYTE || size == EA_4BYTE || size == EA_8BYTE || size == EA_16BYTE);
2168
2169     unsigned result = 0;
2170     unsigned utemp  = (unsigned)size;
2171
2172     // Compute log base 2 of utemp (aka 'size')
2173     while (utemp > 1)
2174     {
2175         result++;
2176         utemp >>= 1;
2177     }
2178
2179     return result;
2180 }
2181
2182 /************************************************************************
2183  *
2184  *  A helper method to perform a Rotate-Right shift operation
2185  *  the source is 'value' and it is rotated right by 'sh' bits
2186  *  'value' is considered to be a fixed size 'width' set of bits.
2187  *
2188  *  Example
2189  *      value is '00001111', sh is 2 and width is 8
2190  *     result is '11000011'
2191  */
2192
2193 /*static*/ UINT64 emitter::ROR_helper(UINT64 value, unsigned sh, unsigned width)
2194 {
2195     assert(width <= 64);
2196     // Check that 'value' fits in 'width' bits
2197     assert((width == 64) || (value < (1ULL << width)));
2198     // We don't support shifts >= width
2199     assert(sh < width);
2200
2201     UINT64 result;
2202
2203     unsigned rsh = sh;
2204     unsigned lsh = width - rsh;
2205
2206     result = (value >> rsh);
2207     result |= (value << lsh);
2208
2209     if (width < 64)
2210     {
2211         // mask off any extra bits that we got from the left shift
2212         result &= ((1ULL << width) - 1);
2213     }
2214     return result;
2215 }
2216 /************************************************************************
2217  *
2218  *  A helper method to perform a 'NOT' bitwise complement operation.
2219  *  'value' is considered to be a fixed size 'width' set of bits.
2220  *
2221  *  Example
2222  *      value is '01001011', and width is 8
2223  *     result is '10110100'
2224  */
2225
2226 /*static*/ UINT64 emitter::NOT_helper(UINT64 value, unsigned width)
2227 {
2228     assert(width <= 64);
2229
2230     UINT64 result = ~value;
2231
2232     if (width < 64)
2233     {
2234         // Check that 'value' fits in 'width' bits. Don't consider "sign" bits above width.
2235         UINT64 maxVal       = 1ULL << width;
2236         UINT64 lowBitsMask  = maxVal - 1;
2237         UINT64 signBitsMask = ~lowBitsMask | (1ULL << (width - 1)); // The high bits must be set, and the top bit
2238                                                                     // (sign bit) must be set.
2239         assert((value < maxVal) || ((value & signBitsMask) == signBitsMask));
2240
2241         // mask off any extra bits that we got from the complement operation
2242         result &= lowBitsMask;
2243     }
2244
2245     return result;
2246 }
2247
2248 /************************************************************************
2249  *
2250  *  A helper method to perform a bit Replicate operation
2251  *  the source is 'value' with a fixed size 'width' set of bits.
2252  *  value is replicated to fill out 32 or 64 bits as determined by 'size'.
2253  *
2254  *  Example
2255  *      value is '11000011' (0xE3), width is 8 and size is EA_8BYTE
2256  *     result is '11000011 11000011 11000011 11000011 11000011 11000011 11000011 11000011'
2257  *               0xE3E3E3E3E3E3E3E3
2258  */
2259
2260 /*static*/ UINT64 emitter::Replicate_helper(UINT64 value, unsigned width, emitAttr size)
2261 {
2262     assert(emitter::isValidGeneralDatasize(size));
2263
2264     unsigned immWidth = (size == EA_8BYTE) ? 64 : 32;
2265     assert(width <= immWidth);
2266
2267     UINT64   result     = value;
2268     unsigned filledBits = width;
2269
2270     while (filledBits < immWidth)
2271     {
2272         value <<= width;
2273         result |= value;
2274         filledBits += width;
2275     }
2276     return result;
2277 }
2278
2279 /************************************************************************
2280  *
2281  *  Convert an imm(N,r,s) into a 64-bit immediate
2282  *  inputs 'bmImm' a bitMaskImm struct
2283  *         'size' specifies the size of the result (64 or 32 bits)
2284  */
2285
2286 /*static*/ INT64 emitter::emitDecodeBitMaskImm(const emitter::bitMaskImm bmImm, emitAttr size)
2287 {
2288     assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2289
2290     unsigned N = bmImm.immN; // read the N,R and S values from the 'bitMaskImm' encoding
2291     unsigned R = bmImm.immR;
2292     unsigned S = bmImm.immS;
2293
2294     unsigned elemWidth = 64; // used when immN == 1
2295
2296     if (bmImm.immN == 0) // find the smaller elemWidth when immN == 0
2297     {
2298         // Scan S for the highest bit not set
2299         elemWidth = 32;
2300         for (unsigned bitNum = 5; bitNum > 0; bitNum--)
2301         {
2302             unsigned oneBit = elemWidth;
2303             if ((S & oneBit) == 0)
2304                 break;
2305             elemWidth /= 2;
2306         }
2307     }
2308     else
2309     {
2310         assert(size == EA_8BYTE);
2311     }
2312
2313     unsigned maskSR = elemWidth - 1;
2314
2315     S &= maskSR;
2316     R &= maskSR;
2317
2318     // encoding for S is one less than the number of consecutive one bits
2319     S++; // Number of consecutive ones to generate in 'welem'
2320
2321     // At this point:
2322     //
2323     //    'elemWidth' is the number of bits that we will use for the ROR and Replicate operations
2324     //    'S'         is the number of consecutive 1 bits for the immediate
2325     //    'R'         is the number of bits that we will Rotate Right the immediate
2326     //    'size'      selects the final size of the immedate that we return (64 or 32 bits)
2327
2328     assert(S < elemWidth); // 'elemWidth' consecutive one's is a reserved encoding
2329
2330     UINT64 welem;
2331     UINT64 wmask;
2332
2333     welem = (1ULL << S) - 1;
2334
2335     wmask = ROR_helper(welem, R, elemWidth);
2336     wmask = Replicate_helper(wmask, elemWidth, size);
2337
2338     return wmask;
2339 }
2340
2341 /*****************************************************************************
2342  *
2343  *  Check if an immediate can use the left shifted by 12 bits encoding
2344  */
2345
2346 /*static*/ bool emitter::canEncodeWithShiftImmBy12(INT64 imm)
2347 {
2348     if (imm < 0)
2349     {
2350         imm = -imm; // convert to unsigned
2351     }
2352
2353     if (imm < 0)
2354     {
2355         return false; // Must be MIN_INT64
2356     }
2357
2358     if ((imm & 0xfff) != 0) // Now the low 12 bits all have to be zero
2359     {
2360         return false;
2361     }
2362
2363     imm >>= 12; // shift right by 12 bits
2364
2365     return (imm <= 0x0fff); // Does it fit in 12 bits
2366 }
2367
2368 /*****************************************************************************
2369  *
2370  *  Normalize the 'imm' so that the upper bits, as defined by 'size' are zero
2371  */
2372
2373 /*static*/ INT64 emitter::normalizeImm64(INT64 imm, emitAttr size)
2374 {
2375     unsigned immWidth = getBitWidth(size);
2376     INT64    result   = imm;
2377
2378     if (immWidth < 64)
2379     {
2380         // Check that 'imm' fits in 'immWidth' bits. Don't consider "sign" bits above width.
2381         INT64 maxVal      = 1LL << immWidth;
2382         INT64 lowBitsMask = maxVal - 1;
2383         INT64 hiBitsMask  = ~lowBitsMask;
2384         INT64 signBitsMask =
2385             hiBitsMask | (1LL << (immWidth - 1)); // The high bits must be set, and the top bit (sign bit) must be set.
2386         assert((imm < maxVal) || ((imm & signBitsMask) == signBitsMask));
2387
2388         // mask off the hiBits
2389         result &= lowBitsMask;
2390     }
2391     return result;
2392 }
2393
2394 /*****************************************************************************
2395  *
2396  *  Normalize the 'imm' so that the upper bits, as defined by 'size' are zero
2397  */
2398
2399 /*static*/ INT32 emitter::normalizeImm32(INT32 imm, emitAttr size)
2400 {
2401     unsigned immWidth = getBitWidth(size);
2402     INT32    result   = imm;
2403
2404     if (immWidth < 32)
2405     {
2406         // Check that 'imm' fits in 'immWidth' bits. Don't consider "sign" bits above width.
2407         INT32 maxVal       = 1 << immWidth;
2408         INT32 lowBitsMask  = maxVal - 1;
2409         INT32 hiBitsMask   = ~lowBitsMask;
2410         INT32 signBitsMask = hiBitsMask | (1 << (immWidth - 1)); // The high bits must be set, and the top bit
2411                                                                  // (sign bit) must be set.
2412         assert((imm < maxVal) || ((imm & signBitsMask) == signBitsMask));
2413
2414         // mask off the hiBits
2415         result &= lowBitsMask;
2416     }
2417     return result;
2418 }
2419
2420 /************************************************************************
2421  *
2422  *  returns true if 'imm' of 'size bits (32/64) can be encoded
2423  *  using the ARM64 'bitmask immediate' form.
2424  *  When a non-null value is passed for 'wbBMI' then this method
2425  *  writes back the 'N','S' and 'R' values use to encode this immediate
2426  *
2427  */
2428
2429 /*static*/ bool emitter::canEncodeBitMaskImm(INT64 imm, emitAttr size, emitter::bitMaskImm* wbBMI)
2430 {
2431     assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2432
2433     unsigned immWidth = (size == EA_8BYTE) ? 64 : 32;
2434     unsigned maxLen   = (size == EA_8BYTE) ? 6 : 5;
2435
2436     imm = normalizeImm64(imm, size);
2437
2438     // Starting with len=1, elemWidth is 2 bits
2439     //               len=2, elemWidth is 4 bits
2440     //               len=3, elemWidth is 8 bits
2441     //               len=4, elemWidth is 16 bits
2442     //               len=5, elemWidth is 32 bits
2443     // (optionally)  len=6, elemWidth is 64 bits
2444     //
2445     for (unsigned len = 1; (len <= maxLen); len++)
2446     {
2447         unsigned elemWidth = 1 << len;
2448         UINT64   elemMask  = ((UINT64)-1) >> (64 - elemWidth);
2449         UINT64   tempImm   = (UINT64)imm;        // A working copy of 'imm' that we can mutate
2450         UINT64   elemVal   = tempImm & elemMask; // The low 'elemWidth' bits of 'imm'
2451
2452         // Check for all 1's or 0's as these can't be encoded
2453         if ((elemVal == 0) || (elemVal == elemMask))
2454             continue;
2455
2456         // 'checkedBits' is the count of bits that are known to match 'elemVal' when replicated
2457         unsigned checkedBits = elemWidth; // by definition the first 'elemWidth' bits match
2458
2459         // Now check to see if each of the next bits match...
2460         //
2461         while (checkedBits < immWidth)
2462         {
2463             tempImm >>= elemWidth;
2464
2465             UINT64 nextElem = tempImm & elemMask;
2466             if (nextElem != elemVal)
2467             {
2468                 // Not matching, exit this loop and checkedBits will not be equal to immWidth
2469                 break;
2470             }
2471
2472             // The 'nextElem' is matching, so increment 'checkedBits'
2473             checkedBits += elemWidth;
2474         }
2475
2476         // Did the full immediate contain bits that can be formed by repeating 'elemVal'?
2477         if (checkedBits == immWidth)
2478         {
2479             // We are not quite done, since the only values that we can encode as a
2480             // 'bitmask immediate' are those that can be formed by starting with a
2481             // bit string of 0*1* that is rotated by some number of bits.
2482             //
2483             // We check to see if 'elemVal' can be formed using these restrictions.
2484             //
2485             // Observation:
2486             // Rotating by one bit any value that passes these restrictions
2487             // can be xor-ed with the original value and will result it a string
2488             // of bits that have exactly two 1 bits: 'elemRorXor'
2489             // Further the distance between the two one bits tells us the value
2490             // of S and the location of the 1 bits tells us the value of R
2491             //
2492             // Some examples:   (immWidth is 8)
2493             //
2494             // S=4,R=0   S=5,R=3   S=3,R=6
2495             // elemVal:        00001111  11100011  00011100
2496             // elemRor:        10000111  11110001  00001110
2497             // elemRorXor:     10001000  00010010  00010010
2498             //      compute S  45678---  ---5678-  ---3210-
2499             //      compute R  01234567  ---34567  ------67
2500
2501             UINT64 elemRor    = ROR_helper(elemVal, 1, elemWidth); // Rotate 'elemVal' Right by one bit
2502             UINT64 elemRorXor = elemVal ^ elemRor;                 // Xor elemVal and elemRor
2503
2504             // If we only have a two-bit change in elemROR then we can form a mask for this value
2505             unsigned bitCount = 0;
2506             UINT64   oneBit   = 0x1;
2507             unsigned R        = elemWidth; // R is shift count for ROR (rotate right shift)
2508             unsigned S        = 0;         // S is number of consecutive one bits
2509             int      incr     = -1;
2510
2511             // Loop over the 'elemWidth' bits in 'elemRorXor'
2512             //
2513             for (unsigned bitNum = 0; bitNum < elemWidth; bitNum++)
2514             {
2515                 if (incr == -1)
2516                 {
2517                     R--; // We decrement R by one whenever incr is -1
2518                 }
2519                 if (bitCount == 1)
2520                 {
2521                     S += incr; // We incr/decr S, after we find the first one bit in 'elemRorXor'
2522                 }
2523
2524                 // Is this bit position a 1 bit in 'elemRorXor'?
2525                 //
2526                 if (oneBit & elemRorXor)
2527                 {
2528                     bitCount++;
2529                     // Is this the first 1 bit that we found in 'elemRorXor'?
2530                     if (bitCount == 1)
2531                     {
2532                         // Does this 1 bit represent a transition to zero bits?
2533                         bool toZeros = ((oneBit & elemVal) != 0);
2534                         if (toZeros)
2535                         {
2536                             // S :: Count down from elemWidth
2537                             S    = elemWidth;
2538                             incr = -1;
2539                         }
2540                         else // this 1 bit represent a transition to one bits.
2541                         {
2542                             // S :: Count up from zero
2543                             S    = 0;
2544                             incr = +1;
2545                         }
2546                     }
2547                     else // bitCount > 1
2548                     {
2549                         // We found the second (or third...) 1 bit in 'elemRorXor'
2550                         incr = 0; // stop decrementing 'R'
2551
2552                         if (bitCount > 2)
2553                         {
2554                             // More than 2 transitions from 0/1 in 'elemVal'
2555                             // This means that 'elemVal' can't be encoded
2556                             // using a 'bitmask immediate'.
2557                             //
2558                             // Furthermore, it will continue to fail
2559                             // with any larger 'len' that we try.
2560                             // so just return false.
2561                             //
2562                             return false;
2563                         }
2564                     }
2565                 }
2566
2567                 // shift oneBit left by one bit to test the next position
2568                 oneBit <<= 1;
2569             }
2570
2571             // We expect that bitCount will always be two at this point
2572             // but just in case return false for any bad cases.
2573             //
2574             assert(bitCount == 2);
2575             if (bitCount != 2)
2576                 return false;
2577
2578             // Perform some sanity checks on the values of 'S' and 'R'
2579             assert(S > 0);
2580             assert(S < elemWidth);
2581             assert(R < elemWidth);
2582
2583             // Does the caller want us to return the N,R,S encoding values?
2584             //
2585             if (wbBMI != nullptr)
2586             {
2587
2588                 // The encoding used for S is one less than the
2589                 //  number of consecutive one bits
2590                 S--;
2591
2592                 if (len == 6)
2593                 {
2594                     wbBMI->immN = 1;
2595                 }
2596                 else
2597                 {
2598                     wbBMI->immN = 0;
2599                     // The encoding used for 'S' here is a bit peculiar.
2600                     //
2601                     // The upper bits need to be complemented, followed by a zero bit
2602                     // then the value of 'S-1'
2603                     //
2604                     unsigned upperBitsOfS = 64 - (1 << (len + 1));
2605                     S |= upperBitsOfS;
2606                 }
2607                 wbBMI->immR = R;
2608                 wbBMI->immS = S;
2609
2610                 // Verify that what we are returning is correct.
2611                 assert(imm == emitDecodeBitMaskImm(*wbBMI, size));
2612             }
2613             // Tell the caller that we can successfully encode this immediate
2614             // using a 'bitmask immediate'.
2615             //
2616             return true;
2617         }
2618     }
2619     return false;
2620 }
2621
2622 /************************************************************************
2623  *
2624  *  Convert a 64-bit immediate into its 'bitmask immediate' representation imm(N,r,s)
2625  */
2626
2627 /*static*/ emitter::bitMaskImm emitter::emitEncodeBitMaskImm(INT64 imm, emitAttr size)
2628 {
2629     emitter::bitMaskImm result;
2630     result.immNRS = 0;
2631
2632     bool canEncode = canEncodeBitMaskImm(imm, size, &result);
2633     assert(canEncode);
2634
2635     return result;
2636 }
2637
2638 /************************************************************************
2639  *
2640  *  Convert an imm(i16,hw) into a 32/64-bit immediate
2641  *  inputs 'hwImm' a halfwordImm struct
2642  *         'size' specifies the size of the result (64 or 32 bits)
2643  */
2644
2645 /*static*/ INT64 emitter::emitDecodeHalfwordImm(const emitter::halfwordImm hwImm, emitAttr size)
2646 {
2647     assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2648
2649     unsigned hw  = hwImm.immHW;
2650     INT64    val = (INT64)hwImm.immVal;
2651
2652     assert((hw <= 1) || (size == EA_8BYTE));
2653
2654     INT64 result = val << (16 * hw);
2655     return result;
2656 }
2657
2658 /************************************************************************
2659  *
2660  *  returns true if 'imm' of 'size' bits (32/64) can be encoded
2661  *  using the ARM64 'halfword immediate' form.
2662  *  When a non-null value is passed for 'wbHWI' then this method
2663  *  writes back the 'immHW' and 'immVal' values use to encode this immediate
2664  *
2665  */
2666
2667 /*static*/ bool emitter::canEncodeHalfwordImm(INT64 imm, emitAttr size, emitter::halfwordImm* wbHWI)
2668 {
2669     assert(isValidGeneralDatasize(size)); // Only EA_4BYTE or EA_8BYTE forms
2670
2671     unsigned immWidth = (size == EA_8BYTE) ? 64 : 32;
2672     unsigned maxHW    = (size == EA_8BYTE) ? 4 : 2;
2673
2674     // setup immMask to a (EA_4BYTE) 0x00000000_FFFFFFFF or (EA_8BYTE) 0xFFFFFFFF_FFFFFFFF
2675     const UINT64 immMask = ((UINT64)-1) >> (64 - immWidth);
2676     const INT64  mask16  = (INT64)0xFFFF;
2677
2678     imm = normalizeImm64(imm, size);
2679
2680     // Try each of the valid hw shift sizes
2681     for (unsigned hw = 0; (hw < maxHW); hw++)
2682     {
2683         INT64 curMask   = mask16 << (hw * 16); // Represents the mask of the bits in the current halfword
2684         INT64 checkBits = immMask & ~curMask;
2685
2686         // Excluding the current halfword (using ~curMask)
2687         //  does the immediate have zero bits in every other bit that we care about?
2688         //  note we care about all 64-bits for EA_8BYTE
2689         //  and we care about the lowest 32 bits for EA_4BYTE
2690         //
2691         if ((imm & checkBits) == 0)
2692         {
2693             // Does the caller want us to return the imm(i16,hw) encoding values?
2694             //
2695             if (wbHWI != nullptr)
2696             {
2697                 INT64 val     = ((imm & curMask) >> (hw * 16)) & mask16;
2698                 wbHWI->immHW  = hw;
2699                 wbHWI->immVal = val;
2700
2701                 // Verify that what we are returning is correct.
2702                 assert(imm == emitDecodeHalfwordImm(*wbHWI, size));
2703             }
2704             // Tell the caller that we can successfully encode this immediate
2705             // using a 'halfword immediate'.
2706             //
2707             return true;
2708         }
2709     }
2710     return false;
2711 }
2712
2713 /************************************************************************
2714  *
2715  *  Convert a 64-bit immediate into its 'halfword immediate' representation imm(i16,hw)
2716  */
2717
2718 /*static*/ emitter::halfwordImm emitter::emitEncodeHalfwordImm(INT64 imm, emitAttr size)
2719 {
2720     emitter::halfwordImm result;
2721     result.immHWVal = 0;
2722
2723     bool canEncode = canEncodeHalfwordImm(imm, size, &result);
2724     assert(canEncode);
2725
2726     return result;
2727 }
2728
2729 /************************************************************************
2730  *
2731  *  Convert an imm(i8,sh) into a 16/32-bit immediate
2732  *  inputs 'bsImm' a byteShiftedImm struct
2733  *         'size' specifies the size of the result (16 or 32 bits)
2734  */
2735
2736 /*static*/ INT32 emitter::emitDecodeByteShiftedImm(const emitter::byteShiftedImm bsImm, emitAttr size)
2737 {
2738     bool     onesShift = (bsImm.immOnes == 1);
2739     unsigned bySh      = bsImm.immBY;         // Num Bytes to shift 0,1,2,3
2740     INT32    val       = (INT32)bsImm.immVal; // 8-bit immediate
2741     INT32    result    = val;
2742
2743     if (bySh > 0)
2744     {
2745         assert((size == EA_2BYTE) || (size == EA_4BYTE)); // Only EA_2BYTE or EA_4BYTE forms
2746         if (size == EA_2BYTE)
2747         {
2748             assert(bySh < 2);
2749         }
2750         else
2751         {
2752             assert(bySh < 4);
2753         }
2754
2755         result <<= (8 * bySh);
2756
2757         if (onesShift)
2758         {
2759             result |= ((1 << (8 * bySh)) - 1);
2760         }
2761     }
2762     return result;
2763 }
2764
2765 /************************************************************************
2766  *
2767  *  returns true if 'imm' of 'size' bits (16/32) can be encoded
2768  *  using the ARM64 'byteShifted immediate' form.
2769  *  When a non-null value is passed for 'wbBSI' then this method
2770  *  writes back the 'immBY' and 'immVal' values use to encode this immediate
2771  *
2772  */
2773
2774 /*static*/ bool emitter::canEncodeByteShiftedImm(INT64                    imm,
2775                                                  emitAttr                 size,
2776                                                  bool                     allow_MSL,
2777                                                  emitter::byteShiftedImm* wbBSI)
2778 {
2779     bool     canEncode = false;
2780     bool     onesShift = false; // true if we use the shifting ones variant
2781     unsigned bySh      = 0;     // number of bytes to shift: 0, 1, 2, 3
2782     unsigned imm8      = 0;     // immediate to use in the encoding
2783
2784     imm = normalizeImm64(imm, size);
2785
2786     if (size == EA_1BYTE)
2787     {
2788         imm8 = (unsigned)imm;
2789         assert(imm8 < 0x100);
2790         canEncode = true;
2791     }
2792     else if (size == EA_8BYTE)
2793     {
2794         imm8 = (unsigned)imm;
2795         assert(imm8 < 0x100);
2796         canEncode = true;
2797     }
2798     else
2799     {
2800         assert((size == EA_2BYTE) || (size == EA_4BYTE)); // Only EA_2BYTE or EA_4BYTE forms
2801
2802         unsigned immWidth = (size == EA_4BYTE) ? 32 : 16;
2803         unsigned maxBY    = (size == EA_4BYTE) ? 4 : 2;
2804
2805         // setup immMask to a (EA_2BYTE) 0x0000FFFF or (EA_4BYTE) 0xFFFFFFFF
2806         const UINT32 immMask = ((UINT32)-1) >> (32 - immWidth);
2807         const INT32  mask8   = (INT32)0xFF;
2808
2809         // Try each of the valid by shift sizes
2810         for (bySh = 0; (bySh < maxBY); bySh++)
2811         {
2812             INT32 curMask   = mask8 << (bySh * 8); // Represents the mask of the bits in the current byteShifted
2813             INT32 checkBits = immMask & ~curMask;
2814             INT32 immCheck  = (imm & checkBits);
2815
2816             // Excluding the current byte (using ~curMask)
2817             //  does the immediate have zero bits in every other bit that we care about?
2818             //  or can be use the shifted one variant?
2819             //  note we care about all 32-bits for EA_4BYTE
2820             //  and we care about the lowest 16 bits for EA_2BYTE
2821             //
2822             if (immCheck == 0)
2823             {
2824                 canEncode = true;
2825             }
2826             if (allow_MSL)
2827             {
2828                 if ((bySh == 1) && (immCheck == 0xFF))
2829                 {
2830                     canEncode = true;
2831                     onesShift = true;
2832                 }
2833                 else if ((bySh == 2) && (immCheck == 0xFFFF))
2834                 {
2835                     canEncode = true;
2836                     onesShift = true;
2837                 }
2838             }
2839             if (canEncode)
2840             {
2841                 imm8 = (unsigned)(((imm & curMask) >> (bySh * 8)) & mask8);
2842                 break;
2843             }
2844         }
2845     }
2846
2847     if (canEncode)
2848     {
2849         // Does the caller want us to return the imm(i8,bySh) encoding values?
2850         //
2851         if (wbBSI != nullptr)
2852         {
2853             wbBSI->immOnes = onesShift;
2854             wbBSI->immBY   = bySh;
2855             wbBSI->immVal  = imm8;
2856
2857             // Verify that what we are returning is correct.
2858             assert(imm == emitDecodeByteShiftedImm(*wbBSI, size));
2859         }
2860         // Tell the caller that we can successfully encode this immediate
2861         // using a 'byteShifted immediate'.
2862         //
2863         return true;
2864     }
2865     return false;
2866 }
2867
2868 /************************************************************************
2869  *
2870  *  Convert a 32-bit immediate into its 'byteShifted immediate' representation imm(i8,by)
2871  */
2872
2873 /*static*/ emitter::byteShiftedImm emitter::emitEncodeByteShiftedImm(INT64 imm, emitAttr size, bool allow_MSL)
2874 {
2875     emitter::byteShiftedImm result;
2876     result.immBSVal = 0;
2877
2878     bool canEncode = canEncodeByteShiftedImm(imm, size, allow_MSL, &result);
2879     assert(canEncode);
2880
2881     return result;
2882 }
2883
2884 /************************************************************************
2885  *
2886  *  Convert a 'float 8-bit immediate' into a double.
2887  *  inputs 'fpImm' a floatImm8 struct
2888  */
2889
2890 /*static*/ double emitter::emitDecodeFloatImm8(const emitter::floatImm8 fpImm)
2891 {
2892     unsigned sign  = fpImm.immSign;
2893     unsigned exp   = fpImm.immExp ^ 0x4;
2894     unsigned mant  = fpImm.immMant + 16;
2895     unsigned scale = 16 * 8;
2896
2897     while (exp > 0)
2898     {
2899         scale /= 2;
2900         exp--;
2901     }
2902
2903     double result = ((double)mant) / ((double)scale);
2904     if (sign == 1)
2905     {
2906         result = -result;
2907     }
2908
2909     return result;
2910 }
2911
2912 /************************************************************************
2913  *
2914  *  returns true if the 'immDbl' can be encoded using the 'float 8-bit immediate' form.
2915  *  also returns the encoding if wbFPI is non-null
2916  *
2917  */
2918
2919 /*static*/ bool emitter::canEncodeFloatImm8(double immDbl, emitter::floatImm8* wbFPI)
2920 {
2921     bool   canEncode = false;
2922     double val       = immDbl;
2923
2924     int sign = 0;
2925     if (val < 0.0)
2926     {
2927         val  = -val;
2928         sign = 1;
2929     }
2930
2931     int exp = 0;
2932     while ((val < 1.0) && (exp >= -4))
2933     {
2934         val *= 2.0;
2935         exp--;
2936     }
2937     while ((val >= 2.0) && (exp <= 5))
2938     {
2939         val *= 0.5;
2940         exp++;
2941     }
2942     exp += 3;
2943     val *= 16.0;
2944     int ival = (int)val;
2945
2946     if ((exp >= 0) && (exp <= 7))
2947     {
2948         if (val == (double)ival)
2949         {
2950             canEncode = true;
2951
2952             if (wbFPI != nullptr)
2953             {
2954                 ival -= 16;
2955                 assert((ival >= 0) && (ival <= 15));
2956
2957                 wbFPI->immSign = sign;
2958                 wbFPI->immExp  = exp ^ 0x4;
2959                 wbFPI->immMant = ival;
2960                 unsigned imm8  = wbFPI->immFPIVal;
2961                 assert((imm8 >= 0) && (imm8 <= 0xff));
2962             }
2963         }
2964     }
2965
2966     return canEncode;
2967 }
2968
2969 /************************************************************************
2970  *
2971  *  Convert a double into its 'float 8-bit immediate' representation
2972  */
2973
2974 /*static*/ emitter::floatImm8 emitter::emitEncodeFloatImm8(double immDbl)
2975 {
2976     emitter::floatImm8 result;
2977     result.immFPIVal = 0;
2978
2979     bool canEncode = canEncodeFloatImm8(immDbl, &result);
2980     assert(canEncode);
2981
2982     return result;
2983 }
2984
2985 /*****************************************************************************
2986  *
2987  *  For the given 'ins' returns the reverse instruction
2988  *  if one exists, otherwise returns INS_INVALID
2989  */
2990
2991 /*static*/ instruction emitter::insReverse(instruction ins)
2992 {
2993     switch (ins)
2994     {
2995         case INS_add:
2996             return INS_sub;
2997         case INS_adds:
2998             return INS_subs;
2999
3000         case INS_sub:
3001             return INS_add;
3002         case INS_subs:
3003             return INS_adds;
3004
3005         case INS_cmp:
3006             return INS_cmn;
3007         case INS_cmn:
3008             return INS_cmp;
3009
3010         case INS_ccmp:
3011             return INS_ccmn;
3012         case INS_ccmn:
3013             return INS_ccmp;
3014
3015         default:
3016             return INS_invalid;
3017     }
3018 }
3019
3020 /*****************************************************************************
3021  *
3022  *  For the given 'datasize' and 'elemsize', make the proper arrangement option
3023  *  returns the insOpts that specifies the vector register arrangement
3024  *  if one does not exist returns INS_OPTS_NONE
3025  */
3026
3027 /*static*/ insOpts emitter::optMakeArrangement(emitAttr datasize, emitAttr elemsize)
3028 {
3029     insOpts result = INS_OPTS_NONE;
3030
3031     if (datasize == EA_8BYTE)
3032     {
3033         switch (elemsize)
3034         {
3035             case EA_1BYTE:
3036                 result = INS_OPTS_8B;
3037                 break;
3038             case EA_2BYTE:
3039                 result = INS_OPTS_4H;
3040                 break;
3041             case EA_4BYTE:
3042                 result = INS_OPTS_2S;
3043                 break;
3044             case EA_8BYTE:
3045                 result = INS_OPTS_1D;
3046                 break;
3047             default:
3048                 unreached();
3049                 break;
3050         }
3051     }
3052     else if (datasize == EA_16BYTE)
3053     {
3054         switch (elemsize)
3055         {
3056             case EA_1BYTE:
3057                 result = INS_OPTS_16B;
3058                 break;
3059             case EA_2BYTE:
3060                 result = INS_OPTS_8H;
3061                 break;
3062             case EA_4BYTE:
3063                 result = INS_OPTS_4S;
3064                 break;
3065             case EA_8BYTE:
3066                 result = INS_OPTS_2D;
3067                 break;
3068             default:
3069                 unreached();
3070                 break;
3071         }
3072     }
3073     return result;
3074 }
3075
3076 /*****************************************************************************
3077  *
3078  *  For the given 'datasize' and arrangement 'opts'
3079  *  returns true is the pair spcifies a valid arrangement
3080  */
3081 /*static*/ bool emitter::isValidArrangement(emitAttr datasize, insOpts opt)
3082 {
3083     if (datasize == EA_8BYTE)
3084     {
3085         if ((opt == INS_OPTS_8B) || (opt == INS_OPTS_4H) || (opt == INS_OPTS_2S) || (opt == INS_OPTS_1D))
3086         {
3087             return true;
3088         }
3089     }
3090     else if (datasize == EA_16BYTE)
3091     {
3092         if ((opt == INS_OPTS_16B) || (opt == INS_OPTS_8H) || (opt == INS_OPTS_4S) || (opt == INS_OPTS_2D))
3093         {
3094             return true;
3095         }
3096     }
3097     return false;
3098 }
3099
3100 //  For the given 'arrangement' returns the 'datasize' specified by the vector register arrangement
3101 //  asserts and returns EA_UNKNOWN if an invalid 'arrangement' value is passed
3102 //
3103 /*static*/ emitAttr emitter::optGetDatasize(insOpts arrangement)
3104 {
3105     if ((arrangement == INS_OPTS_8B) || (arrangement == INS_OPTS_4H) || (arrangement == INS_OPTS_2S) ||
3106         (arrangement == INS_OPTS_1D))
3107     {
3108         return EA_8BYTE;
3109     }
3110     else if ((arrangement == INS_OPTS_16B) || (arrangement == INS_OPTS_8H) || (arrangement == INS_OPTS_4S) ||
3111              (arrangement == INS_OPTS_2D))
3112     {
3113         return EA_16BYTE;
3114     }
3115     else
3116     {
3117         assert(!" invalid 'arrangement' value");
3118         return EA_UNKNOWN;
3119     }
3120 }
3121
3122 //  For the given 'arrangement' returns the 'elemsize' specified by the vector register arrangement
3123 //  asserts and returns EA_UNKNOWN if an invalid 'arrangement' value is passed
3124 //
3125 /*static*/ emitAttr emitter::optGetElemsize(insOpts arrangement)
3126 {
3127     if ((arrangement == INS_OPTS_8B) || (arrangement == INS_OPTS_16B))
3128     {
3129         return EA_1BYTE;
3130     }
3131     else if ((arrangement == INS_OPTS_4H) || (arrangement == INS_OPTS_8H))
3132     {
3133         return EA_2BYTE;
3134     }
3135     else if ((arrangement == INS_OPTS_2S) || (arrangement == INS_OPTS_4S))
3136     {
3137         return EA_4BYTE;
3138     }
3139     else if ((arrangement == INS_OPTS_1D) || (arrangement == INS_OPTS_2D))
3140     {
3141         return EA_8BYTE;
3142     }
3143     else
3144     {
3145         assert(!" invalid 'arrangement' value");
3146         return EA_UNKNOWN;
3147     }
3148 }
3149
3150 //  For the given 'arrangement' returns the 'widen-arrangement' specified by the vector register arrangement
3151 //  asserts and returns INS_OPTS_NONE if an invalid 'arrangement' value is passed
3152 //
3153 /*static*/ insOpts emitter::optWidenElemsize(insOpts arrangement)
3154 {
3155     if ((arrangement == INS_OPTS_8B) || (arrangement == INS_OPTS_16B))
3156     {
3157         return INS_OPTS_8H;
3158     }
3159     else if ((arrangement == INS_OPTS_4H) || (arrangement == INS_OPTS_8H))
3160     {
3161         return INS_OPTS_4S;
3162     }
3163     else if ((arrangement == INS_OPTS_2S) || (arrangement == INS_OPTS_4S))
3164     {
3165         return INS_OPTS_2D;
3166     }
3167     else
3168     {
3169         assert(!" invalid 'arrangement' value");
3170         return INS_OPTS_NONE;
3171     }
3172 }
3173
3174 //  For the given 'conversion' returns the 'dstsize' specified by the conversion option
3175 /*static*/ emitAttr emitter::optGetDstsize(insOpts conversion)
3176 {
3177     switch (conversion)
3178     {
3179         case INS_OPTS_S_TO_8BYTE:
3180         case INS_OPTS_D_TO_8BYTE:
3181         case INS_OPTS_4BYTE_TO_D:
3182         case INS_OPTS_8BYTE_TO_D:
3183         case INS_OPTS_S_TO_D:
3184         case INS_OPTS_H_TO_D:
3185
3186             return EA_8BYTE;
3187
3188         case INS_OPTS_S_TO_4BYTE:
3189         case INS_OPTS_D_TO_4BYTE:
3190         case INS_OPTS_4BYTE_TO_S:
3191         case INS_OPTS_8BYTE_TO_S:
3192         case INS_OPTS_D_TO_S:
3193         case INS_OPTS_H_TO_S:
3194
3195             return EA_4BYTE;
3196
3197         case INS_OPTS_S_TO_H:
3198         case INS_OPTS_D_TO_H:
3199
3200             return EA_2BYTE;
3201
3202         default:
3203             assert(!" invalid 'conversion' value");
3204             return EA_UNKNOWN;
3205     }
3206 }
3207
3208 //  For the given 'conversion' returns the 'srcsize' specified by the conversion option
3209 /*static*/ emitAttr emitter::optGetSrcsize(insOpts conversion)
3210 {
3211     switch (conversion)
3212     {
3213         case INS_OPTS_D_TO_8BYTE:
3214         case INS_OPTS_D_TO_4BYTE:
3215         case INS_OPTS_8BYTE_TO_D:
3216         case INS_OPTS_8BYTE_TO_S:
3217         case INS_OPTS_D_TO_S:
3218         case INS_OPTS_D_TO_H:
3219
3220             return EA_8BYTE;
3221
3222         case INS_OPTS_S_TO_8BYTE:
3223         case INS_OPTS_S_TO_4BYTE:
3224         case INS_OPTS_4BYTE_TO_S:
3225         case INS_OPTS_4BYTE_TO_D:
3226         case INS_OPTS_S_TO_D:
3227         case INS_OPTS_S_TO_H:
3228
3229             return EA_4BYTE;
3230
3231         case INS_OPTS_H_TO_S:
3232         case INS_OPTS_H_TO_D:
3233
3234             return EA_2BYTE;
3235
3236         default:
3237             assert(!" invalid 'conversion' value");
3238             return EA_UNKNOWN;
3239     }
3240 }
3241
3242 //    For the given 'size' and 'index' returns true if it specifies a valid index for a vector register of 'size'
3243 /*static*/ bool emitter::isValidVectorIndex(emitAttr datasize, emitAttr elemsize, ssize_t index)
3244 {
3245     assert(isValidVectorDatasize(datasize));
3246     assert(isValidVectorElemsize(elemsize));
3247
3248     bool result = false;
3249     if (index >= 0)
3250     {
3251         if (datasize == EA_8BYTE)
3252         {
3253             switch (elemsize)
3254             {
3255                 case EA_1BYTE:
3256                     result = (index < 8);
3257                     break;
3258                 case EA_2BYTE:
3259                     result = (index < 4);
3260                     break;
3261                 case EA_4BYTE:
3262                     result = (index < 2);
3263                     break;
3264                 case EA_8BYTE:
3265                     result = (index < 1);
3266                     break;
3267                 default:
3268                     unreached();
3269                     break;
3270             }
3271         }
3272         else if (datasize == EA_16BYTE)
3273         {
3274             switch (elemsize)
3275             {
3276                 case EA_1BYTE:
3277                     result = (index < 16);
3278                     break;
3279                 case EA_2BYTE:
3280                     result = (index < 8);
3281                     break;
3282                 case EA_4BYTE:
3283                     result = (index < 4);
3284                     break;
3285                 case EA_8BYTE:
3286                     result = (index < 2);
3287                     break;
3288                 default:
3289                     unreached();
3290                     break;
3291             }
3292         }
3293     }
3294     return result;
3295 }
3296
3297 /*****************************************************************************
3298  *
3299  *  Add an instruction with no operands.
3300  */
3301
3302 void emitter::emitIns(instruction ins)
3303 {
3304     instrDesc* id  = emitNewInstrSmall(EA_8BYTE);
3305     insFormat  fmt = emitInsFormat(ins);
3306
3307     assert(fmt == IF_SN_0A);
3308
3309     id->idIns(ins);
3310     id->idInsFmt(fmt);
3311
3312     dispIns(id);
3313     appendToCurIG(id);
3314 }
3315
3316 /*****************************************************************************
3317  *
3318  *  Add an instruction with a single immediate value.
3319  */
3320
3321 void emitter::emitIns_I(instruction ins, emitAttr attr, ssize_t imm)
3322 {
3323     insFormat fmt = IF_NONE;
3324
3325     /* Figure out the encoding format of the instruction */
3326     switch (ins)
3327     {
3328         case INS_brk:
3329             if ((imm & 0x0000ffff) == imm)
3330             {
3331                 fmt = IF_SI_0A;
3332             }
3333             else
3334             {
3335                 assert(!"Instruction cannot be encoded: IF_SI_0A");
3336             }
3337             break;
3338         default:
3339             unreached();
3340             break;
3341     }
3342     assert(fmt != IF_NONE);
3343
3344     instrDesc* id = emitNewInstrSC(attr, imm);
3345
3346     id->idIns(ins);
3347     id->idInsFmt(fmt);
3348
3349     dispIns(id);
3350     appendToCurIG(id);
3351 }
3352
3353 /*****************************************************************************
3354  *
3355  *  Add an instruction referencing a single register.
3356  */
3357
3358 void emitter::emitIns_R(instruction ins, emitAttr attr, regNumber reg)
3359 {
3360     emitAttr   size = EA_SIZE(attr);
3361     insFormat  fmt  = IF_NONE;
3362     instrDesc* id   = nullptr;
3363
3364     /* Figure out the encoding format of the instruction */
3365     switch (ins)
3366     {
3367         case INS_br:
3368         case INS_ret:
3369             assert(isGeneralRegister(reg));
3370             id = emitNewInstrSmall(attr);
3371             id->idReg1(reg);
3372             fmt = IF_BR_1A;
3373             break;
3374
3375         default:
3376             unreached();
3377     }
3378
3379     assert(fmt != IF_NONE);
3380
3381     id->idIns(ins);
3382     id->idInsFmt(fmt);
3383
3384     dispIns(id);
3385     appendToCurIG(id);
3386 }
3387
3388 /*****************************************************************************
3389  *
3390  *  Add an instruction referencing a register and a constant.
3391  */
3392
3393 void emitter::emitIns_R_I(instruction ins, emitAttr attr, regNumber reg, ssize_t imm, insOpts opt /* = INS_OPTS_NONE */)
3394 {
3395     emitAttr  size      = EA_SIZE(attr);
3396     emitAttr  elemsize  = EA_UNKNOWN;
3397     insFormat fmt       = IF_NONE;
3398     bool      canEncode = false;
3399
3400     /* Figure out the encoding format of the instruction */
3401     switch (ins)
3402     {
3403         bitMaskImm     bmi;
3404         halfwordImm    hwi;
3405         byteShiftedImm bsi;
3406         ssize_t        notOfImm;
3407
3408         case INS_tst:
3409             assert(insOptsNone(opt));
3410             assert(isGeneralRegister(reg));
3411             bmi.immNRS = 0;
3412             canEncode  = canEncodeBitMaskImm(imm, size, &bmi);
3413             if (canEncode)
3414             {
3415                 imm = bmi.immNRS;
3416                 assert(isValidImmNRS(imm, size));
3417                 fmt = IF_DI_1C;
3418             }
3419             break;
3420
3421         case INS_movk:
3422         case INS_movn:
3423         case INS_movz:
3424             assert(isValidGeneralDatasize(size));
3425             assert(insOptsNone(opt)); // No LSL here (you must use emitIns_R_I_I if a shift is needed)
3426             assert(isGeneralRegister(reg));
3427             assert(isValidUimm16(imm));
3428
3429             hwi.immHW  = 0;
3430             hwi.immVal = imm;
3431             assert(imm == emitDecodeHalfwordImm(hwi, size));
3432
3433             imm       = hwi.immHWVal;
3434             canEncode = true;
3435             fmt       = IF_DI_1B;
3436             break;
3437
3438         case INS_mov:
3439             assert(isValidGeneralDatasize(size));
3440             assert(insOptsNone(opt)); // No explicit LSL here
3441             // We will automatically determine the shift based upon the imm
3442
3443             // First try the standard 'halfword immediate' imm(i16,hw)
3444             hwi.immHWVal = 0;
3445             canEncode    = canEncodeHalfwordImm(imm, size, &hwi);
3446             if (canEncode)
3447             {
3448                 // uses a movz encoding
3449                 assert(isGeneralRegister(reg));
3450                 imm = hwi.immHWVal;
3451                 assert(isValidImmHWVal(imm, size));
3452                 fmt = IF_DI_1B;
3453                 break;
3454             }
3455
3456             // Next try the ones-complement form of 'halfword immediate' imm(i16,hw)
3457             notOfImm  = NOT_helper(imm, getBitWidth(size));
3458             canEncode = canEncodeHalfwordImm(notOfImm, size, &hwi);
3459             if (canEncode)
3460             {
3461                 assert(isGeneralRegister(reg));
3462                 imm = hwi.immHWVal;
3463                 ins = INS_movn; // uses a movn encoding
3464                 assert(isValidImmHWVal(imm, size));
3465                 fmt = IF_DI_1B;
3466                 break;
3467             }
3468
3469             // Finally try the 'bitmask immediate' imm(N,r,s)
3470             bmi.immNRS = 0;
3471             canEncode  = canEncodeBitMaskImm(imm, size, &bmi);
3472             if (canEncode)
3473             {
3474                 assert(isGeneralRegisterOrSP(reg));
3475                 reg = encodingSPtoZR(reg);
3476                 imm = bmi.immNRS;
3477                 assert(isValidImmNRS(imm, size));
3478                 fmt = IF_DI_1D;
3479                 break;
3480             }
3481             else
3482             {
3483                 assert(!"Instruction cannot be encoded: mov imm");
3484             }
3485
3486             break;
3487
3488         case INS_movi:
3489             assert(isValidVectorDatasize(size));
3490             assert(isVectorRegister(reg));
3491             if (insOptsNone(opt) && (size == EA_8BYTE))
3492             {
3493                 opt = INS_OPTS_1D;
3494             }
3495             assert(isValidArrangement(size, opt));
3496             elemsize = optGetElemsize(opt);
3497
3498             if (elemsize == EA_8BYTE)
3499             {
3500                 size_t   uimm = imm;
3501                 ssize_t  imm8 = 0;
3502                 unsigned pos  = 0;
3503                 canEncode     = true;
3504                 bool failed   = false;
3505                 while (uimm != 0)
3506                 {
3507                     INT64 loByte = uimm & 0xFF;
3508                     if (((loByte == 0) || (loByte == 0xFF)) && (pos < 8))
3509                     {
3510                         if (loByte == 0xFF)
3511                         {
3512                             imm8 |= (1 << pos);
3513                         }
3514                         uimm >>= 8;
3515                         pos++;
3516                     }
3517                     else
3518                     {
3519                         canEncode = false;
3520                         break;
3521                     }
3522                 }
3523                 imm = imm8;
3524                 assert(isValidUimm8(imm));
3525                 fmt = IF_DV_1B;
3526                 break;
3527             }
3528             else
3529             {
3530                 // Vector operation
3531
3532                 // No explicit LSL/MSL is used for the immediate
3533                 // We will automatically determine the shift based upon the value of imm
3534
3535                 // First try the standard 'byteShifted immediate' imm(i8,bySh)
3536                 bsi.immBSVal = 0;
3537                 canEncode    = canEncodeByteShiftedImm(imm, elemsize, true, &bsi);
3538                 if (canEncode)
3539                 {
3540                     imm = bsi.immBSVal;
3541                     assert(isValidImmBSVal(imm, size));
3542                     fmt = IF_DV_1B;
3543                     break;
3544                 }
3545
3546                 // Next try the ones-complement form of the 'immediate' imm(i8,bySh)
3547                 if ((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE)) // Only EA_2BYTE or EA_4BYTE forms
3548                 {
3549                     notOfImm  = NOT_helper(imm, getBitWidth(elemsize));
3550                     canEncode = canEncodeByteShiftedImm(notOfImm, elemsize, true, &bsi);
3551                     if (canEncode)
3552                     {
3553                         imm = bsi.immBSVal;
3554                         ins = INS_mvni; // uses a mvni encoding
3555                         assert(isValidImmBSVal(imm, size));
3556                         fmt = IF_DV_1B;
3557                         break;
3558                     }
3559                 }
3560             }
3561             break;
3562
3563         case INS_orr:
3564         case INS_bic:
3565         case INS_mvni:
3566             assert(isValidVectorDatasize(size));
3567             assert(isVectorRegister(reg));
3568             assert(isValidArrangement(size, opt));
3569             elemsize = optGetElemsize(opt);
3570             assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE)); // Only EA_2BYTE or EA_4BYTE forms
3571
3572             // Vector operation
3573
3574             // No explicit LSL/MSL is used for the immediate
3575             // We will automatically determine the shift based upon the value of imm
3576
3577             // First try the standard 'byteShifted immediate' imm(i8,bySh)
3578             bsi.immBSVal = 0;
3579             canEncode    = canEncodeByteShiftedImm(imm, elemsize,
3580                                                 (ins == INS_mvni), // mvni supports the ones shifting variant (aka MSL)
3581                                                 &bsi);
3582             if (canEncode)
3583             {
3584                 imm = bsi.immBSVal;
3585                 assert(isValidImmBSVal(imm, size));
3586                 fmt = IF_DV_1B;
3587                 break;
3588             }
3589             break;
3590
3591         case INS_cmp:
3592         case INS_cmn:
3593             assert(insOptsNone(opt));
3594             assert(isGeneralRegister(reg));
3595
3596             if (unsigned_abs(imm) <= 0x0fff)
3597             {
3598                 if (imm < 0)
3599                 {
3600                     ins = insReverse(ins);
3601                     imm = -imm;
3602                 }
3603                 assert(isValidUimm12(imm));
3604                 canEncode = true;
3605                 fmt       = IF_DI_1A;
3606             }
3607             else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
3608             {
3609                 // Encoding will use a 12-bit left shift of the immediate
3610                 opt = INS_OPTS_LSL12;
3611                 if (imm < 0)
3612                 {
3613                     ins = insReverse(ins);
3614                     imm = -imm;
3615                 }
3616                 assert((imm & 0xfff) == 0);
3617                 imm >>= 12;
3618                 assert(isValidUimm12(imm));
3619                 canEncode = true;
3620                 fmt       = IF_DI_1A;
3621             }
3622             else
3623             {
3624                 assert(!"Instruction cannot be encoded: IF_DI_1A");
3625             }
3626             break;
3627
3628         default:
3629             unreached();
3630             break;
3631
3632     } // end switch (ins)
3633
3634     assert(canEncode);
3635     assert(fmt != IF_NONE);
3636
3637     instrDesc* id = emitNewInstrSC(attr, imm);
3638
3639     id->idIns(ins);
3640     id->idInsFmt(fmt);
3641     id->idInsOpt(opt);
3642
3643     id->idReg1(reg);
3644
3645     dispIns(id);
3646     appendToCurIG(id);
3647 }
3648
3649 /*****************************************************************************
3650  *
3651  *  Add an instruction referencing a register and a floating point constant.
3652  */
3653
3654 void emitter::emitIns_R_F(
3655     instruction ins, emitAttr attr, regNumber reg, double immDbl, insOpts opt /* = INS_OPTS_NONE */)
3656
3657 {
3658     emitAttr  size      = EA_SIZE(attr);
3659     emitAttr  elemsize  = EA_UNKNOWN;
3660     insFormat fmt       = IF_NONE;
3661     ssize_t   imm       = 0;
3662     bool      canEncode = false;
3663
3664     /* Figure out the encoding format of the instruction */
3665     switch (ins)
3666     {
3667         floatImm8 fpi;
3668
3669         case INS_fcmp:
3670         case INS_fcmpe:
3671             assert(insOptsNone(opt));
3672             assert(isValidVectorElemsizeFloat(size));
3673             assert(isVectorRegister(reg));
3674             if (immDbl == 0.0)
3675             {
3676                 canEncode = true;
3677                 fmt       = IF_DV_1C;
3678             }
3679             break;
3680
3681         case INS_fmov:
3682             assert(isVectorRegister(reg));
3683             fpi.immFPIVal = 0;
3684             canEncode     = canEncodeFloatImm8(immDbl, &fpi);
3685
3686             if (insOptsAnyArrangement(opt))
3687             {
3688                 // Vector operation
3689                 assert(isValidVectorDatasize(size));
3690                 assert(isValidArrangement(size, opt));
3691                 elemsize = optGetElemsize(opt);
3692                 assert(isValidVectorElemsizeFloat(elemsize));
3693                 assert(opt != INS_OPTS_1D); // Reserved encoding
3694
3695                 if (canEncode)
3696                 {
3697                     imm = fpi.immFPIVal;
3698                     assert((imm >= 0) && (imm <= 0xff));
3699                     fmt = IF_DV_1B;
3700                 }
3701             }
3702             else
3703             {
3704                 // Scalar operation
3705                 assert(insOptsNone(opt));
3706                 assert(isValidVectorElemsizeFloat(size));
3707
3708                 if (canEncode)
3709                 {
3710                     imm = fpi.immFPIVal;
3711                     assert((imm >= 0) && (imm <= 0xff));
3712                     fmt = IF_DV_1A;
3713                 }
3714             }
3715             break;
3716
3717         default:
3718             unreached();
3719             break;
3720
3721     } // end switch (ins)
3722
3723     assert(canEncode);
3724     assert(fmt != IF_NONE);
3725
3726     instrDesc* id = emitNewInstrSC(attr, imm);
3727
3728     id->idIns(ins);
3729     id->idInsFmt(fmt);
3730     id->idInsOpt(opt);
3731
3732     id->idReg1(reg);
3733
3734     dispIns(id);
3735     appendToCurIG(id);
3736 }
3737
3738 /*****************************************************************************
3739  *
3740  *  Add an instruction referencing two registers
3741  */
3742
3743 void emitter::emitIns_R_R(
3744     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insOpts opt /* = INS_OPTS_NONE */)
3745 {
3746     emitAttr  size     = EA_SIZE(attr);
3747     emitAttr  elemsize = EA_UNKNOWN;
3748     insFormat fmt      = IF_NONE;
3749
3750     /* Figure out the encoding format of the instruction */
3751     switch (ins)
3752     {
3753         case INS_mov:
3754             assert(insOptsNone(opt));
3755             // Is the mov even necessary?
3756             if (reg1 == reg2)
3757             {
3758                 // A mov with a EA_4BYTE has the side-effect of clearing the upper bits
3759                 // So only eliminate mov instructions that are not clearing the upper bits
3760                 //
3761                 if (isGeneralRegisterOrSP(reg1) && (size == EA_8BYTE))
3762                 {
3763                     return;
3764                 }
3765                 else if (isVectorRegister(reg1) && (size == EA_16BYTE))
3766                 {
3767                     return;
3768                 }
3769             }
3770
3771             // Check for the 'mov' aliases for the vector registers
3772             if (isVectorRegister(reg1))
3773             {
3774                 if (isVectorRegister(reg2) && isValidVectorDatasize(size))
3775                 {
3776                     return emitIns_R_R_R(INS_mov, size, reg1, reg2, reg2);
3777                 }
3778                 else
3779                 {
3780                     return emitIns_R_R_I(INS_mov, size, reg1, reg2, 0);
3781                 }
3782             }
3783             else
3784             {
3785                 if (isVectorRegister(reg2))
3786                 {
3787                     assert(isGeneralRegister(reg1));
3788                     return emitIns_R_R_I(INS_mov, size, reg1, reg2, 0);
3789                 }
3790             }
3791
3792             // Is this a MOV to/from SP instruction?
3793             if ((reg1 == REG_SP) || (reg2 == REG_SP))
3794             {
3795                 assert(isGeneralRegisterOrSP(reg1));
3796                 assert(isGeneralRegisterOrSP(reg2));
3797                 reg1 = encodingSPtoZR(reg1);
3798                 reg2 = encodingSPtoZR(reg2);
3799                 fmt  = IF_DR_2G;
3800             }
3801             else
3802             {
3803                 assert(insOptsNone(opt));
3804                 assert(isGeneralRegister(reg1));
3805                 assert(isGeneralRegisterOrZR(reg2));
3806                 fmt = IF_DR_2E;
3807             }
3808             break;
3809
3810         case INS_dup:
3811             // Vector operation
3812             assert(insOptsAnyArrangement(opt));
3813             assert(isVectorRegister(reg1));
3814             assert(isGeneralRegisterOrZR(reg2));
3815             assert(isValidVectorDatasize(size));
3816             assert(isValidArrangement(size, opt));
3817             fmt = IF_DV_2C;
3818             break;
3819
3820         case INS_abs:
3821         case INS_not:
3822             assert(isVectorRegister(reg1));
3823             assert(isVectorRegister(reg2));
3824             // for 'NOT' we can construct the arrangement: 8B or 16B
3825             if ((ins == INS_not) && insOptsNone(opt))
3826             {
3827                 assert(isValidVectorDatasize(size));
3828                 elemsize = EA_1BYTE;
3829                 opt      = optMakeArrangement(size, elemsize);
3830             }
3831             if (insOptsNone(opt))
3832             {
3833                 // Scalar operation
3834                 assert(size == EA_8BYTE); // Only type D is supported
3835                 fmt = IF_DV_2L;
3836             }
3837             else
3838             {
3839                 // Vector operation
3840                 assert(insOptsAnyArrangement(opt));
3841                 assert(isValidVectorDatasize(size));
3842                 assert(isValidArrangement(size, opt));
3843                 elemsize = optGetElemsize(opt);
3844                 if (ins == INS_not)
3845                 {
3846                     assert(elemsize == EA_1BYTE);
3847                 }
3848                 fmt = IF_DV_2M;
3849             }
3850             break;
3851
3852         case INS_mvn:
3853         case INS_neg:
3854             if (isVectorRegister(reg1))
3855             {
3856                 assert(isVectorRegister(reg2));
3857                 // for 'mvn' we can construct the arrangement: 8B or 16b
3858                 if ((ins == INS_mvn) && insOptsNone(opt))
3859                 {
3860                     assert(isValidVectorDatasize(size));
3861                     elemsize = EA_1BYTE;
3862                     opt      = optMakeArrangement(size, elemsize);
3863                 }
3864                 if (insOptsNone(opt))
3865                 {
3866                     // Scalar operation
3867                     assert(size == EA_8BYTE); // Only type D is supported
3868                     fmt = IF_DV_2L;
3869                 }
3870                 else
3871                 {
3872                     // Vector operation
3873                     assert(isValidVectorDatasize(size));
3874                     assert(isValidArrangement(size, opt));
3875                     elemsize = optGetElemsize(opt);
3876                     if (ins == INS_mvn)
3877                     {
3878                         assert(elemsize == EA_1BYTE); // Only supports 8B or 16B
3879                     }
3880                     fmt = IF_DV_2M;
3881                 }
3882                 break;
3883             }
3884             __fallthrough;
3885
3886         case INS_negs:
3887             assert(insOptsNone(opt));
3888             assert(isGeneralRegister(reg1));
3889             assert(isGeneralRegisterOrZR(reg2));
3890             fmt = IF_DR_2E;
3891             break;
3892
3893         case INS_sxtw:
3894             assert(size == EA_8BYTE);
3895             __fallthrough;
3896
3897         case INS_sxtb:
3898         case INS_sxth:
3899         case INS_uxtb:
3900         case INS_uxth:
3901             assert(insOptsNone(opt));
3902             assert(isValidGeneralDatasize(size));
3903             assert(isGeneralRegister(reg1));
3904             assert(isGeneralRegister(reg2));
3905             fmt = IF_DR_2H;
3906             break;
3907
3908         case INS_sxtl:
3909         case INS_sxtl2:
3910         case INS_uxtl:
3911         case INS_uxtl2:
3912             return emitIns_R_R_I(ins, size, reg1, reg2, 0, opt);
3913
3914         case INS_cls:
3915         case INS_clz:
3916         case INS_rbit:
3917         case INS_rev16:
3918         case INS_rev32:
3919         case INS_cnt:
3920             if (isVectorRegister(reg1))
3921             {
3922                 assert(isVectorRegister(reg2));
3923                 assert(isValidVectorDatasize(size));
3924                 assert(isValidArrangement(size, opt));
3925                 elemsize = optGetElemsize(opt);
3926                 if ((ins == INS_cls) || (ins == INS_clz))
3927                 {
3928                     assert(elemsize != EA_8BYTE); // No encoding for type D
3929                 }
3930                 else if (ins == INS_rev32)
3931                 {
3932                     assert((elemsize == EA_2BYTE) || (elemsize == EA_1BYTE));
3933                 }
3934                 else
3935                 {
3936                     assert(elemsize == EA_1BYTE); // Only supports 8B or 16B
3937                 }
3938                 fmt = IF_DV_2M;
3939                 break;
3940             }
3941             if (ins == INS_cnt)
3942             {
3943                 // Doesn't have general register version(s)
3944                 break;
3945             }
3946
3947             __fallthrough;
3948
3949         case INS_rev:
3950             assert(insOptsNone(opt));
3951             assert(isGeneralRegister(reg1));
3952             assert(isGeneralRegister(reg2));
3953             if (ins == INS_rev32)
3954             {
3955                 assert(size == EA_8BYTE);
3956             }
3957             else
3958             {
3959                 assert(isValidGeneralDatasize(size));
3960             }
3961             fmt = IF_DR_2G;
3962             break;
3963
3964         case INS_addv:
3965         case INS_saddlv:
3966         case INS_smaxv:
3967         case INS_sminv:
3968         case INS_uaddlv:
3969         case INS_umaxv:
3970         case INS_uminv:
3971         case INS_rev64:
3972             assert(isVectorRegister(reg1));
3973             assert(isVectorRegister(reg2));
3974             assert(isValidVectorDatasize(size));
3975             assert(isValidArrangement(size, opt));
3976             elemsize = optGetElemsize(opt);
3977             assert(elemsize != EA_8BYTE); // No encoding for type D
3978             fmt = IF_DV_2M;
3979             break;
3980
3981         case INS_xtn:
3982         case INS_xtn2:
3983             assert(isVectorRegister(reg1));
3984             assert(isVectorRegister(reg2));
3985             assert(isValidVectorDatasize(size));
3986             assert(isValidArrangement(size, opt));
3987             elemsize = optGetElemsize(opt);
3988             // size is determined by instruction
3989             if (ins == INS_xtn)
3990             {
3991                 assert(size == EA_8BYTE);
3992             }
3993             else // ins == INS_xtn2
3994             {
3995                 assert(size == EA_16BYTE);
3996             }
3997             assert(elemsize != EA_8BYTE); // Narrowing must not end with 8 byte data
3998             fmt = IF_DV_2M;
3999             break;
4000
4001         case INS_ldar:
4002         case INS_ldaxr:
4003         case INS_ldxr:
4004         case INS_stlr:
4005             assert(isValidGeneralDatasize(size));
4006
4007             __fallthrough;
4008
4009         case INS_ldarb:
4010         case INS_ldaxrb:
4011         case INS_ldxrb:
4012         case INS_ldarh:
4013         case INS_ldaxrh:
4014         case INS_ldxrh:
4015         case INS_stlrb:
4016         case INS_stlrh:
4017             assert(isValidGeneralLSDatasize(size));
4018             assert(isGeneralRegisterOrZR(reg1));
4019             assert(isGeneralRegisterOrSP(reg2));
4020             assert(insOptsNone(opt));
4021
4022             reg2 = encodingSPtoZR(reg2);
4023
4024             fmt = IF_LS_2A;
4025             break;
4026
4027         case INS_ldr:
4028         case INS_ldrb:
4029         case INS_ldrh:
4030         case INS_ldrsb:
4031         case INS_ldrsh:
4032         case INS_ldrsw:
4033         case INS_str:
4034         case INS_strb:
4035         case INS_strh:
4036
4037         case INS_cmp:
4038         case INS_cmn:
4039         case INS_tst:
4040             assert(insOptsNone(opt));
4041             emitIns_R_R_I(ins, attr, reg1, reg2, 0, INS_OPTS_NONE);
4042             return;
4043
4044         case INS_fmov:
4045             assert(isValidVectorElemsizeFloat(size));
4046
4047             // Is the mov even necessary?
4048             if (reg1 == reg2)
4049             {
4050                 return;
4051             }
4052
4053             if (isVectorRegister(reg1))
4054             {
4055                 if (isVectorRegister(reg2))
4056                 {
4057                     assert(insOptsNone(opt));
4058                     fmt = IF_DV_2G;
4059                 }
4060                 else
4061                 {
4062                     assert(isGeneralRegister(reg2));
4063
4064                     // if the optional conversion specifier is not present we calculate it
4065                     if (opt == INS_OPTS_NONE)
4066                     {
4067                         opt = (size == EA_4BYTE) ? INS_OPTS_4BYTE_TO_S : INS_OPTS_8BYTE_TO_D;
4068                     }
4069                     assert(insOptsConvertIntToFloat(opt));
4070
4071                     fmt = IF_DV_2I;
4072                 }
4073             }
4074             else
4075             {
4076                 assert(isGeneralRegister(reg1));
4077                 assert(isVectorRegister(reg2));
4078
4079                 // if the optional conversion specifier is not present we calculate it
4080                 if (opt == INS_OPTS_NONE)
4081                 {
4082                     opt = (size == EA_4BYTE) ? INS_OPTS_S_TO_4BYTE : INS_OPTS_D_TO_8BYTE;
4083                 }
4084                 assert(insOptsConvertFloatToInt(opt));
4085
4086                 fmt = IF_DV_2H;
4087             }
4088             break;
4089
4090         case INS_fcmp:
4091         case INS_fcmpe:
4092             assert(insOptsNone(opt));
4093             assert(isValidVectorElemsizeFloat(size));
4094             assert(isVectorRegister(reg1));
4095             assert(isVectorRegister(reg2));
4096             fmt = IF_DV_2K;
4097             break;
4098
4099         case INS_fcvtns:
4100         case INS_fcvtnu:
4101         case INS_fcvtas:
4102         case INS_fcvtau:
4103         case INS_fcvtps:
4104         case INS_fcvtpu:
4105         case INS_fcvtms:
4106         case INS_fcvtmu:
4107         case INS_fcvtzs:
4108         case INS_fcvtzu:
4109             if (insOptsAnyArrangement(opt))
4110             {
4111                 // Vector operation
4112                 assert(isVectorRegister(reg1));
4113                 assert(isVectorRegister(reg2));
4114                 assert(isValidVectorDatasize(size));
4115                 assert(isValidArrangement(size, opt));
4116                 elemsize = optGetElemsize(opt);
4117                 assert(isValidVectorElemsizeFloat(elemsize));
4118                 assert(opt != INS_OPTS_1D); // Reserved encoding
4119                 fmt = IF_DV_2A;
4120             }
4121             else
4122             {
4123                 // Scalar operation
4124                 assert(isVectorRegister(reg2));
4125                 if (isVectorRegister(reg1))
4126                 {
4127                     assert(insOptsNone(opt));
4128                     assert(isValidVectorElemsizeFloat(size));
4129                     fmt = IF_DV_2G;
4130                 }
4131                 else
4132                 {
4133                     assert(isGeneralRegister(reg1));
4134                     assert(insOptsConvertFloatToInt(opt));
4135                     assert(isValidVectorElemsizeFloat(size));
4136                     fmt = IF_DV_2H;
4137                 }
4138             }
4139             break;
4140
4141         case INS_fcvtl:
4142         case INS_fcvtl2:
4143         case INS_fcvtn:
4144         case INS_fcvtn2:
4145             assert(isVectorRegister(reg1));
4146             assert(isVectorRegister(reg2));
4147             assert(isValidVectorDatasize(size));
4148             assert(insOptsNone(opt));
4149             assert(size == EA_8BYTE); // Narrowing from Double or Widening to Double (Half not supported)
4150             fmt = IF_DV_2G;
4151             break;
4152
4153         case INS_scvtf:
4154         case INS_ucvtf:
4155             if (insOptsAnyArrangement(opt))
4156             {
4157                 // Vector operation
4158                 assert(isVectorRegister(reg1));
4159                 assert(isVectorRegister(reg2));
4160                 assert(isValidVectorDatasize(size));
4161                 assert(isValidArrangement(size, opt));
4162                 elemsize = optGetElemsize(opt);
4163                 assert(isValidVectorElemsizeFloat(elemsize));
4164                 assert(opt != INS_OPTS_1D); // Reserved encoding
4165                 fmt = IF_DV_2A;
4166             }
4167             else
4168             {
4169                 // Scalar operation
4170                 assert(isVectorRegister(reg1));
4171                 if (isVectorRegister(reg2))
4172                 {
4173                     assert(insOptsNone(opt));
4174                     assert(isValidVectorElemsizeFloat(size));
4175                     fmt = IF_DV_2G;
4176                 }
4177                 else
4178                 {
4179                     assert(isGeneralRegister(reg2));
4180                     assert(insOptsConvertIntToFloat(opt));
4181                     assert(isValidVectorElemsizeFloat(size));
4182                     fmt = IF_DV_2I;
4183                 }
4184             }
4185             break;
4186
4187         case INS_fabs:
4188         case INS_fneg:
4189         case INS_fsqrt:
4190         case INS_frinta:
4191         case INS_frinti:
4192         case INS_frintm:
4193         case INS_frintn:
4194         case INS_frintp:
4195         case INS_frintx:
4196         case INS_frintz:
4197             if (insOptsAnyArrangement(opt))
4198             {
4199                 // Vector operation
4200                 assert(isVectorRegister(reg1));
4201                 assert(isVectorRegister(reg2));
4202                 assert(isValidVectorDatasize(size));
4203                 assert(isValidArrangement(size, opt));
4204                 elemsize = optGetElemsize(opt);
4205                 assert(isValidVectorElemsizeFloat(elemsize));
4206                 assert(opt != INS_OPTS_1D); // Reserved encoding
4207                 fmt = IF_DV_2A;
4208             }
4209             else
4210             {
4211                 // Scalar operation
4212                 assert(insOptsNone(opt));
4213                 assert(isValidVectorElemsizeFloat(size));
4214                 assert(isVectorRegister(reg1));
4215                 assert(isVectorRegister(reg2));
4216                 fmt = IF_DV_2G;
4217             }
4218             break;
4219
4220         case INS_faddp:
4221             // Scalar operation
4222             assert(insOptsNone(opt));
4223             assert(isValidVectorElemsizeFloat(size));
4224             assert(isVectorRegister(reg1));
4225             assert(isVectorRegister(reg2));
4226             fmt = IF_DV_2G;
4227             break;
4228
4229         case INS_fcvt:
4230             assert(insOptsConvertFloatToFloat(opt));
4231             assert(isValidVectorFcvtsize(size));
4232             assert(isVectorRegister(reg1));
4233             assert(isVectorRegister(reg2));
4234             fmt = IF_DV_2J;
4235             break;
4236
4237         default:
4238             unreached();
4239             break;
4240
4241     } // end switch (ins)
4242
4243     assert(fmt != IF_NONE);
4244
4245     instrDesc* id = emitNewInstrSmall(attr);
4246
4247     id->idIns(ins);
4248     id->idInsFmt(fmt);
4249     id->idInsOpt(opt);
4250
4251     id->idReg1(reg1);
4252     id->idReg2(reg2);
4253
4254     dispIns(id);
4255     appendToCurIG(id);
4256 }
4257
4258 /*****************************************************************************
4259  *
4260  *  Add an instruction referencing a register and two constants.
4261  */
4262
4263 void emitter::emitIns_R_I_I(
4264     instruction ins, emitAttr attr, regNumber reg, ssize_t imm1, ssize_t imm2, insOpts opt /* = INS_OPTS_NONE */)
4265 {
4266     emitAttr  size   = EA_SIZE(attr);
4267     insFormat fmt    = IF_NONE;
4268     size_t    immOut = 0; // composed from imm1 and imm2 and stored in the instrDesc
4269
4270     /* Figure out the encoding format of the instruction */
4271     switch (ins)
4272     {
4273         bool        canEncode;
4274         halfwordImm hwi;
4275
4276         case INS_mov:
4277             ins = INS_movz; // INS_mov with LSL is an alias for INS_movz LSL
4278             __fallthrough;
4279
4280         case INS_movk:
4281         case INS_movn:
4282         case INS_movz:
4283             assert(isValidGeneralDatasize(size));
4284             assert(isGeneralRegister(reg));
4285             assert(isValidUimm16(imm1));
4286             assert(insOptsLSL(opt)); // Must be INS_OPTS_LSL
4287
4288             if (size == EA_8BYTE)
4289             {
4290                 assert((imm2 == 0) || (imm2 == 16) || // shift amount: 0, 16, 32 or 48
4291                        (imm2 == 32) || (imm2 == 48));
4292             }
4293             else // EA_4BYTE
4294             {
4295                 assert((imm2 == 0) || (imm2 == 16)); // shift amount: 0 or 16
4296             }
4297
4298             hwi.immHWVal = 0;
4299
4300             switch (imm2)
4301             {
4302                 case 0:
4303                     hwi.immHW = 0;
4304                     canEncode = true;
4305                     break;
4306
4307                 case 16:
4308                     hwi.immHW = 1;
4309                     canEncode = true;
4310                     break;
4311
4312                 case 32:
4313                     hwi.immHW = 2;
4314                     canEncode = true;
4315                     break;
4316
4317                 case 48:
4318                     hwi.immHW = 3;
4319                     canEncode = true;
4320                     break;
4321
4322                 default:
4323                     canEncode = false;
4324             }
4325
4326             if (canEncode)
4327             {
4328                 hwi.immVal = imm1;
4329
4330                 immOut = hwi.immHWVal;
4331                 assert(isValidImmHWVal(immOut, size));
4332                 fmt = IF_DI_1B;
4333             }
4334             break;
4335
4336         default:
4337             unreached();
4338             break;
4339
4340     } // end switch (ins)
4341
4342     assert(fmt != IF_NONE);
4343
4344     instrDesc* id = emitNewInstrSC(attr, immOut);
4345
4346     id->idIns(ins);
4347     id->idInsFmt(fmt);
4348
4349     id->idReg1(reg);
4350
4351     dispIns(id);
4352     appendToCurIG(id);
4353 }
4354
4355 /*****************************************************************************
4356  *
4357  *  Add an instruction referencing two registers and a constant.
4358  */
4359
4360 void emitter::emitIns_R_R_I(
4361     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm, insOpts opt /* = INS_OPTS_NONE */)
4362 {
4363     emitAttr  size       = EA_SIZE(attr);
4364     emitAttr  elemsize   = EA_UNKNOWN;
4365     insFormat fmt        = IF_NONE;
4366     bool      isLdSt     = false;
4367     bool      isSIMD     = false;
4368     bool      isAddSub   = false;
4369     bool      setFlags   = false;
4370     unsigned  scale      = 0;
4371     bool      unscaledOp = false;
4372
4373     /* Figure out the encoding format of the instruction */
4374     switch (ins)
4375     {
4376         bool       canEncode;
4377         bitMaskImm bmi;
4378
4379         case INS_mov:
4380             // Check for the 'mov' aliases for the vector registers
4381             assert(insOptsNone(opt));
4382             assert(isValidVectorElemsize(size));
4383             elemsize = size;
4384             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4385
4386             if (isVectorRegister(reg1))
4387             {
4388                 if (isGeneralRegisterOrZR(reg2))
4389                 {
4390                     fmt = IF_DV_2C; // Alias for 'ins'
4391                     break;
4392                 }
4393                 else if (isVectorRegister(reg2))
4394                 {
4395                     fmt = IF_DV_2E; // Alias for 'dup'
4396                     break;
4397                 }
4398             }
4399             else // isGeneralRegister(reg1)
4400             {
4401                 assert(isGeneralRegister(reg1));
4402                 if (isVectorRegister(reg2))
4403                 {
4404                     fmt = IF_DV_2B; // Alias for 'umov'
4405                     break;
4406                 }
4407             }
4408             assert(!" invalid INS_mov operands");
4409             break;
4410
4411         case INS_lsl:
4412         case INS_lsr:
4413         case INS_asr:
4414             assert(insOptsNone(opt));
4415             assert(isValidGeneralDatasize(size));
4416             assert(isGeneralRegister(reg1));
4417             assert(isGeneralRegister(reg2));
4418             assert(isValidImmShift(imm, size));
4419             fmt = IF_DI_2D;
4420             break;
4421
4422         case INS_ror:
4423             assert(insOptsNone(opt));
4424             assert(isValidGeneralDatasize(size));
4425             assert(isGeneralRegister(reg1));
4426             assert(isGeneralRegister(reg2));
4427             assert(isValidImmShift(imm, size));
4428             fmt = IF_DI_2B;
4429             break;
4430
4431         case INS_sshr:
4432         case INS_ssra:
4433         case INS_srshr:
4434         case INS_srsra:
4435         case INS_shl:
4436         case INS_ushr:
4437         case INS_usra:
4438         case INS_urshr:
4439         case INS_ursra:
4440         case INS_sri:
4441         case INS_sli:
4442             assert(isVectorRegister(reg1));
4443             assert(isVectorRegister(reg2));
4444             if (insOptsAnyArrangement(opt))
4445             {
4446                 // Vector operation
4447                 assert(isValidVectorDatasize(size));
4448                 assert(isValidArrangement(size, opt));
4449                 elemsize = optGetElemsize(opt);
4450                 assert(isValidVectorElemsize(elemsize));
4451                 assert(isValidImmShift(imm, elemsize));
4452                 assert(opt != INS_OPTS_1D); // Reserved encoding
4453                 fmt = IF_DV_2O;
4454                 break;
4455             }
4456             else
4457             {
4458                 // Scalar operation
4459                 assert(insOptsNone(opt));
4460                 assert(size == EA_8BYTE); // only supported size
4461                 assert(isValidImmShift(imm, size));
4462                 fmt = IF_DV_2N;
4463             }
4464             break;
4465
4466         case INS_sxtl:
4467         case INS_uxtl:
4468             assert(imm == 0);
4469             __fallthrough;
4470
4471         case INS_shrn:
4472         case INS_rshrn:
4473         case INS_sshll:
4474         case INS_ushll:
4475             assert(isVectorRegister(reg1));
4476             assert(isVectorRegister(reg2));
4477             // Vector operation
4478             assert(size == EA_8BYTE);
4479             assert(isValidArrangement(size, opt));
4480             elemsize = optGetElemsize(opt);
4481             assert(elemsize != EA_8BYTE); // Reserved encodings
4482             assert(isValidVectorElemsize(elemsize));
4483             assert(isValidImmShift(imm, elemsize));
4484             fmt = IF_DV_2O;
4485             break;
4486
4487         case INS_sxtl2:
4488         case INS_uxtl2:
4489             assert(imm == 0);
4490             __fallthrough;
4491
4492         case INS_shrn2:
4493         case INS_rshrn2:
4494         case INS_sshll2:
4495         case INS_ushll2:
4496             assert(isVectorRegister(reg1));
4497             assert(isVectorRegister(reg2));
4498             // Vector operation
4499             assert(size == EA_16BYTE);
4500             assert(isValidArrangement(size, opt));
4501             elemsize = optGetElemsize(opt);
4502             assert(elemsize != EA_8BYTE); // Reserved encodings
4503             assert(isValidVectorElemsize(elemsize));
4504             assert(isValidImmShift(imm, elemsize));
4505             fmt = IF_DV_2O;
4506             break;
4507
4508         case INS_mvn:
4509         case INS_neg:
4510         case INS_negs:
4511             assert(isValidGeneralDatasize(size));
4512             assert(isGeneralRegister(reg1));
4513             assert(isGeneralRegisterOrZR(reg2));
4514
4515             if (imm == 0)
4516             {
4517                 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4518
4519                 fmt = IF_DR_2E;
4520             }
4521             else
4522             {
4523                 if (ins == INS_mvn)
4524                 {
4525                     assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
4526                 }
4527                 else // neg or negs
4528                 {
4529                     assert(insOptsAluShift(opt)); // a non-zero imm, must select shift kind, can't use ROR
4530                 }
4531                 assert(isValidImmShift(imm, size));
4532                 fmt = IF_DR_2F;
4533             }
4534             break;
4535
4536         case INS_tst:
4537             assert(isValidGeneralDatasize(size));
4538             assert(isGeneralRegisterOrZR(reg1));
4539             assert(isGeneralRegister(reg2));
4540
4541             if (insOptsAnyShift(opt))
4542             {
4543                 assert(isValidImmShift(imm, size) && (imm != 0));
4544                 fmt = IF_DR_2B;
4545             }
4546             else
4547             {
4548                 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4549                 assert(imm == 0);
4550                 fmt = IF_DR_2A;
4551             }
4552             break;
4553
4554         case INS_cmp:
4555         case INS_cmn:
4556             assert(isValidGeneralDatasize(size));
4557             assert(isGeneralRegisterOrSP(reg1));
4558             assert(isGeneralRegister(reg2));
4559
4560             reg1 = encodingSPtoZR(reg1);
4561             if (insOptsAnyExtend(opt))
4562             {
4563                 assert((imm >= 0) && (imm <= 4));
4564
4565                 fmt = IF_DR_2C;
4566             }
4567             else if (imm == 0)
4568             {
4569                 assert(insOptsNone(opt)); // a zero imm, means no alu shift kind
4570
4571                 fmt = IF_DR_2A;
4572             }
4573             else
4574             {
4575                 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
4576                 assert(isValidImmShift(imm, size));
4577                 fmt = IF_DR_2B;
4578             }
4579             break;
4580
4581         case INS_ands:
4582         case INS_and:
4583         case INS_eor:
4584         case INS_orr:
4585             assert(insOptsNone(opt));
4586             assert(isGeneralRegister(reg2));
4587             if (ins == INS_ands)
4588             {
4589                 assert(isGeneralRegister(reg1));
4590             }
4591             else
4592             {
4593                 assert(isGeneralRegisterOrSP(reg1));
4594                 reg1 = encodingSPtoZR(reg1);
4595             }
4596
4597             bmi.immNRS = 0;
4598             canEncode  = canEncodeBitMaskImm(imm, size, &bmi);
4599             if (canEncode)
4600             {
4601                 imm = bmi.immNRS;
4602                 assert(isValidImmNRS(imm, size));
4603                 fmt = IF_DI_2C;
4604             }
4605             break;
4606
4607         case INS_dup: // by element, imm selects the element of reg2
4608             assert(isVectorRegister(reg1));
4609             if (isVectorRegister(reg2))
4610             {
4611                 if (insOptsAnyArrangement(opt))
4612                 {
4613                     // Vector operation
4614                     assert(isValidVectorDatasize(size));
4615                     assert(isValidArrangement(size, opt));
4616                     elemsize = optGetElemsize(opt);
4617                     assert(isValidVectorElemsize(elemsize));
4618                     assert(isValidVectorIndex(size, elemsize, imm));
4619                     assert(opt != INS_OPTS_1D); // Reserved encoding
4620                     fmt = IF_DV_2D;
4621                     break;
4622                 }
4623                 else
4624                 {
4625                     // Scalar operation
4626                     assert(insOptsNone(opt));
4627                     elemsize = size;
4628                     assert(isValidVectorElemsize(elemsize));
4629                     assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4630                     fmt = IF_DV_2E;
4631                     break;
4632                 }
4633             }
4634             __fallthrough;
4635
4636         case INS_ins: // (MOV from general)
4637             assert(insOptsNone(opt));
4638             assert(isValidVectorElemsize(size));
4639             assert(isVectorRegister(reg1));
4640             assert(isGeneralRegisterOrZR(reg2));
4641             elemsize = size;
4642             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4643             fmt = IF_DV_2C;
4644             break;
4645
4646         case INS_umov: // (MOV to general)
4647             assert(insOptsNone(opt));
4648             assert(isValidVectorElemsize(size));
4649             assert(isGeneralRegister(reg1));
4650             assert(isVectorRegister(reg2));
4651             elemsize = size;
4652             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4653             fmt = IF_DV_2B;
4654             break;
4655
4656         case INS_smov:
4657             assert(insOptsNone(opt));
4658             assert(isValidVectorElemsize(size));
4659             assert(size != EA_8BYTE); // no encoding, use INS_umov
4660             assert(isGeneralRegister(reg1));
4661             assert(isVectorRegister(reg2));
4662             elemsize = size;
4663             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
4664             fmt = IF_DV_2B;
4665             break;
4666
4667         case INS_add:
4668         case INS_sub:
4669             setFlags = false;
4670             isAddSub = true;
4671             break;
4672
4673         case INS_adds:
4674         case INS_subs:
4675             setFlags = true;
4676             isAddSub = true;
4677             break;
4678
4679         case INS_ldrsb:
4680         case INS_ldursb:
4681             // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4682             assert(isValidGeneralDatasize(size));
4683             unscaledOp = (ins == INS_ldursb);
4684             scale      = 0;
4685             isLdSt     = true;
4686             break;
4687
4688         case INS_ldrsh:
4689         case INS_ldursh:
4690             // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4691             assert(isValidGeneralDatasize(size));
4692             unscaledOp = (ins == INS_ldursh);
4693             scale      = 1;
4694             isLdSt     = true;
4695             break;
4696
4697         case INS_ldrsw:
4698         case INS_ldursw:
4699             // 'size' specifies how we sign-extend into 4 or 8 bytes of the target register
4700             assert(size == EA_8BYTE);
4701             unscaledOp = (ins == INS_ldursw);
4702             scale      = 2;
4703             isLdSt     = true;
4704             break;
4705
4706         case INS_ldrb:
4707         case INS_strb:
4708             // size is ignored
4709             unscaledOp = false;
4710             scale      = 0;
4711             isLdSt     = true;
4712             break;
4713
4714         case INS_ldurb:
4715         case INS_sturb:
4716             // size is ignored
4717             unscaledOp = true;
4718             scale      = 0;
4719             isLdSt     = true;
4720             break;
4721
4722         case INS_ldrh:
4723         case INS_strh:
4724             // size is ignored
4725             unscaledOp = false;
4726             scale      = 1;
4727             isLdSt     = true;
4728             break;
4729
4730         case INS_ldurh:
4731         case INS_sturh:
4732             // size is ignored
4733             unscaledOp = true;
4734             scale      = 0;
4735             isLdSt     = true;
4736             break;
4737
4738         case INS_ldr:
4739         case INS_str:
4740             // Is the target a vector register?
4741             if (isVectorRegister(reg1))
4742             {
4743                 assert(isValidVectorLSDatasize(size));
4744                 assert(isGeneralRegisterOrSP(reg2));
4745                 isSIMD = true;
4746             }
4747             else
4748             {
4749                 assert(isValidGeneralDatasize(size));
4750             }
4751             unscaledOp = false;
4752             scale      = NaturalScale_helper(size);
4753             isLdSt     = true;
4754             break;
4755
4756         case INS_ldur:
4757         case INS_stur:
4758             // Is the target a vector register?
4759             if (isVectorRegister(reg1))
4760             {
4761                 assert(isValidVectorLSDatasize(size));
4762                 assert(isGeneralRegisterOrSP(reg2));
4763                 isSIMD = true;
4764             }
4765             else
4766             {
4767                 assert(isValidGeneralDatasize(size));
4768             }
4769             unscaledOp = true;
4770             scale      = 0;
4771             isLdSt     = true;
4772             break;
4773
4774         default:
4775             unreached();
4776             break;
4777
4778     } // end switch (ins)
4779
4780     if (isLdSt)
4781     {
4782         assert(!isAddSub);
4783
4784         if (isSIMD)
4785         {
4786             assert(isValidVectorLSDatasize(size));
4787             assert(isVectorRegister(reg1));
4788             assert((scale >= 0) && (scale <= 4));
4789         }
4790         else
4791         {
4792             assert(isValidGeneralLSDatasize(size));
4793             assert(isGeneralRegisterOrZR(reg1));
4794             assert((scale >= 0) && (scale <= 3));
4795         }
4796
4797         assert(isGeneralRegisterOrSP(reg2));
4798
4799         // Load/Store reserved encodings:
4800         if (insOptsIndexed(opt))
4801         {
4802             assert(reg1 != reg2);
4803         }
4804
4805         reg2 = encodingSPtoZR(reg2);
4806
4807         ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
4808         if (imm == 0)
4809         {
4810             assert(insOptsNone(opt)); // PRE/POST Index doesn't make sense with an immediate of zero
4811
4812             fmt = IF_LS_2A;
4813         }
4814         else if (insOptsIndexed(opt) || unscaledOp || (imm < 0) || ((imm & mask) != 0))
4815         {
4816             if ((imm >= -256) && (imm <= 255))
4817             {
4818                 fmt = IF_LS_2C;
4819             }
4820             else
4821             {
4822                 assert(!"Instruction cannot be encoded: IF_LS_2C");
4823             }
4824         }
4825         else if (imm > 0)
4826         {
4827             assert(insOptsNone(opt));
4828             assert(!unscaledOp);
4829
4830             if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
4831             {
4832                 imm >>= scale; // The immediate is scaled by the size of the ld/st
4833
4834                 fmt = IF_LS_2B;
4835             }
4836             else
4837             {
4838                 assert(!"Instruction cannot be encoded: IF_LS_2B");
4839             }
4840         }
4841     }
4842     else if (isAddSub)
4843     {
4844         assert(!isLdSt);
4845         assert(insOptsNone(opt));
4846
4847         if (setFlags) // Can't encode SP with setFlags
4848         {
4849             assert(isGeneralRegister(reg1));
4850             assert(isGeneralRegister(reg2));
4851         }
4852         else
4853         {
4854             assert(isGeneralRegisterOrSP(reg1));
4855             assert(isGeneralRegisterOrSP(reg2));
4856
4857             // Is it just a mov?
4858             if (imm == 0)
4859             {
4860                 // Is the mov even necessary?
4861                 if (reg1 != reg2)
4862                 {
4863                     emitIns_R_R(INS_mov, attr, reg1, reg2);
4864                 }
4865                 return;
4866             }
4867
4868             reg1 = encodingSPtoZR(reg1);
4869             reg2 = encodingSPtoZR(reg2);
4870         }
4871
4872         if (unsigned_abs(imm) <= 0x0fff)
4873         {
4874             if (imm < 0)
4875             {
4876                 ins = insReverse(ins);
4877                 imm = -imm;
4878             }
4879             assert(isValidUimm12(imm));
4880             fmt = IF_DI_2A;
4881         }
4882         else if (canEncodeWithShiftImmBy12(imm)) // Try the shifted by 12 encoding
4883         {
4884             // Encoding will use a 12-bit left shift of the immediate
4885             opt = INS_OPTS_LSL12;
4886             if (imm < 0)
4887             {
4888                 ins = insReverse(ins);
4889                 imm = -imm;
4890             }
4891             assert((imm & 0xfff) == 0);
4892             imm >>= 12;
4893             assert(isValidUimm12(imm));
4894             fmt = IF_DI_2A;
4895         }
4896         else
4897         {
4898             assert(!"Instruction cannot be encoded: IF_DI_2A");
4899         }
4900     }
4901
4902     assert(fmt != IF_NONE);
4903
4904     instrDesc* id = emitNewInstrSC(attr, imm);
4905
4906     id->idIns(ins);
4907     id->idInsFmt(fmt);
4908     id->idInsOpt(opt);
4909
4910     id->idReg1(reg1);
4911     id->idReg2(reg2);
4912
4913     dispIns(id);
4914     appendToCurIG(id);
4915 }
4916
4917 /*****************************************************************************
4918 *
4919 *  Add an instruction referencing two registers and a constant.
4920 *  Also checks for a large immediate that needs a second instruction
4921 *  and will load it in reg1
4922 *
4923 *  - Supports instructions: add, adds, sub, subs, and, ands, eor and orr
4924 *  - Requires that reg1 is a general register and not SP or ZR
4925 *  - Requires that reg1 != reg2
4926 */
4927 void emitter::emitIns_R_R_Imm(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, ssize_t imm)
4928 {
4929     assert(isGeneralRegister(reg1));
4930     assert(reg1 != reg2);
4931
4932     bool immFits = true;
4933
4934     switch (ins)
4935     {
4936         case INS_add:
4937         case INS_adds:
4938         case INS_sub:
4939         case INS_subs:
4940             immFits = emitter::emitIns_valid_imm_for_add(imm, attr);
4941             break;
4942
4943         case INS_ands:
4944         case INS_and:
4945         case INS_eor:
4946         case INS_orr:
4947             immFits = emitter::emitIns_valid_imm_for_alu(imm, attr);
4948             break;
4949
4950         default:
4951             assert(!"Unsupported instruction in emitIns_R_R_Imm");
4952     }
4953
4954     if (immFits)
4955     {
4956         emitIns_R_R_I(ins, attr, reg1, reg2, imm);
4957     }
4958     else
4959     {
4960         // Load 'imm' into the reg1 register
4961         // then issue:   'ins'  reg1, reg2, reg1
4962         //
4963         codeGen->instGen_Set_Reg_To_Imm(attr, reg1, imm);
4964         emitIns_R_R_R(ins, attr, reg1, reg2, reg1);
4965     }
4966 }
4967
4968 /*****************************************************************************
4969  *
4970  *  Add an instruction referencing three registers.
4971  */
4972
4973 void emitter::emitIns_R_R_R(
4974     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insOpts opt) /* = INS_OPTS_NONE */
4975 {
4976     emitAttr  size     = EA_SIZE(attr);
4977     emitAttr  elemsize = EA_UNKNOWN;
4978     insFormat fmt      = IF_NONE;
4979
4980     /* Figure out the encoding format of the instruction */
4981     switch (ins)
4982     {
4983         case INS_lsl:
4984         case INS_lsr:
4985         case INS_asr:
4986         case INS_ror:
4987         case INS_adc:
4988         case INS_adcs:
4989         case INS_sbc:
4990         case INS_sbcs:
4991         case INS_udiv:
4992         case INS_sdiv:
4993         case INS_mneg:
4994         case INS_smull:
4995         case INS_smnegl:
4996         case INS_smulh:
4997         case INS_umull:
4998         case INS_umnegl:
4999         case INS_umulh:
5000         case INS_lslv:
5001         case INS_lsrv:
5002         case INS_asrv:
5003         case INS_rorv:
5004             assert(insOptsNone(opt));
5005             assert(isValidGeneralDatasize(size));
5006             assert(isGeneralRegister(reg1));
5007             assert(isGeneralRegister(reg2));
5008             assert(isGeneralRegister(reg3));
5009             fmt = IF_DR_3A;
5010             break;
5011
5012         case INS_mul:
5013             if (insOptsNone(opt))
5014             {
5015                 // general register
5016                 assert(isValidGeneralDatasize(size));
5017                 assert(isGeneralRegister(reg1));
5018                 assert(isGeneralRegister(reg2));
5019                 assert(isGeneralRegister(reg3));
5020                 fmt = IF_DR_3A;
5021                 break;
5022             }
5023             __fallthrough;
5024
5025         case INS_mla:
5026         case INS_mls:
5027         case INS_pmul:
5028             assert(insOptsAnyArrangement(opt));
5029             assert(isVectorRegister(reg1));
5030             assert(isVectorRegister(reg2));
5031             assert(isVectorRegister(reg3));
5032             assert(isValidVectorDatasize(size));
5033             assert(isValidArrangement(size, opt));
5034             elemsize = optGetElemsize(opt);
5035             if (ins == INS_pmul)
5036             {
5037                 assert(elemsize == EA_1BYTE); // only supports 8B or 16B
5038             }
5039             else // INS_mul, INS_mla, INS_mls
5040             {
5041                 assert(elemsize != EA_8BYTE); // can't use 2D or 1D
5042             }
5043             fmt = IF_DV_3A;
5044             break;
5045
5046         case INS_add:
5047         case INS_sub:
5048             if (isVectorRegister(reg1))
5049             {
5050                 assert(isVectorRegister(reg2));
5051                 assert(isVectorRegister(reg3));
5052
5053                 if (insOptsAnyArrangement(opt))
5054                 {
5055                     // Vector operation
5056                     assert(opt != INS_OPTS_1D); // Reserved encoding
5057                     assert(isValidVectorDatasize(size));
5058                     assert(isValidArrangement(size, opt));
5059                     fmt = IF_DV_3A;
5060                 }
5061                 else
5062                 {
5063                     // Scalar operation
5064                     assert(insOptsNone(opt));
5065                     assert(size == EA_8BYTE);
5066                     fmt = IF_DV_3E;
5067                 }
5068                 break;
5069             }
5070             __fallthrough;
5071
5072         case INS_adds:
5073         case INS_subs:
5074             emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, INS_OPTS_NONE);
5075             return;
5076
5077         case INS_cmeq:
5078         case INS_cmge:
5079         case INS_cmgt:
5080         case INS_cmhi:
5081         case INS_cmhs:
5082         case INS_ctst:
5083             assert(isVectorRegister(reg1));
5084             assert(isVectorRegister(reg2));
5085             assert(isVectorRegister(reg3));
5086
5087             if (isValidVectorDatasize(size))
5088             {
5089                 // Vector operation
5090                 assert(insOptsAnyArrangement(opt));
5091                 assert(isValidArrangement(size, opt));
5092                 elemsize = optGetElemsize(opt);
5093                 fmt      = IF_DV_3A;
5094             }
5095             else
5096             {
5097                 NYI("Untested");
5098                 // Scalar operation
5099                 assert(size == EA_8BYTE); // Only Double supported
5100                 fmt = IF_DV_3E;
5101             }
5102             break;
5103
5104         case INS_fcmeq:
5105         case INS_fcmge:
5106         case INS_fcmgt:
5107             assert(isVectorRegister(reg1));
5108             assert(isVectorRegister(reg2));
5109             assert(isVectorRegister(reg3));
5110
5111             if (isValidVectorDatasize(size))
5112             {
5113                 // Vector operation
5114                 assert(insOptsAnyArrangement(opt));
5115                 assert(isValidArrangement(size, opt));
5116                 elemsize = optGetElemsize(opt);
5117                 assert((elemsize == EA_8BYTE) || (elemsize == EA_4BYTE)); // Only Double/Float supported
5118                 assert(opt != INS_OPTS_1D);                               // Reserved encoding
5119                 fmt = IF_DV_3B;
5120             }
5121             else
5122             {
5123                 NYI("Untested");
5124                 // Scalar operation
5125                 assert((size == EA_8BYTE) || (size == EA_4BYTE)); // Only Double/Float supported
5126                 fmt = IF_DV_3D;
5127             }
5128             break;
5129
5130         case INS_saba:
5131         case INS_sabd:
5132         case INS_smax:
5133         case INS_smin:
5134         case INS_uaba:
5135         case INS_uabd:
5136         case INS_umax:
5137         case INS_umin:
5138             assert(isVectorRegister(reg1));
5139             assert(isVectorRegister(reg2));
5140             assert(isVectorRegister(reg3));
5141             assert(insOptsAnyArrangement(opt));
5142
5143             // Vector operation
5144             assert(isValidVectorDatasize(size));
5145             assert(isValidArrangement(size, opt));
5146             elemsize = optGetElemsize(opt);
5147             assert(elemsize != EA_8BYTE); // can't use 2D or 1D
5148
5149             fmt = IF_DV_3A;
5150             break;
5151
5152         case INS_mov:
5153             assert(isVectorRegister(reg1));
5154             assert(isVectorRegister(reg2));
5155             assert(reg2 == reg3);
5156             assert(isValidVectorDatasize(size));
5157             // INS_mov is an alias for INS_orr (vector register)
5158             if (opt == INS_OPTS_NONE)
5159             {
5160                 elemsize = EA_1BYTE;
5161                 opt      = optMakeArrangement(size, elemsize);
5162             }
5163             assert(isValidArrangement(size, opt));
5164             fmt = IF_DV_3C;
5165             break;
5166
5167         case INS_and:
5168         case INS_bic:
5169         case INS_eor:
5170         case INS_orr:
5171         case INS_orn:
5172             if (isVectorRegister(reg1))
5173             {
5174                 assert(isValidVectorDatasize(size));
5175                 assert(isVectorRegister(reg2));
5176                 assert(isVectorRegister(reg3));
5177                 if (opt == INS_OPTS_NONE)
5178                 {
5179                     elemsize = EA_1BYTE;
5180                     opt      = optMakeArrangement(size, elemsize);
5181                 }
5182                 assert(isValidArrangement(size, opt));
5183                 fmt = IF_DV_3C;
5184                 break;
5185             }
5186             __fallthrough;
5187
5188         case INS_ands:
5189         case INS_bics:
5190         case INS_eon:
5191             emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0, INS_OPTS_NONE);
5192             return;
5193
5194         case INS_bsl:
5195         case INS_bit:
5196         case INS_bif:
5197             assert(isValidVectorDatasize(size));
5198             assert(isVectorRegister(reg1));
5199             assert(isVectorRegister(reg2));
5200             assert(isVectorRegister(reg3));
5201             if (opt == INS_OPTS_NONE)
5202             {
5203                 elemsize = EA_1BYTE;
5204                 opt      = optMakeArrangement(size, elemsize);
5205             }
5206             assert(isValidArrangement(size, opt));
5207             fmt = IF_DV_3C;
5208             break;
5209
5210         case INS_fadd:
5211         case INS_fsub:
5212         case INS_fdiv:
5213         case INS_fmax:
5214         case INS_fmin:
5215         case INS_fabd:
5216         case INS_fmul:
5217         case INS_fmulx:
5218             assert(isVectorRegister(reg1));
5219             assert(isVectorRegister(reg2));
5220             assert(isVectorRegister(reg3));
5221             if (insOptsAnyArrangement(opt))
5222             {
5223                 // Vector operation
5224                 assert(isValidVectorDatasize(size));
5225                 assert(isValidArrangement(size, opt));
5226                 elemsize = optGetElemsize(opt);
5227                 assert(isValidVectorElemsizeFloat(elemsize));
5228                 assert(opt != INS_OPTS_1D); // Reserved encoding
5229                 fmt = IF_DV_3B;
5230             }
5231             else
5232             {
5233                 // Scalar operation
5234                 assert(insOptsNone(opt));
5235                 assert(isValidScalarDatasize(size));
5236                 fmt = IF_DV_3D;
5237             }
5238             break;
5239
5240         case INS_fnmul:
5241             // Scalar operation
5242             assert(insOptsNone(opt));
5243             assert(isVectorRegister(reg1));
5244             assert(isVectorRegister(reg2));
5245             assert(isVectorRegister(reg3));
5246             assert(isValidScalarDatasize(size));
5247             fmt = IF_DV_3D;
5248             break;
5249
5250         case INS_faddp:
5251         case INS_fmla:
5252         case INS_fmls:
5253             assert(isVectorRegister(reg1));
5254             assert(isVectorRegister(reg2));
5255             assert(isVectorRegister(reg3));
5256             assert(insOptsAnyArrangement(opt)); // no scalar encoding, use 4-operand 'fmadd' or 'fmsub'
5257
5258             // Vector operation
5259             assert(isValidVectorDatasize(size));
5260             assert(isValidArrangement(size, opt));
5261             elemsize = optGetElemsize(opt);
5262             assert(isValidVectorElemsizeFloat(elemsize));
5263             assert(opt != INS_OPTS_1D); // Reserved encoding
5264             fmt = IF_DV_3B;
5265             break;
5266
5267         case INS_ldr:
5268         case INS_ldrb:
5269         case INS_ldrh:
5270         case INS_ldrsb:
5271         case INS_ldrsh:
5272         case INS_ldrsw:
5273         case INS_str:
5274         case INS_strb:
5275         case INS_strh:
5276             emitIns_R_R_R_Ext(ins, attr, reg1, reg2, reg3, opt);
5277             return;
5278
5279         case INS_ldp:
5280         case INS_ldpsw:
5281         case INS_ldnp:
5282         case INS_stp:
5283         case INS_stnp:
5284             emitIns_R_R_R_I(ins, attr, reg1, reg2, reg3, 0);
5285             return;
5286
5287         case INS_stxr:
5288         case INS_stxrb:
5289         case INS_stxrh:
5290         case INS_stlxr:
5291         case INS_stlxrb:
5292         case INS_stlxrh:
5293             assert(isGeneralRegisterOrZR(reg1));
5294             assert(isGeneralRegisterOrZR(reg2));
5295             assert(isGeneralRegisterOrSP(reg3));
5296             fmt = IF_LS_3D;
5297             break;
5298
5299         default:
5300             unreached();
5301             break;
5302
5303     } // end switch (ins)
5304
5305     assert(fmt != IF_NONE);
5306
5307     instrDesc* id = emitNewInstr(attr);
5308
5309     id->idIns(ins);
5310     id->idInsFmt(fmt);
5311     id->idInsOpt(opt);
5312
5313     id->idReg1(reg1);
5314     id->idReg2(reg2);
5315     id->idReg3(reg3);
5316
5317     dispIns(id);
5318     appendToCurIG(id);
5319 }
5320
5321 /*****************************************************************************
5322  *
5323  *  Add an instruction referencing three registers and a constant.
5324  */
5325
5326 void emitter::emitIns_R_R_R_I(instruction ins,
5327                               emitAttr    attr,
5328                               regNumber   reg1,
5329                               regNumber   reg2,
5330                               regNumber   reg3,
5331                               ssize_t     imm,
5332                               insOpts     opt /* = INS_OPTS_NONE */,
5333                               emitAttr    attrReg2 /* = EA_UNKNOWN */)
5334 {
5335     emitAttr  size     = EA_SIZE(attr);
5336     emitAttr  elemsize = EA_UNKNOWN;
5337     insFormat fmt      = IF_NONE;
5338     bool      isLdSt   = false;
5339     bool      isSIMD   = false;
5340     bool      isAddSub = false;
5341     bool      setFlags = false;
5342     unsigned  scale    = 0;
5343
5344     /* Figure out the encoding format of the instruction */
5345     switch (ins)
5346     {
5347         case INS_extr:
5348             assert(insOptsNone(opt));
5349             assert(isValidGeneralDatasize(size));
5350             assert(isGeneralRegister(reg1));
5351             assert(isGeneralRegister(reg2));
5352             assert(isGeneralRegister(reg3));
5353             assert(isValidImmShift(imm, size));
5354             fmt = IF_DR_3E;
5355             break;
5356
5357         case INS_and:
5358         case INS_ands:
5359         case INS_eor:
5360         case INS_orr:
5361         case INS_bic:
5362         case INS_bics:
5363         case INS_eon:
5364         case INS_orn:
5365             assert(isValidGeneralDatasize(size));
5366             assert(isGeneralRegister(reg1));
5367             assert(isGeneralRegister(reg2));
5368             assert(isGeneralRegister(reg3));
5369             assert(isValidImmShift(imm, size));
5370             if (imm == 0)
5371             {
5372                 assert(insOptsNone(opt)); // a zero imm, means no shift kind
5373                 fmt = IF_DR_3A;
5374             }
5375             else
5376             {
5377                 assert(insOptsAnyShift(opt)); // a non-zero imm, must select shift kind
5378                 fmt = IF_DR_3B;
5379             }
5380             break;
5381
5382         case INS_fmul: // by element, imm[0..3] selects the element of reg3
5383         case INS_fmla:
5384         case INS_fmls:
5385         case INS_fmulx:
5386             assert(isVectorRegister(reg1));
5387             assert(isVectorRegister(reg2));
5388             assert(isVectorRegister(reg3));
5389             if (insOptsAnyArrangement(opt))
5390             {
5391                 // Vector operation
5392                 assert(isValidVectorDatasize(size));
5393                 assert(isValidArrangement(size, opt));
5394                 elemsize = optGetElemsize(opt);
5395                 assert(isValidVectorElemsizeFloat(elemsize));
5396                 assert(isValidVectorIndex(size, elemsize, imm));
5397                 assert(opt != INS_OPTS_1D); // Reserved encoding
5398                 fmt = IF_DV_3BI;
5399             }
5400             else
5401             {
5402                 // Scalar operation
5403                 assert(insOptsNone(opt));
5404                 assert(isValidScalarDatasize(size));
5405                 elemsize = size;
5406                 assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
5407                 fmt = IF_DV_3DI;
5408             }
5409             break;
5410
5411         case INS_mul: // by element, imm[0..7] selects the element of reg3
5412         case INS_mla:
5413         case INS_mls:
5414             assert(isVectorRegister(reg1));
5415             assert(isVectorRegister(reg2));
5416             assert(isVectorRegister(reg3));
5417             // Vector operation
5418             assert(insOptsAnyArrangement(opt));
5419             assert(isValidVectorDatasize(size));
5420             assert(isValidArrangement(size, opt));
5421             elemsize = optGetElemsize(opt);
5422             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
5423             // Only has encodings for H or S elemsize
5424             assert((elemsize == EA_2BYTE) || (elemsize == EA_4BYTE));
5425             // Only has encodings for V0..V15
5426             if ((elemsize == EA_2BYTE) && (reg3 >= REG_V16))
5427             {
5428                 noway_assert(!"Invalid reg3");
5429             }
5430             fmt = IF_DV_3AI;
5431             break;
5432
5433         case INS_add:
5434         case INS_sub:
5435             setFlags = false;
5436             isAddSub = true;
5437             break;
5438
5439         case INS_adds:
5440         case INS_subs:
5441             setFlags = true;
5442             isAddSub = true;
5443             break;
5444
5445         case INS_ldpsw:
5446             scale  = 2;
5447             isLdSt = true;
5448             break;
5449
5450         case INS_ldnp:
5451         case INS_stnp:
5452             assert(insOptsNone(opt)); // Can't use Pre/Post index on these two instructions
5453             __fallthrough;
5454
5455         case INS_ldp:
5456         case INS_stp:
5457             // Is the target a vector register?
5458             if (isVectorRegister(reg1))
5459             {
5460                 scale  = NaturalScale_helper(size);
5461                 isSIMD = true;
5462             }
5463             else
5464             {
5465                 scale = (size == EA_8BYTE) ? 3 : 2;
5466             }
5467             isLdSt = true;
5468             break;
5469
5470         default:
5471             unreached();
5472             break;
5473
5474     } // end switch (ins)
5475
5476     if (isLdSt)
5477     {
5478         assert(!isAddSub);
5479         assert(isGeneralRegisterOrSP(reg3));
5480         assert(insOptsNone(opt) || insOptsIndexed(opt));
5481
5482         if (isSIMD)
5483         {
5484             assert(isValidVectorLSPDatasize(size));
5485             assert(isVectorRegister(reg1));
5486             assert(isVectorRegister(reg2));
5487             assert((scale >= 2) && (scale <= 4));
5488         }
5489         else
5490         {
5491             assert(isValidGeneralDatasize(size));
5492             assert(isGeneralRegisterOrZR(reg1));
5493             assert(isGeneralRegisterOrZR(reg2));
5494             assert((scale == 2) || (scale == 3));
5495         }
5496
5497         // Load/Store Pair reserved encodings:
5498         if (emitInsIsLoad(ins))
5499         {
5500             assert(reg1 != reg2);
5501         }
5502         if (insOptsIndexed(opt))
5503         {
5504             assert(reg1 != reg3);
5505             assert(reg2 != reg3);
5506         }
5507
5508         reg3 = encodingSPtoZR(reg3);
5509
5510         ssize_t mask = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
5511         if (imm == 0)
5512         {
5513             assert(insOptsNone(opt)); // PRE/POST Index doesn't make sense with an immediate of zero
5514
5515             fmt = IF_LS_3B;
5516         }
5517         else
5518         {
5519             if ((imm & mask) == 0)
5520             {
5521                 imm >>= scale; // The immediate is scaled by the size of the ld/st
5522
5523                 if ((imm >= -64) && (imm <= 63))
5524                 {
5525                     fmt = IF_LS_3C;
5526                 }
5527             }
5528 #ifdef DEBUG
5529             if (fmt != IF_LS_3C)
5530             {
5531                 assert(!"Instruction cannot be encoded: IF_LS_3C");
5532             }
5533 #endif
5534         }
5535     }
5536     else if (isAddSub)
5537     {
5538         bool reg2IsSP = (reg2 == REG_SP);
5539         assert(!isLdSt);
5540         assert(isValidGeneralDatasize(size));
5541         assert(isGeneralRegister(reg3));
5542
5543         if (setFlags || insOptsAluShift(opt)) // Can't encode SP in reg1 with setFlags or AluShift option
5544         {
5545             assert(isGeneralRegisterOrZR(reg1));
5546         }
5547         else
5548         {
5549             assert(isGeneralRegisterOrSP(reg1));
5550             reg1 = encodingSPtoZR(reg1);
5551         }
5552
5553         if (insOptsAluShift(opt)) // Can't encode SP in reg2 with AluShift option
5554         {
5555             assert(isGeneralRegister(reg2));
5556         }
5557         else
5558         {
5559             assert(isGeneralRegisterOrSP(reg2));
5560             reg2 = encodingSPtoZR(reg2);
5561         }
5562
5563         if (insOptsAnyExtend(opt))
5564         {
5565             assert((imm >= 0) && (imm <= 4));
5566
5567             fmt = IF_DR_3C;
5568         }
5569         else if (insOptsAluShift(opt))
5570         {
5571             // imm should be non-zero and in [1..63]
5572             assert(isValidImmShift(imm, size) && (imm != 0));
5573             fmt = IF_DR_3B;
5574         }
5575         else if (imm == 0)
5576         {
5577             assert(insOptsNone(opt));
5578
5579             if (reg2IsSP)
5580             {
5581                 // To encode the SP register as reg2 we must use the IF_DR_3C encoding
5582                 // and also specify a LSL of zero (imm == 0)
5583                 opt = INS_OPTS_LSL;
5584                 fmt = IF_DR_3C;
5585             }
5586             else
5587             {
5588                 fmt = IF_DR_3A;
5589             }
5590         }
5591         else
5592         {
5593             assert(!"Instruction cannot be encoded: Add/Sub IF_DR_3A");
5594         }
5595     }
5596     assert(fmt != IF_NONE);
5597
5598     instrDesc* id = emitNewInstrCns(attr, imm);
5599
5600     id->idIns(ins);
5601     id->idInsFmt(fmt);
5602     id->idInsOpt(opt);
5603
5604     id->idReg1(reg1);
5605     id->idReg2(reg2);
5606     id->idReg3(reg3);
5607
5608     // Record the attribute for the second register in the pair
5609     id->idGCrefReg2(GCT_NONE);
5610     if (attrReg2 != EA_UNKNOWN)
5611     {
5612         // Record the attribute for the second register in the pair
5613         assert((fmt == IF_LS_3B) || (fmt == IF_LS_3C));
5614         if (EA_IS_GCREF(attrReg2))
5615         {
5616             id->idGCrefReg2(GCT_GCREF);
5617         }
5618         else if (EA_IS_BYREF(attrReg2))
5619         {
5620             id->idGCrefReg2(GCT_BYREF);
5621         }
5622     }
5623
5624     dispIns(id);
5625     appendToCurIG(id);
5626 }
5627
5628 /*****************************************************************************
5629  *
5630  *  Add an instruction referencing three registers, with an extend option
5631  */
5632
5633 void emitter::emitIns_R_R_R_Ext(instruction ins,
5634                                 emitAttr    attr,
5635                                 regNumber   reg1,
5636                                 regNumber   reg2,
5637                                 regNumber   reg3,
5638                                 insOpts     opt,         /* = INS_OPTS_NONE */
5639                                 int         shiftAmount) /* = -1 -- unset   */
5640 {
5641     emitAttr  size   = EA_SIZE(attr);
5642     insFormat fmt    = IF_NONE;
5643     bool      isSIMD = false;
5644     int       scale  = -1;
5645
5646     /* Figure out the encoding format of the instruction */
5647     switch (ins)
5648     {
5649         case INS_ldrb:
5650         case INS_ldrsb:
5651         case INS_strb:
5652             scale = 0;
5653             break;
5654
5655         case INS_ldrh:
5656         case INS_ldrsh:
5657         case INS_strh:
5658             scale = 1;
5659             break;
5660
5661         case INS_ldrsw:
5662             scale = 2;
5663             break;
5664
5665         case INS_ldr:
5666         case INS_str:
5667             // Is the target a vector register?
5668             if (isVectorRegister(reg1))
5669             {
5670                 assert(isValidVectorLSDatasize(size));
5671                 scale  = NaturalScale_helper(size);
5672                 isSIMD = true;
5673             }
5674             else
5675             {
5676                 assert(isValidGeneralDatasize(size));
5677                 scale = (size == EA_8BYTE) ? 3 : 2;
5678             }
5679
5680             break;
5681
5682         default:
5683             unreached();
5684             break;
5685
5686     } // end switch (ins)
5687
5688     assert(scale != -1);
5689     assert(insOptsLSExtend(opt));
5690
5691     if (isSIMD)
5692     {
5693         assert(isValidVectorLSDatasize(size));
5694         assert(isVectorRegister(reg1));
5695     }
5696     else
5697     {
5698         assert(isValidGeneralLSDatasize(size));
5699         assert(isGeneralRegisterOrZR(reg1));
5700     }
5701
5702     assert(isGeneralRegisterOrSP(reg2));
5703     assert(isGeneralRegister(reg3));
5704
5705     // Load/Store reserved encodings:
5706     if (insOptsIndexed(opt))
5707     {
5708         assert(reg1 != reg2);
5709     }
5710
5711     if (shiftAmount == -1)
5712     {
5713         shiftAmount = insOptsLSL(opt) ? scale : 0;
5714     }
5715     assert((shiftAmount == scale) || (shiftAmount == 0));
5716
5717     reg2 = encodingSPtoZR(reg2);
5718     fmt  = IF_LS_3A;
5719
5720     instrDesc* id = emitNewInstr(attr);
5721
5722     id->idIns(ins);
5723     id->idInsFmt(fmt);
5724     id->idInsOpt(opt);
5725
5726     id->idReg1(reg1);
5727     id->idReg2(reg2);
5728     id->idReg3(reg3);
5729     id->idReg3Scaled(shiftAmount == scale);
5730
5731     dispIns(id);
5732     appendToCurIG(id);
5733 }
5734
5735 /*****************************************************************************
5736  *
5737  *  Add an instruction referencing two registers and two constants.
5738  */
5739
5740 void emitter::emitIns_R_R_I_I(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, int imm1, int imm2)
5741 {
5742     emitAttr  size     = EA_SIZE(attr);
5743     emitAttr  elemsize = EA_UNKNOWN;
5744     insFormat fmt      = IF_NONE;
5745     size_t    immOut   = 0; // composed from imm1 and imm2 and stored in the instrDesc
5746
5747     /* Figure out the encoding format of the instruction */
5748     switch (ins)
5749     {
5750         int        lsb;
5751         int        width;
5752         bitMaskImm bmi;
5753
5754         case INS_bfm:
5755         case INS_sbfm:
5756         case INS_ubfm:
5757             assert(isGeneralRegister(reg1));
5758             assert(isGeneralRegister(reg2));
5759             assert(isValidImmShift(imm1, size));
5760             assert(isValidImmShift(imm2, size));
5761             bmi.immNRS = 0;
5762             bmi.immN   = (size == EA_8BYTE);
5763             bmi.immR   = imm1;
5764             bmi.immS   = imm2;
5765             immOut     = bmi.immNRS;
5766             fmt        = IF_DI_2D;
5767             break;
5768
5769         case INS_bfi:
5770         case INS_sbfiz:
5771         case INS_ubfiz:
5772             assert(isGeneralRegister(reg1));
5773             assert(isGeneralRegister(reg2));
5774             lsb   = getBitWidth(size) - imm1;
5775             width = imm2 - 1;
5776             assert(isValidImmShift(lsb, size));
5777             assert(isValidImmShift(width, size));
5778             bmi.immNRS = 0;
5779             bmi.immN   = (size == EA_8BYTE);
5780             bmi.immR   = lsb;
5781             bmi.immS   = width;
5782             immOut     = bmi.immNRS;
5783             fmt        = IF_DI_2D;
5784             break;
5785
5786         case INS_bfxil:
5787         case INS_sbfx:
5788         case INS_ubfx:
5789             assert(isGeneralRegister(reg1));
5790             assert(isGeneralRegister(reg2));
5791             lsb   = imm1;
5792             width = imm2 + imm1 - 1;
5793             assert(isValidImmShift(lsb, size));
5794             assert(isValidImmShift(width, size));
5795             bmi.immNRS = 0;
5796             bmi.immN   = (size == EA_8BYTE);
5797             bmi.immR   = imm1;
5798             bmi.immS   = imm2 + imm1 - 1;
5799             immOut     = bmi.immNRS;
5800             fmt        = IF_DI_2D;
5801             break;
5802
5803         case INS_mov:
5804         case INS_ins:
5805             assert(isVectorRegister(reg1));
5806             assert(isVectorRegister(reg2));
5807             elemsize = size;
5808             assert(isValidVectorElemsize(elemsize));
5809             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm1));
5810             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm2));
5811             immOut = (imm1 << 4) + imm2;
5812             fmt    = IF_DV_2F;
5813             break;
5814
5815         default:
5816             unreached();
5817             break;
5818     }
5819     assert(fmt != IF_NONE);
5820
5821     instrDesc* id = emitNewInstrSC(attr, immOut);
5822
5823     id->idIns(ins);
5824     id->idInsFmt(fmt);
5825
5826     id->idReg1(reg1);
5827     id->idReg2(reg2);
5828
5829     dispIns(id);
5830     appendToCurIG(id);
5831 }
5832
5833 /*****************************************************************************
5834  *
5835  *  Add an instruction referencing four registers.
5836  */
5837
5838 void emitter::emitIns_R_R_R_R(
5839     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, regNumber reg4)
5840 {
5841     emitAttr  size = EA_SIZE(attr);
5842     insFormat fmt  = IF_NONE;
5843
5844     /* Figure out the encoding format of the instruction */
5845     switch (ins)
5846     {
5847         case INS_madd:
5848         case INS_msub:
5849         case INS_smaddl:
5850         case INS_smsubl:
5851         case INS_umaddl:
5852         case INS_umsubl:
5853             assert(isValidGeneralDatasize(size));
5854             assert(isGeneralRegister(reg1));
5855             assert(isGeneralRegister(reg2));
5856             assert(isGeneralRegister(reg3));
5857             assert(isGeneralRegister(reg4));
5858             fmt = IF_DR_4A;
5859             break;
5860
5861         case INS_fmadd:
5862         case INS_fmsub:
5863         case INS_fnmadd:
5864         case INS_fnmsub:
5865             // Scalar operation
5866             assert(isValidScalarDatasize(size));
5867             assert(isVectorRegister(reg1));
5868             assert(isVectorRegister(reg2));
5869             assert(isVectorRegister(reg3));
5870             assert(isVectorRegister(reg4));
5871             fmt = IF_DV_4A;
5872             break;
5873
5874         case INS_invalid:
5875             fmt = IF_NONE;
5876             break;
5877
5878         default:
5879             unreached();
5880             break;
5881     }
5882     assert(fmt != IF_NONE);
5883
5884     instrDesc* id = emitNewInstr(attr);
5885
5886     id->idIns(ins);
5887     id->idInsFmt(fmt);
5888
5889     id->idReg1(reg1);
5890     id->idReg2(reg2);
5891     id->idReg3(reg3);
5892     id->idReg4(reg4);
5893
5894     dispIns(id);
5895     appendToCurIG(id);
5896 }
5897
5898 /*****************************************************************************
5899  *
5900  *  Add an instruction referencing a register and a condition code
5901  */
5902
5903 void emitter::emitIns_R_COND(instruction ins, emitAttr attr, regNumber reg, insCond cond)
5904 {
5905     emitAttr     size = EA_SIZE(attr);
5906     insFormat    fmt  = IF_NONE;
5907     condFlagsImm cfi;
5908     cfi.immCFVal = 0;
5909
5910     /* Figure out the encoding format of the instruction */
5911     switch (ins)
5912     {
5913         case INS_cset:
5914         case INS_csetm:
5915             assert(isGeneralRegister(reg));
5916             cfi.cond = cond;
5917             fmt      = IF_DR_1D;
5918             break;
5919
5920         default:
5921             unreached();
5922             break;
5923
5924     } // end switch (ins)
5925
5926     assert(fmt != IF_NONE);
5927     assert(isValidImmCond(cfi.immCFVal));
5928
5929     instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
5930
5931     id->idIns(ins);
5932     id->idInsFmt(fmt);
5933     id->idInsOpt(INS_OPTS_NONE);
5934
5935     id->idReg1(reg);
5936
5937     dispIns(id);
5938     appendToCurIG(id);
5939 }
5940
5941 /*****************************************************************************
5942  *
5943  *  Add an instruction referencing two registers and a condition code
5944  */
5945
5946 void emitter::emitIns_R_R_COND(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insCond cond)
5947 {
5948     emitAttr     size = EA_SIZE(attr);
5949     insFormat    fmt  = IF_NONE;
5950     condFlagsImm cfi;
5951     cfi.immCFVal = 0;
5952
5953     /* Figure out the encoding format of the instruction */
5954     switch (ins)
5955     {
5956         case INS_cinc:
5957         case INS_cinv:
5958         case INS_cneg:
5959             assert(isGeneralRegister(reg1));
5960             assert(isGeneralRegister(reg2));
5961             cfi.cond = cond;
5962             fmt      = IF_DR_2D;
5963             break;
5964         default:
5965             unreached();
5966             break;
5967
5968     } // end switch (ins)
5969
5970     assert(fmt != IF_NONE);
5971     assert(isValidImmCond(cfi.immCFVal));
5972
5973     instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
5974
5975     id->idIns(ins);
5976     id->idInsFmt(fmt);
5977     id->idInsOpt(INS_OPTS_NONE);
5978
5979     id->idReg1(reg1);
5980     id->idReg2(reg2);
5981
5982     dispIns(id);
5983     appendToCurIG(id);
5984 }
5985
5986 /*****************************************************************************
5987  *
5988  *  Add an instruction referencing two registers and a condition code
5989  */
5990
5991 void emitter::emitIns_R_R_R_COND(
5992     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, insCond cond)
5993 {
5994     emitAttr     size = EA_SIZE(attr);
5995     insFormat    fmt  = IF_NONE;
5996     condFlagsImm cfi;
5997     cfi.immCFVal = 0;
5998
5999     /* Figure out the encoding format of the instruction */
6000     switch (ins)
6001     {
6002         case INS_csel:
6003         case INS_csinc:
6004         case INS_csinv:
6005         case INS_csneg:
6006             assert(isGeneralRegister(reg1));
6007             assert(isGeneralRegister(reg2));
6008             assert(isGeneralRegister(reg3));
6009             cfi.cond = cond;
6010             fmt      = IF_DR_3D;
6011             break;
6012
6013         default:
6014             unreached();
6015             break;
6016
6017     } // end switch (ins)
6018
6019     assert(fmt != IF_NONE);
6020     assert(isValidImmCond(cfi.immCFVal));
6021
6022     instrDesc* id = emitNewInstr(attr);
6023
6024     id->idIns(ins);
6025     id->idInsFmt(fmt);
6026     id->idInsOpt(INS_OPTS_NONE);
6027
6028     id->idReg1(reg1);
6029     id->idReg2(reg2);
6030     id->idReg3(reg3);
6031     id->idSmallCns(cfi.immCFVal);
6032
6033     dispIns(id);
6034     appendToCurIG(id);
6035 }
6036
6037 /*****************************************************************************
6038  *
6039  *  Add an instruction referencing two registers the flags and a condition code
6040  */
6041
6042 void emitter::emitIns_R_R_FLAGS_COND(
6043     instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, insCflags flags, insCond cond)
6044 {
6045     emitAttr     size = EA_SIZE(attr);
6046     insFormat    fmt  = IF_NONE;
6047     condFlagsImm cfi;
6048     cfi.immCFVal = 0;
6049
6050     /* Figure out the encoding format of the instruction */
6051     switch (ins)
6052     {
6053         case INS_ccmp:
6054         case INS_ccmn:
6055             assert(isGeneralRegister(reg1));
6056             assert(isGeneralRegister(reg2));
6057             cfi.flags = flags;
6058             cfi.cond  = cond;
6059             fmt       = IF_DR_2I;
6060             break;
6061         default:
6062             unreached();
6063             break;
6064     } // end switch (ins)
6065
6066     assert(fmt != IF_NONE);
6067     assert(isValidImmCondFlags(cfi.immCFVal));
6068
6069     instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6070
6071     id->idIns(ins);
6072     id->idInsFmt(fmt);
6073     id->idInsOpt(INS_OPTS_NONE);
6074
6075     id->idReg1(reg1);
6076     id->idReg2(reg2);
6077
6078     dispIns(id);
6079     appendToCurIG(id);
6080 }
6081
6082 /*****************************************************************************
6083  *
6084  *  Add an instruction referencing a register, an immediate, the flags and a condition code
6085  */
6086
6087 void emitter::emitIns_R_I_FLAGS_COND(
6088     instruction ins, emitAttr attr, regNumber reg, int imm, insCflags flags, insCond cond)
6089 {
6090     emitAttr     size = EA_SIZE(attr);
6091     insFormat    fmt  = IF_NONE;
6092     condFlagsImm cfi;
6093     cfi.immCFVal = 0;
6094
6095     /* Figure out the encoding format of the instruction */
6096     switch (ins)
6097     {
6098         case INS_ccmp:
6099         case INS_ccmn:
6100             assert(isGeneralRegister(reg));
6101             if (imm < 0)
6102             {
6103                 ins = insReverse(ins);
6104                 imm = -imm;
6105             }
6106             if ((imm >= 0) && (imm <= 31))
6107             {
6108                 cfi.imm5  = imm;
6109                 cfi.flags = flags;
6110                 cfi.cond  = cond;
6111                 fmt       = IF_DI_1F;
6112             }
6113             else
6114             {
6115                 assert(!"Instruction cannot be encoded: ccmp/ccmn imm5");
6116             }
6117             break;
6118         default:
6119             unreached();
6120             break;
6121     } // end switch (ins)
6122
6123     assert(fmt != IF_NONE);
6124     assert(isValidImmCondFlagsImm5(cfi.immCFVal));
6125
6126     instrDesc* id = emitNewInstrSC(attr, cfi.immCFVal);
6127
6128     id->idIns(ins);
6129     id->idInsFmt(fmt);
6130     id->idInsOpt(INS_OPTS_NONE);
6131
6132     id->idReg1(reg);
6133
6134     dispIns(id);
6135     appendToCurIG(id);
6136 }
6137
6138 /*****************************************************************************
6139  *
6140  *  Add a memory barrier instruction with a 'barrier' immediate
6141  */
6142
6143 void emitter::emitIns_BARR(instruction ins, insBarrier barrier)
6144 {
6145     insFormat fmt = IF_NONE;
6146     ssize_t   imm = 0;
6147
6148     /* Figure out the encoding format of the instruction */
6149     switch (ins)
6150     {
6151         case INS_dsb:
6152         case INS_dmb:
6153         case INS_isb:
6154
6155             fmt = IF_SI_0B;
6156             imm = (ssize_t)barrier;
6157             break;
6158         default:
6159             unreached();
6160             break;
6161     } // end switch (ins)
6162
6163     assert(fmt != IF_NONE);
6164
6165     instrDesc* id = emitNewInstrSC(EA_8BYTE, imm);
6166
6167     id->idIns(ins);
6168     id->idInsFmt(fmt);
6169     id->idInsOpt(INS_OPTS_NONE);
6170
6171     dispIns(id);
6172     appendToCurIG(id);
6173 }
6174
6175 /*****************************************************************************
6176  *
6177  *  Add an instruction with a static data member operand. If 'size' is 0, the
6178  *  instruction operates on the address of the static member instead of its
6179  *  value (e.g. "push offset clsvar", rather than "push dword ptr [clsvar]").
6180  */
6181
6182 void emitter::emitIns_C(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, int offs)
6183 {
6184     NYI("emitIns_C");
6185 }
6186
6187 /*****************************************************************************
6188  *
6189  *  Add an instruction referencing stack-based local variable.
6190  */
6191
6192 void emitter::emitIns_S(instruction ins, emitAttr attr, int varx, int offs)
6193 {
6194     NYI("emitIns_S");
6195 }
6196
6197 /*****************************************************************************
6198  *
6199  *  Add an instruction referencing a register and a stack-based local variable.
6200  */
6201 void emitter::emitIns_R_S(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
6202 {
6203     emitAttr  size  = EA_SIZE(attr);
6204     insFormat fmt   = IF_NONE;
6205     int       disp  = 0;
6206     unsigned  scale = 0;
6207
6208     assert(offs >= 0);
6209
6210     // TODO-ARM64-CQ: use unscaled loads?
6211     /* Figure out the encoding format of the instruction */
6212     switch (ins)
6213     {
6214         case INS_strb:
6215         case INS_ldrb:
6216         case INS_ldrsb:
6217             scale = 0;
6218             break;
6219
6220         case INS_strh:
6221         case INS_ldrh:
6222         case INS_ldrsh:
6223             scale = 1;
6224             break;
6225
6226         case INS_ldrsw:
6227             scale = 2;
6228             break;
6229
6230         case INS_str:
6231         case INS_ldr:
6232             assert(isValidGeneralDatasize(size) || isValidVectorDatasize(size));
6233             scale = genLog2(EA_SIZE_IN_BYTES(size));
6234             break;
6235
6236         case INS_lea:
6237             assert(size == EA_8BYTE);
6238             scale = 0;
6239             break;
6240
6241         default:
6242             NYI("emitIns_R_S"); // FP locals?
6243             return;
6244
6245     } // end switch (ins)
6246
6247     /* Figure out the variable's frame position */
6248     ssize_t imm;
6249     int     base;
6250     bool    FPbased;
6251
6252     base = emitComp->lvaFrameAddress(varx, &FPbased);
6253     disp = base + offs;
6254     assert((scale >= 0) && (scale <= 4));
6255
6256     regNumber reg2 = FPbased ? REG_FPBASE : REG_SPBASE;
6257     reg2           = encodingSPtoZR(reg2);
6258
6259     if (ins == INS_lea)
6260     {
6261         if (disp >= 0)
6262         {
6263             ins = INS_add;
6264             imm = disp;
6265         }
6266         else
6267         {
6268             ins = INS_sub;
6269             imm = -disp;
6270         }
6271
6272         if (imm <= 0x0fff)
6273         {
6274             fmt = IF_DI_2A; // add reg1,reg2,#disp
6275         }
6276         else
6277         {
6278             regNumber rsvdReg = codeGen->rsGetRsvdReg();
6279             codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6280             fmt = IF_DR_3A; // add reg1,reg2,rsvdReg
6281         }
6282     }
6283     else
6284     {
6285         bool    useRegForImm = false;
6286         ssize_t mask         = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6287
6288         imm = disp;
6289         if (imm == 0)
6290         {
6291             fmt = IF_LS_2A;
6292         }
6293         else if ((imm < 0) || ((imm & mask) != 0))
6294         {
6295             if ((imm >= -256) && (imm <= 255))
6296             {
6297                 fmt = IF_LS_2C;
6298             }
6299             else
6300             {
6301                 useRegForImm = true;
6302             }
6303         }
6304         else if (imm > 0)
6305         {
6306             if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
6307             {
6308                 imm >>= scale; // The immediate is scaled by the size of the ld/st
6309
6310                 fmt = IF_LS_2B;
6311             }
6312             else
6313             {
6314                 useRegForImm = true;
6315             }
6316         }
6317
6318         if (useRegForImm)
6319         {
6320             regNumber rsvdReg = codeGen->rsGetRsvdReg();
6321             codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6322             fmt = IF_LS_3A;
6323         }
6324     }
6325
6326     assert(fmt != IF_NONE);
6327
6328     instrDesc* id = emitNewInstrCns(attr, imm);
6329
6330     id->idIns(ins);
6331     id->idInsFmt(fmt);
6332     id->idInsOpt(INS_OPTS_NONE);
6333
6334     id->idReg1(reg1);
6335     id->idReg2(reg2);
6336     id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6337     id->idSetIsLclVar();
6338
6339 #ifdef DEBUG
6340     id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6341 #endif
6342
6343     dispIns(id);
6344     appendToCurIG(id);
6345 }
6346
6347 /*****************************************************************************
6348  *
6349  *  Add an instruction referencing two register and consectutive stack-based local variable slots.
6350  */
6351 void emitter::emitIns_R_R_S_S(
6352     instruction ins, emitAttr attr1, emitAttr attr2, regNumber reg1, regNumber reg2, int varx, int offs)
6353 {
6354     assert((ins == INS_ldp) || (ins == INS_ldnp));
6355     assert(EA_8BYTE == EA_SIZE(attr1));
6356     assert(EA_8BYTE == EA_SIZE(attr2));
6357     assert(isGeneralRegisterOrZR(reg1));
6358     assert(isGeneralRegisterOrZR(reg2));
6359     assert(offs >= 0);
6360
6361     insFormat      fmt   = IF_LS_3B;
6362     int            disp  = 0;
6363     const unsigned scale = 3;
6364
6365     /* Figure out the variable's frame position */
6366     int  base;
6367     bool FPbased;
6368
6369     base = emitComp->lvaFrameAddress(varx, &FPbased);
6370     disp = base + offs;
6371
6372     // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6373     regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE;
6374     reg3           = encodingSPtoZR(reg3);
6375
6376     bool    useRegForAdr = true;
6377     ssize_t imm          = disp;
6378     ssize_t mask         = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6379     if (imm == 0)
6380     {
6381         useRegForAdr = false;
6382     }
6383     else
6384     {
6385         if ((imm & mask) == 0)
6386         {
6387             ssize_t immShift = imm >> scale; // The immediate is scaled by the size of the ld/st
6388
6389             if ((immShift >= -64) && (immShift <= 63))
6390             {
6391                 fmt          = IF_LS_3C;
6392                 useRegForAdr = false;
6393                 imm          = immShift;
6394             }
6395         }
6396     }
6397
6398     if (useRegForAdr)
6399     {
6400         regNumber rsvd = codeGen->rsGetRsvdReg();
6401         emitIns_R_R_Imm(INS_add, EA_PTRSIZE, rsvd, reg3, imm);
6402         reg3 = rsvd;
6403         imm  = 0;
6404     }
6405
6406     assert(fmt != IF_NONE);
6407
6408     instrDesc* id = emitNewInstrCns(attr1, imm);
6409
6410     id->idIns(ins);
6411     id->idInsFmt(fmt);
6412     id->idInsOpt(INS_OPTS_NONE);
6413
6414     // Record the attribute for the second register in the pair
6415     if (EA_IS_GCREF(attr2))
6416     {
6417         id->idGCrefReg2(GCT_GCREF);
6418     }
6419     else if (EA_IS_BYREF(attr2))
6420     {
6421         id->idGCrefReg2(GCT_BYREF);
6422     }
6423     else
6424     {
6425         id->idGCrefReg2(GCT_NONE);
6426     }
6427
6428     id->idReg1(reg1);
6429     id->idReg2(reg2);
6430     id->idReg3(reg3);
6431     id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6432     id->idSetIsLclVar();
6433
6434 #ifdef DEBUG
6435     id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6436 #endif
6437
6438     dispIns(id);
6439     appendToCurIG(id);
6440 }
6441
6442 /*****************************************************************************
6443  *
6444  *  Add an instruction referencing a stack-based local variable and a register
6445  */
6446 void emitter::emitIns_S_R(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs)
6447 {
6448     assert(offs >= 0);
6449     emitAttr  size          = EA_SIZE(attr);
6450     insFormat fmt           = IF_NONE;
6451     int       disp          = 0;
6452     unsigned  scale         = 0;
6453     bool      isVectorStore = false;
6454
6455     // TODO-ARM64-CQ: use unscaled loads?
6456     /* Figure out the encoding format of the instruction */
6457     switch (ins)
6458     {
6459         case INS_strb:
6460             scale = 0;
6461             assert(isGeneralRegisterOrZR(reg1));
6462             break;
6463
6464         case INS_strh:
6465             scale = 1;
6466             assert(isGeneralRegisterOrZR(reg1));
6467             break;
6468
6469         case INS_str:
6470             if (isGeneralRegisterOrZR(reg1))
6471             {
6472                 assert(isValidGeneralDatasize(size));
6473                 scale = (size == EA_8BYTE) ? 3 : 2;
6474             }
6475             else
6476             {
6477                 assert(isVectorRegister(reg1));
6478                 assert(isValidVectorLSDatasize(size));
6479                 scale         = NaturalScale_helper(size);
6480                 isVectorStore = true;
6481             }
6482             break;
6483
6484         default:
6485             NYI("emitIns_S_R"); // FP locals?
6486             return;
6487
6488     } // end switch (ins)
6489
6490     /* Figure out the variable's frame position */
6491     int  base;
6492     bool FPbased;
6493
6494     base = emitComp->lvaFrameAddress(varx, &FPbased);
6495     disp = base + offs;
6496     assert(scale >= 0);
6497     if (isVectorStore)
6498     {
6499         assert(scale <= 4);
6500     }
6501     else
6502     {
6503         assert(scale <= 3);
6504     }
6505
6506     // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6507     regNumber reg2 = FPbased ? REG_FPBASE : REG_SPBASE;
6508     reg2           = encodingSPtoZR(reg2);
6509
6510     bool    useRegForImm = false;
6511     ssize_t imm          = disp;
6512     ssize_t mask         = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6513     if (imm == 0)
6514     {
6515         fmt = IF_LS_2A;
6516     }
6517     else if ((imm < 0) || ((imm & mask) != 0))
6518     {
6519         if ((imm >= -256) && (imm <= 255))
6520         {
6521             fmt = IF_LS_2C;
6522         }
6523         else
6524         {
6525             useRegForImm = true;
6526         }
6527     }
6528     else if (imm > 0)
6529     {
6530         if (((imm & mask) == 0) && ((imm >> scale) < 0x1000))
6531         {
6532             imm >>= scale; // The immediate is scaled by the size of the ld/st
6533
6534             fmt = IF_LS_2B;
6535         }
6536         else
6537         {
6538             useRegForImm = true;
6539         }
6540     }
6541
6542     if (useRegForImm)
6543     {
6544         // The reserved register is not stored in idReg3() since that field overlaps with iiaLclVar.
6545         // It is instead implicit when idSetIsLclVar() is set, with this encoding format.
6546         regNumber rsvdReg = codeGen->rsGetRsvdReg();
6547         codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, rsvdReg, imm);
6548         fmt = IF_LS_3A;
6549     }
6550
6551     assert(fmt != IF_NONE);
6552
6553     instrDesc* id = emitNewInstrCns(attr, imm);
6554
6555     id->idIns(ins);
6556     id->idInsFmt(fmt);
6557     id->idInsOpt(INS_OPTS_NONE);
6558
6559     id->idReg1(reg1);
6560     id->idReg2(reg2);
6561     id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6562     id->idSetIsLclVar();
6563
6564 #ifdef DEBUG
6565     id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6566 #endif
6567
6568     dispIns(id);
6569     appendToCurIG(id);
6570 }
6571
6572 /*****************************************************************************
6573  *
6574  *  Add an instruction referencing consecutive stack-based local variable slots and two registers
6575  */
6576 void emitter::emitIns_S_S_R_R(
6577     instruction ins, emitAttr attr1, emitAttr attr2, regNumber reg1, regNumber reg2, int varx, int offs)
6578 {
6579     assert((ins == INS_stp) || (ins == INS_stnp));
6580     assert(EA_8BYTE == EA_SIZE(attr1));
6581     assert(EA_8BYTE == EA_SIZE(attr2));
6582     assert(isGeneralRegisterOrZR(reg1));
6583     assert(isGeneralRegisterOrZR(reg2));
6584     assert(offs >= 0);
6585
6586     insFormat      fmt   = IF_LS_3B;
6587     int            disp  = 0;
6588     const unsigned scale = 3;
6589
6590     /* Figure out the variable's frame position */
6591     int  base;
6592     bool FPbased;
6593
6594     base = emitComp->lvaFrameAddress(varx, &FPbased);
6595     disp = base + offs;
6596
6597     // TODO-ARM64-CQ: with compLocallocUsed, should we use REG_SAVED_LOCALLOC_SP instead?
6598     regNumber reg3 = FPbased ? REG_FPBASE : REG_SPBASE;
6599     reg3           = encodingSPtoZR(reg3);
6600
6601     bool    useRegForAdr = true;
6602     ssize_t imm          = disp;
6603     ssize_t mask         = (1 << scale) - 1; // the mask of low bits that must be zero to encode the immediate
6604     if (imm == 0)
6605     {
6606         useRegForAdr = false;
6607     }
6608     else
6609     {
6610         if ((imm & mask) == 0)
6611         {
6612             ssize_t immShift = imm >> scale; // The immediate is scaled by the size of the ld/st
6613
6614             if ((immShift >= -64) && (immShift <= 63))
6615             {
6616                 fmt          = IF_LS_3C;
6617                 useRegForAdr = false;
6618                 imm          = immShift;
6619             }
6620         }
6621     }
6622
6623     if (useRegForAdr)
6624     {
6625         regNumber rsvd = codeGen->rsGetRsvdReg();
6626         emitIns_R_R_Imm(INS_add, EA_PTRSIZE, rsvd, reg3, imm);
6627         reg3 = rsvd;
6628         imm  = 0;
6629     }
6630
6631     assert(fmt != IF_NONE);
6632
6633     instrDesc* id = emitNewInstrCns(attr1, imm);
6634
6635     id->idIns(ins);
6636     id->idInsFmt(fmt);
6637     id->idInsOpt(INS_OPTS_NONE);
6638
6639     // Record the attribute for the second register in the pair
6640     if (EA_IS_GCREF(attr2))
6641     {
6642         id->idGCrefReg2(GCT_GCREF);
6643     }
6644     else if (EA_IS_BYREF(attr2))
6645     {
6646         id->idGCrefReg2(GCT_BYREF);
6647     }
6648     else
6649     {
6650         id->idGCrefReg2(GCT_NONE);
6651     }
6652
6653     id->idReg1(reg1);
6654     id->idReg2(reg2);
6655     id->idReg3(reg3);
6656     id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs);
6657     id->idSetIsLclVar();
6658
6659 #ifdef DEBUG
6660     id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs;
6661 #endif
6662
6663     dispIns(id);
6664     appendToCurIG(id);
6665 }
6666
6667 /*****************************************************************************
6668  *
6669  *  Add an instruction referencing stack-based local variable and an immediate
6670  */
6671 void emitter::emitIns_S_I(instruction ins, emitAttr attr, int varx, int offs, int val)
6672 {
6673     NYI("emitIns_S_I");
6674 }
6675
6676 /*****************************************************************************
6677  *
6678  *  Add an instruction with a register + static member operands.
6679  *  Constant is stored into JIT data which is adjacent to code.
6680  *  No relocation is needed. PC-relative offset will be encoded directly into instruction.
6681  *
6682  */
6683 void emitter::emitIns_R_C(
6684     instruction ins, emitAttr attr, regNumber reg, regNumber addrReg, CORINFO_FIELD_HANDLE fldHnd, int offs)
6685 {
6686     assert(offs >= 0);
6687     assert(instrDesc::fitsInSmallCns(offs));
6688
6689     emitAttr      size = EA_SIZE(attr);
6690     insFormat     fmt  = IF_NONE;
6691     int           disp = 0;
6692     instrDescJmp* id   = emitNewInstrJmp();
6693
6694     switch (ins)
6695     {
6696         case INS_adr:
6697             // This is case to get address to the constant data.
6698             fmt = IF_LARGEADR;
6699             assert(isGeneralRegister(reg));
6700             assert(isValidGeneralDatasize(size));
6701             break;
6702
6703         case INS_ldr:
6704             fmt = IF_LARGELDC;
6705             if (isVectorRegister(reg))
6706             {
6707                 assert(isValidScalarDatasize(size));
6708                 // For vector (float/double) register, we should have an integer address reg to
6709                 // compute long address which consists of page address and page offset.
6710                 // For integer constant, this is not needed since the dest reg can be used to
6711                 // compute address as well as contain the final contents.
6712                 assert(isGeneralRegister(reg) || (addrReg != REG_NA));
6713             }
6714             else
6715             {
6716                 assert(isGeneralRegister(reg));
6717                 assert(isValidGeneralDatasize(size));
6718             }
6719             break;
6720         default:
6721             unreached();
6722     }
6723
6724     assert(fmt != IF_NONE);
6725
6726     id->idIns(ins);
6727     id->idInsFmt(fmt);
6728     id->idInsOpt(INS_OPTS_NONE);
6729     id->idSmallCns(offs);
6730     id->idOpSize(size);
6731     id->idAddr()->iiaFieldHnd = fldHnd;
6732     id->idSetIsBound(); // We won't patch address since we will know the exact distance once JIT code and data are
6733                         // allocated together.
6734
6735     id->idReg1(reg); // destination register that will get the constant value.
6736     if (addrReg != REG_NA)
6737     {
6738         id->idReg2(addrReg); // integer register to compute long address (used for vector dest when we end up with long
6739                              // address)
6740     }
6741     id->idjShort = false; // Assume loading constant from long address
6742
6743     // Keep it long if it's in cold code.
6744     id->idjKeepLong = emitComp->fgIsBlockCold(emitComp->compCurBB);
6745
6746 #ifdef DEBUG
6747     if (emitComp->opts.compLongAddress)
6748         id->idjKeepLong = 1;
6749 #endif // DEBUG
6750
6751     // If it's possible to be shortened, then put it in jump list
6752     // to be revisited by emitJumpDistBind.
6753     if (!id->idjKeepLong)
6754     {
6755         /* Record the jump's IG and offset within it */
6756         id->idjIG   = emitCurIG;
6757         id->idjOffs = emitCurIGsize;
6758
6759         /* Append this jump to this IG's jump list */
6760         id->idjNext      = emitCurIGjmpList;
6761         emitCurIGjmpList = id;
6762
6763 #if EMITTER_STATS
6764         emitTotalIGjmps++;
6765 #endif
6766     }
6767
6768     dispIns(id);
6769     appendToCurIG(id);
6770 }
6771
6772 /*****************************************************************************
6773  *
6774  *  Add an instruction with a static member + constant.
6775  */
6776
6777 void emitter::emitIns_C_I(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, ssize_t offs, ssize_t val)
6778 {
6779     NYI("emitIns_C_I");
6780 }
6781
6782 /*****************************************************************************
6783  *
6784  *  Add an instruction with a static member + register operands.
6785  */
6786
6787 void emitter::emitIns_C_R(instruction ins, emitAttr attr, CORINFO_FIELD_HANDLE fldHnd, regNumber reg, int offs)
6788 {
6789     assert(!"emitIns_C_R not supported for RyuJIT backend");
6790 }
6791
6792 void emitter::emitIns_R_AR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
6793 {
6794     NYI("emitIns_R_AR");
6795 }
6796
6797 // This computes address from the immediate which is relocatable.
6798 void emitter::emitIns_R_AI(instruction ins, emitAttr attr, regNumber ireg, ssize_t addr)
6799 {
6800     assert(EA_IS_RELOC(attr));
6801     emitAttr      size    = EA_SIZE(attr);
6802     insFormat     fmt     = IF_DI_1E;
6803     bool          needAdd = false;
6804     instrDescJmp* id      = emitNewInstrJmp();
6805
6806     switch (ins)
6807     {
6808         case INS_adrp:
6809             // This computes page address.
6810             // page offset is needed using add.
6811             needAdd = true;
6812             break;
6813         case INS_adr:
6814             break;
6815         default:
6816             unreached();
6817     }
6818
6819     id->idIns(ins);
6820     id->idInsFmt(fmt);
6821     id->idInsOpt(INS_OPTS_NONE);
6822     id->idOpSize(size);
6823     id->idAddr()->iiaAddr = (BYTE*)addr;
6824     id->idReg1(ireg);
6825     id->idSetIsDspReloc();
6826
6827     dispIns(id);
6828     appendToCurIG(id);
6829
6830     if (needAdd)
6831     {
6832         // add reg, reg, imm
6833         ins           = INS_add;
6834         fmt           = IF_DI_2A;
6835         instrDesc* id = emitAllocInstr(attr);
6836         assert(id->idIsReloc());
6837
6838         id->idIns(ins);
6839         id->idInsFmt(fmt);
6840         id->idInsOpt(INS_OPTS_NONE);
6841         id->idOpSize(size);
6842         id->idAddr()->iiaAddr = (BYTE*)addr;
6843         id->idReg1(ireg);
6844         id->idReg2(ireg);
6845
6846         dispIns(id);
6847         appendToCurIG(id);
6848     }
6849 }
6850
6851 void emitter::emitIns_AR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, int offs)
6852 {
6853     NYI("emitIns_AR_R");
6854 }
6855
6856 void emitter::emitIns_R_ARR(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
6857 {
6858     NYI("emitIns_R_ARR");
6859 }
6860
6861 void emitter::emitIns_ARR_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, int disp)
6862 {
6863     NYI("emitIns_R_ARR");
6864 }
6865
6866 void emitter::emitIns_R_ARX(
6867     instruction ins, emitAttr attr, regNumber ireg, regNumber reg, regNumber rg2, unsigned mul, int disp)
6868 {
6869     NYI("emitIns_R_ARR");
6870 }
6871
6872 /*****************************************************************************
6873  *
6874  *  Record that a jump instruction uses the short encoding
6875  *
6876  */
6877 void emitter::emitSetShortJump(instrDescJmp* id)
6878 {
6879     if (id->idjKeepLong)
6880         return;
6881
6882     insFormat fmt = IF_NONE;
6883     if (emitIsCondJump(id))
6884     {
6885         switch (id->idIns())
6886         {
6887             case INS_cbz:
6888             case INS_cbnz:
6889                 fmt = IF_BI_1A;
6890                 break;
6891             case INS_tbz:
6892             case INS_tbnz:
6893                 fmt = IF_BI_1B;
6894                 break;
6895             default:
6896                 fmt = IF_BI_0B;
6897                 break;
6898         }
6899     }
6900     else if (emitIsLoadLabel(id))
6901     {
6902         fmt = IF_DI_1E;
6903     }
6904     else if (emitIsLoadConstant(id))
6905     {
6906         fmt = IF_LS_1A;
6907     }
6908     else
6909     {
6910         unreached();
6911     }
6912
6913     id->idInsFmt(fmt);
6914     id->idjShort = true;
6915 }
6916
6917 /*****************************************************************************
6918  *
6919  *  Add a label instruction.
6920  */
6921
6922 void emitter::emitIns_R_L(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
6923 {
6924     assert(dst->bbFlags & BBF_JMP_TARGET);
6925
6926     insFormat fmt = IF_NONE;
6927
6928     switch (ins)
6929     {
6930         case INS_adr:
6931             fmt = IF_LARGEADR;
6932             break;
6933         default:
6934             unreached();
6935     }
6936
6937     instrDescJmp* id = emitNewInstrJmp();
6938
6939     id->idIns(ins);
6940     id->idInsFmt(fmt);
6941     id->idjShort             = false;
6942     id->idAddr()->iiaBBlabel = dst;
6943     id->idReg1(reg);
6944     id->idOpSize(EA_PTRSIZE);
6945
6946 #ifdef DEBUG
6947     // Mark the catch return
6948     if (emitComp->compCurBB->bbJumpKind == BBJ_EHCATCHRET)
6949     {
6950         id->idDebugOnlyInfo()->idCatchRet = true;
6951     }
6952 #endif // DEBUG
6953
6954     id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
6955
6956 #ifdef DEBUG
6957     if (emitComp->opts.compLongAddress)
6958         id->idjKeepLong = 1;
6959 #endif // DEBUG
6960
6961     /* Record the jump's IG and offset within it */
6962
6963     id->idjIG   = emitCurIG;
6964     id->idjOffs = emitCurIGsize;
6965
6966     /* Append this jump to this IG's jump list */
6967
6968     id->idjNext      = emitCurIGjmpList;
6969     emitCurIGjmpList = id;
6970
6971 #if EMITTER_STATS
6972     emitTotalIGjmps++;
6973 #endif
6974
6975     dispIns(id);
6976     appendToCurIG(id);
6977 }
6978
6979 /*****************************************************************************
6980  *
6981  *  Add a data label instruction.
6982  */
6983
6984 void emitter::emitIns_R_D(instruction ins, emitAttr attr, unsigned offs, regNumber reg)
6985 {
6986     NYI("emitIns_R_D");
6987 }
6988
6989 void emitter::emitIns_J_R(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg)
6990 {
6991     assert((ins == INS_cbz) || (ins == INS_cbnz));
6992
6993     assert(dst != nullptr);
6994     assert((dst->bbFlags & BBF_JMP_TARGET) != 0);
6995
6996     insFormat fmt = IF_LARGEJMP;
6997
6998     instrDescJmp* id = emitNewInstrJmp();
6999
7000     id->idIns(ins);
7001     id->idInsFmt(fmt);
7002     id->idReg1(reg);
7003     id->idjShort = false;
7004     id->idOpSize(EA_SIZE(attr));
7005
7006     id->idAddr()->iiaBBlabel = dst;
7007     id->idjKeepLong          = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7008
7009     /* Record the jump's IG and offset within it */
7010
7011     id->idjIG   = emitCurIG;
7012     id->idjOffs = emitCurIGsize;
7013
7014     /* Append this jump to this IG's jump list */
7015
7016     id->idjNext      = emitCurIGjmpList;
7017     emitCurIGjmpList = id;
7018
7019 #if EMITTER_STATS
7020     emitTotalIGjmps++;
7021 #endif
7022
7023     dispIns(id);
7024     appendToCurIG(id);
7025 }
7026
7027 void emitter::emitIns_J_R_I(instruction ins, emitAttr attr, BasicBlock* dst, regNumber reg, int imm)
7028 {
7029     assert((ins == INS_tbz) || (ins == INS_tbnz));
7030
7031     assert(dst != nullptr);
7032     assert((dst->bbFlags & BBF_JMP_TARGET) != 0);
7033     assert((EA_SIZE(attr) == EA_4BYTE) || (EA_SIZE(attr) == EA_8BYTE));
7034     assert(imm < ((EA_SIZE(attr) == EA_4BYTE) ? 32 : 64));
7035
7036     insFormat fmt = IF_LARGEJMP;
7037
7038     instrDescJmp* id = emitNewInstrJmp();
7039
7040     id->idIns(ins);
7041     id->idInsFmt(fmt);
7042     id->idReg1(reg);
7043     id->idjShort = false;
7044     id->idSmallCns(imm);
7045     id->idOpSize(EA_SIZE(attr));
7046
7047     id->idAddr()->iiaBBlabel = dst;
7048     id->idjKeepLong          = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7049
7050     /* Record the jump's IG and offset within it */
7051
7052     id->idjIG   = emitCurIG;
7053     id->idjOffs = emitCurIGsize;
7054
7055     /* Append this jump to this IG's jump list */
7056
7057     id->idjNext      = emitCurIGjmpList;
7058     emitCurIGjmpList = id;
7059
7060 #if EMITTER_STATS
7061     emitTotalIGjmps++;
7062 #endif
7063
7064     dispIns(id);
7065     appendToCurIG(id);
7066 }
7067
7068 void emitter::emitIns_J(instruction ins, BasicBlock* dst, int instrCount)
7069 {
7070     insFormat fmt = IF_NONE;
7071
7072     if (dst != nullptr)
7073     {
7074         assert(dst->bbFlags & BBF_JMP_TARGET);
7075     }
7076     else
7077     {
7078         assert(instrCount != 0);
7079     }
7080
7081     /* Figure out the encoding format of the instruction */
7082
7083     bool idjShort = false;
7084     switch (ins)
7085     {
7086         case INS_bl_local:
7087         case INS_b:
7088             // Unconditional jump is a single form.
7089             idjShort = true;
7090             fmt      = IF_BI_0A;
7091             break;
7092
7093         case INS_beq:
7094         case INS_bne:
7095         case INS_bhs:
7096         case INS_blo:
7097         case INS_bmi:
7098         case INS_bpl:
7099         case INS_bvs:
7100         case INS_bvc:
7101         case INS_bhi:
7102         case INS_bls:
7103         case INS_bge:
7104         case INS_blt:
7105         case INS_bgt:
7106         case INS_ble:
7107             // Assume conditional jump is long.
7108             fmt = IF_LARGEJMP;
7109             break;
7110
7111         default:
7112             unreached();
7113             break;
7114     }
7115
7116     instrDescJmp* id = emitNewInstrJmp();
7117
7118     id->idIns(ins);
7119     id->idInsFmt(fmt);
7120     id->idjShort = idjShort;
7121
7122 #ifdef DEBUG
7123     // Mark the finally call
7124     if (ins == INS_bl_local && emitComp->compCurBB->bbJumpKind == BBJ_CALLFINALLY)
7125     {
7126         id->idDebugOnlyInfo()->idFinallyCall = true;
7127     }
7128 #endif // DEBUG
7129
7130     if (dst != nullptr)
7131     {
7132         id->idAddr()->iiaBBlabel = dst;
7133
7134         // Skip unconditional jump that has a single form.
7135         // TODO-ARM64-NYI: enable hot/cold splittingNYI.
7136         // The target needs to be relocated.
7137         if (!idjShort)
7138         {
7139             id->idjKeepLong = emitComp->fgInDifferentRegions(emitComp->compCurBB, dst);
7140
7141 #ifdef DEBUG
7142             if (emitComp->opts.compLongAddress) // Force long branches
7143                 id->idjKeepLong = 1;
7144 #endif // DEBUG
7145         }
7146     }
7147     else
7148     {
7149         id->idAddr()->iiaSetInstrCount(instrCount);
7150         id->idjKeepLong = false;
7151         /* This jump must be short */
7152         emitSetShortJump(id);
7153         id->idSetIsBound();
7154     }
7155
7156     /* Record the jump's IG and offset within it */
7157
7158     id->idjIG   = emitCurIG;
7159     id->idjOffs = emitCurIGsize;
7160
7161     /* Append this jump to this IG's jump list */
7162
7163     id->idjNext      = emitCurIGjmpList;
7164     emitCurIGjmpList = id;
7165
7166 #if EMITTER_STATS
7167     emitTotalIGjmps++;
7168 #endif
7169
7170     dispIns(id);
7171     appendToCurIG(id);
7172 }
7173
7174 /*****************************************************************************
7175  *
7176  *  Add a call instruction (direct or indirect).
7177  *      argSize<0 means that the caller will pop the arguments
7178  *
7179  * The other arguments are interpreted depending on callType as shown:
7180  * Unless otherwise specified, ireg,xreg,xmul,disp should have default values.
7181  *
7182  * EC_FUNC_TOKEN       : addr is the method address
7183  * EC_FUNC_ADDR        : addr is the absolute address of the function
7184  *
7185  * If callType is one of these emitCallTypes, addr has to be NULL.
7186  * EC_INDIR_R          : "call ireg".
7187  *
7188  * For ARM xreg, xmul and disp are never used and should always be 0/REG_NA.
7189  *
7190  *  Please consult the "debugger team notification" comment in genFnProlog().
7191  */
7192
7193 void emitter::emitIns_Call(EmitCallType          callType,
7194                            CORINFO_METHOD_HANDLE methHnd,
7195                            INDEBUG_LDISASM_COMMA(CORINFO_SIG_INFO* sigInfo) // used to report call sites to the EE
7196                            void*            addr,
7197                            ssize_t          argSize,
7198                            emitAttr         retSize,
7199                            emitAttr         secondRetSize,
7200                            VARSET_VALARG_TP ptrVars,
7201                            regMaskTP        gcrefRegs,
7202                            regMaskTP        byrefRegs,
7203                            IL_OFFSETX       ilOffset /* = BAD_IL_OFFSET */,
7204                            regNumber        ireg /* = REG_NA */,
7205                            regNumber        xreg /* = REG_NA */,
7206                            unsigned         xmul /* = 0     */,
7207                            ssize_t          disp /* = 0     */,
7208                            bool             isJump /* = false */,
7209                            bool             isNoGC /* = false */,
7210                            bool             isProfLeaveCB /* = false */)
7211 {
7212     /* Sanity check the arguments depending on callType */
7213
7214     assert(callType < EC_COUNT);
7215     assert((callType != EC_FUNC_TOKEN && callType != EC_FUNC_ADDR) ||
7216            (ireg == REG_NA && xreg == REG_NA && xmul == 0 && disp == 0));
7217     assert(callType < EC_INDIR_R || addr == NULL);
7218     assert(callType != EC_INDIR_R || (ireg < REG_COUNT && xreg == REG_NA && xmul == 0 && disp == 0));
7219
7220     // ARM never uses these
7221     assert(xreg == REG_NA && xmul == 0 && disp == 0);
7222
7223     // Our stack level should be always greater than the bytes of arguments we push. Just
7224     // a sanity test.
7225     assert((unsigned)abs(argSize) <= codeGen->genStackLevel);
7226
7227     int        argCnt;
7228     instrDesc* id;
7229
7230     /* This is the saved set of registers after a normal call */
7231     regMaskTP savedSet = RBM_CALLEE_SAVED;
7232
7233     /* some special helper calls have a different saved set registers */
7234
7235     if (isNoGC)
7236     {
7237         assert(emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
7238
7239         // Get the set of registers that this call kills and remove it from the saved set.
7240         savedSet = RBM_ALLINT & ~emitComp->compNoGCHelperCallKillSet(Compiler::eeGetHelperNum(methHnd));
7241
7242         // In case of Leave profiler callback, we need to preserve liveness of REG_PROFILER_RET_SCRATCH
7243         if (isProfLeaveCB)
7244         {
7245             savedSet |= RBM_PROFILER_RET_SCRATCH;
7246         }
7247     }
7248     else
7249     {
7250         assert(!emitNoGChelper(Compiler::eeGetHelperNum(methHnd)));
7251     }
7252
7253     /* Trim out any callee-trashed registers from the live set */
7254
7255     gcrefRegs &= savedSet;
7256     byrefRegs &= savedSet;
7257
7258 #ifdef DEBUG
7259     if (EMIT_GC_VERBOSE)
7260     {
7261         printf("Call: GCvars=%s ", VarSetOps::ToString(emitComp, ptrVars));
7262         dumpConvertedVarSet(emitComp, ptrVars);
7263         printf(", gcrefRegs=");
7264         printRegMaskInt(gcrefRegs);
7265         emitDispRegSet(gcrefRegs);
7266         printf(", byrefRegs=");
7267         printRegMaskInt(byrefRegs);
7268         emitDispRegSet(byrefRegs);
7269         printf("\n");
7270     }
7271 #endif
7272
7273     assert(argSize % REGSIZE_BYTES == 0);
7274     argCnt = (int)(argSize / (int)REGSIZE_BYTES);
7275
7276     /* Managed RetVal: emit sequence point for the call */
7277     if (emitComp->opts.compDbgInfo && ilOffset != BAD_IL_OFFSET)
7278     {
7279         codeGen->genIPmappingAdd(ilOffset, false);
7280     }
7281
7282     /*
7283         We need to allocate the appropriate instruction descriptor based
7284         on whether this is a direct/indirect call, and whether we need to
7285         record an updated set of live GC variables.
7286      */
7287
7288     if (callType >= EC_INDIR_R)
7289     {
7290         /* Indirect call, virtual calls */
7291
7292         assert(callType == EC_INDIR_R);
7293
7294         id = emitNewInstrCallInd(argCnt, disp, ptrVars, gcrefRegs, byrefRegs, retSize, secondRetSize);
7295     }
7296     else
7297     {
7298         /* Helper/static/nonvirtual/function calls (direct or through handle),
7299            and calls to an absolute addr. */
7300
7301         assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
7302
7303         id = emitNewInstrCallDir(argCnt, ptrVars, gcrefRegs, byrefRegs, retSize, secondRetSize);
7304     }
7305
7306     /* Update the emitter's live GC ref sets */
7307
7308     VarSetOps::Assign(emitComp, emitThisGCrefVars, ptrVars);
7309     emitThisGCrefRegs = gcrefRegs;
7310     emitThisByrefRegs = byrefRegs;
7311
7312     /* Set the instruction - special case jumping a function */
7313     instruction ins;
7314     insFormat   fmt = IF_NONE;
7315
7316     id->idSetIsNoGC(isNoGC);
7317
7318     /* Record the address: method, indirection, or funcptr */
7319
7320     if (callType > EC_FUNC_ADDR)
7321     {
7322         /* This is an indirect call (either a virtual call or func ptr call) */
7323
7324         switch (callType)
7325         {
7326             case EC_INDIR_R: // the address is in a register
7327
7328                 id->idSetIsCallRegPtr();
7329
7330                 if (isJump)
7331                 {
7332                     ins = INS_br_tail; // INS_br_tail  Reg
7333                 }
7334                 else
7335                 {
7336                     ins = INS_blr; // INS_blr Reg
7337                 }
7338                 fmt = IF_BR_1B;
7339
7340                 id->idIns(ins);
7341                 id->idInsFmt(fmt);
7342
7343                 id->idReg3(ireg);
7344                 assert(xreg == REG_NA);
7345                 break;
7346
7347             default:
7348                 NO_WAY("unexpected instruction");
7349                 break;
7350         }
7351     }
7352     else
7353     {
7354         /* This is a simple direct call: "call helper/method/addr" */
7355
7356         assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_ADDR);
7357
7358         assert(addr != NULL);
7359
7360         if (isJump)
7361         {
7362             ins = INS_b_tail; // INS_b_tail imm28
7363         }
7364         else
7365         {
7366             ins = INS_bl; // INS_bl imm28
7367         }
7368         fmt = IF_BI_0C;
7369
7370         id->idIns(ins);
7371         id->idInsFmt(fmt);
7372
7373         id->idAddr()->iiaAddr = (BYTE*)addr;
7374
7375         if (callType == EC_FUNC_ADDR)
7376         {
7377             id->idSetIsCallAddr();
7378         }
7379
7380         if (emitComp->opts.compReloc)
7381         {
7382             id->idSetIsDspReloc();
7383         }
7384     }
7385
7386 #ifdef DEBUG
7387     if (EMIT_GC_VERBOSE)
7388     {
7389         if (id->idIsLargeCall())
7390         {
7391             printf("[%02u] Rec call GC vars = %s\n", id->idDebugOnlyInfo()->idNum,
7392                    VarSetOps::ToString(emitComp, ((instrDescCGCA*)id)->idcGCvars));
7393         }
7394     }
7395
7396     id->idDebugOnlyInfo()->idMemCookie = (size_t)methHnd; // method token
7397     id->idDebugOnlyInfo()->idCallSig   = sigInfo;
7398 #endif // DEBUG
7399
7400 #ifdef LATE_DISASM
7401     if (addr != nullptr)
7402     {
7403         codeGen->getDisAssembler().disSetMethod((size_t)addr, methHnd);
7404     }
7405 #endif // LATE_DISASM
7406
7407     dispIns(id);
7408     appendToCurIG(id);
7409 }
7410
7411 /*****************************************************************************
7412  *
7413  *  Returns true if 'imm' is valid Cond encoding
7414  */
7415
7416 /*static*/ bool emitter::isValidImmCond(ssize_t imm)
7417 {
7418     // range check the ssize_t value, to make sure it is a small unsigned value
7419     // and that only the bits in the cfi.cond are set
7420     if ((imm < 0) || (imm > 0xF))
7421         return false;
7422
7423     condFlagsImm cfi;
7424     cfi.immCFVal = (unsigned)imm;
7425
7426     return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7427 }
7428
7429 /*****************************************************************************
7430  *
7431  *  Returns true if 'imm' is valid Cond/Flags encoding
7432  */
7433
7434 /*static*/ bool emitter::isValidImmCondFlags(ssize_t imm)
7435 {
7436     // range check the ssize_t value, to make sure it is a small unsigned value
7437     // and that only the bits in the cfi.cond or cfi.flags are set
7438     if ((imm < 0) || (imm > 0xFF))
7439         return false;
7440
7441     condFlagsImm cfi;
7442     cfi.immCFVal = (unsigned)imm;
7443
7444     return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7445 }
7446
7447 /*****************************************************************************
7448  *
7449  *  Returns true if 'imm' is valid Cond/Flags/Imm5 encoding
7450  */
7451
7452 /*static*/ bool emitter::isValidImmCondFlagsImm5(ssize_t imm)
7453 {
7454     // range check the ssize_t value, to make sure it is a small unsigned value
7455     // and that only the bits in the cfi.cond, cfi.flags or cfi.imm5 are set
7456     if ((imm < 0) || (imm > 0x1FFF))
7457         return false;
7458
7459     condFlagsImm cfi;
7460     cfi.immCFVal = (unsigned)imm;
7461
7462     return (cfi.cond <= INS_COND_LE); // Don't allow 14 & 15 (AL & NV).
7463 }
7464
7465 /*****************************************************************************
7466  *
7467  *  Returns an encoding for the specified register used in the 'Rd' position
7468  */
7469
7470 /*static*/ emitter::code_t emitter::insEncodeReg_Rd(regNumber reg)
7471 {
7472     assert(isIntegerRegister(reg));
7473     emitter::code_t ureg = (emitter::code_t)reg;
7474     assert((ureg >= 0) && (ureg <= 31));
7475     return ureg;
7476 }
7477
7478 /*****************************************************************************
7479  *
7480  *  Returns an encoding for the specified register used in the 'Rt' position
7481  */
7482
7483 /*static*/ emitter::code_t emitter::insEncodeReg_Rt(regNumber reg)
7484 {
7485     assert(isIntegerRegister(reg));
7486     emitter::code_t ureg = (emitter::code_t)reg;
7487     assert((ureg >= 0) && (ureg <= 31));
7488     return ureg;
7489 }
7490
7491 /*****************************************************************************
7492  *
7493  *  Returns an encoding for the specified register used in the 'Rn' position
7494  */
7495
7496 /*static*/ emitter::code_t emitter::insEncodeReg_Rn(regNumber reg)
7497 {
7498     assert(isIntegerRegister(reg));
7499     emitter::code_t ureg = (emitter::code_t)reg;
7500     assert((ureg >= 0) && (ureg <= 31));
7501     return ureg << 5;
7502 }
7503
7504 /*****************************************************************************
7505  *
7506  *  Returns an encoding for the specified register used in the 'Rm' position
7507  */
7508
7509 /*static*/ emitter::code_t emitter::insEncodeReg_Rm(regNumber reg)
7510 {
7511     assert(isIntegerRegister(reg));
7512     emitter::code_t ureg = (emitter::code_t)reg;
7513     assert((ureg >= 0) && (ureg <= 31));
7514     return ureg << 16;
7515 }
7516
7517 /*****************************************************************************
7518  *
7519  *  Returns an encoding for the specified register used in the 'Ra' position
7520  */
7521
7522 /*static*/ emitter::code_t emitter::insEncodeReg_Ra(regNumber reg)
7523 {
7524     assert(isIntegerRegister(reg));
7525     emitter::code_t ureg = (emitter::code_t)reg;
7526     assert((ureg >= 0) && (ureg <= 31));
7527     return ureg << 10;
7528 }
7529
7530 /*****************************************************************************
7531  *
7532  *  Returns an encoding for the specified register used in the 'Vd' position
7533  */
7534
7535 /*static*/ emitter::code_t emitter::insEncodeReg_Vd(regNumber reg)
7536 {
7537     assert(emitter::isVectorRegister(reg));
7538     emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7539     assert((ureg >= 0) && (ureg <= 31));
7540     return ureg;
7541 }
7542
7543 /*****************************************************************************
7544  *
7545  *  Returns an encoding for the specified register used in the 'Vt' position
7546  */
7547
7548 /*static*/ emitter::code_t emitter::insEncodeReg_Vt(regNumber reg)
7549 {
7550     assert(emitter::isVectorRegister(reg));
7551     emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7552     assert((ureg >= 0) && (ureg <= 31));
7553     return ureg;
7554 }
7555
7556 /*****************************************************************************
7557  *
7558  *  Returns an encoding for the specified register used in the 'Vn' position
7559  */
7560
7561 /*static*/ emitter::code_t emitter::insEncodeReg_Vn(regNumber reg)
7562 {
7563     assert(emitter::isVectorRegister(reg));
7564     emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7565     assert((ureg >= 0) && (ureg <= 31));
7566     return ureg << 5;
7567 }
7568
7569 /*****************************************************************************
7570  *
7571  *  Returns an encoding for the specified register used in the 'Vm' position
7572  */
7573
7574 /*static*/ emitter::code_t emitter::insEncodeReg_Vm(regNumber reg)
7575 {
7576     assert(emitter::isVectorRegister(reg));
7577     emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7578     assert((ureg >= 0) && (ureg <= 31));
7579     return ureg << 16;
7580 }
7581
7582 /*****************************************************************************
7583  *
7584  *  Returns an encoding for the specified register used in the 'Va' position
7585  */
7586
7587 /*static*/ emitter::code_t emitter::insEncodeReg_Va(regNumber reg)
7588 {
7589     assert(emitter::isVectorRegister(reg));
7590     emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_V0;
7591     assert((ureg >= 0) && (ureg <= 31));
7592     return ureg << 10;
7593 }
7594
7595 /*****************************************************************************
7596  *
7597  *  Returns an encoding for the specified condition code.
7598  */
7599
7600 /*static*/ emitter::code_t emitter::insEncodeCond(insCond cond)
7601 {
7602     emitter::code_t uimm = (emitter::code_t)cond;
7603     return uimm << 12;
7604 }
7605
7606 /*****************************************************************************
7607  *
7608  *  Returns an encoding for the condition code with the lowest bit inverted (marked by invert(<cond>) in the
7609  *  architecture manual).
7610  */
7611
7612 /*static*/ emitter::code_t emitter::insEncodeInvertedCond(insCond cond)
7613 {
7614     emitter::code_t uimm = (emitter::code_t)cond;
7615     uimm ^= 1; // invert the lowest bit
7616     return uimm << 12;
7617 }
7618
7619 /*****************************************************************************
7620  *
7621  *  Returns an encoding for the specified flags.
7622  */
7623
7624 /*static*/ emitter::code_t emitter::insEncodeFlags(insCflags flags)
7625 {
7626     emitter::code_t uimm = (emitter::code_t)flags;
7627     return uimm;
7628 }
7629
7630 /*****************************************************************************
7631  *
7632  *  Returns the encoding for the Shift Count bits to be used for Arm64 encodings
7633  */
7634
7635 /*static*/ emitter::code_t emitter::insEncodeShiftCount(ssize_t imm, emitAttr size)
7636 {
7637     assert((imm & 0x003F) == imm);
7638     assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
7639
7640     return (emitter::code_t)imm << 10;
7641 }
7642
7643 /*****************************************************************************
7644  *
7645  *  Returns the encoding to select a 64-bit datasize for an Arm64 instruction
7646  */
7647
7648 /*static*/ emitter::code_t emitter::insEncodeDatasize(emitAttr size)
7649 {
7650     if (size == EA_8BYTE)
7651     {
7652         return 0x80000000; // set the bit at location 31
7653     }
7654     else
7655     {
7656         assert(size == EA_4BYTE);
7657         return 0;
7658     }
7659 }
7660
7661 /*****************************************************************************
7662  *
7663  *  Returns the encoding to select the datasize for the general load/store Arm64 instructions
7664  *
7665  */
7666
7667 /*static*/ emitter::code_t emitter::insEncodeDatasizeLS(emitter::code_t code, emitAttr size)
7668 {
7669     bool exclusive = ((code & 0x35000000) == 0);
7670
7671     if ((code & 0x00800000) && !exclusive) // Is this a sign-extending opcode? (i.e. ldrsw, ldrsh, ldrsb)
7672     {
7673         if ((code & 0x80000000) == 0) // Is it a ldrsh or ldrsb and not ldrsw ?
7674         {
7675             if (EA_SIZE(size) != EA_8BYTE) // Do we need to encode the 32-bit Rt size bit?
7676             {
7677                 return 0x00400000; // set the bit at location 22
7678             }
7679         }
7680     }
7681     else if (code & 0x80000000) // Is this a ldr/str/ldur/stur opcode?
7682     {
7683         if (EA_SIZE(size) == EA_8BYTE) // Do we need to encode the 64-bit size bit?
7684         {
7685             return 0x40000000; // set the bit at location 30
7686         }
7687     }
7688     return 0;
7689 }
7690
7691 /*****************************************************************************
7692  *
7693  *  Returns the encoding to select the datasize for the vector load/store Arm64 instructions
7694  *
7695  */
7696
7697 /*static*/ emitter::code_t emitter::insEncodeDatasizeVLS(emitter::code_t code, emitAttr size)
7698 {
7699     code_t result = 0;
7700
7701     // Check bit 29
7702     if ((code & 0x20000000) == 0)
7703     {
7704         // LDR literal
7705
7706         if (size == EA_16BYTE)
7707         {
7708             // set the operation size in bit 31
7709             result = 0x80000000;
7710         }
7711         else if (size == EA_8BYTE)
7712         {
7713             // set the operation size in bit 30
7714             result = 0x40000000;
7715         }
7716         else
7717         {
7718             assert(size == EA_4BYTE);
7719             // no bits are set
7720             result = 0x00000000;
7721         }
7722     }
7723     else
7724     {
7725         // LDR non-literal
7726
7727         if (size == EA_16BYTE)
7728         {
7729             // The operation size in bits 31 and 30 are zero
7730             // Bit 23 specifies a 128-bit Load/Store
7731             result = 0x00800000;
7732         }
7733         else if (size == EA_8BYTE)
7734         {
7735             // set the operation size in bits 31 and 30
7736             result = 0xC0000000;
7737         }
7738         else if (size == EA_4BYTE)
7739         {
7740             // set the operation size in bit 31
7741             result = 0x80000000;
7742         }
7743         else if (size == EA_2BYTE)
7744         {
7745             // set the operation size in bit 30
7746             result = 0x40000000;
7747         }
7748         else
7749         {
7750             assert(size == EA_1BYTE);
7751             // The operation size in bits 31 and 30 are zero
7752             result = 0x00000000;
7753         }
7754     }
7755
7756     // Or in bit 26 to indicate a Vector register is used as 'target'
7757     result |= 0x04000000;
7758
7759     return result;
7760 }
7761
7762 /*****************************************************************************
7763  *
7764  *  Returns the encoding to select the datasize for the vector load/store Arm64 instructions
7765  *
7766  */
7767
7768 /*static*/ emitter::code_t emitter::insEncodeDatasizeVPLS(emitter::code_t code, emitAttr size)
7769 {
7770     code_t result = 0;
7771
7772     if (size == EA_16BYTE)
7773     {
7774         // The operation size in bits 31 and 30 are zero
7775         // Bit 23 specifies a 128-bit Load/Store
7776         result = 0x80000000;
7777     }
7778     else if (size == EA_8BYTE)
7779     {
7780         // set the operation size in bits 31 and 30
7781         result = 0x40000000;
7782     }
7783     else if (size == EA_4BYTE)
7784     {
7785         // set the operation size in bit 31
7786         result = 0x00000000;
7787     }
7788
7789     // Or in bit 26 to indicate a Vector register is used as 'target'
7790     result |= 0x04000000;
7791
7792     return result;
7793 }
7794
7795 /*****************************************************************************
7796  *
7797  *  Returns the encoding to set the size bit and the N bits for a 'bitfield' instruction
7798  *
7799  */
7800
7801 /*static*/ emitter::code_t emitter::insEncodeDatasizeBF(emitter::code_t code, emitAttr size)
7802 {
7803     // is bit 30 equal to 0?
7804     if ((code & 0x40000000) == 0) // is the opcode one of extr, sxtb, sxth or sxtw
7805     {
7806         if (size == EA_8BYTE) // Do we need to set the sf and N bits?
7807         {
7808             return 0x80400000; // set the sf-bit at location 31 and the N-bit at location 22
7809         }
7810     }
7811     return 0; // don't set any bits
7812 }
7813
7814 /*****************************************************************************
7815  *
7816  *  Returns the encoding to select the 64/128-bit datasize for an Arm64 vector instruction
7817  */
7818
7819 /*static*/ emitter::code_t emitter::insEncodeVectorsize(emitAttr size)
7820 {
7821     if (size == EA_16BYTE)
7822     {
7823         return 0x40000000; // set the bit at location 30
7824     }
7825     else
7826     {
7827         assert(size == EA_8BYTE);
7828         return 0;
7829     }
7830 }
7831
7832 /*****************************************************************************
7833  *
7834  *  Returns the encoding to select 'index' for an Arm64 vector elem instruction
7835  */
7836 /*static*/ emitter::code_t emitter::insEncodeVectorIndex(emitAttr elemsize, ssize_t index)
7837 {
7838     code_t bits = (code_t)index;
7839     if (elemsize == EA_1BYTE)
7840     {
7841         bits <<= 1;
7842         bits |= 1;
7843     }
7844     else if (elemsize == EA_2BYTE)
7845     {
7846         bits <<= 2;
7847         bits |= 2;
7848     }
7849     else if (elemsize == EA_4BYTE)
7850     {
7851         bits <<= 3;
7852         bits |= 4;
7853     }
7854     else
7855     {
7856         assert(elemsize == EA_8BYTE);
7857         bits <<= 4;
7858         bits |= 8;
7859     }
7860     assert((bits >= 1) && (bits <= 0x1f));
7861
7862     return (bits << 16); // bits at locations [20,19,18,17,16]
7863 }
7864
7865 /*****************************************************************************
7866  *
7867  *  Returns the encoding to select 'index2' for an Arm64 'ins' elem instruction
7868  */
7869 /*static*/ emitter::code_t emitter::insEncodeVectorIndex2(emitAttr elemsize, ssize_t index2)
7870 {
7871     code_t bits = (code_t)index2;
7872     if (elemsize == EA_1BYTE)
7873     {
7874         // bits are correct
7875     }
7876     else if (elemsize == EA_2BYTE)
7877     {
7878         bits <<= 1;
7879     }
7880     else if (elemsize == EA_4BYTE)
7881     {
7882         bits <<= 2;
7883     }
7884     else
7885     {
7886         assert(elemsize == EA_8BYTE);
7887         bits <<= 3;
7888     }
7889     assert((bits >= 0) && (bits <= 0xf));
7890
7891     return (bits << 11); // bits at locations [14,13,12,11]
7892 }
7893
7894 /*****************************************************************************
7895  *
7896  *  Returns the encoding to select the 'index' for an Arm64 'mul' by elem instruction
7897  */
7898 /*static*/ emitter::code_t emitter::insEncodeVectorIndexLMH(emitAttr elemsize, ssize_t index)
7899 {
7900     code_t bits = 0;
7901
7902     if (elemsize == EA_2BYTE)
7903     {
7904         assert((index >= 0) && (index <= 7));
7905         if (index & 0x4)
7906         {
7907             bits |= (1 << 11); // set bit 11 'H'
7908         }
7909         if (index & 0x2)
7910         {
7911             bits |= (1 << 21); // set bit 21 'L'
7912         }
7913         if (index & 0x1)
7914         {
7915             bits |= (1 << 20); // set bit 20 'M'
7916         }
7917     }
7918     else if (elemsize == EA_4BYTE)
7919     {
7920         assert((index >= 0) && (index <= 3));
7921         if (index & 0x2)
7922         {
7923             bits |= (1 << 11); // set bit 11 'H'
7924         }
7925         if (index & 0x1)
7926         {
7927             bits |= (1 << 21); // set bit 21 'L'
7928         }
7929     }
7930     else
7931     {
7932         assert(!"Invalid 'elemsize' value");
7933     }
7934
7935     return bits;
7936 }
7937
7938 /*****************************************************************************
7939  *
7940  *   Returns the encoding to shift by 'shift' for an Arm64 vector or scalar instruction
7941  */
7942
7943 /*static*/ emitter::code_t emitter::insEncodeVectorShift(emitAttr size, ssize_t shift)
7944 {
7945     assert(shift < getBitWidth(size));
7946
7947     code_t imm = (code_t)(getBitWidth(size) + shift);
7948
7949     return imm << 16;
7950 }
7951
7952 /*****************************************************************************
7953  *
7954  *  Returns the encoding to select the 1/2/4/8 byte elemsize for an Arm64 vector instruction
7955  */
7956
7957 /*static*/ emitter::code_t emitter::insEncodeElemsize(emitAttr size)
7958 {
7959     if (size == EA_8BYTE)
7960     {
7961         return 0x00C00000; // set the bit at location 23 and 22
7962     }
7963     else if (size == EA_4BYTE)
7964     {
7965         return 0x00800000; // set the bit at location 23
7966     }
7967     else if (size == EA_2BYTE)
7968     {
7969         return 0x00400000; // set the bit at location 22
7970     }
7971     assert(size == EA_1BYTE);
7972     return 0x00000000;
7973 }
7974
7975 /*****************************************************************************
7976  *
7977  *  Returns the encoding to select the 4/8 byte elemsize for an Arm64 float vector instruction
7978  */
7979
7980 /*static*/ emitter::code_t emitter::insEncodeFloatElemsize(emitAttr size)
7981 {
7982     if (size == EA_8BYTE)
7983     {
7984         return 0x00400000; // set the bit at location 22
7985     }
7986     assert(size == EA_4BYTE);
7987     return 0x00000000;
7988 }
7989
7990 // Returns the encoding to select the index for an Arm64 float vector by elem instruction
7991 /*static*/ emitter::code_t emitter::insEncodeFloatIndex(emitAttr elemsize, ssize_t index)
7992 {
7993     code_t result = 0x00000000;
7994     if (elemsize == EA_8BYTE)
7995     {
7996         assert((index >= 0) && (index <= 1));
7997         if (index == 1)
7998         {
7999             result |= 0x00000800; // 'H' - set the bit at location 11
8000         }
8001     }
8002     else
8003     {
8004         assert(elemsize == EA_4BYTE);
8005         assert((index >= 0) && (index <= 3));
8006         if (index & 2)
8007         {
8008             result |= 0x00000800; // 'H' - set the bit at location 11
8009         }
8010         if (index & 1)
8011         {
8012             result |= 0x00200000; // 'L' - set the bit at location 21
8013         }
8014     }
8015     return result;
8016 }
8017
8018 /*****************************************************************************
8019  *
8020  *  Returns the encoding to select the fcvt operation for Arm64 instructions
8021  */
8022 /*static*/ emitter::code_t emitter::insEncodeConvertOpt(insFormat fmt, insOpts conversion)
8023 {
8024     code_t result = 0;
8025     switch (conversion)
8026     {
8027         case INS_OPTS_S_TO_D: // Single to Double
8028             assert(fmt == IF_DV_2J);
8029             result = 0x00008000; // type=00, opc=01
8030             break;
8031
8032         case INS_OPTS_D_TO_S: // Double to Single
8033             assert(fmt == IF_DV_2J);
8034             result = 0x00400000; // type=01, opc=00
8035             break;
8036
8037         case INS_OPTS_H_TO_S: // Half to Single
8038             assert(fmt == IF_DV_2J);
8039             result = 0x00C00000; // type=11, opc=00
8040             break;
8041
8042         case INS_OPTS_H_TO_D: // Half to Double
8043             assert(fmt == IF_DV_2J);
8044             result = 0x00C08000; // type=11, opc=01
8045             break;
8046
8047         case INS_OPTS_S_TO_H: // Single to Half
8048             assert(fmt == IF_DV_2J);
8049             result = 0x00018000; // type=00, opc=11
8050             break;
8051
8052         case INS_OPTS_D_TO_H: // Double to Half
8053             assert(fmt == IF_DV_2J);
8054             result = 0x00418000; // type=01, opc=11
8055             break;
8056
8057         case INS_OPTS_S_TO_4BYTE: // Single to INT32
8058             assert(fmt == IF_DV_2H);
8059             result = 0x00000000; // sf=0, type=00
8060             break;
8061
8062         case INS_OPTS_D_TO_4BYTE: // Double to INT32
8063             assert(fmt == IF_DV_2H);
8064             result = 0x00400000; // sf=0, type=01
8065             break;
8066
8067         case INS_OPTS_S_TO_8BYTE: // Single to INT64
8068             assert(fmt == IF_DV_2H);
8069             result = 0x80000000; // sf=1, type=00
8070             break;
8071
8072         case INS_OPTS_D_TO_8BYTE: // Double to INT64
8073             assert(fmt == IF_DV_2H);
8074             result = 0x80400000; // sf=1, type=01
8075             break;
8076
8077         case INS_OPTS_4BYTE_TO_S: // INT32 to Single
8078             assert(fmt == IF_DV_2I);
8079             result = 0x00000000; // sf=0, type=00
8080             break;
8081
8082         case INS_OPTS_4BYTE_TO_D: // INT32 to Double
8083             assert(fmt == IF_DV_2I);
8084             result = 0x00400000; // sf=0, type=01
8085             break;
8086
8087         case INS_OPTS_8BYTE_TO_S: // INT64 to Single
8088             assert(fmt == IF_DV_2I);
8089             result = 0x80000000; // sf=1, type=00
8090             break;
8091
8092         case INS_OPTS_8BYTE_TO_D: // INT64 to Double
8093             assert(fmt == IF_DV_2I);
8094             result = 0x80400000; // sf=1, type=01
8095             break;
8096
8097         default:
8098             assert(!"Invalid 'conversion' value");
8099             break;
8100     }
8101     return result;
8102 }
8103
8104 /*****************************************************************************
8105  *
8106  *  Returns the encoding to have the Rn register be updated Pre/Post indexed
8107  *  or not updated
8108  */
8109
8110 /*static*/ emitter::code_t emitter::insEncodeIndexedOpt(insOpts opt)
8111 {
8112     assert(emitter::insOptsNone(opt) || emitter::insOptsIndexed(opt));
8113
8114     if (emitter::insOptsIndexed(opt))
8115     {
8116         if (emitter::insOptsPostIndex(opt))
8117         {
8118             return 0x00000400; // set the bit at location 10
8119         }
8120         else
8121         {
8122             assert(emitter::insOptsPreIndex(opt));
8123             return 0x00000C00; // set the bit at location 10 and 11
8124         }
8125     }
8126     else
8127     {
8128         assert(emitter::insOptsNone(opt));
8129         return 0; // bits 10 and 11 are zero
8130     }
8131 }
8132
8133 /*****************************************************************************
8134  *
8135  *  Returns the encoding for a ldp/stp instruction to have the Rn register
8136  *  be updated Pre/Post indexed or not updated
8137  */
8138
8139 /*static*/ emitter::code_t emitter::insEncodePairIndexedOpt(instruction ins, insOpts opt)
8140 {
8141     assert(emitter::insOptsNone(opt) || emitter::insOptsIndexed(opt));
8142
8143     if ((ins == INS_ldnp) || (ins == INS_stnp))
8144     {
8145         assert(emitter::insOptsNone(opt));
8146         return 0; // bits 23 and 24 are zero
8147     }
8148     else
8149     {
8150         if (emitter::insOptsIndexed(opt))
8151         {
8152             if (emitter::insOptsPostIndex(opt))
8153             {
8154                 return 0x00800000; // set the bit at location 23
8155             }
8156             else
8157             {
8158                 assert(emitter::insOptsPreIndex(opt));
8159                 return 0x01800000; // set the bit at location 24 and 23
8160             }
8161         }
8162         else
8163         {
8164             assert(emitter::insOptsNone(opt));
8165             return 0x01000000; // set the bit at location 24
8166         }
8167     }
8168 }
8169
8170 /*****************************************************************************
8171  *
8172  *  Returns the encoding to apply a Shift Type on the Rm register
8173  */
8174
8175 /*static*/ emitter::code_t emitter::insEncodeShiftType(insOpts opt)
8176 {
8177     if (emitter::insOptsNone(opt))
8178     {
8179         // None implies the we encode LSL (with a zero immediate)
8180         opt = INS_OPTS_LSL;
8181     }
8182     assert(emitter::insOptsAnyShift(opt));
8183
8184     emitter::code_t option = (emitter::code_t)opt - (emitter::code_t)INS_OPTS_LSL;
8185     assert(option <= 3);
8186
8187     return option << 22; // bits 23, 22
8188 }
8189
8190 /*****************************************************************************
8191  *
8192  *  Returns the encoding to apply a 12 bit left shift to the immediate
8193  */
8194
8195 /*static*/ emitter::code_t emitter::insEncodeShiftImm12(insOpts opt)
8196 {
8197     if (emitter::insOptsLSL12(opt))
8198     {
8199         return 0x00400000; // set the bit at location 22
8200     }
8201     return 0;
8202 }
8203
8204 /*****************************************************************************
8205  *
8206  *  Returns the encoding to have the Rm register use an extend operation
8207  */
8208
8209 /*static*/ emitter::code_t emitter::insEncodeExtend(insOpts opt)
8210 {
8211     if (emitter::insOptsNone(opt) || (opt == INS_OPTS_LSL))
8212     {
8213         // None or LSL implies the we encode UXTX
8214         opt = INS_OPTS_UXTX;
8215     }
8216     assert(emitter::insOptsAnyExtend(opt));
8217
8218     emitter::code_t option = (emitter::code_t)opt - (emitter::code_t)INS_OPTS_UXTB;
8219     assert(option <= 7);
8220
8221     return option << 13; // bits 15,14,13
8222 }
8223
8224 /*****************************************************************************
8225  *
8226  *  Returns the encoding to scale the Rm register by {0,1,2,3,4}
8227  *  when using an extend operation
8228  */
8229
8230 /*static*/ emitter::code_t emitter::insEncodeExtendScale(ssize_t imm)
8231 {
8232     assert((imm >= 0) && (imm <= 4));
8233
8234     return (emitter::code_t)imm << 10; // bits 12,11,10
8235 }
8236
8237 /*****************************************************************************
8238  *
8239  *  Returns the encoding to have the Rm register be auto scaled by the ld/st size
8240  */
8241
8242 /*static*/ emitter::code_t emitter::insEncodeReg3Scale(bool isScaled)
8243 {
8244     if (isScaled)
8245     {
8246         return 0x00001000; // set the bit at location 12
8247     }
8248     else
8249     {
8250         return 0;
8251     }
8252 }
8253
8254 BYTE* emitter::emitOutputLoadLabel(BYTE* dst, BYTE* srcAddr, BYTE* dstAddr, instrDescJmp* id)
8255 {
8256     instruction ins    = id->idIns();
8257     insFormat   fmt    = id->idInsFmt();
8258     regNumber   dstReg = id->idReg1();
8259     if (id->idjShort)
8260     {
8261         // adr x, [rel addr] --  compute address: current addr(ip) + rel addr.
8262         assert(ins == INS_adr);
8263         assert(fmt == IF_DI_1E);
8264         ssize_t distVal = (ssize_t)(dstAddr - srcAddr);
8265         dst             = emitOutputShortAddress(dst, ins, fmt, distVal, dstReg);
8266     }
8267     else
8268     {
8269         // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8270         assert(fmt == IF_LARGEADR);
8271         ssize_t relPageAddr =
8272             (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8273         dst = emitOutputShortAddress(dst, INS_adrp, IF_DI_1E, relPageAddr, dstReg);
8274
8275         // add x, x, page offs -- compute address = page addr + page offs
8276         ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8277         assert(isValidUimm12(imm12));
8278         code_t code =
8279             emitInsCode(INS_add, IF_DI_2A);  // DI_2A  X0010001shiiiiii iiiiiinnnnnddddd   1100 0000   imm(i12, sh)
8280         code |= insEncodeDatasize(EA_8BYTE); // X
8281         code |= ((code_t)imm12 << 10);       // iiiiiiiiiiii
8282         code |= insEncodeReg_Rd(dstReg);     // ddddd
8283         code |= insEncodeReg_Rn(dstReg);     // nnnnn
8284         dst += emitOutput_Instr(dst, code);
8285     }
8286     return dst;
8287 }
8288
8289 /*****************************************************************************
8290  *
8291  *  Output a local jump or other instruction with a pc-relative immediate.
8292  *  Note that this may be invoked to overwrite an existing jump instruction at 'dst'
8293  *  to handle forward branch patching.
8294  */
8295
8296 BYTE* emitter::emitOutputLJ(insGroup* ig, BYTE* dst, instrDesc* i)
8297 {
8298     instrDescJmp* id = (instrDescJmp*)i;
8299
8300     unsigned srcOffs;
8301     unsigned dstOffs;
8302     BYTE*    srcAddr;
8303     BYTE*    dstAddr;
8304     ssize_t  distVal;
8305     ssize_t  loBits;
8306
8307     // Set default ins/fmt from id.
8308     instruction ins = id->idIns();
8309     insFormat   fmt = id->idInsFmt();
8310
8311     bool loadLabel    = false;
8312     bool isJump       = false;
8313     bool loadConstant = false;
8314
8315     switch (ins)
8316     {
8317         default:
8318             isJump = true;
8319             break;
8320
8321         case INS_tbz:
8322         case INS_tbnz:
8323         case INS_cbz:
8324         case INS_cbnz:
8325             isJump = true;
8326             break;
8327
8328         case INS_ldr:
8329         case INS_ldrsw:
8330             loadConstant = true;
8331             break;
8332
8333         case INS_adr:
8334         case INS_adrp:
8335             loadLabel = true;
8336             break;
8337     }
8338
8339     /* Figure out the distance to the target */
8340
8341     srcOffs = emitCurCodeOffs(dst);
8342     srcAddr = emitOffsetToPtr(srcOffs);
8343
8344     if (id->idAddr()->iiaIsJitDataOffset())
8345     {
8346         assert(loadConstant || loadLabel);
8347         int doff = id->idAddr()->iiaGetJitDataOffset();
8348         assert(doff >= 0);
8349         ssize_t imm = emitGetInsSC(id);
8350         assert((imm >= 0) && (imm < 0x1000)); // 0x1000 is arbitrary, currently 'imm' is always 0
8351
8352         unsigned dataOffs = (unsigned)(doff + imm);
8353         assert(dataOffs < emitDataSize());
8354         dstAddr = emitDataOffsetToPtr(dataOffs);
8355
8356         regNumber dstReg  = id->idReg1();
8357         regNumber addrReg = dstReg; // an integer register to compute long address.
8358         emitAttr  opSize  = id->idOpSize();
8359
8360         if (loadConstant)
8361         {
8362             if (id->idjShort)
8363             {
8364                 // ldr x/v, [rel addr] -- load constant from current addr(ip) + rel addr.
8365                 assert(ins == INS_ldr);
8366                 assert(fmt == IF_LS_1A);
8367                 distVal = (ssize_t)(dstAddr - srcAddr);
8368                 dst     = emitOutputShortConstant(dst, ins, fmt, distVal, dstReg, opSize);
8369             }
8370             else
8371             {
8372                 // adrp x, [rel page addr] -- compute page address: current page addr + rel page addr
8373                 assert(fmt == IF_LARGELDC);
8374                 ssize_t relPageAddr =
8375                     (((ssize_t)dstAddr & 0xFFFFFFFFFFFFF000LL) - ((ssize_t)srcAddr & 0xFFFFFFFFFFFFF000LL)) >> 12;
8376                 if (isVectorRegister(dstReg))
8377                 {
8378                     // Update addrReg with the reserved integer register
8379                     // since we cannot use dstReg (vector) to load constant directly from memory.
8380                     addrReg = id->idReg2();
8381                     assert(isGeneralRegister(addrReg));
8382                 }
8383                 ins = INS_adrp;
8384                 fmt = IF_DI_1E;
8385                 dst = emitOutputShortAddress(dst, ins, fmt, relPageAddr, addrReg);
8386
8387                 // ldr x, [x, page offs] -- load constant from page address + page offset into integer register.
8388                 ssize_t imm12 = (ssize_t)dstAddr & 0xFFF; // 12 bits
8389                 assert(isValidUimm12(imm12));
8390                 ins = INS_ldr;
8391                 fmt = IF_LS_2B;
8392                 dst = emitOutputShortConstant(dst, ins, fmt, imm12, addrReg, opSize);
8393
8394                 // fmov v, d -- copy constant in integer register to vector register.
8395                 // This is needed only for vector constant.
8396                 if (addrReg != dstReg)
8397                 {
8398                     //  fmov    Vd,Rn                DV_2I  X00111100X100111 000000nnnnnddddd   1E27 0000   Vd,Rn
8399                     //  (scalar, from general)
8400                     assert(isVectorRegister(dstReg) && isGeneralRegister(addrReg));
8401                     ins         = INS_fmov;
8402                     fmt         = IF_DV_2I;
8403                     code_t code = emitInsCode(ins, fmt);
8404
8405                     code |= insEncodeReg_Vd(dstReg);  // ddddd
8406                     code |= insEncodeReg_Rn(addrReg); // nnnnn
8407                     if (id->idOpSize() == EA_8BYTE)
8408                     {
8409                         code |= 0x80400000; // X ... X
8410                     }
8411                     dst += emitOutput_Instr(dst, code);
8412                 }
8413             }
8414         }
8415         else
8416         {
8417             assert(loadLabel);
8418             dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8419         }
8420
8421         return dst;
8422     }
8423
8424     assert(loadLabel || isJump);
8425
8426     if (id->idAddr()->iiaHasInstrCount())
8427     {
8428         assert(ig != NULL);
8429         int      instrCount = id->idAddr()->iiaGetInstrCount();
8430         unsigned insNum     = emitFindInsNum(ig, id);
8431         if (instrCount < 0)
8432         {
8433             // Backward branches using instruction count must be within the same instruction group.
8434             assert(insNum + 1 >= (unsigned)(-instrCount));
8435         }
8436         dstOffs = ig->igOffs + emitFindOffset(ig, (insNum + 1 + instrCount));
8437         dstAddr = emitOffsetToPtr(dstOffs);
8438     }
8439     else
8440     {
8441         dstOffs = id->idAddr()->iiaIGlabel->igOffs;
8442         dstAddr = emitOffsetToPtr(dstOffs);
8443     }
8444
8445     distVal = (ssize_t)(dstAddr - srcAddr);
8446
8447     if (dstOffs <= srcOffs)
8448     {
8449 #if DEBUG_EMIT
8450         /* This is a backward jump - distance is known at this point */
8451
8452         if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8453         {
8454             size_t blkOffs = id->idjIG->igOffs;
8455
8456             if (INTERESTING_JUMP_NUM == 0)
8457                 printf("[3] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8458             printf("[3] Jump  block is at %08X - %02X = %08X\n", blkOffs, emitOffsAdj, blkOffs - emitOffsAdj);
8459             printf("[3] Jump        is at %08X - %02X = %08X\n", srcOffs, emitOffsAdj, srcOffs - emitOffsAdj);
8460             printf("[3] Label block is at %08X - %02X = %08X\n", dstOffs, emitOffsAdj, dstOffs - emitOffsAdj);
8461         }
8462 #endif
8463     }
8464     else
8465     {
8466         /* This is a  forward jump - distance will be an upper limit */
8467
8468         emitFwdJumps = true;
8469
8470         /* The target offset will be closer by at least 'emitOffsAdj', but only if this
8471            jump doesn't cross the hot-cold boundary. */
8472
8473         if (!emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8474         {
8475             dstOffs -= emitOffsAdj;
8476             distVal -= emitOffsAdj;
8477         }
8478
8479         /* Record the location of the jump for later patching */
8480
8481         id->idjOffs = dstOffs;
8482
8483         /* Are we overflowing the id->idjOffs bitfield? */
8484         if (id->idjOffs != dstOffs)
8485             IMPL_LIMITATION("Method is too large");
8486
8487 #if DEBUG_EMIT
8488         if (id->idDebugOnlyInfo()->idNum == (unsigned)INTERESTING_JUMP_NUM || INTERESTING_JUMP_NUM == 0)
8489         {
8490             size_t blkOffs = id->idjIG->igOffs;
8491
8492             if (INTERESTING_JUMP_NUM == 0)
8493                 printf("[4] Jump %u:\n", id->idDebugOnlyInfo()->idNum);
8494             printf("[4] Jump  block is at %08X\n", blkOffs);
8495             printf("[4] Jump        is at %08X\n", srcOffs);
8496             printf("[4] Label block is at %08X - %02X = %08X\n", dstOffs + emitOffsAdj, emitOffsAdj, dstOffs);
8497         }
8498 #endif
8499     }
8500
8501 #ifdef DEBUG
8502     if (0 && emitComp->verbose)
8503     {
8504         size_t sz          = 4;
8505         int    distValSize = id->idjShort ? 4 : 8;
8506         printf("; %s jump [%08X/%03u] from %0*X to %0*X: dist = %08XH\n", (dstOffs <= srcOffs) ? "Fwd" : "Bwd",
8507                dspPtr(id), id->idDebugOnlyInfo()->idNum, distValSize, srcOffs + sz, distValSize, dstOffs, distVal);
8508     }
8509 #endif
8510
8511     /* For forward jumps, record the address of the distance value */
8512     id->idjTemp.idjAddr = (distVal > 0) ? dst : NULL;
8513
8514     if (emitJumpCrossHotColdBoundary(srcOffs, dstOffs))
8515     {
8516         assert(!id->idjShort);
8517         NYI_ARM64("Relocation Support for long address");
8518     }
8519
8520     assert(insOptsNone(id->idInsOpt()));
8521
8522     if (isJump)
8523     {
8524         if (id->idjShort)
8525         {
8526             // Short conditional/unconditional jump
8527             assert(!id->idjKeepLong);
8528             assert(emitJumpCrossHotColdBoundary(srcOffs, dstOffs) == false);
8529             assert((fmt == IF_BI_0A) || (fmt == IF_BI_0B) || (fmt == IF_BI_1A) || (fmt == IF_BI_1B));
8530         }
8531         else
8532         {
8533             // Long conditional jump
8534             assert(fmt == IF_LARGEJMP);
8535             // This is a pseudo-instruction format representing a large conditional branch, to allow
8536             // us to get a greater branch target range than we can get by using a straightforward conditional
8537             // branch. It is encoded as a short conditional branch that branches around a long unconditional
8538             // branch.
8539             //
8540             // Conceptually, we have:
8541             //
8542             //      b<cond> L_target
8543             //
8544             // The code we emit is:
8545             //
8546             //      b<!cond> L_not  // 4 bytes. Note that we reverse the condition.
8547             //      b L_target      // 4 bytes
8548             //   L_not:
8549             //
8550             // Note that we don't actually insert any blocks: we simply encode "b <!cond> L_not" as a branch with
8551             // the correct offset. Note also that this works for both integer and floating-point conditions, because
8552             // the condition inversion takes ordered/unordered into account, preserving NaN behavior. For example,
8553             // "GT" (greater than) is inverted to "LE" (less than, equal, or unordered).
8554
8555             instruction reverseIns;
8556             insFormat   reverseFmt;
8557
8558             switch (ins)
8559             {
8560                 case INS_cbz:
8561                     reverseIns = INS_cbnz;
8562                     reverseFmt = IF_BI_1A;
8563                     break;
8564                 case INS_cbnz:
8565                     reverseIns = INS_cbz;
8566                     reverseFmt = IF_BI_1A;
8567                     break;
8568                 case INS_tbz:
8569                     reverseIns = INS_tbnz;
8570                     reverseFmt = IF_BI_1B;
8571                     break;
8572                 case INS_tbnz:
8573                     reverseIns = INS_tbz;
8574                     reverseFmt = IF_BI_1B;
8575                     break;
8576                 default:
8577                     reverseIns = emitJumpKindToIns(emitReverseJumpKind(emitInsToJumpKind(ins)));
8578                     reverseFmt = IF_BI_0B;
8579             }
8580
8581             dst =
8582                 emitOutputShortBranch(dst,
8583                                       reverseIns, // reverse the conditional instruction
8584                                       reverseFmt,
8585                                       8, /* 8 bytes from start of this large conditional pseudo-instruction to L_not. */
8586                                       id);
8587
8588             // Now, pretend we've got a normal unconditional branch, and fall through to the code to emit that.
8589             ins = INS_b;
8590             fmt = IF_BI_0A;
8591
8592             // The distVal was computed based on the beginning of the pseudo-instruction,
8593             // So subtract the size of the conditional branch so that it is relative to the
8594             // unconditional branch.
8595             distVal -= 4;
8596         }
8597
8598         dst = emitOutputShortBranch(dst, ins, fmt, distVal, id);
8599     }
8600     else if (loadLabel)
8601     {
8602         dst = emitOutputLoadLabel(dst, srcAddr, dstAddr, id);
8603     }
8604
8605     return dst;
8606 }
8607
8608 /*****************************************************************************
8609 *
8610 *  Output a short branch instruction.
8611 */
8612 BYTE* emitter::emitOutputShortBranch(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, instrDescJmp* id)
8613 {
8614     code_t code = emitInsCode(ins, fmt);
8615
8616     ssize_t loBits = (distVal & 3);
8617     noway_assert(loBits == 0);
8618     distVal >>= 2; // branch offset encodings are scaled by 4.
8619
8620     if (fmt == IF_BI_0A)
8621     {
8622         // INS_b or INS_bl_local
8623         noway_assert(isValidSimm26(distVal));
8624         distVal &= 0x3FFFFFFLL;
8625         code |= distVal;
8626     }
8627     else if (fmt == IF_BI_0B) // BI_0B   01010100iiiiiiii iiiiiiiiiiiXXXXX      simm19:00
8628     {
8629         // INS_beq, INS_bne, etc...
8630         noway_assert(isValidSimm19(distVal));
8631         distVal &= 0x7FFFFLL;
8632         code |= distVal << 5;
8633     }
8634     else if (fmt == IF_BI_1A) // BI_1A   X.......iiiiiiii iiiiiiiiiiittttt      Rt simm19:00
8635     {
8636         // INS_cbz or INS_cbnz
8637         assert(id != nullptr);
8638         code |= insEncodeDatasize(id->idOpSize()); // X
8639         code |= insEncodeReg_Rt(id->idReg1());     // ttttt
8640
8641         noway_assert(isValidSimm19(distVal));
8642         distVal &= 0x7FFFFLL; // 19 bits
8643         code |= distVal << 5;
8644     }
8645     else if (fmt == IF_BI_1B) // BI_1B   B.......bbbbbiii iiiiiiiiiiittttt      Rt imm6, simm14:00
8646     {
8647         // INS_tbz or INS_tbnz
8648         assert(id != nullptr);
8649         ssize_t imm = emitGetInsSC(id);
8650         assert(isValidImmShift(imm, id->idOpSize()));
8651
8652         if (imm & 0x20) // test bit 32-63 ?
8653         {
8654             code |= 0x80000000; // B
8655         }
8656         code |= ((imm & 0x1F) << 19);          // bbbbb
8657         code |= insEncodeReg_Rt(id->idReg1()); // ttttt
8658
8659         noway_assert(isValidSimm14(distVal));
8660         distVal &= 0x3FFFLL; // 14 bits
8661         code |= distVal << 5;
8662     }
8663     else
8664     {
8665         assert(!"Unknown fmt for emitOutputShortBranch");
8666     }
8667
8668     dst += emitOutput_Instr(dst, code);
8669
8670     return dst;
8671 }
8672
8673 /*****************************************************************************
8674 *
8675 *  Output a short address instruction.
8676 */
8677 BYTE* emitter::emitOutputShortAddress(BYTE* dst, instruction ins, insFormat fmt, ssize_t distVal, regNumber reg)
8678 {
8679     ssize_t loBits = (distVal & 3);
8680     distVal >>= 2;
8681
8682     code_t code = emitInsCode(ins, fmt);
8683     if (fmt == IF_DI_1E) // DI_1E   .ii.....iiiiiiii iiiiiiiiiiiddddd      Rd simm21
8684     {
8685         // INS_adr or INS_adrp
8686         code |= insEncodeReg_Rd(reg); // ddddd
8687
8688         noway_assert(isValidSimm19(distVal));
8689         distVal &= 0x7FFFFLL; // 19 bits
8690         code |= distVal << 5;
8691         code |= loBits << 29; //  2 bits
8692     }
8693     else
8694     {
8695         assert(!"Unknown fmt for emitOutputShortAddress");
8696     }
8697
8698     dst += emitOutput_Instr(dst, code);
8699
8700     return dst;
8701 }
8702
8703 /*****************************************************************************
8704 *
8705 *  Output a short constant instruction.
8706 */
8707 BYTE* emitter::emitOutputShortConstant(
8708     BYTE* dst, instruction ins, insFormat fmt, ssize_t imm, regNumber reg, emitAttr opSize)
8709 {
8710     code_t code = emitInsCode(ins, fmt);
8711
8712     if (fmt == IF_LS_1A)
8713     {
8714         // LS_1A   XX...V..iiiiiiii iiiiiiiiiiittttt      Rt simm21
8715         // INS_ldr or INS_ldrsw (PC-Relative)
8716
8717         ssize_t loBits = (imm & 3);
8718         noway_assert(loBits == 0);
8719         ssize_t distVal = imm >>= 2; // load offset encodings are scaled by 4.
8720
8721         noway_assert(isValidSimm19(distVal));
8722
8723         // Is the target a vector register?
8724         if (isVectorRegister(reg))
8725         {
8726             code |= insEncodeDatasizeVLS(code, opSize); // XX V
8727             code |= insEncodeReg_Vt(reg);               // ttttt
8728         }
8729         else
8730         {
8731             assert(isGeneralRegister(reg));
8732             // insEncodeDatasizeLS is not quite right for this case.
8733             // So just specialize it.
8734             if ((ins == INS_ldr) && (opSize == EA_8BYTE))
8735             {
8736                 // set the operation size in bit 30
8737                 code |= 0x40000000;
8738             }
8739
8740             code |= insEncodeReg_Rt(reg); // ttttt
8741         }
8742
8743         distVal &= 0x7FFFFLL; // 19 bits
8744         code |= distVal << 5;
8745     }
8746     else if (fmt == IF_LS_2B)
8747     {
8748         //  ldr     Rt,[Xn+pimm12]       LS_2B  1X11100101iiiiii iiiiiinnnnnttttt   B940 0000   imm(0-4095<<{2,3})
8749         // INS_ldr or INS_ldrsw (PC-Relative)
8750         noway_assert(isValidUimm12(imm));
8751         assert(isGeneralRegister(reg));
8752
8753         if (opSize == EA_8BYTE)
8754         {
8755             // insEncodeDatasizeLS is not quite right for this case.
8756             // So just specialize it.
8757             if (ins == INS_ldr)
8758             {
8759                 // set the operation size in bit 30
8760                 code |= 0x40000000;
8761             }
8762             // Low 3 bits should be 0 -- 8 byte JIT data should be aligned on 8 byte.
8763             assert((imm & 7) == 0);
8764             imm >>= 3;
8765         }
8766         else
8767         {
8768             assert(opSize == EA_4BYTE);
8769             // Low 2 bits should be 0 -- 4 byte aligned data.
8770             assert((imm & 3) == 0);
8771             imm >>= 2;
8772         }
8773
8774         code |= insEncodeReg_Rt(reg); // ttttt
8775         code |= insEncodeReg_Rn(reg); // nnnnn
8776         code |= imm << 10;
8777     }
8778     else
8779     {
8780         assert(!"Unknown fmt for emitOutputShortConstant");
8781     }
8782
8783     dst += emitOutput_Instr(dst, code);
8784
8785     return dst;
8786 }
8787 /*****************************************************************************
8788  *
8789  *  Output a call instruction.
8790  */
8791
8792 unsigned emitter::emitOutputCall(insGroup* ig, BYTE* dst, instrDesc* id, code_t code)
8793 {
8794     const unsigned char callInstrSize = sizeof(code_t); // 4 bytes
8795     regMaskTP           gcrefRegs;
8796     regMaskTP           byrefRegs;
8797
8798     VARSET_TP GCvars(VarSetOps::UninitVal());
8799
8800     // Is this a "fat" call descriptor?
8801     if (id->idIsLargeCall())
8802     {
8803         instrDescCGCA* idCall = (instrDescCGCA*)id;
8804         gcrefRegs             = idCall->idcGcrefRegs;
8805         byrefRegs             = idCall->idcByrefRegs;
8806         VarSetOps::Assign(emitComp, GCvars, idCall->idcGCvars);
8807     }
8808     else
8809     {
8810         assert(!id->idIsLargeDsp());
8811         assert(!id->idIsLargeCns());
8812
8813         gcrefRegs = emitDecodeCallGCregs(id);
8814         byrefRegs = 0;
8815         VarSetOps::AssignNoCopy(emitComp, GCvars, VarSetOps::MakeEmpty(emitComp));
8816     }
8817
8818     /* We update the GC info before the call as the variables cannot be
8819         used by the call. Killing variables before the call helps with
8820         boundary conditions if the call is CORINFO_HELP_THROW - see bug 50029.
8821         If we ever track aliased variables (which could be used by the
8822         call), we would have to keep them alive past the call. */
8823
8824     emitUpdateLiveGCvars(GCvars, dst);
8825
8826     // Now output the call instruction and update the 'dst' pointer
8827     //
8828     unsigned outputInstrSize = emitOutput_Instr(dst, code);
8829     dst += outputInstrSize;
8830
8831     // All call instructions are 4-byte in size on ARM64
8832     //
8833     assert(outputInstrSize == callInstrSize);
8834
8835     // If the method returns a GC ref, mark INTRET (R0) appropriately.
8836     if (id->idGCref() == GCT_GCREF)
8837     {
8838         gcrefRegs |= RBM_INTRET;
8839     }
8840     else if (id->idGCref() == GCT_BYREF)
8841     {
8842         byrefRegs |= RBM_INTRET;
8843     }
8844
8845     // If is a multi-register return method is called, mark INTRET_1 (X1) appropriately
8846     if (id->idIsLargeCall())
8847     {
8848         instrDescCGCA* idCall = (instrDescCGCA*)id;
8849         if (idCall->idSecondGCref() == GCT_GCREF)
8850         {
8851             gcrefRegs |= RBM_INTRET_1;
8852         }
8853         else if (idCall->idSecondGCref() == GCT_BYREF)
8854         {
8855             byrefRegs |= RBM_INTRET_1;
8856         }
8857     }
8858
8859     // If the GC register set has changed, report the new set.
8860     if (gcrefRegs != emitThisGCrefRegs)
8861     {
8862         emitUpdateLiveGCregs(GCT_GCREF, gcrefRegs, dst);
8863     }
8864     // If the Byref register set has changed, report the new set.
8865     if (byrefRegs != emitThisByrefRegs)
8866     {
8867         emitUpdateLiveGCregs(GCT_BYREF, byrefRegs, dst);
8868     }
8869
8870     // Some helper calls may be marked as not requiring GC info to be recorded.
8871     if ((!id->idIsNoGC()))
8872     {
8873         // On ARM64, as on AMD64, we don't change the stack pointer to push/pop args.
8874         // So we're not really doing a "stack pop" here (note that "args" is 0), but we use this mechanism
8875         // to record the call for GC info purposes.  (It might be best to use an alternate call,
8876         // and protect "emitStackPop" under the EMIT_TRACK_STACK_DEPTH preprocessor variable.)
8877         emitStackPop(dst, /*isCall*/ true, callInstrSize, /*args*/ 0);
8878
8879         // Do we need to record a call location for GC purposes?
8880         //
8881         if (!emitFullGCinfo)
8882         {
8883             emitRecordGCcall(dst, callInstrSize);
8884         }
8885     }
8886     return callInstrSize;
8887 }
8888
8889 /*****************************************************************************
8890  *
8891  *  Emit a 32-bit Arm64 instruction
8892  */
8893
8894 /*static*/ unsigned emitter::emitOutput_Instr(BYTE* dst, code_t code)
8895 {
8896     assert(sizeof(code_t) == 4);
8897     *((code_t*)dst) = code;
8898
8899     return sizeof(code_t);
8900 }
8901
8902 /*****************************************************************************
8903 *
8904  *  Append the machine code corresponding to the given instruction descriptor
8905  *  to the code block at '*dp'; the base of the code block is 'bp', and 'ig'
8906  *  is the instruction group that contains the instruction. Updates '*dp' to
8907  *  point past the generated code, and returns the size of the instruction
8908  *  descriptor in bytes.
8909  */
8910
8911 size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
8912 {
8913     BYTE*         dst  = *dp;
8914     BYTE*         odst = dst;
8915     code_t        code = 0;
8916     size_t        sz   = emitGetInstrDescSize(id); // TODO-ARM64-Cleanup: on ARM, this is set in each case. why?
8917     instruction   ins  = id->idIns();
8918     insFormat     fmt  = id->idInsFmt();
8919     emitAttr      size = id->idOpSize();
8920     unsigned char callInstrSize = 0;
8921     unsigned      condcode;
8922
8923 #ifdef DEBUG
8924 #if DUMP_GC_TABLES
8925     bool dspOffs = emitComp->opts.dspGCtbls;
8926 #else
8927     bool dspOffs = !emitComp->opts.disDiffable;
8928 #endif
8929 #endif // DEBUG
8930
8931     assert(REG_NA == (int)REG_NA);
8932
8933     VARSET_TP GCvars(VarSetOps::UninitVal());
8934
8935     /* What instruction format have we got? */
8936
8937     switch (fmt)
8938     {
8939         ssize_t  imm;
8940         ssize_t  index;
8941         ssize_t  index2;
8942         unsigned scale;
8943         unsigned cmode;
8944         unsigned immShift;
8945         bool     hasShift;
8946         emitAttr extSize;
8947         emitAttr elemsize;
8948         emitAttr datasize;
8949
8950         case IF_BI_0A: // BI_0A   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
8951         case IF_BI_0B: // BI_0B   ......iiiiiiiiii iiiiiiiiiii.....               simm19:00
8952         case IF_LARGEJMP:
8953             assert(id->idGCref() == GCT_NONE);
8954             assert(id->idIsBound());
8955             dst = emitOutputLJ(ig, dst, id);
8956             sz  = sizeof(instrDescJmp);
8957             break;
8958
8959         case IF_BI_0C: // BI_0C   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
8960             code = emitInsCode(ins, fmt);
8961             sz   = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
8962             dst += emitOutputCall(ig, dst, id, code);
8963             // Always call RecordRelocation so that we wire in a JumpStub when we don't reach
8964             emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_BRANCH26);
8965             break;
8966
8967         case IF_BI_1A: // BI_1A   ......iiiiiiiiii iiiiiiiiiiittttt      Rt       simm19: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_BI_1B: // BI_1B   B.......bbbbbiii iiiiiiiiiiittttt      Rt imm6, simm14:00
8976             assert(insOptsNone(id->idInsOpt()));
8977             assert(id->idIsBound());
8978
8979             dst = emitOutputLJ(ig, dst, id);
8980             sz  = sizeof(instrDescJmp);
8981             break;
8982
8983         case IF_BR_1A: // BR_1A   ................ ......nnnnn.....         Rn
8984             assert(insOptsNone(id->idInsOpt()));
8985             assert((ins == INS_ret) || (ins == INS_br));
8986             code = emitInsCode(ins, fmt);
8987             code |= insEncodeReg_Rn(id->idReg1()); // nnnnn
8988
8989             dst += emitOutput_Instr(dst, code);
8990             break;
8991
8992         case IF_BR_1B: // BR_1B   ................ ......nnnnn.....         Rn
8993             assert(insOptsNone(id->idInsOpt()));
8994             assert((ins == INS_br_tail) || (ins == INS_blr));
8995             code = emitInsCode(ins, fmt);
8996             code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
8997
8998             sz = id->idIsLargeCall() ? sizeof(instrDescCGCA) : sizeof(instrDesc);
8999             dst += emitOutputCall(ig, dst, id, code);
9000             break;
9001
9002         case IF_LS_1A: // LS_1A   XX...V..iiiiiiii iiiiiiiiiiittttt      Rt    PC imm(1MB)
9003         case IF_LARGELDC:
9004             assert(insOptsNone(id->idInsOpt()));
9005             assert(id->idIsBound());
9006
9007             dst = emitOutputLJ(ig, dst, id);
9008             sz  = sizeof(instrDescJmp);
9009             break;
9010
9011         case IF_LS_2A: // LS_2A   .X.......X...... ......nnnnnttttt      Rt Rn
9012             assert(insOptsNone(id->idInsOpt()));
9013             code = emitInsCode(ins, fmt);
9014             // Is the target a vector register?
9015             if (isVectorRegister(id->idReg1()))
9016             {
9017                 code &= 0x3FFFFFFF;                                 // clear the size bits
9018                 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9019                 code |= insEncodeReg_Vt(id->idReg1());              // ttttt
9020             }
9021             else
9022             {
9023                 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9024                 code |= insEncodeReg_Rt(id->idReg1());             // ttttt
9025             }
9026             code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9027             dst += emitOutput_Instr(dst, code);
9028             break;
9029
9030         case IF_LS_2B: // LS_2B   .X.......Xiiiiii iiiiiinnnnnttttt      Rt Rn    imm(0-4095)
9031             assert(insOptsNone(id->idInsOpt()));
9032             imm = emitGetInsSC(id);
9033             assert(isValidUimm12(imm));
9034             code = emitInsCode(ins, fmt);
9035             // Is the target a vector register?
9036             if (isVectorRegister(id->idReg1()))
9037             {
9038                 code &= 0x3FFFFFFF;                                 // clear the size bits
9039                 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9040                 code |= insEncodeReg_Vt(id->idReg1());              // ttttt
9041             }
9042             else
9043             {
9044                 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9045                 code |= insEncodeReg_Rt(id->idReg1());             // ttttt
9046             }
9047             code |= ((code_t)imm << 10);           // iiiiiiiiiiii
9048             code |= insEncodeReg_Rn(id->idReg2()); // nnnnn
9049             dst += emitOutput_Instr(dst, code);
9050             break;
9051
9052         case IF_LS_2C: // LS_2C   .X.......X.iiiii iiiiPPnnnnnttttt      Rt Rn    imm(-256..+255) no/pre/post inc
9053             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9054             imm = emitGetInsSC(id);
9055             assert((imm >= -256) && (imm <= 255)); // signed 9 bits
9056             imm &= 0x1ff;                          // force into unsigned 9 bit representation
9057             code = emitInsCode(ins, fmt);
9058             // Is the target a vector register?
9059             if (isVectorRegister(id->idReg1()))
9060             {
9061                 code &= 0x3FFFFFFF;                                 // clear the size bits
9062                 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9063                 code |= insEncodeReg_Vt(id->idReg1());              // ttttt
9064             }
9065             else
9066             {
9067                 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9068                 code |= insEncodeReg_Rt(id->idReg1());             // ttttt
9069             }
9070             code |= insEncodeIndexedOpt(id->idInsOpt()); // PP
9071             code |= ((code_t)imm << 12);                 // iiiiiiiii
9072             code |= insEncodeReg_Rn(id->idReg2());       // nnnnn
9073             dst += emitOutput_Instr(dst, code);
9074             break;
9075
9076         case IF_LS_3A: // LS_3A   .X.......X.mmmmm oooS..nnnnnttttt      Rt Rn Rm ext(Rm) LSL {}
9077             assert(insOptsLSExtend(id->idInsOpt()));
9078             code = emitInsCode(ins, fmt);
9079             // Is the target a vector register?
9080             if (isVectorRegister(id->idReg1()))
9081             {
9082                 code &= 0x3FFFFFFF;                                 // clear the size bits
9083                 code |= insEncodeDatasizeVLS(code, id->idOpSize()); // XX
9084                 code |= insEncodeReg_Vt(id->idReg1());              // ttttt
9085             }
9086             else
9087             {
9088                 code |= insEncodeDatasizeLS(code, id->idOpSize()); // .X.......X
9089                 code |= insEncodeReg_Rt(id->idReg1());             // ttttt
9090             }
9091             code |= insEncodeExtend(id->idInsOpt()); // ooo
9092             code |= insEncodeReg_Rn(id->idReg2());   // nnnnn
9093             if (id->idIsLclVar())
9094             {
9095                 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9096             }
9097             else
9098             {
9099                 code |= insEncodeReg3Scale(id->idReg3Scaled()); // S
9100                 code |= insEncodeReg_Rm(id->idReg3());          // mmmmm
9101             }
9102             dst += emitOutput_Instr(dst, code);
9103             break;
9104
9105         case IF_LS_3B: // LS_3B   X............... .aaaaannnnnddddd      Rd Ra Rn
9106             assert(insOptsNone(id->idInsOpt()));
9107             code = emitInsCode(ins, fmt);
9108             // Is the target a vector register?
9109             if (isVectorRegister(id->idReg1()))
9110             {
9111                 code &= 0x3FFFFFFF;                                  // clear the size bits
9112                 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9113                 code |= insEncodeReg_Vt(id->idReg1());               // ttttt
9114                 code |= insEncodeReg_Va(id->idReg2());               // aaaaa
9115             }
9116             else
9117             {
9118                 code |= insEncodeDatasize(id->idOpSize()); // X
9119                 code |= insEncodeReg_Rt(id->idReg1());     // ttttt
9120                 code |= insEncodeReg_Ra(id->idReg2());     // aaaaa
9121             }
9122             code |= insEncodeReg_Rn(id->idReg3()); // nnnnn
9123             dst += emitOutput_Instr(dst, code);
9124             break;
9125
9126         case IF_LS_3C: // LS_3C   X......PP.iiiiii iaaaaannnnnddddd      Rd Ra Rn imm(im7,sh)
9127             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
9128             imm = emitGetInsSC(id);
9129             assert((imm >= -64) && (imm <= 63)); // signed 7 bits
9130             imm &= 0x7f;                         // force into unsigned 7 bit representation
9131             code = emitInsCode(ins, fmt);
9132             // Is the target a vector register?
9133             if (isVectorRegister(id->idReg1()))
9134             {
9135                 code &= 0x3FFFFFFF;                                  // clear the size bits
9136                 code |= insEncodeDatasizeVPLS(code, id->idOpSize()); // XX
9137                 code |= insEncodeReg_Vt(id->idReg1());               // ttttt
9138                 code |= insEncodeReg_Va(id->idReg2());               // aaaaa
9139             }
9140             else
9141             {
9142                 code |= insEncodeDatasize(id->idOpSize()); // X
9143                 code |= insEncodeReg_Rt(id->idReg1());     // ttttt
9144                 code |= insEncodeReg_Ra(id->idReg2());     // aaaaa
9145             }
9146             code |= insEncodePairIndexedOpt(ins, id->idInsOpt()); // PP
9147             code |= ((code_t)imm << 15);                          // iiiiiiiii
9148             code |= insEncodeReg_Rn(id->idReg3());                // nnnnn
9149             dst += emitOutput_Instr(dst, code);
9150             break;
9151
9152         case IF_LS_3D: // LS_3D   .X.......X.mmmmm ......nnnnnttttt      Wm Rt Rn
9153             code = emitInsCode(ins, fmt);
9154             // Arm64 store exclusive unpredictable cases
9155             assert(id->idReg1() != id->idReg2());
9156             assert(id->idReg1() != id->idReg3());
9157             code |= insEncodeDatasizeLS(code, id->idOpSize()); // X
9158             code |= insEncodeReg_Rm(id->idReg1());             // mmmmm
9159             code |= insEncodeReg_Rt(id->idReg2());             // ttttt
9160             code |= insEncodeReg_Rn(id->idReg3());             // nnnnn
9161             dst += emitOutput_Instr(dst, code);
9162             break;
9163
9164         case IF_DI_1A: // DI_1A   X.......shiiiiii iiiiiinnnnn.....         Rn    imm(i12,sh)
9165             assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9166             imm = emitGetInsSC(id);
9167             assert(isValidUimm12(imm));
9168             code = emitInsCode(ins, fmt);
9169             code |= insEncodeDatasize(id->idOpSize());   // X
9170             code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9171             code |= ((code_t)imm << 10);                 // iiiiiiiiiiii
9172             code |= insEncodeReg_Rn(id->idReg1());       // nnnnn
9173             dst += emitOutput_Instr(dst, code);
9174             break;
9175
9176         case IF_DI_1B: // DI_1B   X........hwiiiii iiiiiiiiiiiddddd      Rd       imm(i16,hw)
9177             imm = emitGetInsSC(id);
9178             assert(isValidImmHWVal(imm, id->idOpSize()));
9179             code = emitInsCode(ins, fmt);
9180             code |= insEncodeDatasize(id->idOpSize()); // X
9181             code |= ((code_t)imm << 5);                // hwiiiii iiiiiiiiiii
9182             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9183             dst += emitOutput_Instr(dst, code);
9184             break;
9185
9186         case IF_DI_1C: // DI_1C   X........Nrrrrrr ssssssnnnnn.....         Rn    imm(N,r,s)
9187             imm = emitGetInsSC(id);
9188             assert(isValidImmNRS(imm, id->idOpSize()));
9189             code = emitInsCode(ins, fmt);
9190             code |= ((code_t)imm << 10);               // Nrrrrrrssssss
9191             code |= insEncodeDatasize(id->idOpSize()); // X
9192             code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9193             dst += emitOutput_Instr(dst, code);
9194             break;
9195
9196         case IF_DI_1D: // DI_1D   X........Nrrrrrr ssssss.....ddddd      Rd       imm(N,r,s)
9197             imm = emitGetInsSC(id);
9198             assert(isValidImmNRS(imm, id->idOpSize()));
9199             code = emitInsCode(ins, fmt);
9200             code |= ((code_t)imm << 10);               // Nrrrrrrssssss
9201             code |= insEncodeDatasize(id->idOpSize()); // X
9202             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9203             dst += emitOutput_Instr(dst, code);
9204             break;
9205
9206         case IF_DI_1E: // DI_1E   .ii.....iiiiiiii iiiiiiiiiiiddddd      Rd       simm21
9207         case IF_LARGEADR:
9208             assert(insOptsNone(id->idInsOpt()));
9209             if (id->idIsReloc())
9210             {
9211                 code = emitInsCode(ins, fmt);
9212                 code |= insEncodeReg_Rd(id->idReg1()); // ddddd
9213                 dst += emitOutput_Instr(dst, code);
9214                 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEBASE_REL21);
9215             }
9216             else
9217             {
9218                 // Local jmp/load case which does not need a relocation.
9219                 assert(id->idIsBound());
9220                 dst = emitOutputLJ(ig, dst, id);
9221             }
9222             sz = sizeof(instrDescJmp);
9223             break;
9224
9225         case IF_DI_1F: // DI_1F   X..........iiiii cccc..nnnnn.nzcv      Rn imm5  nzcv cond
9226             imm = emitGetInsSC(id);
9227             assert(isValidImmCondFlagsImm5(imm));
9228             {
9229                 condFlagsImm cfi;
9230                 cfi.immCFVal = (unsigned)imm;
9231                 code         = emitInsCode(ins, fmt);
9232                 code |= insEncodeDatasize(id->idOpSize()); // X
9233                 code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9234                 code |= ((code_t)cfi.imm5 << 16);          // iiiii
9235                 code |= insEncodeFlags(cfi.flags);         // nzcv
9236                 code |= insEncodeCond(cfi.cond);           // cccc
9237                 dst += emitOutput_Instr(dst, code);
9238             }
9239             break;
9240
9241         case IF_DI_2A: // DI_2A   X.......shiiiiii iiiiiinnnnnddddd      Rd Rn    imm(i12,sh)
9242             assert(insOptsNone(id->idInsOpt()) || insOptsLSL12(id->idInsOpt()));
9243             imm = emitGetInsSC(id);
9244             assert(isValidUimm12(imm));
9245             code = emitInsCode(ins, fmt);
9246             code |= insEncodeDatasize(id->idOpSize());   // X
9247             code |= insEncodeShiftImm12(id->idInsOpt()); // sh
9248             code |= ((code_t)imm << 10);                 // iiiiiiiiiiii
9249             code |= insEncodeReg_Rd(id->idReg1());       // ddddd
9250             code |= insEncodeReg_Rn(id->idReg2());       // nnnnn
9251             dst += emitOutput_Instr(dst, code);
9252
9253             if (id->idIsReloc())
9254             {
9255                 assert(sz == sizeof(instrDesc));
9256                 assert(id->idAddr()->iiaAddr != nullptr);
9257                 emitRecordRelocation(odst, id->idAddr()->iiaAddr, IMAGE_REL_ARM64_PAGEOFFSET_12A);
9258             }
9259             break;
9260
9261         case IF_DI_2B: // DI_2B   X.........Xnnnnn ssssssnnnnnddddd      Rd Rn    imm(0-63)
9262             code = emitInsCode(ins, fmt);
9263             imm  = emitGetInsSC(id);
9264             assert(isValidImmShift(imm, id->idOpSize()));
9265             code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9266             code |= insEncodeReg_Rd(id->idReg1());             // ddddd
9267             code |= insEncodeReg_Rn(id->idReg2());             // nnnnn
9268             code |= insEncodeReg_Rm(id->idReg2());             // Reg2 also in mmmmm
9269             code |= insEncodeShiftCount(imm, id->idOpSize());  // ssssss
9270             dst += emitOutput_Instr(dst, code);
9271             break;
9272
9273         case IF_DI_2C: // DI_2C   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imm(N,r,s)
9274             imm = emitGetInsSC(id);
9275             assert(isValidImmNRS(imm, id->idOpSize()));
9276             code = emitInsCode(ins, fmt);
9277             code |= ((code_t)imm << 10);               // Nrrrrrrssssss
9278             code |= insEncodeDatasize(id->idOpSize()); // X
9279             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9280             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9281             dst += emitOutput_Instr(dst, code);
9282             break;
9283
9284         case IF_DI_2D: // DI_2D   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imr, imms   (N,r,s)
9285             if (ins == INS_asr || ins == INS_lsl || ins == INS_lsr)
9286             {
9287                 imm = emitGetInsSC(id);
9288                 assert(isValidImmShift(imm, id->idOpSize()));
9289
9290                 // Shift immediates are aliases of the SBFM/UBFM instructions
9291                 // that actually take 2 registers and 2 constants,
9292                 // Since we stored the shift immediate value
9293                 // we need to calculate the N,R and S values here.
9294
9295                 bitMaskImm bmi;
9296                 bmi.immNRS = 0;
9297
9298                 bmi.immN = (size == EA_8BYTE) ? 1 : 0;
9299                 bmi.immR = imm;
9300                 bmi.immS = (size == EA_8BYTE) ? 0x3f : 0x1f;
9301
9302                 // immR and immS are now set correctly for INS_asr and INS_lsr
9303                 // but for INS_lsl we have to adjust the values for immR and immS
9304                 //
9305                 if (ins == INS_lsl)
9306                 {
9307                     bmi.immR = -imm & bmi.immS;
9308                     bmi.immS = bmi.immS - imm;
9309                 }
9310
9311                 // setup imm with the proper 13 bit value N:R:S
9312                 //
9313                 imm = bmi.immNRS;
9314             }
9315             else
9316             {
9317                 // The other instructions have already have encoded N,R and S values
9318                 imm = emitGetInsSC(id);
9319             }
9320             assert(isValidImmNRS(imm, id->idOpSize()));
9321
9322             code = emitInsCode(ins, fmt);
9323             code |= ((code_t)imm << 10);               // Nrrrrrrssssss
9324             code |= insEncodeDatasize(id->idOpSize()); // X
9325             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9326             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9327             dst += emitOutput_Instr(dst, code);
9328             break;
9329
9330         case IF_DR_1D: // DR_1D   X............... cccc.......ddddd      Rd       cond
9331             imm = emitGetInsSC(id);
9332             assert(isValidImmCond(imm));
9333             {
9334                 condFlagsImm cfi;
9335                 cfi.immCFVal = (unsigned)imm;
9336                 code         = emitInsCode(ins, fmt);
9337                 code |= insEncodeDatasize(id->idOpSize()); // X
9338                 code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9339                 code |= insEncodeInvertedCond(cfi.cond);   // cccc
9340                 dst += emitOutput_Instr(dst, code);
9341             }
9342             break;
9343
9344         case IF_DR_2A: // DR_2A   X..........mmmmm ......nnnnn.....         Rn Rm
9345             assert(insOptsNone(id->idInsOpt()));
9346             code = emitInsCode(ins, fmt);
9347             code |= insEncodeDatasize(id->idOpSize()); // X
9348             code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9349             code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9350             dst += emitOutput_Instr(dst, code);
9351             break;
9352
9353         case IF_DR_2B: // DR_2B   X.......sh.mmmmm ssssssnnnnn.....         Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
9354             code = emitInsCode(ins, fmt);
9355             imm  = emitGetInsSC(id);
9356             assert(isValidImmShift(imm, id->idOpSize()));
9357             code |= insEncodeDatasize(id->idOpSize());        // X
9358             code |= insEncodeShiftType(id->idInsOpt());       // sh
9359             code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9360             code |= insEncodeReg_Rn(id->idReg1());            // nnnnn
9361             code |= insEncodeReg_Rm(id->idReg2());            // mmmmm
9362             dst += emitOutput_Instr(dst, code);
9363             break;
9364
9365         case IF_DR_2C: // DR_2C   X..........mmmmm ooosssnnnnn.....         Rn Rm ext(Rm) LSL imm(0-4)
9366             code = emitInsCode(ins, fmt);
9367             imm  = emitGetInsSC(id);
9368             assert((imm >= 0) && (imm <= 4));          // imm [0..4]
9369             code |= insEncodeDatasize(id->idOpSize()); // X
9370             code |= insEncodeExtend(id->idInsOpt());   // ooo
9371             code |= insEncodeExtendScale(imm);         // sss
9372             code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9373             code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9374             dst += emitOutput_Instr(dst, code);
9375             break;
9376
9377         case IF_DR_2D: // DR_2D   X..........nnnnn cccc..nnnnnddddd      Rd Rn    cond
9378             imm = emitGetInsSC(id);
9379             assert(isValidImmCond(imm));
9380             {
9381                 condFlagsImm cfi;
9382                 cfi.immCFVal = (unsigned)imm;
9383                 code         = emitInsCode(ins, fmt);
9384                 code |= insEncodeDatasize(id->idOpSize()); // X
9385                 code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9386                 code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9387                 code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9388                 code |= insEncodeInvertedCond(cfi.cond);   // cccc
9389                 dst += emitOutput_Instr(dst, code);
9390             }
9391             break;
9392
9393         case IF_DR_2E: // DR_2E   X..........mmmmm ...........ddddd      Rd    Rm
9394             code = emitInsCode(ins, fmt);
9395             code |= insEncodeDatasize(id->idOpSize()); // X
9396             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9397             code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9398             dst += emitOutput_Instr(dst, code);
9399             break;
9400
9401         case IF_DR_2F: // DR_2F   X.......sh.mmmmm ssssss.....ddddd      Rd    Rm {LSL,LSR,ASR} imm(0-63)
9402             code = emitInsCode(ins, fmt);
9403             imm  = emitGetInsSC(id);
9404             assert(isValidImmShift(imm, id->idOpSize()));
9405             code |= insEncodeDatasize(id->idOpSize());        // X
9406             code |= insEncodeShiftType(id->idInsOpt());       // sh
9407             code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9408             code |= insEncodeReg_Rd(id->idReg1());            // ddddd
9409             code |= insEncodeReg_Rm(id->idReg2());            // mmmmm
9410             dst += emitOutput_Instr(dst, code);
9411             break;
9412
9413         case IF_DR_2G: // DR_2G   X............... .....xnnnnnddddd      Rd Rn
9414             code = emitInsCode(ins, fmt);
9415             code |= insEncodeDatasize(id->idOpSize()); // X
9416             if (ins == INS_rev)
9417             {
9418                 if (size == EA_8BYTE)
9419                 {
9420                     code |= 0x00000400; // x - bit at location 10
9421                 }
9422             }
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_2H: // DR_2H   X........X...... ......nnnnnddddd      Rd Rn
9429             code = emitInsCode(ins, fmt);
9430             code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9431             code |= insEncodeReg_Rd(id->idReg1());             // ddddd
9432             code |= insEncodeReg_Rn(id->idReg2());             // nnnnn
9433             dst += emitOutput_Instr(dst, code);
9434             break;
9435
9436         case IF_DR_2I: // DR_2I   X..........mmmmm cccc..nnnnn.nzcv      Rn Rm    nzcv cond
9437             imm = emitGetInsSC(id);
9438             assert(isValidImmCondFlags(imm));
9439             {
9440                 condFlagsImm cfi;
9441                 cfi.immCFVal = (unsigned)imm;
9442                 code         = emitInsCode(ins, fmt);
9443                 code |= insEncodeDatasize(id->idOpSize()); // X
9444                 code |= insEncodeReg_Rn(id->idReg1());     // nnnnn
9445                 code |= insEncodeReg_Rm(id->idReg2());     // mmmmm
9446                 code |= insEncodeFlags(cfi.flags);         // nzcv
9447                 code |= insEncodeCond(cfi.cond);           // cccc
9448                 dst += emitOutput_Instr(dst, code);
9449             }
9450             break;
9451
9452         case IF_DR_3A: // DR_3A   X..........mmmmm ......nnnnnmmmmm      Rd Rn Rm
9453             code = emitInsCode(ins, fmt);
9454             code |= insEncodeDatasize(id->idOpSize()); // X
9455             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9456             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9457             if (id->idIsLclVar())
9458             {
9459                 code |= insEncodeReg_Rm(codeGen->rsGetRsvdReg()); // mmmmm
9460             }
9461             else
9462             {
9463                 code |= insEncodeReg_Rm(id->idReg3()); // mmmmm
9464             }
9465             dst += emitOutput_Instr(dst, code);
9466             break;
9467
9468         case IF_DR_3B: // DR_3B   X.......sh.mmmmm ssssssnnnnnddddd      Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
9469             code = emitInsCode(ins, fmt);
9470             imm  = emitGetInsSC(id);
9471             assert(isValidImmShift(imm, id->idOpSize()));
9472             code |= insEncodeDatasize(id->idOpSize());        // X
9473             code |= insEncodeReg_Rd(id->idReg1());            // ddddd
9474             code |= insEncodeReg_Rn(id->idReg2());            // nnnnn
9475             code |= insEncodeReg_Rm(id->idReg3());            // mmmmm
9476             code |= insEncodeShiftType(id->idInsOpt());       // sh
9477             code |= insEncodeShiftCount(imm, id->idOpSize()); // ssssss
9478             dst += emitOutput_Instr(dst, code);
9479             break;
9480
9481         case IF_DR_3C: // DR_3C   X..........mmmmm ooosssnnnnnddddd      Rd Rn Rm ext(Rm) LSL imm(0-4)
9482             code = emitInsCode(ins, fmt);
9483             imm  = emitGetInsSC(id);
9484             assert((imm >= 0) && (imm <= 4));          // imm [0..4]
9485             code |= insEncodeDatasize(id->idOpSize()); // X
9486             code |= insEncodeExtend(id->idInsOpt());   // ooo
9487             code |= insEncodeExtendScale(imm);         // sss
9488             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9489             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9490             code |= insEncodeReg_Rm(id->idReg3());     // mmmmm
9491             dst += emitOutput_Instr(dst, code);
9492             break;
9493
9494         case IF_DR_3D: // DR_3D   X..........mmmmm cccc..nnnnnddddd      Rd Rn Rm cond
9495             imm = emitGetInsSC(id);
9496             assert(isValidImmCond(imm));
9497             {
9498                 condFlagsImm cfi;
9499                 cfi.immCFVal = (unsigned)imm;
9500                 code         = emitInsCode(ins, fmt);
9501                 code |= insEncodeDatasize(id->idOpSize()); // X
9502                 code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9503                 code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9504                 code |= insEncodeReg_Rm(id->idReg3());     // mmmmm
9505                 code |= insEncodeCond(cfi.cond);           // cccc
9506                 dst += emitOutput_Instr(dst, code);
9507             }
9508             break;
9509
9510         case IF_DR_3E: // DR_3E   X........X.mmmmm ssssssnnnnnddddd      Rd Rn Rm imm(0-63)
9511             code = emitInsCode(ins, fmt);
9512             imm  = emitGetInsSC(id);
9513             assert(isValidImmShift(imm, id->idOpSize()));
9514             code |= insEncodeDatasizeBF(code, id->idOpSize()); // X........X
9515             code |= insEncodeReg_Rd(id->idReg1());             // ddddd
9516             code |= insEncodeReg_Rn(id->idReg2());             // nnnnn
9517             code |= insEncodeReg_Rm(id->idReg3());             // mmmmm
9518             code |= insEncodeShiftCount(imm, id->idOpSize());  // ssssss
9519             dst += emitOutput_Instr(dst, code);
9520             break;
9521
9522         case IF_DR_4A: // DR_4A   X..........mmmmm .aaaaannnnnmmmmm      Rd Rn Rm Ra
9523             code = emitInsCode(ins, fmt);
9524             code |= insEncodeDatasize(id->idOpSize()); // X
9525             code |= insEncodeReg_Rd(id->idReg1());     // ddddd
9526             code |= insEncodeReg_Rn(id->idReg2());     // nnnnn
9527             code |= insEncodeReg_Rm(id->idReg3());     // mmmmm
9528             code |= insEncodeReg_Ra(id->idReg4());     // aaaaa
9529             dst += emitOutput_Instr(dst, code);
9530             break;
9531
9532         case IF_DV_1A: // DV_1A   .........X.iiiii iii........ddddd      Vd imm8    (fmov - immediate scalar)
9533             imm      = emitGetInsSC(id);
9534             elemsize = id->idOpSize();
9535             code     = emitInsCode(ins, fmt);
9536             code |= insEncodeFloatElemsize(elemsize); // X
9537             code |= ((code_t)imm << 13);              // iiiii iii
9538             code |= insEncodeReg_Vd(id->idReg1());    // ddddd
9539             dst += emitOutput_Instr(dst, code);
9540             break;
9541
9542         case IF_DV_1B: // DV_1B   .QX..........iii cmod..iiiiiddddd      Vd imm8    (immediate vector)
9543             imm      = emitGetInsSC(id) & 0x0ff;
9544             immShift = (emitGetInsSC(id) & 0x700) >> 8;
9545             elemsize = optGetElemsize(id->idInsOpt());
9546             cmode    = 0;
9547             switch (elemsize)
9548             { // cmode
9549                 case EA_1BYTE:
9550                     cmode = 0xE; // 1110
9551                     break;
9552                 case EA_2BYTE:
9553                     cmode = 0x8;
9554                     cmode |= (immShift << 1); // 10x0
9555                     break;
9556                 case EA_4BYTE:
9557                     if (immShift < 4)
9558                     {
9559                         cmode = 0x0;
9560                         cmode |= (immShift << 1); // 0xx0
9561                     }
9562                     else // MSL
9563                     {
9564                         cmode = 0xC;
9565                         if (immShift & 2)
9566                             cmode |= 1; // 110x
9567                     }
9568                     break;
9569                 case EA_8BYTE:
9570                     cmode = 0xE; // 1110
9571                     break;
9572                 default:
9573                     unreached();
9574                     break;
9575             }
9576
9577             code = emitInsCode(ins, fmt);
9578             code |= insEncodeVectorsize(id->idOpSize()); // Q
9579             if ((ins == INS_fmov) || (ins == INS_movi))
9580             {
9581                 if (elemsize == EA_8BYTE)
9582                 {
9583                     code |= 0x20000000; // X
9584                 }
9585             }
9586             if (ins != INS_fmov)
9587             {
9588                 assert((cmode >= 0) && (cmode <= 0xF));
9589                 code |= (cmode << 12); // cmod
9590             }
9591             code |= (((code_t)imm >> 5) << 16);    // iii
9592             code |= (((code_t)imm & 0x1f) << 5);   // iiiii
9593             code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9594             dst += emitOutput_Instr(dst, code);
9595             break;
9596
9597         case IF_DV_1C: // DV_1C   .........X...... ......nnnnn.....      Vn #0.0    (fcmp - with zero)
9598             elemsize = id->idOpSize();
9599             code     = emitInsCode(ins, fmt);
9600             code |= insEncodeFloatElemsize(elemsize); // X
9601             code |= insEncodeReg_Vn(id->idReg1());    // nnnnn
9602             dst += emitOutput_Instr(dst, code);
9603             break;
9604
9605         case IF_DV_2A: // DV_2A   .Q.......X...... ......nnnnnddddd      Vd Vn      (fabs, fcvt - vector)
9606             elemsize = optGetElemsize(id->idInsOpt());
9607             code     = emitInsCode(ins, fmt);
9608             code |= insEncodeVectorsize(id->idOpSize()); // Q
9609             code |= insEncodeFloatElemsize(elemsize);    // X
9610             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9611             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9612             dst += emitOutput_Instr(dst, code);
9613             break;
9614
9615         case IF_DV_2B: // DV_2B   .Q.........iiiii ......nnnnnddddd      Rd Vn[] (umov/smov    - to general)
9616             elemsize = id->idOpSize();
9617             index    = emitGetInsSC(id);
9618             datasize = (elemsize == EA_8BYTE) ? EA_16BYTE : EA_8BYTE;
9619             if (ins == INS_smov)
9620             {
9621                 datasize = EA_16BYTE;
9622             }
9623             code = emitInsCode(ins, fmt);
9624             code |= insEncodeVectorsize(datasize);         // Q
9625             code |= insEncodeVectorIndex(elemsize, index); // iiiii
9626             code |= insEncodeReg_Rd(id->idReg1());         // ddddd
9627             code |= insEncodeReg_Vn(id->idReg2());         // nnnnn
9628             dst += emitOutput_Instr(dst, code);
9629             break;
9630
9631         case IF_DV_2C: // DV_2C   .Q.........iiiii ......nnnnnddddd      Vd Rn   (dup/ins - vector from general)
9632             if (ins == INS_dup)
9633             {
9634                 datasize = id->idOpSize();
9635                 elemsize = optGetElemsize(id->idInsOpt());
9636                 index    = 0;
9637             }
9638             else // INS_ins
9639             {
9640                 datasize = EA_16BYTE;
9641                 elemsize = id->idOpSize();
9642                 index    = emitGetInsSC(id);
9643             }
9644             code = emitInsCode(ins, fmt);
9645             code |= insEncodeVectorsize(datasize);         // Q
9646             code |= insEncodeVectorIndex(elemsize, index); // iiiii
9647             code |= insEncodeReg_Vd(id->idReg1());         // ddddd
9648             code |= insEncodeReg_Rn(id->idReg2());         // nnnnn
9649             dst += emitOutput_Instr(dst, code);
9650             break;
9651
9652         case IF_DV_2D: // DV_2D   .Q.........iiiii ......nnnnnddddd      Vd Vn[]   (dup - vector)
9653             index    = emitGetInsSC(id);
9654             elemsize = optGetElemsize(id->idInsOpt());
9655             code     = emitInsCode(ins, fmt);
9656             code |= insEncodeVectorsize(id->idOpSize());   // Q
9657             code |= insEncodeVectorIndex(elemsize, index); // iiiii
9658             code |= insEncodeReg_Vd(id->idReg1());         // ddddd
9659             code |= insEncodeReg_Vn(id->idReg2());         // nnnnn
9660             dst += emitOutput_Instr(dst, code);
9661             break;
9662
9663         case IF_DV_2E: // DV_2E   ...........iiiii ......nnnnnddddd      Vd Vn[]   (dup - scalar)
9664             index    = emitGetInsSC(id);
9665             elemsize = id->idOpSize();
9666             code     = emitInsCode(ins, fmt);
9667             code |= insEncodeVectorIndex(elemsize, index); // iiiii
9668             code |= insEncodeReg_Vd(id->idReg1());         // ddddd
9669             code |= insEncodeReg_Vn(id->idReg2());         // nnnnn
9670             dst += emitOutput_Instr(dst, code);
9671             break;
9672
9673         case IF_DV_2F: // DV_2F   ...........iiiii .jjjj.nnnnnddddd      Vd[] Vn[] (ins - element)
9674             elemsize = id->idOpSize();
9675             imm      = emitGetInsSC(id);
9676             index    = (imm >> 4) & 0xf;
9677             index2   = imm & 0xf;
9678             code     = emitInsCode(ins, fmt);
9679             code |= insEncodeVectorIndex(elemsize, index);   // iiiii
9680             code |= insEncodeVectorIndex2(elemsize, index2); // jjjj
9681             code |= insEncodeReg_Vd(id->idReg1());           // ddddd
9682             code |= insEncodeReg_Vn(id->idReg2());           // nnnnn
9683             dst += emitOutput_Instr(dst, code);
9684             break;
9685
9686         case IF_DV_2G: // DV_2G   .........X...... ......nnnnnddddd      Vd Vn      (fmov,fcvtXX - register)
9687             elemsize = id->idOpSize();
9688             code     = emitInsCode(ins, fmt);
9689             code |= insEncodeFloatElemsize(elemsize); // X
9690             code |= insEncodeReg_Vd(id->idReg1());    // ddddd
9691             code |= insEncodeReg_Vn(id->idReg2());    // nnnnn
9692             dst += emitOutput_Instr(dst, code);
9693             break;
9694
9695         case IF_DV_2H: // DV_2H   X........X...... ......nnnnnddddd      Rd Vn      (fmov - to general)
9696             elemsize = id->idOpSize();
9697             code     = emitInsCode(ins, fmt);
9698             code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X   X
9699             code |= insEncodeReg_Rd(id->idReg1());            // ddddd
9700             code |= insEncodeReg_Vn(id->idReg2());            // nnnnn
9701             dst += emitOutput_Instr(dst, code);
9702             break;
9703
9704         case IF_DV_2I: // DV_2I   X........X...... ......nnnnnddddd      Vd Rn      (fmov - from general)
9705             elemsize = id->idOpSize();
9706             code     = emitInsCode(ins, fmt);
9707             code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // X   X
9708             code |= insEncodeReg_Vd(id->idReg1());            // ddddd
9709             code |= insEncodeReg_Rn(id->idReg2());            // nnnnn
9710             dst += emitOutput_Instr(dst, code);
9711             break;
9712
9713         case IF_DV_2J: // DV_2J   ........SS.....D D.....nnnnnddddd      Vd Vn      (fcvt)
9714             code = emitInsCode(ins, fmt);
9715             code |= insEncodeConvertOpt(fmt, id->idInsOpt()); // SS DD
9716             code |= insEncodeReg_Vd(id->idReg1());            // ddddd
9717             code |= insEncodeReg_Vn(id->idReg2());            // nnnnn
9718             dst += emitOutput_Instr(dst, code);
9719             break;
9720
9721         case IF_DV_2K: // DV_2K   .........X.mmmmm ......nnnnn.....      Vn Vm      (fcmp)
9722             elemsize = id->idOpSize();
9723             code     = emitInsCode(ins, fmt);
9724             code |= insEncodeFloatElemsize(elemsize); // X
9725             code |= insEncodeReg_Vn(id->idReg1());    // nnnnn
9726             code |= insEncodeReg_Vm(id->idReg2());    // mmmmm
9727             dst += emitOutput_Instr(dst, code);
9728             break;
9729
9730         case IF_DV_2L: // DV_2L   ........XX...... ......nnnnnddddd      Vd Vn      (abs, neg - scalar)
9731             elemsize = id->idOpSize();
9732             code     = emitInsCode(ins, fmt);
9733             code |= insEncodeElemsize(elemsize);   // XX
9734             code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9735             code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9736             dst += emitOutput_Instr(dst, code);
9737             break;
9738
9739         case IF_DV_2M: // DV_2M   .Q......XX...... ......nnnnnddddd      Vd Vn      (abs, neg   - vector)
9740             elemsize = optGetElemsize(id->idInsOpt());
9741             code     = emitInsCode(ins, fmt);
9742             code |= insEncodeVectorsize(id->idOpSize()); // Q
9743             code |= insEncodeElemsize(elemsize);         // XX
9744             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9745             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9746             dst += emitOutput_Instr(dst, code);
9747             break;
9748
9749         case IF_DV_2N: // DV_2N   .........iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - scalar)
9750             imm  = emitGetInsSC(id);
9751             code = emitInsCode(ins, fmt);
9752             code |= insEncodeVectorShift(EA_8BYTE, imm); // iiiiiii
9753             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9754             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9755             dst += emitOutput_Instr(dst, code);
9756             break;
9757
9758         case IF_DV_2O: // DV_2O   .Q.......iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - vector)
9759             imm      = emitGetInsSC(id);
9760             elemsize = optGetElemsize(id->idInsOpt());
9761             code     = emitInsCode(ins, fmt);
9762             code |= insEncodeVectorsize(id->idOpSize()); // Q
9763             code |= insEncodeVectorShift(elemsize, imm); // iiiiiii
9764             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9765             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9766             dst += emitOutput_Instr(dst, code);
9767             break;
9768
9769         case IF_DV_3A: // DV_3A   .Q......XX.mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
9770             code     = emitInsCode(ins, fmt);
9771             elemsize = optGetElemsize(id->idInsOpt());
9772             code |= insEncodeVectorsize(id->idOpSize()); // Q
9773             code |= insEncodeElemsize(elemsize);         // XX
9774             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9775             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9776             code |= insEncodeReg_Vm(id->idReg3());       // mmmmm
9777             dst += emitOutput_Instr(dst, code);
9778             break;
9779
9780         case IF_DV_3AI: // DV_3AI  .Q......XXLMmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector)
9781             code     = emitInsCode(ins, fmt);
9782             imm      = emitGetInsSC(id);
9783             elemsize = optGetElemsize(id->idInsOpt());
9784             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
9785             code |= insEncodeVectorsize(id->idOpSize());    // Q
9786             code |= insEncodeElemsize(elemsize);            // XX
9787             code |= insEncodeVectorIndexLMH(elemsize, imm); // LM H
9788             code |= insEncodeReg_Vd(id->idReg1());          // ddddd
9789             code |= insEncodeReg_Vn(id->idReg2());          // nnnnn
9790             code |= insEncodeReg_Vm(id->idReg3());          // mmmmm
9791             dst += emitOutput_Instr(dst, code);
9792             break;
9793
9794         case IF_DV_3B: // DV_3B   .Q.......X.mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
9795             code     = emitInsCode(ins, fmt);
9796             elemsize = optGetElemsize(id->idInsOpt());
9797             code |= insEncodeVectorsize(id->idOpSize()); // Q
9798             code |= insEncodeFloatElemsize(elemsize);    // X
9799             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9800             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9801             code |= insEncodeReg_Vm(id->idReg3());       // mmmmm
9802             dst += emitOutput_Instr(dst, code);
9803             break;
9804
9805         case IF_DV_3BI: // DV_3BI  .Q.......XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector by elem)
9806             code     = emitInsCode(ins, fmt);
9807             imm      = emitGetInsSC(id);
9808             elemsize = optGetElemsize(id->idInsOpt());
9809             assert(isValidVectorIndex(id->idOpSize(), elemsize, imm));
9810             code |= insEncodeVectorsize(id->idOpSize()); // Q
9811             code |= insEncodeFloatElemsize(elemsize);    // X
9812             code |= insEncodeFloatIndex(elemsize, imm);  // L H
9813             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9814             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9815             code |= insEncodeReg_Vm(id->idReg3());       // mmmmm
9816             dst += emitOutput_Instr(dst, code);
9817             break;
9818
9819         case IF_DV_3C: // DV_3C   .Q.........mmmmm ......nnnnnddddd      Vd Vn Vm   (vector)
9820             code = emitInsCode(ins, fmt);
9821             code |= insEncodeVectorsize(id->idOpSize()); // Q
9822             code |= insEncodeReg_Vd(id->idReg1());       // ddddd
9823             code |= insEncodeReg_Vn(id->idReg2());       // nnnnn
9824             code |= insEncodeReg_Vm(id->idReg3());       // mmmmm
9825             dst += emitOutput_Instr(dst, code);
9826             break;
9827
9828         case IF_DV_3D: // DV_3D   .........X.mmmmm ......nnnnnddddd      Vd Vn Vm   (scalar)
9829             code = emitInsCode(ins, fmt);
9830             code |= insEncodeFloatElemsize(id->idOpSize()); // X
9831             code |= insEncodeReg_Vd(id->idReg1());          // ddddd
9832             code |= insEncodeReg_Vn(id->idReg2());          // nnnnn
9833             code |= insEncodeReg_Vm(id->idReg3());          // mmmmm
9834             dst += emitOutput_Instr(dst, code);
9835             break;
9836
9837         case IF_DV_3DI: // DV_3DI  .........XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (scalar by elem)
9838             code     = emitInsCode(ins, fmt);
9839             imm      = emitGetInsSC(id);
9840             elemsize = id->idOpSize();
9841             assert(isValidVectorIndex(EA_16BYTE, elemsize, imm));
9842             code |= insEncodeFloatElemsize(elemsize);   // X
9843             code |= insEncodeFloatIndex(elemsize, imm); // L H
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_3E: // DV_3E   ...........mmmmm ......nnnnnddddd      Vd Vn Vm   (scalar)
9851             code = emitInsCode(ins, fmt);
9852             code |= insEncodeReg_Vd(id->idReg1()); // ddddd
9853             code |= insEncodeReg_Vn(id->idReg2()); // nnnnn
9854             code |= insEncodeReg_Vm(id->idReg3()); // mmmmm
9855             dst += emitOutput_Instr(dst, code);
9856             break;
9857
9858         case IF_DV_4A: // DV_4A   .........X.mmmmm .aaaaannnnnddddd      Vd Va Vn Vm (scalar)
9859             code     = emitInsCode(ins, fmt);
9860             elemsize = id->idOpSize();
9861             code |= insEncodeFloatElemsize(elemsize); // X
9862             code |= insEncodeReg_Vd(id->idReg1());    // ddddd
9863             code |= insEncodeReg_Vn(id->idReg2());    // nnnnn
9864             code |= insEncodeReg_Vm(id->idReg3());    // mmmmm
9865             code |= insEncodeReg_Va(id->idReg4());    // aaaaa
9866             dst += emitOutput_Instr(dst, code);
9867             break;
9868
9869         case IF_SN_0A: // SN_0A   ................ ................
9870             code = emitInsCode(ins, fmt);
9871             dst += emitOutput_Instr(dst, code);
9872             break;
9873
9874         case IF_SI_0A: // SI_0A   ...........iiiii iiiiiiiiiii.....               imm16
9875             imm = emitGetInsSC(id);
9876             assert(isValidUimm16(imm));
9877             code = emitInsCode(ins, fmt);
9878             code |= ((code_t)imm << 5); // iiiii iiiiiiiiiii
9879             dst += emitOutput_Instr(dst, code);
9880             break;
9881
9882         case IF_SI_0B: // SI_0B   ................ ....bbbb........               imm4 - barrier
9883             imm = emitGetInsSC(id);
9884             assert((imm >= 0) && (imm <= 15));
9885             code = emitInsCode(ins, fmt);
9886             code |= ((code_t)imm << 8); // bbbb
9887             dst += emitOutput_Instr(dst, code);
9888             break;
9889
9890         default:
9891             assert(!"Unexpected format");
9892             break;
9893     }
9894
9895     // Determine if any registers now hold GC refs, or whether a register that was overwritten held a GC ref.
9896     // We assume here that "id->idGCref()" is not GC_NONE only if the instruction described by "id" writes a
9897     // GC ref to register "id->idReg1()".  (It may, apparently, also not be GC_NONE in other cases, such as
9898     // for stores, but we ignore those cases here.)
9899     if (emitInsMayWriteToGCReg(id)) // True if "id->idIns()" writes to a register than can hold GC ref.
9900     {
9901         // We assume that "idReg1" is the primary destination register for all instructions
9902         if (id->idGCref() != GCT_NONE)
9903         {
9904             emitGCregLiveUpd(id->idGCref(), id->idReg1(), dst);
9905         }
9906         else
9907         {
9908             emitGCregDeadUpd(id->idReg1(), dst);
9909         }
9910
9911         if (emitInsMayWriteMultipleRegs(id))
9912         {
9913             // INS_ldp etc...
9914             // "idReg2" is the secondary destination register
9915             if (id->idGCrefReg2() != GCT_NONE)
9916             {
9917                 emitGCregLiveUpd(id->idGCrefReg2(), id->idReg2(), dst);
9918             }
9919             else
9920             {
9921                 emitGCregDeadUpd(id->idReg2(), dst);
9922             }
9923         }
9924     }
9925
9926     // Now we determine if the instruction has written to a (local variable) stack location, and either written a GC
9927     // ref or overwritten one.
9928     if (emitInsWritesToLclVarStackLoc(id) || emitInsWritesToLclVarStackLocPair(id))
9929     {
9930         int      varNum = id->idAddr()->iiaLclVar.lvaVarNum();
9931         unsigned ofs    = AlignDown(id->idAddr()->iiaLclVar.lvaOffset(), TARGET_POINTER_SIZE);
9932         bool     FPbased;
9933         int      adr = emitComp->lvaFrameAddress(varNum, &FPbased);
9934         if (id->idGCref() != GCT_NONE)
9935         {
9936             emitGCvarLiveUpd(adr + ofs, varNum, id->idGCref(), dst);
9937         }
9938         else
9939         {
9940             // If the type of the local is a gc ref type, update the liveness.
9941             var_types vt;
9942             if (varNum >= 0)
9943             {
9944                 // "Regular" (non-spill-temp) local.
9945                 vt = var_types(emitComp->lvaTable[varNum].lvType);
9946             }
9947             else
9948             {
9949                 TempDsc* tmpDsc = emitComp->tmpFindNum(varNum);
9950                 vt              = tmpDsc->tdTempType();
9951             }
9952             if (vt == TYP_REF || vt == TYP_BYREF)
9953                 emitGCvarDeadUpd(adr + ofs, dst);
9954         }
9955         if (emitInsWritesToLclVarStackLocPair(id))
9956         {
9957             unsigned ofs2 = ofs + TARGET_POINTER_SIZE;
9958             if (id->idGCrefReg2() != GCT_NONE)
9959             {
9960                 emitGCvarLiveUpd(adr + ofs2, varNum, id->idGCrefReg2(), dst);
9961             }
9962             else
9963             {
9964                 // If the type of the local is a gc ref type, update the liveness.
9965                 var_types vt;
9966                 if (varNum >= 0)
9967                 {
9968                     // "Regular" (non-spill-temp) local.
9969                     vt = var_types(emitComp->lvaTable[varNum].lvType);
9970                 }
9971                 else
9972                 {
9973                     TempDsc* tmpDsc = emitComp->tmpFindNum(varNum);
9974                     vt              = tmpDsc->tdTempType();
9975                 }
9976                 if (vt == TYP_REF || vt == TYP_BYREF)
9977                     emitGCvarDeadUpd(adr + ofs2, dst);
9978             }
9979         }
9980     }
9981
9982 #ifdef DEBUG
9983     /* Make sure we set the instruction descriptor size correctly */
9984
9985     size_t expected = emitSizeOfInsDsc(id);
9986     assert(sz == expected);
9987
9988     if (emitComp->opts.disAsm || emitComp->opts.dspEmit || emitComp->verbose)
9989     {
9990         emitDispIns(id, false, dspOffs, true, emitCurCodeOffs(odst), *dp, (dst - *dp), ig);
9991     }
9992
9993     if (emitComp->compDebugBreak)
9994     {
9995         // For example, set JitBreakEmitOutputInstr=a6 will break when this method is called for
9996         // emitting instruction a6, (i.e. IN00a6 in jitdump).
9997         if ((unsigned)JitConfig.JitBreakEmitOutputInstr() == id->idDebugOnlyInfo()->idNum)
9998         {
9999             assert(!"JitBreakEmitOutputInstr reached");
10000         }
10001     }
10002 #endif
10003
10004     /* All instructions are expected to generate code */
10005
10006     assert(*dp != dst);
10007
10008     *dp = dst;
10009
10010     return sz;
10011 }
10012
10013 /*****************************************************************************/
10014 /*****************************************************************************/
10015
10016 #ifdef DEBUG
10017
10018 /*****************************************************************************
10019  *
10020  *  Display the instruction name
10021  */
10022 void emitter::emitDispInst(instruction ins)
10023 {
10024     const char* insstr = codeGen->genInsName(ins);
10025     size_t      len    = strlen(insstr);
10026
10027     /* Display the instruction name */
10028
10029     printf("%s", insstr);
10030
10031     //
10032     // Add at least one space after the instruction name
10033     // and add spaces until we have reach the normal size of 8
10034     do
10035     {
10036         printf(" ");
10037         len++;
10038     } while (len < 8);
10039 }
10040
10041 /*****************************************************************************
10042  *
10043  *  Display an reloc value
10044  *  If we are formatting for an assembly listing don't print the hex value
10045  *  since it will prevent us from doing assembly diffs
10046  */
10047 void emitter::emitDispReloc(int value, bool addComma)
10048 {
10049     if (emitComp->opts.disAsm)
10050     {
10051         printf("(reloc)");
10052     }
10053     else
10054     {
10055         printf("(reloc 0x%x)", dspPtr(value));
10056     }
10057
10058     if (addComma)
10059         printf(", ");
10060 }
10061
10062 /*****************************************************************************
10063  *
10064  *  Display an immediate value
10065  */
10066 void emitter::emitDispImm(ssize_t imm, bool addComma, bool alwaysHex /* =false */)
10067 {
10068     if (strictArmAsm)
10069     {
10070         printf("#");
10071     }
10072
10073     // Munge any pointers if we want diff-able disassembly.
10074     // Since some may be emitted as partial words, print as diffable anything that has
10075     // significant bits beyond the lowest 8-bits.
10076     if (emitComp->opts.disDiffable)
10077     {
10078         ssize_t top56bits = (imm >> 8);
10079         if ((top56bits != 0) && (top56bits != -1))
10080             imm = 0xD1FFAB1E;
10081     }
10082
10083     if (!alwaysHex && (imm > -1000) && (imm < 1000))
10084     {
10085         printf("%d", imm);
10086     }
10087     else
10088     {
10089         if ((imm < 0) && ((imm & 0xFFFFFFFF00000000LL) == 0xFFFFFFFF00000000LL))
10090         {
10091             printf("-");
10092             imm = -imm;
10093         }
10094
10095         if ((imm & 0xFFFFFFFF00000000LL) != 0)
10096         {
10097             printf("0x%llx", imm);
10098         }
10099         else
10100         {
10101             printf("0x%02x", imm);
10102         }
10103     }
10104
10105     if (addComma)
10106         printf(", ");
10107 }
10108
10109 /*****************************************************************************
10110  *
10111  *  Display a float zero constant
10112  */
10113 void emitter::emitDispFloatZero()
10114 {
10115     if (strictArmAsm)
10116     {
10117         printf("#");
10118     }
10119     printf("0.0");
10120 }
10121
10122 /*****************************************************************************
10123  *
10124  *  Display an encoded float constant value
10125  */
10126 void emitter::emitDispFloatImm(ssize_t imm8)
10127 {
10128     assert((0 <= imm8) && (imm8 <= 0x0ff));
10129     if (strictArmAsm)
10130     {
10131         printf("#");
10132     }
10133
10134     floatImm8 fpImm;
10135     fpImm.immFPIVal = (unsigned)imm8;
10136     double result   = emitDecodeFloatImm8(fpImm);
10137
10138     printf("%.4f", result);
10139 }
10140
10141 /*****************************************************************************
10142  *
10143  *  Display an immediate that is optionally LSL12.
10144  */
10145 void emitter::emitDispImmOptsLSL12(ssize_t imm, insOpts opt)
10146 {
10147     if (!strictArmAsm && insOptsLSL12(opt))
10148     {
10149         imm <<= 12;
10150     }
10151     emitDispImm(imm, false);
10152     if (strictArmAsm && insOptsLSL12(opt))
10153     {
10154         printf(", LSL #12");
10155     }
10156 }
10157
10158 /*****************************************************************************
10159  *
10160  *  Display an ARM64 condition code for the conditional instructions
10161  */
10162 void emitter::emitDispCond(insCond cond)
10163 {
10164     const static char* armCond[16] = {"eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc",
10165                                       "hi", "ls", "ge", "lt", "gt", "le", "AL", "NV"}; // The last two are invalid
10166     unsigned imm = (unsigned)cond;
10167     assert((0 <= imm) && (imm < ArrLen(armCond)));
10168     printf(armCond[imm]);
10169 }
10170
10171 /*****************************************************************************
10172  *
10173  *  Display an ARM64 flags for the conditional instructions
10174  */
10175 void emitter::emitDispFlags(insCflags flags)
10176 {
10177     const static char* armFlags[16] = {"0", "v",  "c",  "cv",  "z",  "zv",  "zc",  "zcv",
10178                                        "n", "nv", "nc", "ncv", "nz", "nzv", "nzc", "nzcv"};
10179     unsigned imm = (unsigned)flags;
10180     assert((0 <= imm) && (imm < ArrLen(armFlags)));
10181     printf(armFlags[imm]);
10182 }
10183
10184 /*****************************************************************************
10185  *
10186  *  Display an ARM64 'barrier' for the memory barrier instructions
10187  */
10188 void emitter::emitDispBarrier(insBarrier barrier)
10189 {
10190     const static char* armBarriers[16] = {"#0", "oshld", "oshst", "osh", "#4",  "nshld", "nshst", "nsh",
10191                                           "#8", "ishld", "ishst", "ish", "#12", "ld",    "st",    "sy"};
10192     unsigned imm = (unsigned)barrier;
10193     assert((0 <= imm) && (imm < ArrLen(armBarriers)));
10194     printf(armBarriers[imm]);
10195 }
10196
10197 /*****************************************************************************
10198  *
10199  *  Prints the encoding for the Shift Type encoding
10200  */
10201
10202 void emitter::emitDispShiftOpts(insOpts opt)
10203 {
10204     if (opt == INS_OPTS_LSL)
10205         printf(" LSL ");
10206     else if (opt == INS_OPTS_LSR)
10207         printf(" LSR ");
10208     else if (opt == INS_OPTS_ASR)
10209         printf(" ASR ");
10210     else if (opt == INS_OPTS_ROR)
10211         printf(" ROR ");
10212     else if (opt == INS_OPTS_MSL)
10213         printf(" MSL ");
10214     else
10215         assert(!"Bad value");
10216 }
10217
10218 /*****************************************************************************
10219  *
10220  *  Prints the encoding for the Extend Type encoding
10221  */
10222
10223 void emitter::emitDispExtendOpts(insOpts opt)
10224 {
10225     if (opt == INS_OPTS_UXTB)
10226         printf("UXTB");
10227     else if (opt == INS_OPTS_UXTH)
10228         printf("UXTH");
10229     else if (opt == INS_OPTS_UXTW)
10230         printf("UXTW");
10231     else if (opt == INS_OPTS_UXTX)
10232         printf("UXTX");
10233     else if (opt == INS_OPTS_SXTB)
10234         printf("SXTB");
10235     else if (opt == INS_OPTS_SXTH)
10236         printf("SXTH");
10237     else if (opt == INS_OPTS_SXTW)
10238         printf("SXTW");
10239     else if (opt == INS_OPTS_SXTX)
10240         printf("SXTX");
10241     else
10242         assert(!"Bad value");
10243 }
10244
10245 /*****************************************************************************
10246  *
10247  *  Prints the encoding for the Extend Type encoding in loads/stores
10248  */
10249
10250 void emitter::emitDispLSExtendOpts(insOpts opt)
10251 {
10252     if (opt == INS_OPTS_LSL)
10253         printf("LSL");
10254     else if (opt == INS_OPTS_UXTW)
10255         printf("UXTW");
10256     else if (opt == INS_OPTS_UXTX)
10257         printf("UXTX");
10258     else if (opt == INS_OPTS_SXTW)
10259         printf("SXTW");
10260     else if (opt == INS_OPTS_SXTX)
10261         printf("SXTX");
10262     else
10263         assert(!"Bad value");
10264 }
10265
10266 /*****************************************************************************
10267  *
10268  *  Display a register
10269  */
10270 void emitter::emitDispReg(regNumber reg, emitAttr attr, bool addComma)
10271 {
10272     emitAttr size = EA_SIZE(attr);
10273     printf(emitRegName(reg, size));
10274
10275     if (addComma)
10276         printf(", ");
10277 }
10278
10279 /*****************************************************************************
10280  *
10281  *  Display a vector register with an arrangement suffix
10282  */
10283 void emitter::emitDispVectorReg(regNumber reg, insOpts opt, bool addComma)
10284 {
10285     assert(isVectorRegister(reg));
10286     printf(emitVectorRegName(reg));
10287     emitDispArrangement(opt);
10288
10289     if (addComma)
10290         printf(", ");
10291 }
10292
10293 /*****************************************************************************
10294  *
10295  *  Display an vector register index suffix
10296  */
10297 void emitter::emitDispVectorRegIndex(regNumber reg, emitAttr elemsize, ssize_t index, bool addComma)
10298 {
10299     assert(isVectorRegister(reg));
10300     printf(emitVectorRegName(reg));
10301
10302     switch (elemsize)
10303     {
10304         case EA_1BYTE:
10305             printf(".b");
10306             break;
10307         case EA_2BYTE:
10308             printf(".h");
10309             break;
10310         case EA_4BYTE:
10311             printf(".s");
10312             break;
10313         case EA_8BYTE:
10314             printf(".d");
10315             break;
10316         default:
10317             assert(!"invalid elemsize");
10318             break;
10319     }
10320
10321     printf("[%d]", index);
10322
10323     if (addComma)
10324         printf(", ");
10325 }
10326
10327 /*****************************************************************************
10328  *
10329  *  Display an arrangement suffix
10330  */
10331 void emitter::emitDispArrangement(insOpts opt)
10332 {
10333     const char* str = "???";
10334
10335     switch (opt)
10336     {
10337         case INS_OPTS_8B:
10338             str = "8b";
10339             break;
10340         case INS_OPTS_16B:
10341             str = "16b";
10342             break;
10343         case INS_OPTS_4H:
10344             str = "4h";
10345             break;
10346         case INS_OPTS_8H:
10347             str = "8h";
10348             break;
10349         case INS_OPTS_2S:
10350             str = "2s";
10351             break;
10352         case INS_OPTS_4S:
10353             str = "4s";
10354             break;
10355         case INS_OPTS_1D:
10356             str = "1d";
10357             break;
10358         case INS_OPTS_2D:
10359             str = "2d";
10360             break;
10361
10362         default:
10363             assert(!"Invalid insOpt for vector register");
10364     }
10365     printf(".");
10366     printf(str);
10367 }
10368
10369 /*****************************************************************************
10370  *
10371  *  Display a register with an optional shift operation
10372  */
10373 void emitter::emitDispShiftedReg(regNumber reg, insOpts opt, ssize_t imm, emitAttr attr)
10374 {
10375     emitAttr size = EA_SIZE(attr);
10376     assert((imm & 0x003F) == imm);
10377     assert(((imm & 0x0020) == 0) || (size == EA_8BYTE));
10378
10379     printf(emitRegName(reg, size));
10380
10381     if (imm > 0)
10382     {
10383         if (strictArmAsm)
10384         {
10385             printf(",");
10386         }
10387         emitDispShiftOpts(opt);
10388         emitDispImm(imm, false);
10389     }
10390 }
10391
10392 /*****************************************************************************
10393  *
10394  *  Display a register with an optional extend and scale operations
10395  */
10396 void emitter::emitDispExtendReg(regNumber reg, insOpts opt, ssize_t imm)
10397 {
10398     assert((imm >= 0) && (imm <= 4));
10399     assert(insOptsNone(opt) || insOptsAnyExtend(opt) || (opt == INS_OPTS_LSL));
10400
10401     // size is based on the extend option, not the instr size.
10402     emitAttr size = insOpts32BitExtend(opt) ? EA_4BYTE : EA_8BYTE;
10403
10404     if (strictArmAsm)
10405     {
10406         if (insOptsNone(opt))
10407         {
10408             emitDispReg(reg, size, false);
10409         }
10410         else
10411         {
10412             emitDispReg(reg, size, true);
10413             if (opt == INS_OPTS_LSL)
10414                 printf("LSL");
10415             else
10416                 emitDispExtendOpts(opt);
10417             if ((imm > 0) || (opt == INS_OPTS_LSL))
10418             {
10419                 printf(" ");
10420                 emitDispImm(imm, false);
10421             }
10422         }
10423     }
10424     else // !strictArmAsm
10425     {
10426         if (insOptsNone(opt))
10427         {
10428             emitDispReg(reg, size, false);
10429         }
10430         else
10431         {
10432             if (opt != INS_OPTS_LSL)
10433             {
10434                 emitDispExtendOpts(opt);
10435                 printf("(");
10436                 emitDispReg(reg, size, false);
10437                 printf(")");
10438             }
10439         }
10440         if (imm > 0)
10441         {
10442             printf("*");
10443             emitDispImm(1 << imm, false);
10444         }
10445     }
10446 }
10447
10448 /*****************************************************************************
10449  *
10450  *  Display an addressing operand [reg + imm]
10451  */
10452 void emitter::emitDispAddrRI(regNumber reg, insOpts opt, ssize_t imm)
10453 {
10454     reg = encodingZRtoSP(reg); // ZR (R31) encodes the SP register
10455
10456     if (strictArmAsm)
10457     {
10458         printf("[");
10459
10460         emitDispReg(reg, EA_8BYTE, false);
10461
10462         if (!insOptsPostIndex(opt) && (imm != 0))
10463         {
10464             printf(",");
10465             emitDispImm(imm, false);
10466         }
10467         printf("]");
10468
10469         if (insOptsPreIndex(opt))
10470         {
10471             printf("!");
10472         }
10473         else if (insOptsPostIndex(opt))
10474         {
10475             printf(",");
10476             emitDispImm(imm, false);
10477         }
10478     }
10479     else // !strictArmAsm
10480     {
10481         printf("[");
10482
10483         const char* operStr = "++";
10484         if (imm < 0)
10485         {
10486             operStr = "--";
10487             imm     = -imm;
10488         }
10489
10490         if (insOptsPreIndex(opt))
10491         {
10492             printf(operStr);
10493         }
10494
10495         emitDispReg(reg, EA_8BYTE, false);
10496
10497         if (insOptsPostIndex(opt))
10498         {
10499             printf(operStr);
10500         }
10501
10502         if (insOptsIndexed(opt))
10503         {
10504             printf(", ");
10505         }
10506         else
10507         {
10508             printf("%c", operStr[1]);
10509         }
10510         emitDispImm(imm, false);
10511         printf("]");
10512     }
10513 }
10514
10515 /*****************************************************************************
10516  *
10517  *  Display an addressing operand [reg + extended reg]
10518  */
10519 void emitter::emitDispAddrRRExt(regNumber reg1, regNumber reg2, insOpts opt, bool isScaled, emitAttr size)
10520 {
10521     reg1 = encodingZRtoSP(reg1); // ZR (R31) encodes the SP register
10522
10523     unsigned scale = 0;
10524     if (isScaled)
10525     {
10526         scale = NaturalScale_helper(size);
10527     }
10528
10529     printf("[");
10530
10531     if (strictArmAsm)
10532     {
10533         emitDispReg(reg1, EA_8BYTE, true);
10534         emitDispExtendReg(reg2, opt, scale);
10535     }
10536     else // !strictArmAsm
10537     {
10538         emitDispReg(reg1, EA_8BYTE, false);
10539         printf("+");
10540         emitDispExtendReg(reg2, opt, scale);
10541     }
10542
10543     printf("]");
10544 }
10545
10546 /*****************************************************************************
10547  *
10548  *  Display (optionally) the instruction encoding in hex
10549  */
10550
10551 void emitter::emitDispInsHex(BYTE* code, size_t sz)
10552 {
10553     // We do not display the instruction hex if we want diff-able disassembly
10554     if (!emitComp->opts.disDiffable)
10555     {
10556         if (sz == 4)
10557         {
10558             printf("  %08X    ", (*((code_t*)code)));
10559         }
10560         else
10561         {
10562             printf("              ");
10563         }
10564     }
10565 }
10566
10567 /****************************************************************************
10568  *
10569  *  Display the given instruction.
10570  */
10571
10572 void emitter::emitDispIns(
10573     instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* pCode, size_t sz, insGroup* ig)
10574 {
10575     if (EMITVERBOSE)
10576     {
10577         unsigned idNum =
10578             id->idDebugOnlyInfo()->idNum; // Do not remove this!  It is needed for VisualStudio conditional breakpoints
10579
10580         printf("IN%04x: ", idNum);
10581     }
10582
10583     if (pCode == NULL)
10584         sz = 0;
10585
10586     if (!emitComp->opts.dspEmit && !isNew && !asmfm && sz)
10587         doffs = true;
10588
10589     /* Display the instruction offset */
10590
10591     emitDispInsOffs(offset, doffs);
10592
10593     /* Display the instruction hex code */
10594
10595     emitDispInsHex(pCode, sz);
10596
10597     printf("      ");
10598
10599     /* Get the instruction and format */
10600
10601     instruction ins = id->idIns();
10602     insFormat   fmt = id->idInsFmt();
10603
10604     emitDispInst(ins);
10605
10606     /* If this instruction has just been added, check its size */
10607
10608     assert(isNew == false || (int)emitSizeOfInsDsc(id) == emitCurIGfreeNext - (BYTE*)id);
10609
10610     /* Figure out the operand size */
10611     emitAttr size = id->idOpSize();
10612     emitAttr attr = size;
10613     if (id->idGCref() == GCT_GCREF)
10614         attr = EA_GCREF;
10615     else if (id->idGCref() == GCT_BYREF)
10616         attr = EA_BYREF;
10617
10618     switch (fmt)
10619     {
10620         code_t       code;
10621         ssize_t      imm;
10622         int          doffs;
10623         bool         isExtendAlias;
10624         bool         canEncode;
10625         bitMaskImm   bmi;
10626         halfwordImm  hwi;
10627         condFlagsImm cfi;
10628         unsigned     scale;
10629         unsigned     immShift;
10630         bool         hasShift;
10631         ssize_t      offs;
10632         const char*  methodName;
10633         emitAttr     elemsize;
10634         emitAttr     datasize;
10635         emitAttr     srcsize;
10636         emitAttr     dstsize;
10637         ssize_t      index;
10638         ssize_t      index2;
10639
10640         case IF_BI_0A: // BI_0A   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
10641         case IF_BI_0B: // BI_0B   ......iiiiiiiiii iiiiiiiiiii.....               simm19:00
10642         case IF_LARGEJMP:
10643         {
10644             if (fmt == IF_LARGEJMP)
10645             {
10646                 printf("(LARGEJMP)");
10647             }
10648             if (id->idAddr()->iiaHasInstrCount())
10649             {
10650                 int instrCount = id->idAddr()->iiaGetInstrCount();
10651
10652                 if (ig == nullptr)
10653                 {
10654                     printf("pc%s%d instructions", (instrCount >= 0) ? "+" : "", instrCount);
10655                 }
10656                 else
10657                 {
10658                     unsigned       insNum  = emitFindInsNum(ig, id);
10659                     UNATIVE_OFFSET srcOffs = ig->igOffs + emitFindOffset(ig, insNum + 1);
10660                     UNATIVE_OFFSET dstOffs = ig->igOffs + emitFindOffset(ig, insNum + 1 + instrCount);
10661                     ssize_t        relOffs = (ssize_t)(emitOffsetToPtr(dstOffs) - emitOffsetToPtr(srcOffs));
10662                     printf("pc%s%d (%d instructions)", (relOffs >= 0) ? "+" : "", relOffs, instrCount);
10663                 }
10664             }
10665             else if (id->idIsBound())
10666             {
10667                 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10668             }
10669             else
10670             {
10671                 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10672             }
10673         }
10674         break;
10675
10676         case IF_BI_0C: // BI_0C   ......iiiiiiiiii iiiiiiiiiiiiiiii               simm26:00
10677             if (id->idIsCallAddr())
10678             {
10679                 offs       = (ssize_t)id->idAddr()->iiaAddr;
10680                 methodName = "";
10681             }
10682             else
10683             {
10684                 offs       = 0;
10685                 methodName = emitComp->eeGetMethodFullName((CORINFO_METHOD_HANDLE)id->idDebugOnlyInfo()->idMemCookie);
10686             }
10687
10688             if (offs)
10689             {
10690                 if (id->idIsDspReloc())
10691                     printf("reloc ");
10692                 printf("%08X", offs);
10693             }
10694             else
10695             {
10696                 printf("%s", methodName);
10697             }
10698             break;
10699
10700         case IF_BI_1A: // BI_1A   ......iiiiiiiiii iiiiiiiiiiittttt      Rt       simm19:00
10701             assert(insOptsNone(id->idInsOpt()));
10702             emitDispReg(id->idReg1(), size, true);
10703             if (id->idIsBound())
10704             {
10705                 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10706             }
10707             else
10708             {
10709                 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10710             }
10711             break;
10712
10713         case IF_BI_1B: // BI_1B   B.......bbbbbiii iiiiiiiiiiittttt      Rt imm6, simm14:00
10714             assert(insOptsNone(id->idInsOpt()));
10715             emitDispReg(id->idReg1(), size, true);
10716             emitDispImm(emitGetInsSC(id), true);
10717             if (id->idIsBound())
10718             {
10719                 printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10720             }
10721             else
10722             {
10723                 printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10724             }
10725             break;
10726
10727         case IF_BR_1A: // BR_1A   ................ ......nnnnn.....         Rn
10728             assert(insOptsNone(id->idInsOpt()));
10729             emitDispReg(id->idReg1(), size, false);
10730             break;
10731
10732         case IF_BR_1B: // BR_1B   ................ ......nnnnn.....         Rn
10733             assert(insOptsNone(id->idInsOpt()));
10734             emitDispReg(id->idReg3(), size, false);
10735             break;
10736
10737         case IF_LS_1A: // LS_1A   XX...V..iiiiiiii iiiiiiiiiiittttt      Rt    PC imm(1MB)
10738         case IF_DI_1E: // DI_1E   .ii.....iiiiiiii iiiiiiiiiiiddddd      Rd       simm21
10739         case IF_LARGELDC:
10740         case IF_LARGEADR:
10741             assert(insOptsNone(id->idInsOpt()));
10742             emitDispReg(id->idReg1(), size, true);
10743             imm = emitGetInsSC(id);
10744
10745             /* Is this actually a reference to a data section? */
10746             if (fmt == IF_LARGEADR)
10747             {
10748                 printf("(LARGEADR)");
10749             }
10750             else if (fmt == IF_LARGELDC)
10751             {
10752                 printf("(LARGELDC)");
10753             }
10754
10755             printf("[");
10756             if (id->idAddr()->iiaIsJitDataOffset())
10757             {
10758                 doffs = Compiler::eeGetJitDataOffs(id->idAddr()->iiaFieldHnd);
10759                 /* Display a data section reference */
10760
10761                 if (doffs & 1)
10762                     printf("@CNS%02u", doffs - 1);
10763                 else
10764                     printf("@RWD%02u", doffs);
10765
10766                 if (imm != 0)
10767                     printf("%+Id", imm);
10768             }
10769             else
10770             {
10771                 assert(imm == 0);
10772                 if (id->idIsReloc())
10773                 {
10774                     printf("RELOC ");
10775                     emitDispImm((ssize_t)id->idAddr()->iiaAddr, false);
10776                 }
10777                 else if (id->idIsBound())
10778                 {
10779                     printf("G_M%03u_IG%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaIGlabel->igNum);
10780                 }
10781                 else
10782                 {
10783                     printf("L_M%03u_BB%02u", Compiler::s_compMethodsCount, id->idAddr()->iiaBBlabel->bbNum);
10784                 }
10785             }
10786             printf("]");
10787             break;
10788
10789         case IF_LS_2A: // LS_2A   .X.......X...... ......nnnnnttttt      Rt Rn
10790             assert(insOptsNone(id->idInsOpt()));
10791             assert(emitGetInsSC(id) == 0);
10792             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10793             emitDispAddrRI(id->idReg2(), id->idInsOpt(), 0);
10794             break;
10795
10796         case IF_LS_2B: // LS_2B   .X.......Xiiiiii iiiiiinnnnnttttt      Rt Rn    imm(0-4095)
10797             assert(insOptsNone(id->idInsOpt()));
10798             imm   = emitGetInsSC(id);
10799             scale = NaturalScale_helper(emitInsLoadStoreSize(id));
10800             imm <<= scale; // The immediate is scaled by the size of the ld/st
10801             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10802             emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
10803             break;
10804
10805         case IF_LS_2C: // LS_2C   .X.......X.iiiii iiiiPPnnnnnttttt      Rt Rn    imm(-256..+255) no/pre/post inc
10806             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
10807             imm = emitGetInsSC(id);
10808             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10809             emitDispAddrRI(id->idReg2(), id->idInsOpt(), imm);
10810             break;
10811
10812         case IF_LS_3A: // LS_3A   .X.......X.mmmmm oooS..nnnnnttttt      Rt Rn Rm ext(Rm) LSL {}
10813             assert(insOptsLSExtend(id->idInsOpt()));
10814             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10815             if (id->idIsLclVar())
10816             {
10817                 emitDispAddrRRExt(id->idReg2(), codeGen->rsGetRsvdReg(), id->idInsOpt(), false, size);
10818             }
10819             else
10820             {
10821                 emitDispAddrRRExt(id->idReg2(), id->idReg3(), id->idInsOpt(), id->idReg3Scaled(), size);
10822             }
10823             break;
10824
10825         case IF_LS_3B: // LS_3B   X............... .aaaaannnnnddddd      Rt Ra Rn
10826             assert(insOptsNone(id->idInsOpt()));
10827             assert(emitGetInsSC(id) == 0);
10828             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10829             emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10830             emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
10831             break;
10832
10833         case IF_LS_3C: // LS_3C   X.........iiiiii iaaaaannnnnddddd      Rt Ra Rn imm(im7,sh)
10834             assert(insOptsNone(id->idInsOpt()) || insOptsIndexed(id->idInsOpt()));
10835             imm   = emitGetInsSC(id);
10836             scale = NaturalScale_helper(emitInsLoadStoreSize(id));
10837             imm <<= scale;
10838             emitDispReg(id->idReg1(), emitInsTargetRegSize(id), true);
10839             emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10840             emitDispAddrRI(id->idReg3(), id->idInsOpt(), imm);
10841             break;
10842
10843         case IF_LS_3D: // LS_3D   .X.......X.mmmmm ......nnnnnttttt      Wm Rt Rn
10844             assert(insOptsNone(id->idInsOpt()));
10845             emitDispReg(id->idReg1(), EA_4BYTE, true);
10846             emitDispReg(id->idReg2(), emitInsTargetRegSize(id), true);
10847             emitDispAddrRI(id->idReg3(), id->idInsOpt(), 0);
10848             break;
10849
10850         case IF_DI_1A: // DI_1A   X.......shiiiiii iiiiiinnnnn.....      Rn       imm(i12,sh)
10851             emitDispReg(id->idReg1(), size, true);
10852             emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
10853             break;
10854
10855         case IF_DI_1B: // DI_1B   X........hwiiiii iiiiiiiiiiiddddd      Rd       imm(i16,hw)
10856             emitDispReg(id->idReg1(), size, true);
10857             hwi.immHWVal = (unsigned)emitGetInsSC(id);
10858             if (ins == INS_mov)
10859             {
10860                 emitDispImm(emitDecodeHalfwordImm(hwi, size), false);
10861             }
10862             else // movz, movn, movk
10863             {
10864                 emitDispImm(hwi.immVal, false);
10865                 if (hwi.immHW != 0)
10866                 {
10867                     emitDispShiftOpts(INS_OPTS_LSL);
10868                     emitDispImm(hwi.immHW * 16, false);
10869                 }
10870             }
10871             break;
10872
10873         case IF_DI_1C: // DI_1C   X........Nrrrrrr ssssssnnnnn.....         Rn    imm(N,r,s)
10874             emitDispReg(id->idReg1(), size, true);
10875             bmi.immNRS = (unsigned)emitGetInsSC(id);
10876             emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
10877             break;
10878
10879         case IF_DI_1D: // DI_1D   X........Nrrrrrr ssssss.....ddddd      Rd       imm(N,r,s)
10880             emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
10881             bmi.immNRS = (unsigned)emitGetInsSC(id);
10882             emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
10883             break;
10884
10885         case IF_DI_2A: // DI_2A   X.......shiiiiii iiiiiinnnnnddddd      Rd Rn    imm(i12,sh)
10886             if ((ins == INS_add) || (ins == INS_sub))
10887             {
10888                 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
10889                 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
10890             }
10891             else
10892             {
10893                 emitDispReg(id->idReg1(), size, true);
10894                 emitDispReg(id->idReg2(), size, true);
10895             }
10896             emitDispImmOptsLSL12(emitGetInsSC(id), id->idInsOpt());
10897             break;
10898
10899         case IF_DI_2B: // DI_2B   X........X.nnnnn ssssssnnnnnddddd      Rd Rn    imm(0-63)
10900             emitDispReg(id->idReg1(), size, true);
10901             emitDispReg(id->idReg2(), size, true);
10902             emitDispImm(emitGetInsSC(id), false);
10903             break;
10904
10905         case IF_DI_2C: // DI_2C   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imm(N,r,s)
10906             if (ins == INS_ands)
10907             {
10908                 emitDispReg(id->idReg1(), size, true);
10909             }
10910             else
10911             {
10912                 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
10913             }
10914             emitDispReg(id->idReg2(), size, true);
10915             bmi.immNRS = (unsigned)emitGetInsSC(id);
10916             emitDispImm(emitDecodeBitMaskImm(bmi, size), false);
10917             break;
10918
10919         case IF_DI_2D: // DI_2D   X........Nrrrrrr ssssssnnnnnddddd      Rd Rn    imr, ims   (N,r,s)
10920             emitDispReg(id->idReg1(), size, true);
10921             emitDispReg(id->idReg2(), size, true);
10922
10923             imm        = emitGetInsSC(id);
10924             bmi.immNRS = (unsigned)imm;
10925
10926             switch (ins)
10927             {
10928                 case INS_bfm:
10929                 case INS_sbfm:
10930                 case INS_ubfm:
10931                     emitDispImm(bmi.immR, true);
10932                     emitDispImm(bmi.immS, false);
10933                     break;
10934
10935                 case INS_bfi:
10936                 case INS_sbfiz:
10937                 case INS_ubfiz:
10938                     emitDispImm(getBitWidth(size) - bmi.immR, true);
10939                     emitDispImm(bmi.immS + 1, false);
10940                     break;
10941
10942                 case INS_bfxil:
10943                 case INS_sbfx:
10944                 case INS_ubfx:
10945                     emitDispImm(bmi.immR, true);
10946                     emitDispImm(bmi.immS - bmi.immR + 1, false);
10947                     break;
10948
10949                 case INS_asr:
10950                 case INS_lsr:
10951                 case INS_lsl:
10952                     emitDispImm(imm, false);
10953                     break;
10954
10955                 default:
10956                     assert(!"Unexpected instruction in IF_DI_2D");
10957             }
10958
10959             break;
10960
10961         case IF_DI_1F: // DI_1F   X..........iiiii cccc..nnnnn.nzcv      Rn imm5  nzcv cond
10962             emitDispReg(id->idReg1(), size, true);
10963             cfi.immCFVal = (unsigned)emitGetInsSC(id);
10964             emitDispImm(cfi.imm5, true);
10965             emitDispFlags(cfi.flags);
10966             printf(",");
10967             emitDispCond(cfi.cond);
10968             break;
10969
10970         case IF_DR_1D: // DR_1D   X............... cccc.......mmmmm      Rd       cond
10971             emitDispReg(id->idReg1(), size, true);
10972             cfi.immCFVal = (unsigned)emitGetInsSC(id);
10973             emitDispCond(cfi.cond);
10974             break;
10975
10976         case IF_DR_2A: // DR_2A   X..........mmmmm ......nnnnn.....         Rn Rm
10977             emitDispReg(id->idReg1(), size, true);
10978             emitDispReg(id->idReg2(), size, false);
10979             break;
10980
10981         case IF_DR_2B: // DR_2B   X.......sh.mmmmm ssssssnnnnn.....         Rn Rm {LSL,LSR,ASR,ROR} imm(0-63)
10982             emitDispReg(id->idReg1(), size, true);
10983             emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
10984             break;
10985
10986         case IF_DR_2C: // DR_2C   X..........mmmmm ooosssnnnnn.....         Rn Rm ext(Rm) LSL imm(0-4)
10987             emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
10988             imm = emitGetInsSC(id);
10989             emitDispExtendReg(id->idReg2(), id->idInsOpt(), imm);
10990             break;
10991
10992         case IF_DR_2D: // DR_2D   X..........nnnnn cccc..nnnnnddddd      Rd Rn    cond
10993             emitDispReg(id->idReg1(), size, true);
10994             emitDispReg(id->idReg2(), size, true);
10995             cfi.immCFVal = (unsigned)emitGetInsSC(id);
10996             emitDispCond(cfi.cond);
10997             break;
10998
10999         case IF_DR_2E: // DR_2E   X..........mmmmm ...........ddddd      Rd    Rm
11000             emitDispReg(id->idReg1(), size, true);
11001             emitDispReg(id->idReg2(), size, false);
11002             break;
11003
11004         case IF_DR_2F: // DR_2F   X.......sh.mmmmm ssssss.....ddddd      Rd    Rm {LSL,LSR,ASR} imm(0-63)
11005             emitDispReg(id->idReg1(), size, true);
11006             emitDispShiftedReg(id->idReg2(), id->idInsOpt(), emitGetInsSC(id), size);
11007             break;
11008
11009         case IF_DR_2G: // DR_2G   X............... ......nnnnnddddd      Rd Rn
11010             emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11011             emitDispReg(encodingZRtoSP(id->idReg2()), size, false);
11012             break;
11013
11014         case IF_DR_2H: // DR_2H   X........X...... ......nnnnnddddd      Rd Rn
11015             emitDispReg(id->idReg1(), size, true);
11016             emitDispReg(id->idReg2(), size, false);
11017             break;
11018
11019         case IF_DR_2I: // DR_2I   X..........mmmmm cccc..nnnnn.nzcv      Rn Rm    nzcv cond
11020             emitDispReg(id->idReg1(), size, true);
11021             emitDispReg(id->idReg2(), size, true);
11022             cfi.immCFVal = (unsigned)emitGetInsSC(id);
11023             emitDispFlags(cfi.flags);
11024             printf(",");
11025             emitDispCond(cfi.cond);
11026             break;
11027
11028         case IF_DR_3A: // DR_3A   X..........mmmmm ......nnnnnmmmmm      Rd Rn Rm
11029             if ((ins == INS_add) || (ins == INS_sub))
11030             {
11031                 emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11032                 emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11033             }
11034             else if ((ins == INS_smull) || (ins == INS_smulh))
11035             {
11036                 // Rd is always 8 bytes
11037                 emitDispReg(id->idReg1(), EA_8BYTE, true);
11038
11039                 // Rn, Rm effective size depends on instruction type
11040                 size = (ins == INS_smulh) ? EA_8BYTE : EA_4BYTE;
11041                 emitDispReg(id->idReg2(), size, true);
11042             }
11043             else
11044             {
11045                 emitDispReg(id->idReg1(), size, true);
11046                 emitDispReg(id->idReg2(), size, true);
11047             }
11048             if (id->idIsLclVar())
11049             {
11050                 emitDispReg(codeGen->rsGetRsvdReg(), size, false);
11051             }
11052             else
11053             {
11054                 emitDispReg(id->idReg3(), size, false);
11055             }
11056
11057             break;
11058
11059         case IF_DR_3B: // DR_3B   X.......sh.mmmmm ssssssnnnnnddddd      Rd Rn Rm {LSL,LSR,ASR} imm(0-63)
11060             emitDispReg(id->idReg1(), size, true);
11061             emitDispReg(id->idReg2(), size, true);
11062             emitDispShiftedReg(id->idReg3(), id->idInsOpt(), emitGetInsSC(id), size);
11063             break;
11064
11065         case IF_DR_3C: // DR_3C   X..........mmmmm ooosssnnnnnddddd      Rd Rn Rm ext(Rm) LSL imm(0-4)
11066             emitDispReg(encodingZRtoSP(id->idReg1()), size, true);
11067             emitDispReg(encodingZRtoSP(id->idReg2()), size, true);
11068             imm = emitGetInsSC(id);
11069             emitDispExtendReg(id->idReg3(), id->idInsOpt(), imm);
11070             break;
11071
11072         case IF_DR_3D: // DR_3D   X..........mmmmm cccc..nnnnnmmmmm      Rd Rn Rm cond
11073             emitDispReg(id->idReg1(), size, true);
11074             emitDispReg(id->idReg2(), size, true);
11075             emitDispReg(id->idReg3(), size, true);
11076             cfi.immCFVal = (unsigned)emitGetInsSC(id);
11077             emitDispCond(cfi.cond);
11078             break;
11079
11080         case IF_DR_3E: // DR_3E   X........X.mmmmm ssssssnnnnnddddd      Rd Rn Rm imm(0-63)
11081             emitDispReg(id->idReg1(), size, true);
11082             emitDispReg(id->idReg2(), size, true);
11083             emitDispReg(id->idReg3(), size, true);
11084             emitDispImm(emitGetInsSC(id), false);
11085             break;
11086
11087         case IF_DR_4A: // DR_4A   X..........mmmmm .aaaaannnnnmmmmm      Rd Rn Rm Ra
11088             emitDispReg(id->idReg1(), size, true);
11089             emitDispReg(id->idReg2(), size, true);
11090             emitDispReg(id->idReg3(), size, true);
11091             emitDispReg(id->idReg4(), size, false);
11092             break;
11093
11094         case IF_DV_1A: // DV_1A   .........X.iiiii iii........ddddd      Vd imm8 (fmov - immediate scalar)
11095             elemsize = id->idOpSize();
11096             emitDispReg(id->idReg1(), elemsize, true);
11097             emitDispFloatImm(emitGetInsSC(id));
11098             break;
11099
11100         case IF_DV_1B: // DV_1B   .QX..........iii cmod..iiiiiddddd      Vd imm8 (immediate vector)
11101             imm      = emitGetInsSC(id) & 0x0ff;
11102             immShift = (emitGetInsSC(id) & 0x700) >> 8;
11103             hasShift = (immShift != 0);
11104             elemsize = optGetElemsize(id->idInsOpt());
11105             if (id->idInsOpt() == INS_OPTS_1D)
11106             {
11107                 assert(elemsize == size);
11108                 emitDispReg(id->idReg1(), size, true);
11109             }
11110             else
11111             {
11112                 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11113             }
11114             if (ins == INS_fmov)
11115             {
11116                 emitDispFloatImm(imm);
11117                 assert(hasShift == false);
11118             }
11119             else
11120             {
11121                 if (elemsize == EA_8BYTE)
11122                 {
11123                     assert(ins == INS_movi);
11124                     ssize_t       imm64 = 0;
11125                     const ssize_t mask8 = 0xFF;
11126                     for (unsigned b = 0; b < 8; b++)
11127                     {
11128                         if (imm & (1 << b))
11129                         {
11130                             imm64 |= (mask8 << (b * 8));
11131                         }
11132                     }
11133                     emitDispImm(imm64, hasShift, true);
11134                 }
11135                 else
11136                 {
11137                     emitDispImm(imm, hasShift, true);
11138                 }
11139                 if (hasShift)
11140                 {
11141                     insOpts  opt   = (immShift & 0x4) ? INS_OPTS_MSL : INS_OPTS_LSL;
11142                     unsigned shift = (immShift & 0x3) * 8;
11143                     emitDispShiftOpts(opt);
11144                     emitDispImm(shift, false);
11145                 }
11146             }
11147             break;
11148
11149         case IF_DV_1C: // DV_1C   .........X...... ......nnnnn.....      Vn #0.0 (fcmp - with zero)
11150             elemsize = id->idOpSize();
11151             emitDispReg(id->idReg1(), elemsize, true);
11152             emitDispFloatZero();
11153             break;
11154
11155         case IF_DV_2A: // DV_2A   .Q.......X...... ......nnnnnddddd      Vd Vn   (fabs, fcvt - vector)
11156         case IF_DV_2M: // DV_2M   .Q......XX...... ......nnnnnddddd      Vd Vn   (abs, neg   - vector)
11157             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11158             emitDispVectorReg(id->idReg2(), id->idInsOpt(), false);
11159             break;
11160
11161         case IF_DV_2N: // DV_2N   .........iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - scalar)
11162             elemsize = id->idOpSize();
11163             emitDispReg(id->idReg1(), elemsize, true);
11164             emitDispReg(id->idReg2(), elemsize, true);
11165             emitDispImm(emitGetInsSC(id), false);
11166             break;
11167
11168         case IF_DV_2O: // DV_2O   .Q.......iiiiiii ......nnnnnddddd      Vd Vn imm   (shift - vector)
11169             imm = emitGetInsSC(id);
11170             // Do we have a sxtl or uxtl instruction?
11171             isExtendAlias = ((ins == INS_sxtl) || (ins == INS_sxtl2) || (ins == INS_uxtl) || (ins == INS_uxtl2));
11172             code          = emitInsCode(ins, fmt);
11173             if (code & 0x00008000) // widen/narrow opcodes
11174             {
11175                 if (code & 0x00002000) // SHL opcodes
11176                 {
11177                     emitDispVectorReg(id->idReg1(), optWidenElemsize(id->idInsOpt()), true);
11178                     emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11179                 }
11180                 else // SHR opcodes
11181                 {
11182                     emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11183                     emitDispVectorReg(id->idReg2(), optWidenElemsize(id->idInsOpt()), !isExtendAlias);
11184                 }
11185             }
11186             else
11187             {
11188                 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11189                 emitDispVectorReg(id->idReg2(), id->idInsOpt(), !isExtendAlias);
11190             }
11191             // Print the immediate unless we have a sxtl or uxtl instruction
11192             if (!isExtendAlias)
11193             {
11194                 emitDispImm(imm, false);
11195             }
11196             break;
11197
11198         case IF_DV_2B: // DV_2B   .Q.........iiiii ......nnnnnddddd      Rd Vn[] (umov/smov    - to general)
11199             srcsize = id->idOpSize();
11200             index   = emitGetInsSC(id);
11201             if (ins == INS_smov)
11202             {
11203                 dstsize = EA_8BYTE;
11204             }
11205             else // INS_umov or INS_mov
11206             {
11207                 dstsize = (srcsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE;
11208             }
11209             emitDispReg(id->idReg1(), dstsize, true);
11210             emitDispVectorRegIndex(id->idReg2(), srcsize, index, false);
11211             break;
11212
11213         case IF_DV_2C: // DV_2C   .Q.........iiiii ......nnnnnddddd      Vd Rn   (dup/ins - vector from general)
11214             if (ins == INS_dup)
11215             {
11216                 datasize = id->idOpSize();
11217                 assert(isValidVectorDatasize(datasize));
11218                 assert(isValidArrangement(datasize, id->idInsOpt()));
11219                 elemsize = optGetElemsize(id->idInsOpt());
11220                 emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11221             }
11222             else // INS_ins
11223             {
11224                 elemsize = id->idOpSize();
11225                 index    = emitGetInsSC(id);
11226                 assert(isValidVectorElemsize(elemsize));
11227                 emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11228             }
11229             emitDispReg(id->idReg2(), (elemsize == EA_8BYTE) ? EA_8BYTE : EA_4BYTE, false);
11230             break;
11231
11232         case IF_DV_2D: // DV_2D   .Q.........iiiii ......nnnnnddddd      Vd Vn[]   (dup - vector)
11233             datasize = id->idOpSize();
11234             assert(isValidVectorDatasize(datasize));
11235             assert(isValidArrangement(datasize, id->idInsOpt()));
11236             elemsize = optGetElemsize(id->idInsOpt());
11237             index    = emitGetInsSC(id);
11238             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11239             emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11240             break;
11241
11242         case IF_DV_2E: // DV_2E   ...........iiiii ......nnnnnddddd      Vd Vn[]   (dup - scalar)
11243             elemsize = id->idOpSize();
11244             index    = emitGetInsSC(id);
11245             emitDispReg(id->idReg1(), elemsize, true);
11246             emitDispVectorRegIndex(id->idReg2(), elemsize, index, false);
11247             break;
11248
11249         case IF_DV_2F: // DV_2F   ...........iiiii .jjjj.nnnnnddddd      Vd[] Vn[] (ins - element)
11250             imm      = emitGetInsSC(id);
11251             index    = (imm >> 4) & 0xf;
11252             index2   = imm & 0xf;
11253             elemsize = id->idOpSize();
11254             emitDispVectorRegIndex(id->idReg1(), elemsize, index, true);
11255             emitDispVectorRegIndex(id->idReg2(), elemsize, index2, false);
11256             break;
11257
11258         case IF_DV_2G: // DV_2G   .........X...... ......nnnnnddddd      Vd Vn      (fmov, fcvtXX - register)
11259         case IF_DV_2K: // DV_2K   .........X.mmmmm ......nnnnn.....      Vn Vm      (fcmp)
11260         case IF_DV_2L: // DV_2L   ........XX...... ......nnnnnddddd      Vd Vn      (abs, neg - scalar)
11261             elemsize = id->idOpSize();
11262             emitDispReg(id->idReg1(), elemsize, true);
11263             emitDispReg(id->idReg2(), elemsize, false);
11264             break;
11265
11266         case IF_DV_2H: // DV_2H   X........X...... ......nnnnnddddd      Rd Vn      (fmov, fcvtXX - to general)
11267         case IF_DV_2I: // DV_2I   X........X...... ......nnnnnddddd      Vd Rn      (fmov, Xcvtf - from general)
11268         case IF_DV_2J: // DV_2J   ........SS.....D D.....nnnnnddddd      Vd Vn      (fcvt)
11269             dstsize = optGetDstsize(id->idInsOpt());
11270             srcsize = optGetSrcsize(id->idInsOpt());
11271
11272             emitDispReg(id->idReg1(), dstsize, true);
11273             emitDispReg(id->idReg2(), srcsize, false);
11274             break;
11275
11276         case IF_DV_3A: // DV_3A   .Q......XX.mmmmm ......nnnnnddddd      Vd Vn Vm  (vector)
11277         case IF_DV_3B: // DV_3B   .Q.........mmmmm ......nnnnnddddd      Vd Vn Vm  (vector)
11278             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11279             emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11280             emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11281             break;
11282
11283         case IF_DV_3C: // DV_3C   .Q.........mmmmm ......nnnnnddddd      Vd Vn Vm  (vector)
11284             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11285             if (ins != INS_mov)
11286             {
11287                 emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11288             }
11289             emitDispVectorReg(id->idReg3(), id->idInsOpt(), false);
11290             break;
11291
11292         case IF_DV_3AI: // DV_3AI  .Q......XXLMmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector by elem)
11293         case IF_DV_3BI: // DV_3BI  .Q........Lmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (vector by elem)
11294             emitDispVectorReg(id->idReg1(), id->idInsOpt(), true);
11295             emitDispVectorReg(id->idReg2(), id->idInsOpt(), true);
11296             elemsize = optGetElemsize(id->idInsOpt());
11297             emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11298             break;
11299
11300         case IF_DV_3D: // DV_3D   .........X.mmmmm ......nnnnnddddd      Vd Vn Vm  (scalar)
11301         case IF_DV_3E: // DV_3E   ...........mmmmm ......nnnnnddddd      Vd Vn Vm  (scalar)
11302             emitDispReg(id->idReg1(), size, true);
11303             emitDispReg(id->idReg2(), size, true);
11304             emitDispReg(id->idReg3(), size, false);
11305             break;
11306
11307         case IF_DV_3DI: // DV_3DI  .........XLmmmmm ....H.nnnnnddddd      Vd Vn Vm[] (scalar by elem)
11308             emitDispReg(id->idReg1(), size, true);
11309             emitDispReg(id->idReg2(), size, true);
11310             elemsize = size;
11311             emitDispVectorRegIndex(id->idReg3(), elemsize, emitGetInsSC(id), false);
11312             break;
11313
11314         case IF_DV_4A: // DV_4A   .........X.mmmmm .aaaaannnnnddddd      Vd Va Vn Vm (scalar)
11315             emitDispReg(id->idReg1(), size, true);
11316             emitDispReg(id->idReg2(), size, true);
11317             emitDispReg(id->idReg3(), size, true);
11318             emitDispReg(id->idReg4(), size, false);
11319             break;
11320
11321         case IF_SN_0A: // SN_0A   ................ ................
11322             break;
11323
11324         case IF_SI_0A: // SI_0A   ...........iiiii iiiiiiiiiii.....               imm16
11325             emitDispImm(emitGetInsSC(id), false);
11326             break;
11327
11328         case IF_SI_0B: // SI_0B   ................ ....bbbb........               imm4 - barrier
11329             emitDispBarrier((insBarrier)emitGetInsSC(id));
11330             break;
11331
11332         default:
11333             printf("unexpected format %s", emitIfName(id->idInsFmt()));
11334             assert(!"unexpectedFormat");
11335             break;
11336     }
11337
11338     if (id->idDebugOnlyInfo()->idVarRefOffs)
11339     {
11340         printf("\t// ");
11341         emitDispFrameRef(id->idAddr()->iiaLclVar.lvaVarNum(), id->idAddr()->iiaLclVar.lvaOffset(),
11342                          id->idDebugOnlyInfo()->idVarRefOffs, asmfm);
11343     }
11344
11345     printf("\n");
11346 }
11347
11348 /*****************************************************************************
11349  *
11350  *  Display a stack frame reference.
11351  */
11352
11353 void emitter::emitDispFrameRef(int varx, int disp, int offs, bool asmfm)
11354 {
11355     printf("[");
11356
11357     if (varx < 0)
11358         printf("TEMP_%02u", -varx);
11359     else
11360         emitComp->gtDispLclVar(+varx, false);
11361
11362     if (disp < 0)
11363         printf("-0x%02x", -disp);
11364     else if (disp > 0)
11365         printf("+0x%02x", +disp);
11366
11367     printf("]");
11368
11369     if (varx >= 0 && emitComp->opts.varNames)
11370     {
11371         LclVarDsc*  varDsc;
11372         const char* varName;
11373
11374         assert((unsigned)varx < emitComp->lvaCount);
11375         varDsc  = emitComp->lvaTable + varx;
11376         varName = emitComp->compLocalVarName(varx, offs);
11377
11378         if (varName)
11379         {
11380             printf("'%s", varName);
11381
11382             if (disp < 0)
11383                 printf("-%d", -disp);
11384             else if (disp > 0)
11385                 printf("+%d", +disp);
11386
11387             printf("'");
11388         }
11389     }
11390 }
11391
11392 #endif // DEBUG
11393
11394 // Generate code for a load or store operation with a potentially complex addressing mode
11395 // This method handles the case of a GT_IND with contained GT_LEA op1 of the x86 form [base + index*sccale + offset]
11396 // Since Arm64 does not directly support this complex of an addressing mode
11397 // we may generates up to three instructions for this for Arm64
11398 //
11399 void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataReg, GenTreeIndir* indir)
11400 {
11401     emitAttr ldstAttr = isVectorRegister(dataReg) ? attr : emitInsAdjustLoadStoreAttr(ins, attr);
11402
11403     GenTree* addr = indir->Addr();
11404
11405     if (addr->isContained())
11406     {
11407         assert(addr->OperGet() == GT_LCL_VAR_ADDR || addr->OperGet() == GT_LEA);
11408
11409         int   offset = 0;
11410         DWORD lsl    = 0;
11411
11412         if (addr->OperGet() == GT_LEA)
11413         {
11414             offset = addr->AsAddrMode()->Offset();
11415             if (addr->AsAddrMode()->gtScale > 0)
11416             {
11417                 assert(isPow2(addr->AsAddrMode()->gtScale));
11418                 BitScanForward(&lsl, addr->AsAddrMode()->gtScale);
11419             }
11420         }
11421
11422         GenTree* memBase = indir->Base();
11423
11424         if (indir->HasIndex())
11425         {
11426             GenTree* index = indir->Index();
11427
11428             if (offset != 0)
11429             {
11430                 regNumber tmpReg = indir->GetSingleTempReg();
11431
11432                 emitAttr addType = varTypeIsGC(memBase) ? EA_BYREF : EA_PTRSIZE;
11433
11434                 if (emitIns_valid_imm_for_add(offset, EA_8BYTE))
11435                 {
11436                     if (lsl > 0)
11437                     {
11438                         // Generate code to set tmpReg = base + index*scale
11439                         emitIns_R_R_R_I(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum, lsl,
11440                                         INS_OPTS_LSL);
11441                     }
11442                     else // no scale
11443                     {
11444                         // Generate code to set tmpReg = base + index
11445                         emitIns_R_R_R(INS_add, addType, tmpReg, memBase->gtRegNum, index->gtRegNum);
11446                     }
11447
11448                     noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11449
11450                     // Then load/store dataReg from/to [tmpReg + offset]
11451                     emitIns_R_R_I(ins, ldstAttr, dataReg, tmpReg, offset);
11452                 }
11453                 else // large offset
11454                 {
11455                     // First load/store tmpReg with the large offset constant
11456                     codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11457                     // Then add the base register
11458                     //      rd = rd + base
11459                     emitIns_R_R_R(INS_add, addType, tmpReg, tmpReg, memBase->gtRegNum);
11460
11461                     noway_assert(emitInsIsLoad(ins) || (tmpReg != dataReg));
11462                     noway_assert(tmpReg != index->gtRegNum);
11463
11464                     // Then load/store dataReg from/to [tmpReg + index*scale]
11465                     emitIns_R_R_R_I(ins, ldstAttr, dataReg, tmpReg, index->gtRegNum, lsl, INS_OPTS_LSL);
11466                 }
11467             }
11468             else // (offset == 0)
11469             {
11470                 if (lsl > 0)
11471                 {
11472                     // Then load/store dataReg from/to [memBase + index*scale]
11473                     emitIns_R_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum, lsl, INS_OPTS_LSL);
11474                 }
11475                 else // no scale
11476                 {
11477                     // Then load/store dataReg from/to [memBase + index]
11478                     emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, index->gtRegNum);
11479                 }
11480             }
11481         }
11482         else // no Index register
11483         {
11484             if (emitIns_valid_imm_for_ldst_offset(offset, EA_SIZE(attr)))
11485             {
11486                 // Then load/store dataReg from/to [memBase + offset]
11487                 emitIns_R_R_I(ins, ldstAttr, dataReg, memBase->gtRegNum, offset);
11488             }
11489             else
11490             {
11491                 // We require a tmpReg to hold the offset
11492                 regNumber tmpReg = indir->GetSingleTempReg();
11493
11494                 // First load/store tmpReg with the large offset constant
11495                 codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset);
11496
11497                 // Then load/store dataReg from/to [memBase + tmpReg]
11498                 emitIns_R_R_R(ins, ldstAttr, dataReg, memBase->gtRegNum, tmpReg);
11499             }
11500         }
11501     }
11502     else // addr is not contained, so we evaluate it into a register
11503     {
11504         // Then load/store dataReg from/to [addrReg]
11505         emitIns_R_R(ins, ldstAttr, dataReg, addr->gtRegNum);
11506     }
11507 }
11508
11509 // The callee must call genConsumeReg() for any non-contained srcs
11510 // and genProduceReg() for any non-contained dsts.
11511
11512 regNumber emitter::emitInsBinary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src)
11513 {
11514     regNumber result = REG_NA;
11515
11516     // dst can only be a reg
11517     assert(!dst->isContained());
11518
11519     // src can be immed or reg
11520     assert(!src->isContained() || src->isContainedIntOrIImmed());
11521
11522     // find immed (if any) - it cannot be a dst
11523     GenTreeIntConCommon* intConst = nullptr;
11524     if (src->isContainedIntOrIImmed())
11525     {
11526         intConst = src->AsIntConCommon();
11527     }
11528
11529     if (intConst)
11530     {
11531         emitIns_R_I(ins, attr, dst->gtRegNum, intConst->IconValue());
11532         return dst->gtRegNum;
11533     }
11534     else
11535     {
11536         emitIns_R_R(ins, attr, dst->gtRegNum, src->gtRegNum);
11537         return dst->gtRegNum;
11538     }
11539 }
11540
11541 // The callee must call genConsumeReg() for any non-contained srcs
11542 // and genProduceReg() for any non-contained dsts.
11543
11544 regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, GenTree* src1, GenTree* src2)
11545 {
11546     regNumber result = REG_NA;
11547
11548     // dst can only be a reg
11549     assert(!dst->isContained());
11550
11551     // find immed (if any) - it cannot be a dst
11552     // Only one src can be an int.
11553     GenTreeIntConCommon* intConst  = nullptr;
11554     GenTree*             nonIntReg = nullptr;
11555
11556     if (varTypeIsFloating(dst))
11557     {
11558         // src1 can only be a reg
11559         assert(!src1->isContained());
11560         // src2 can only be a reg
11561         assert(!src2->isContained());
11562     }
11563     else // not floating point
11564     {
11565         // src2 can be immed or reg
11566         assert(!src2->isContained() || src2->isContainedIntOrIImmed());
11567
11568         // Check src2 first as we can always allow it to be a contained immediate
11569         if (src2->isContainedIntOrIImmed())
11570         {
11571             intConst  = src2->AsIntConCommon();
11572             nonIntReg = src1;
11573         }
11574         // Only for commutative operations do we check src1 and allow it to be a contained immediate
11575         else if (dst->OperIsCommutative())
11576         {
11577             // src1 can be immed or reg
11578             assert(!src1->isContained() || src1->isContainedIntOrIImmed());
11579
11580             // Check src1 and allow it to be a contained immediate
11581             if (src1->isContainedIntOrIImmed())
11582             {
11583                 assert(!src2->isContainedIntOrIImmed());
11584                 intConst  = src1->AsIntConCommon();
11585                 nonIntReg = src2;
11586             }
11587         }
11588         else
11589         {
11590             // src1 can only be a reg
11591             assert(!src1->isContained());
11592         }
11593     }
11594
11595     bool isMulOverflow = false;
11596     if (dst->gtOverflowEx())
11597     {
11598         if ((ins == INS_add) || (ins == INS_adds))
11599         {
11600             ins = INS_adds;
11601         }
11602         else if ((ins == INS_sub) || (ins == INS_subs))
11603         {
11604             ins = INS_subs;
11605         }
11606         else if (ins == INS_mul)
11607         {
11608             isMulOverflow = true;
11609             assert(intConst == nullptr); // overflow format doesn't support an int constant operand
11610         }
11611         else
11612         {
11613             assert(!"Invalid ins for overflow check");
11614         }
11615     }
11616     if (intConst != nullptr)
11617     {
11618         emitIns_R_R_I(ins, attr, dst->gtRegNum, nonIntReg->gtRegNum, intConst->IconValue());
11619     }
11620     else
11621     {
11622         if (isMulOverflow)
11623         {
11624             regNumber extraReg = dst->GetSingleTempReg();
11625             assert(extraReg != dst->gtRegNum);
11626
11627             if ((dst->gtFlags & GTF_UNSIGNED) != 0)
11628             {
11629                 if (attr == EA_4BYTE)
11630                 {
11631                     // Compute 8 byte results from 4 byte by 4 byte multiplication.
11632                     emitIns_R_R_R(INS_umull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11633
11634                     // Get the high result by shifting dst.
11635                     emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11636                 }
11637                 else
11638                 {
11639                     assert(attr == EA_8BYTE);
11640                     // Compute the high result.
11641                     emitIns_R_R_R(INS_umulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11642
11643                     // Now multiply without skewing the high result.
11644                     emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11645                 }
11646
11647                 // zero-sign bit comparison to detect overflow.
11648                 emitIns_R_I(INS_cmp, attr, extraReg, 0);
11649             }
11650             else
11651             {
11652                 int bitShift = 0;
11653                 if (attr == EA_4BYTE)
11654                 {
11655                     // Compute 8 byte results from 4 byte by 4 byte multiplication.
11656                     emitIns_R_R_R(INS_smull, EA_8BYTE, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11657
11658                     // Get the high result by shifting dst.
11659                     emitIns_R_R_I(INS_lsr, EA_8BYTE, extraReg, dst->gtRegNum, 32);
11660
11661                     bitShift = 31;
11662                 }
11663                 else
11664                 {
11665                     assert(attr == EA_8BYTE);
11666                     // Save the high result in a temporary register.
11667                     emitIns_R_R_R(INS_smulh, attr, extraReg, src1->gtRegNum, src2->gtRegNum);
11668
11669                     // Now multiply without skewing the high result.
11670                     emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11671
11672                     bitShift = 63;
11673                 }
11674
11675                 // Sign bit comparison to detect overflow.
11676                 emitIns_R_R_I(INS_cmp, attr, extraReg, dst->gtRegNum, bitShift, INS_OPTS_ASR);
11677             }
11678         }
11679         else
11680         {
11681             // We can just multiply.
11682             emitIns_R_R_R(ins, attr, dst->gtRegNum, src1->gtRegNum, src2->gtRegNum);
11683         }
11684     }
11685
11686     if (dst->gtOverflowEx())
11687     {
11688         assert(!varTypeIsFloating(dst));
11689         codeGen->genCheckOverflow(dst);
11690     }
11691
11692     return dst->gtRegNum;
11693 }
11694
11695 #endif // defined(_TARGET_ARM64_)