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